Posted: . At: 7:41 AM. This was 9 months ago. Post ID: 18321
Page permalink. WordPress uses cookies, or tiny pieces of information stored on your computer, to verify who you are. There are cookies for logged in users and for commenters.
These cookies expire two weeks after they are set.


A nice program to list files in a directory. A version of ls.


This program uses stat to list all files in a directory and show the same information as ls -hula. This is a very nice example of Linux programming.

my_ls.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
 
/********************************************************************
* Description: A version of ls written in c.
* Author: John Cartwright <XXXXXXXXXXXXXXXXXX>
* Created at: Mon Apr  3 10:38:18 AEST 2023
* Computer: localhost.localdomain
* System: Linux 5.14.0-162.18.1.el9_1.x86_64 on x86_64
*
* Copyright (c) 2023 John Cartwright  All rights reserved.
*
********************************************************************/
 
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
 
#define syscall(a, D, S, d) __asm__ __volatile__("syscall" : : "a"(a), "D"(D), "S"(S), "d"(d))
 
void list_files(const char *path) {
 
    struct dirent *entry;
    struct stat file_stat;
    char full_path[PATH_MAX];
 
    DIR *dir = opendir(path);
 
    if (dir == NULL) {
        perror("opendir");
        return;
    }
 
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0) {
            continue;
        }
 
        snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
 
        if (stat(full_path, &file_stat) < 0) {
            perror("stat");
            continue;
        }
 
        struct passwd *user_info = getpwuid(file_stat.st_uid);
        struct group *group_info = getgrgid(file_stat.st_gid);
 
        printf("%s", S_ISDIR(file_stat.st_mode) ? "d" : "-");
        printf("%s", (file_stat.st_mode & S_IRUSR) ? "r" : "-");
        printf("%s", (file_stat.st_mode & S_IWUSR) ? "w" : "-");
        printf("%s", (file_stat.st_mode & S_IXUSR) ? "x" : "-");
        printf("%s", (file_stat.st_mode & S_IRGRP) ? "r" : "-");
        printf("%s", (file_stat.st_mode & S_IWGRP) ? "w" : "-");
        printf("%s", (file_stat.st_mode & S_IXGRP) ? "x" : "-");
        printf("%s", (file_stat.st_mode & S_IROTH) ? "r" : "-");
        printf("%s", (file_stat.st_mode & S_IWOTH) ? "w" : "-");
        printf("%s", (file_stat.st_mode & S_IXOTH) ? "x" : "-");
 
        printf(" %ld", file_stat.st_nlink); /* Print file hardlinks. */
        printf(" %s ", user_info->pw_name); /* Print file owner username. */
        printf("%s ", group_info->gr_name); /* Print file owner groupname. */
 
            if (file_stat.st_size > 1000000) { /* Checking if we are seeing a
                file that is more than one Megabyte. */
            long file_size_bytes = file_stat.st_size;
            double file_size_mb = (double)file_size_bytes / (1024.0 * 1024.0);
            printf(" %.2f MB ", file_size_mb);
            }
            else if (file_stat.st_size > 1000) { /* Checking if we are seeing a
                file that is more than one Kilobyte. */
            long file_size_bytes = file_stat.st_size;
            double file_size_kb = (double)file_size_bytes / 1024.0;
            printf(" %.2f KB ", file_size_kb);
            } else {
                /* Otherwise, the filesize is in bytes and we just print this.
                 * Not too hard.
                */
                printf(" %ld bytes", file_stat.st_size);
            }
        printf(" %ld", file_stat.st_mtime);
        printf(" %s\n", entry->d_name);
    }
 
    closedir(dir);
}
 
int main(int argc, char *argv[]) {
 
    if (argc == 1) {
        list_files(".");
    } else {
        printf("%s", argv[1]);
        list_files(argv[1]);
    }
 
    syscall(1, 1, "End of listing.\n", 16);
    syscall(60, 0, 0, 0);
 
    return 0;
}

