Line data Source code
1 : #include "custom_ls.h"
2 :
3 : int max_size_user;
4 : int max_size_group;
5 : int max_size_file_size;
6 :
7 6 : int ls(const char *path)
8 : {
9 6 : max_size_user = 0;
10 6 : max_size_group = 0;
11 6 : max_size_file_size = 0;
12 :
13 : struct stat path_stat;
14 :
15 6 : if (path == NULL)
16 1 : path = ".";
17 :
18 6 : if (lstat(path, &path_stat) == -1)
19 : {
20 2 : print_error("[ERROR] stat on path");
21 2 : return EXIT_FAILURE;
22 : }
23 :
24 4 : if (S_ISDIR(path_stat.st_mode))
25 3 : list_directory(path);
26 : else
27 1 : file_info(path, path);
28 :
29 4 : return EXIT_SUCCESS;
30 : }
31 :
32 97 : int count_digits(long long value)
33 : {
34 97 : if (value == 0)
35 6 : return 1;
36 :
37 91 : value = llabs(value);
38 91 : int count = 0;
39 :
40 458 : while (value > 0)
41 : {
42 367 : value /= 10;
43 367 : count++;
44 : }
45 :
46 91 : return count;
47 : }
48 :
49 46 : void file_info(const char *full_path, const char *file_name)
50 : {
51 : int space_quantity;
52 :
53 : struct stat file_stat;
54 :
55 46 : if (lstat(full_path, &file_stat) == -1)
56 : {
57 0 : print_error("[ERROR] stat");
58 0 : return;
59 : }
60 :
61 : // User
62 46 : print_generic(STDOUT_FILENO, "%c%s ", get_filetype(file_stat.st_mode), get_permissions(file_stat.st_mode));
63 :
64 46 : space_quantity = max_size_user - strlen(get_owner(file_stat.st_uid));
65 46 : for (int i = 0; i < space_quantity && space_quantity > 0; i++)
66 0 : print_generic(STDOUT_FILENO, " ", get_owner(file_stat.st_uid));
67 :
68 46 : print_generic(STDOUT_FILENO, "%s ", get_owner(file_stat.st_uid));
69 :
70 : // Group
71 46 : space_quantity = max_size_group - strlen(get_group(file_stat.st_gid));
72 46 : for (int i = 0; i < space_quantity && space_quantity > 0; i++)
73 0 : print_generic(STDOUT_FILENO, " ", get_group(file_stat.st_gid));
74 :
75 46 : print_generic(STDOUT_FILENO, "%s ",
76 : get_group(file_stat.st_gid));
77 :
78 : // Size
79 46 : space_quantity = max_size_file_size - count_digits(file_stat.st_size);
80 100 : for (int i = 0; i < space_quantity && space_quantity > 0; i++)
81 54 : print_generic(STDOUT_FILENO, " ");
82 :
83 46 : print_generic(STDOUT_FILENO, "%ld ", file_stat.st_size);
84 :
85 46 : print_generic(STDOUT_FILENO, "%s ", parse_time(file_stat.st_mtime));
86 :
87 : // File name with color
88 46 : if (get_filetype(file_stat.st_mode) == 'd')
89 30 : print_generic(STDOUT_FILENO, "\033[1;34m%s\033[0m\n", file_name);
90 : else
91 16 : print_generic(STDOUT_FILENO, "%s\n", file_name);
92 : }
93 :
94 3 : void list_directory(const char *path)
95 : {
96 : char full_path[MAX_PATH_LENGTH];
97 :
98 3 : DIR *dir_count_size = opendir(path);
99 3 : if (dir_count_size == NULL)
100 : {
101 0 : print_error("[ERROR] Couldn't open the directory");
102 0 : return;
103 : }
104 :
105 : // Count the max size of user, group and file size
106 : struct dirent *file_count_size;
107 48 : while ((file_count_size = readdir(dir_count_size)) != NULL)
108 : {
109 45 : snprintf(full_path, MAX_PATH_LENGTH, "%s/%s", path, file_count_size->d_name);
110 :
111 : struct stat file_stat;
112 :
113 45 : if (lstat(full_path, &file_stat) == -1)
114 : {
115 0 : print_error("[ERROR] stat");
116 0 : return;
117 : }
118 :
119 45 : max_size_user = strlen(get_owner(file_stat.st_uid)) > max_size_user ? strlen(get_owner(file_stat.st_uid)) : max_size_user;
120 45 : max_size_group = strlen(get_group(file_stat.st_gid)) > max_size_group ? strlen(get_group(file_stat.st_gid)) : max_size_group;
121 45 : max_size_file_size = count_digits(file_stat.st_size) > max_size_file_size ? count_digits(file_stat.st_size) : max_size_file_size;
122 : }
123 :
124 3 : closedir(dir_count_size);
125 :
126 3 : DIR *dir = opendir(path);
127 3 : if (dir == NULL)
128 : {
129 0 : print_error("[ERROR] Couldn't open the directory");
130 0 : return;
131 : }
132 :
133 : struct dirent *file;
134 :
135 3 : print("[INFO] Listing directory %s\n", path);
136 :
137 48 : while ((file = readdir(dir)) != NULL)
138 : {
139 45 : snprintf(full_path, MAX_PATH_LENGTH, "%s/%s", path, file->d_name);
140 45 : file_info(full_path, file->d_name);
141 : }
142 :
143 3 : closedir(dir);
144 : }
145 :
146 46 : char *parse_time(time_t time)
147 : {
148 : static char time_str[STR_SIZE];
149 46 : struct tm *broken_time = localtime(&time);
150 :
151 46 : strftime(time_str, STR_SIZE, "%b %d %H:%M", broken_time);
152 :
153 46 : return time_str;
154 : }
155 :
156 92 : char get_filetype(mode_t perm)
157 : {
158 92 : switch (perm & S_IFMT)
159 : {
160 32 : case S_IFREG:
161 32 : return '-';
162 60 : case S_IFDIR:
163 60 : return 'd';
164 0 : case S_IFLNK:
165 0 : return 'l';
166 0 : case S_IFBLK:
167 0 : return 'b';
168 0 : case S_IFCHR:
169 0 : return 'c';
170 0 : case S_IFIFO:
171 0 : return 'p';
172 0 : case S_IFSOCK:
173 0 : return 's';
174 0 : default:
175 0 : return '?';
176 : }
177 : }
178 :
179 46 : char *get_permissions(mode_t perm)
180 : {
181 : static char str[PERM_SIZE];
182 414 : snprintf(str, PERM_SIZE, "%c%c%c%c%c%c%c%c%c",
183 46 : (perm & S_IRUSR) ? 'r' : '-',
184 46 : (perm & S_IWUSR) ? 'w' : '-',
185 46 : (perm & S_IXUSR) ? 'x' : '-',
186 46 : (perm & S_IRGRP) ? 'r' : '-',
187 46 : (perm & S_IWGRP) ? 'w' : '-',
188 46 : (perm & S_IXGRP) ? 'x' : '-',
189 46 : (perm & S_IROTH) ? 'r' : '-',
190 46 : (perm & S_IWOTH) ? 'w' : '-',
191 46 : (perm & S_IXOTH) ? 'x' : '-');
192 46 : return str;
193 : }
194 :
195 140 : char *get_owner(uid_t uid)
196 : {
197 140 : return getpwuid(uid)->pw_name;
198 : }
199 :
200 140 : char *get_group(gid_t gid)
201 : {
202 140 : return getgrgid(gid)->gr_name;
203 : }
|