0

I'm studying c programming in linux,and I wrote this to output information about the files and directories like the standard tool "ls" with "-l",everything works fine except the macro S_ISDIR,Here is my code. Additionally,my os is mint 14 x86_64.

#include<sys/types.h>
#include<time.h>
#include<string.h>
#include<dirent.h>
#include<stdio.h>
#include<sys/stat.h>
#include<unistd.h>
void do_ls(char []);
void show_file_info(struct stat *t){
    printf("mode:    %o\n",t->st_mode);
    if(S_ISDIR(t->st_mode)==0)
        printf("Is a dir\n");
    else
        printf("Is not a dir\n");
    printf("links:   %d\n",t->st_nlink);
    printf("group:   %d\n",t->st_gid);
    printf("user:    %d\n",t->st_uid);
    printf("size:    %d\n",t->st_size);
    printf("modtime: %s\n",ctime(&t->st_mtime));
}
int main(int num,char *a[]){
    if(num==1){
        do_ls(".");
    }
    else{
        while(--num){
            printf("%s :\n",*++a);
            do_ls(*a);
        }
    }
}
void do_ls(char dirname[]){
    DIR *tem=opendir(dirname);
    struct dirent *direntp;
    struct stat *buf;
    char t[256];
    if(tem==NULL){
        fprintf(stderr,"ls: cannot open %s\n",dirname);
    }
    else{
        while((direntp=readdir(tem))!=NULL){
            strcpy(t,dirname);
            printf("%s\n",direntp->d_name);
            strcat(t,"/");
            if(stat(t,buf)==-1){
                perror("");
                break;
            }
            else{
                show_file_info(buf);
            }
        }
        closedir(tem);
    }
}
user1198331
  • 139
  • 2
  • 3
  • 10

3 Answers3

0

The system call

int stat(const char *path, struct stat *buf);

does not allocate memory for *buf.

Either you stay with your declaration

struct stat *buf;

and allocate the memory by hand with

buf = (struct stat *) malloc(sizeof(struct stat));

and free the memory with free at a place where you don't need buf anylonger

or you change the declaration to

struct stat buf;

and let c allocate the memory for you.

More over you should test failing of stat with if(stat(t,&buf) < 0) as recommended in the manual.

Another error is, that you don't pass the filename to stat but the directory name.

I appended a corrected version of your code.


#include<sys/types.h>
#include<time.h>
#include<string.h>
#include<dirent.h>
#include<stdio.h>
#include<sys/stat.h>
#include<unistd.h>

void do_ls(char []);

void show_file_info(struct stat *t){
    printf("mode:    %o\n",t->st_mode);
    if((t->st_mode & S_IFMT) == S_IFDIR)
        printf("Is a dir\n");
    else
        printf("Is not a dir\n");
    printf("links:   %d\n",t->st_nlink);
    printf("group:   %d\n",t->st_gid);
    printf("user:    %d\n",t->st_uid);
    printf("size:    %d\n",t->st_size);
    printf("modtime: %s\n",ctime(&t->st_mtime));
}

int main(int num,char *a[]){
    if(num==1){
        do_ls(".");
    }
    else{
        while(--num){
            printf("%s :\n",*++a);
            do_ls(*a);
        }
    }
}

void do_ls(char dirname[]){
    DIR *tem=opendir(dirname);
    struct dirent *direntp;
    struct stat buf;
    char t[256];

    if(tem==NULL){
        fprintf(stderr,"ls: cannot open %s\n",dirname);
    }
    else{
        while((direntp=readdir(tem))!=NULL){
            strcpy(t,dirname);
            printf("%s\n",direntp->d_name);
            strcat(t,"/");
            strcat(t,direntp->d_name);
            if(stat(t,&buf) < 0){
                perror("");
                break;
            }
            else{
                show_file_info(&buf);
            }
        }
        closedir(tem);
    }

}
user1146332
  • 2,630
  • 1
  • 15
  • 19
  • Thanks for your answer.But the problem remains to be unsolved. "logout" is a directory, but the program output like this mode: 40755 Is not a dir links: 6 group: 1000 user: 1000 size: 4096 modtime: Fri Feb 1 17:59:53 2013 – user1198331 Feb 01 '13 at 10:01
  • I appended a corrected version. Now everything works fine. In your code you didn't passed the filename to `stat` but always the directory name... – user1146332 Feb 01 '13 at 10:12
  • did you compile and run the program?did it give you the right output? – user1198331 Feb 01 '13 at 10:34
  • Yes. I compiled the sources, run the program and get the right output. Maybe `t[256]` isn't sufficient in your test case!? – user1146332 Feb 01 '13 at 10:38
  • Oh,I am confused.Still,it give me the wrong output in my machine.It cannot distinguish directory from a normal file. – user1198331 Feb 01 '13 at 10:42
0

The corrections of user1198331 about stat was right. It is a good practice to generally check all syscalls return values in order to prevent errors.

Still, in your original code, I think this part was wrong:

if(S_ISDIR(t->st_mode)==0)
    printf("Is a dir\n");
else
    printf("Is not a dir\n");

You consider that if S_ISDIR(t->st_mode) returns 0, it is a directory, but actually, S_ISDIR(t->st_mode) returns 0 if the file pointed to by t is not a directory. You, thus, have to do the reverse check.

Scylardor
  • 477
  • 3
  • 11
0

Try following from this link.

#ifndef S_ISDIR
#define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
#endif
Pabitra Dash
  • 1,461
  • 2
  • 21
  • 28