This shows the username and group of the file owner, and the filesize as well. Below is the output this program will give you.

(jcartwright@localhost) 192.168.1.5 Documents  $ ./myls
drwx--x--- 20 jcartwright jcartwright  4.00 KB  1690830117 ..
drwxr-xr-x 2 jcartwright jcartwright  41 bytes 1690498197 html
-rw-r--r-- 1 jcartwright jcartwright  526 bytes 1688428947 vid.py
-rw-r--r-- 1 jcartwright jcartwright  20.58 MB  1688508774 9rbtxh.pdf
-rw-r--r-- 1 jcartwright jcartwright  980 bytes 1688684231 ipv6.asm
-rw-r--r-- 1 jcartwright jcartwright  1.39 KB  1688684236 ipv6.o
-rwxr-xr-x 1 jcartwright jcartwright  8.31 KB  1688684238 ipv6
-rw-r--r-- 1 jcartwright jcartwright  194 bytes 1688942844 colors.sh
drwxr-xr-x 10 jcartwright jcartwright  4.00 KB  1689120655 rtl-sdr
-rw-r--r-- 1 jcartwright jcartwright  177 bytes 1689215012 y.c
-rwxr-xr-x 1 jcartwright jcartwright  25.23 KB  1689215016 y
-rw-r--r-- 1 jcartwright jcartwright  145.71 KB  1689368699 mpv-shot0001.jpg
-rw-r--r-- 1 jcartwright jcartwright  113.08 KB  1689368707 mpv-shot0002.jpg
-rw-r--r-- 1 jcartwright jcartwright  3.89 KB  1689816153 images.c
-rwxr-xr-x 1 jcartwright jcartwright  26.30 KB  1689816160 system_info
-rwxr-xr-x 1 jcartwright jcartwright  205 bytes 1689896400 xp.sh
-rw-r--r-- 1 jcartwright jcartwright  4.00 KB  1690839106 myls.c
-rw-r--r-- 1 jcartwright jcartwright  2.07 KB  1690240175 xlogo.c
-rw-r--r-- 1 jcartwright jcartwright  2.65 KB  1349779195 xterm-color_48x48.xpm
-rw-r--r-- 1 jcartwright jcartwright  2.52 KB  1349650602 xterm_48x48.xpm
-rw-r--r-- 1 jcartwright jcartwright  2.07 KB  1690240294 png.c
-rwxr-xr-x 1 jcartwright jcartwright  26.11 KB  1690240297 xorg_logo
drwxr-xr-x 5 jcartwright jcartwright  4.00 KB  1684566812 wordpress
drwxr-xr-x 12 jcartwright jcartwright  4.00 KB  1587781946 eureka-1.27b-source
-rwxr-xr-x 1 jcartwright jcartwright  25.75 KB  1690692736 lsme
drwxr-xr-x 14 jcartwright jcartwright  4.00 KB  1690747190 yadex
drwxrwxrwx 14 jcartwright jcartwright  24.00 KB  1690680931 fuck
-rwxr-xr-x 1 jcartwright jcartwright  25.70 KB  1690839139 myls
End of listing.

This might be very useful as an example of programming using <sys/stat.h>.

I could also create a file myls.h and include the void function and other stuff in there.

myls.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#define syscall(a, D, S, d) __asm__ __volatile__("syscall" : : "a"(a), "D"(D), "S"(S), "d"(d))
 
