0

i need to recreate the unix ls function for my school project, when i pass the file as an argument i can display the stats of the file, but when i try to put it on the while loop it give me a segmentation fault. and it needs to be on the while loop so that i can read all the file on the directly without having to pass them as arguments

void  ft_perm(char *star)
    {
        struct stat fileStat;
        if(stat(star,&fileStat) < 0)
            return;
        printf((S_ISDIR(fileStat.st_mode))  ? "d" : "-");
        printf( (fileStat.st_mode & S_IRUSR) ? "r" : "-");
        printf( (fileStat.st_mode & S_IWUSR) ? "w" : "-");
        printf( (fileStat.st_mode & S_IXUSR) ? "x" : "-");
        printf( (fileStat.st_mode & S_IRGRP) ? "r" : "-");
        printf( (fileStat.st_mode & S_IWGRP) ? "w" : "-");
        printf( (fileStat.st_mode & S_IXGRP) ? "x" : "-");
        printf( (fileStat.st_mode & S_IROTH) ? "r" : "-");
        printf( (fileStat.st_mode & S_IWOTH) ? "w" : "-");
        printf( (fileStat.st_mode & S_IXOTH) ? "x" : "-");
        return;
    }

    char *ft_group(char *tim)
    {
        int i;
        int j;
        char *s;

        s = (char *)malloc (sizeof(char) * 16);
        i = 3;
        j = 0;
        while( i < 16 )
       {
           s[j] = tim[i];
           i++;
           j++;
       }
       return(s);
    }

    int count ()
    {
        DIR *dir;
        struct dirent *sd;
        int i;

        dir = opendir(".");
        if (!dir)
        {
            printf("error");
            exit(1);
        }
        i = 0;
        while((sd = readdir(dir) ))
        {
            i++;
        }
        return(i);
    }

    int main(int argc, char **argv)
    {
        struct stat statbuf;
        struct group *grp;
        struct passwd *pwd;
        pwd = getpwuid((geteuid()));
        struct dirent **sd; 
        ;
        int i = 1;
        int r = 1;
        while( r < 10)
        {
        stat(sd[i]->d_name,&statbuf);

        ft_perm(sd[i]);
        printf("1  %s",pwd->pw_name);

        if ((grp = getgrgid(statbuf.st_gid)) != NULL)
            printf(" %-8.8s", grp->gr_name);
        else
            printf(" %-8d", statbuf.st_gid);
        printf(" %d", (int)statbuf.st_size);
        printf(" %s\n", ft_group(ctime(&statbuf.st_atime)));
        r++;
        i++;
        }
    }
johnson dubula
  • 31
  • 1
  • 1
  • 7
  • 1
    `sd` seems uninitialized when used here `stat(sd[i]->d_name,&statbuf);` – Support Ukraine Aug 20 '18 at 09:14
  • look at the compiler warnings/errors: https://ideone.com/3NkhSd – mch Aug 20 '18 at 09:17
  • Note: `struct dirent **sd;` can be problematic, depending on how you copy data from the dirent. There is nothing that says the dirent struct returned cannot be a static instance where `readdir` returns the differing information for each file using the same pointer. So simply assigning the pointer returned does not guaranteed unique data within your collection of pointers unless you are making a copy of the information returned within its new storage you are providing... – David C. Rankin Aug 20 '18 at 09:35
  • Specifically from `man 3 dirent` *"The data returned by readdir() may be overwritten by subsequent calls to readdir() for the same directory stream."*, so it is better to allocate storage and save the data to storage you create. (and generally just saving the information you need, filename, inode no., etc..) So you will generally allocate for a `char **` and `ino_t**` to handle the wanted information. An array of struct holding the info desired is a good approach. – David C. Rankin Aug 20 '18 at 09:43

1 Answers1

0

You are not allocating memory to struct dirent **sd; and accessing it sd[i]. It will cause undefined behavior.

Consider the below code for allocating the memory.

struct dirent **sd = malloc(10*sizeof(struct dirent *));
kiran Biradar
  • 12,700
  • 3
  • 19
  • 44