I am creating my own version of ls in and I'm stuck with a segfault

66 Views Asked by At

here is the code that I made for ls -l I created a time functions to get the date of creation of the files then there is get_permission to get all the permissions, then I put it all of it together in a function called my_ls_l and it segfault just here

void get_time(char *str)
{
    str[16] = '\0';
    str = str + 4;
    mini_printf("%s",str);
}

void get_permission(struct stat stat )
{

    my_putchar((S_ISDIR(stat.st_mode)) ? 'd' :
             (S_ISBLK(stat.st_mode) ? 'b' :
             (S_ISCHR(stat.st_mode) ? 'c' : '-')));
    my_putchar((stat.st_mode & S_IRUSR) ? 'r' : '-');
    my_putchar((stat.st_mode & S_IWUSR) ? 'w' : '-');
    my_putchar((stat.st_mode & S_IXUSR) ? 'x' : '-');
    my_putchar((stat.st_mode & S_IRGRP) ? 'r' : '-');
    my_putchar((stat.st_mode & S_IWGRP) ? 'w' : '-');
    my_putchar((stat.st_mode & S_IXGRP) ? 'x' : '-');
    my_putchar((stat.st_mode & S_IROTH) ? 'r' : '-');
    my_putchar((stat.st_mode & S_IWOTH) ? 'w' : '-');
    my_putchar((stat.st_mode & S_IXOTH) ? 'x' :
    (stat.st_mode & S_ISVTX) ? 'T' : '-');
}

int my_ls_l(void)
{
    struct dirent *entry;
    DIR *dir;
    struct stat stat;
    struct passwd *pw = getpwuid(stat.st_uid);
    struct group *grp = getgrgid(stat.st_gid);

    dir = opendir("./");
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_name[0] != '.') {
            get_permission(stat);
            mini_printf("%s", entry->d_name);
            mini_printf("%s",stat.st_nlink);
            mini_printf("%s",entry->d_name_name);
            mini_printf("%s",grp->gr_name);
            mini_printf("%s",stat.st_size);
            get_time(ctime(&stat.st_mtime));
            mini_printf("\n");
        }
    }
    mini_printf("\n");
    closedir(dir);
}
int main(void) {
    my_ls_l();
    return (0);
}

I was trying here to do ls -l and it get the name of the files and then it segfaults and I don't understand why

1

There are 1 best solutions below

1
Refugnic Eternium On

You have multiple problems in your code. The most glaring one being, that you do neither populate your stat structure, nor initialize it, meaning that every property of that structure can have any possible value. (Which makes it useless).

What you'll want is the stat function (https://www.man7.org/linux/man-pages/man2/stat.2.html), something like this:

int my_ls_l(void)
{
    struct dirent *entry;
    DIR *dir;
    struct stat st;


    dir = opendir("./");
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_name[0] != '.'
            && !stat(entry->d_name, &st)
        ) {
            struct passwd *pw = getpwuid(st.st_uid);
            struct group *grp = getgrgid(st.st_gid);
            get_permission(stat);
            mini_printf("%s", entry->d_name);
            mini_printf("%s",st.st_nlink);
            mini_printf("%s",entry->d_name_name);
            mini_printf("%s",grp->gr_name);
            mini_printf("%s",st.st_size);
            get_time(ctime(&st.st_mtime));
            mini_printf("\n");
        }
    }
    mini_printf("\n");
    closedir(dir);
}

Always check the return value of functions like that. Also, it would be best to pass an absolute path to stat, but for starters, the relative path should do.

Another (potential) issue is your use of ctime. You are writing to a buffer of unknown size, which can be overwritten at any given time.

When working with buffers like that, copy the contents to a buffer whose size you know and work with that.

Your gettime function could be optimized like this:

void get_time(char *str)
{
    mini_printf("%s",str + 4);
}

This works, because you are not manipulating the buffer but 'copying' it to the output stream, starting with the 4th character. It is reasonable to assume that the string in the ctime buffer already is 0 terminated.

On another note: Run your code through a debugger. It will help you find errors much faster than we here on StackOverflow could ever do. And it will help you learn to help yourself much better than we can too.