void list_files(const char *path) {
 
    struct dirent *entry;
    struct stat file_stat;
    char full_path[PATH_MAX];
 
    DIR *dir = opendir(path);
 
    if (dir == NULL) {
        perror("opendir");
        return;
    }
 
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0) {
            continue;
        }
 
        snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
 
        if (stat(full_path, &file_stat) < 0) {
            perror("stat");
            continue;
        }
 
        struct passwd *user_info = getpwuid(file_stat.st_uid);
        struct group *group_info = getgrgid(file_stat.st_gid);
 
        printf("%s", S_ISDIR(file_stat.st_mode) ? "d" : "-");
        printf("%s", (file_stat.st_mode & S_IRUSR) ? "r" : "-");
        printf("%s", (file_stat.st_mode & S_IWUSR) ? "w" : "-");
        printf("%s", (file_stat.st_mode & S_IXUSR) ? "x" : "-");
        printf("%s", (file_stat.st_mode & S_IRGRP) ? "r" : "-");
        printf("%s", (file_stat.st_mode & S_IWGRP) ? "w" : "-");
        printf("%s", (file_stat.st_mode & S_IXGRP) ? "x" : "-");
        printf("%s", (file_stat.st_mode & S_IROTH) ? "r" : "-");
        printf("%s", (file_stat.st_mode & S_IWOTH) ? "w" : "-");
        printf("%s", (file_stat.st_mode & S_IXOTH) ? "x" : "-");
 
        printf(" %ld", file_stat.st_nlink); /* Print file hardlinks. */
        printf(" %s ", user_info->pw_name); /* Print file owner username. */
        printf("%s ", group_info->gr_name); /* Print file owner groupname. */
 
            if (file_stat.st_size > 1000000) { /* Checking if we are seeing a
                file that is more than one Megabyte. */
            long file_size_bytes = file_stat.st_size;
            double file_size_mb = (double)file_size_bytes / (1024.0 * 1024.0);
            printf(" %.2f MB ", file_size_mb);
            }
            else if (file_stat.st_size > 1000) { /* Checking if we are seeing a
                file that is more than one Kilobyte. */
            long file_size_bytes = file_stat.st_size;
            double file_size_kb = (double)file_size_bytes / 1024.0;
            printf(" %.2f KB ", file_size_kb);
            } else {
                /* Otherwise, the filesize is in bytes and we just print this.
                 * Not too hard.
                */
                printf(" %ld bytes", file_stat.st_size);
            }
        printf(" %ld", file_stat.st_mtime);
        printf(" %s\n", entry->d_name);
    }
 
    closedir(dir);
}

Once that is done, the main source file is cleaner.

myls.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
 
/********************************************************************
* Description: A version of ls written in c.
* Author: John Cartwright <[email protected]>
* Created at: Mon Apr  3 10:38:18 AEST 2023
* Computer: localhost.localdomain
* System: Linux 5.14.0-162.18.1.el9_1.x86_64 on x86_64
*
* Copyright (c) 2023 John Cartwright  All rights reserved.
*
********************************************************************/
 
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
 
#include "myls.h"
 
int main(int argc, char *argv[]) {
 
    if (argc == 1) {
        list_files(".");
    } else {
        printf("%s", argv[1]);
        list_files(argv[1]);
    }
 
    syscall(1, 1, "End of listing.\n", 16);
    syscall(60, 0, 0, 0);
 
    return 0;
}

This program even compiles and runs on a Macintosh PC. This is amazing. But it is a very simple program.

(04:07 pm)Documents $> ./myls stuff/
stuff/drwx------ 79 jason staff  2.47 KB  1690870016 ..
-rw-r--r-- 1 jason staff  385.37 KB  1546599903 mardi-gras-2016-fuse-magazine.jpg
-rw-r--r-- 1 jason staff  51.30 KB  1514880390 93bffab7a44bc518799a2a68711ad790.jpg
-rw-r--r-- 1 jason staff  335.34 KB  1539597643 1538995576940.png
-rwxrwxrwx 1 jason staff  156.05 KB  1503489616 wifi-crack.png
-rw-r--r-- 1 jason staff  0.96 MB  1547547050 1514877771595.jpg
-rw-r--r-- 1 jason staff  48.23 KB  1545638172 8c9ec9b3d45be9f9c880e850861a5fc7.jpg
-rw-r--r-- 1 jason staff  1.88 MB  1547548193 images.tar.bz2

C code is very portable.

(04:07 pm)Documents $> file myls
myls: Mach-O 64-bit executable x86_64
()deusexmachina.local-_

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.