Issue
I have a function that (ideally) would merely simulate a portion of the ls -l command. It is meant to return permissions for the file, and the name of the file. I don't really care about any other information. It also is not the cleanest, as I am stuck using the VIM editor, and it is significantly less user friendly than modern IDEs.
Code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
void ls_l(const char *path){
DIR *dir;
struct dirent *file;
struct stat fileStat;
dir = opendir(path);
if(!dir) {
printf("opendir failed\n");
return;
}
while (((file = readdir(dir)) != NULL)){
char path2[255];
sprintf(path2, "%s/%s", path, file->d_name);
printf("%s\n", path2);
if(lstat(path2, &fileStat)) {
printf("lstat failed\n");
return;
}
//User permissions
printf( (fileStat.st_mode & S_IRUSR) ? " r" : " -");
printf( (fileStat.st_mode & S_IWUSR) ? "w" : "-");
printf( (fileStat.st_mode & S_IXUSR) ? "x" : "-");
//Group permissions
printf( (fileStat.st_mode & S_IRGRP) ? "r" : "-");
printf( (fileStat.st_mode & S_IWGRP) ? "w" : "-");
printf( (fileStat.st_mode & S_IXGRP) ? "x" : "-");
//Other permissions
printf( (fileStat.st_mode & S_IROTH) ? "r" : "-");
printf( (fileStat.st_mode & S_IWOTH) ? "w" : "-");
printf( (fileStat.st_mode & S_IXOTH) ? "x | " : "- | ");
}
}
void doStep(int stepNum){
chdir("dir0");
char cwd[PATH_MAX];
if(getcwd(cwd, sizeof(cwd)) != NULL){
printf("CWD: %s\n", cwd);
}
else{
printf("getcwd() error");
}
switch (stepNum){
case 1:
printf("Display files and permissions for ./dir0\n");
ls_l(cwd);
break;
case 2:
printf("Change permission for file6.txt to -rwxrwx---\n");
chmod("./file6.txt", S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
S_IWGRP | S_IXGRP);
break;
case 3:
printf("Remove file1.txt and file2.txt from directory dir1\n");
break;
case 4:
printf("Remove dir1 directory\n");
break;
case 5:
printf("Display files and permission for ./dir0\n");
break;
}
}
int main(){
int i;
for (i = 1; i < 2; i++){
doStep(i);
}
return 0;
}
I am only through the user and group permissions and I already have noticed a serious problem with the code. For whatever reason, the group permissions fail to change with each file, and thus do not return the correct values. I am only aware of this because because changing the permissions of a file and checking the return with ls -l gives me different values that that of my code.
I am aware that this isn't a complete program, as I am not finished with it, but it can compile and run on my school UNIX server, so it should suffice for any testing.
I would also like to not that case 2 never functioned before I noticed this error, so if you'd like to help with that as well I would appreciate it.
Edit: I use this to compile: ''' gcc task13prog.c -o task13prog '''
File structure is /dir0, which contains directories /dir1 and /dir2, a regular file called file6.txt, and a symbolic link called link5. I am more or less entirely concerned with this file structure, and only this file structure.
Output as requested by Allan Wind Slightly edited to remove username data
{cslinux1:~/cs3377/project2} pwd
/home/013/t/tm/***/cs3377/project2
{cslinux1:~/cs3377/project2} ./task13prog
CWD: /home/013/t/tm/***/cs3377/project2/dir0
Display files and permissions for ./dir0
/home/013/t/tm/***/cs3377/project2/dir0/.
rwx--x--x | /home/013/t/tm/***/cs3377/project2/dir0/..
rwx--x--x | /home/013/t/tm/***/cs3377/project2/dir0/link5
rwxrwxrwx | /home/013/t/tm/***/cs3377/project2/dir0/dir2
rwx--x--x | /home/013/t/tm/***/cs3377/project2/dir0/file6.txt
rwxrwxrwx | /home/013/t/tm/***/cs3377/project2/dir0/dir1
rwx--x--x | {cslinux1:~/cs3377/project2} ls -l dir0
total 112
drwx--x--x 2 *** sn 54 Apr 3 18:38 dir1
drwx--x--x 2 *** sn 54 Apr 3 18:38 dir2
-rwxrwxrwx 1 *** sn 0 Apr 3 18:38 file6.txt
lrwxrwxrwx 1 *** sn 14 Apr 3 18:38 link5 -> dir2/file4.txt
{cslinux1:~/cs3377/project2}
Final edit: The solution marked as correct was in fact, correct. Upon testing on a fresh linux system the solution functioned as expected. It appears that there was an error in the original environment that prevented me from making changes to permissions and reading permissions accurately.
Solution
I modified your program to pass in the path, checked return values of the functions you call and implemented the suggestion offered up by @MarkPlotnick which is the root cause of your trouble:
#include <limits.h>
void ls_l(const char *path){
DIR *dir;
struct dirent *file;
struct stat fileStat;
dir = opendir(path);
if(!dir) {
printf("opendir failed\n");
return;
}
while (((file = readdir(dir)) != NULL)){
char path2[PATH_MAX];
// if path contains a trailing /, you will end up with //
// in path2 which is ugly but works fine. You could special case that,
// and also special case ./ not being copied into path2
snprintf(path2, PATH_MAX, "%s/%s", path, file->d_name);
printf("%s\n", path2);
if(lstat(path2, &fileStat)) {
printf("lstat failed\n");
return;
}
...
As for step 2, it works for me, so you just need to ensure that file6.txt
is in the dir0/
directory.
Answered By - Allan Wind Answer Checked By - Pedro (WPSolving Volunteer)