1 /* Copyright (C) 2008 Ricardo Catalinas Jiménez <jimenezrick@gmail.com>
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 void init_tree(char *name
)
26 tree_root
= g_node_new(create_new_file(name
, NULL
, TRUE
));
28 path
= g_get_current_dir();
29 tree_root
= g_node_new(create_new_file(path
, NULL
, TRUE
));
34 File
*create_new_file(char *name
, char *path
, gboolean exit_on_error
)
36 struct stat info
, link_info
;
37 File
*file
= malloc(sizeof(File
));
41 file_path
= g_strconcat(path
, "/", name
, NULL
);
45 if (lstat(file_path
, &link_info
) == -1) {
47 PRINT_ERRNO_AND_EXIT();
49 /* Sometimes a file is created and then removed, this under Linux
50 * inotify events can create confusion because we try to stat a
51 * file that no longer exists. The file is removed before we can do
52 * the stat. So we ignore the errno and return NULL to take account
55 /* PRINT_ERRNO_INFO(); */
61 } else if (S_ISLNK(link_info
.st_mode
)) {
62 if (link_info
.st_size
== 0)
63 link_info
.st_size
= PATH_MAX
;
65 file
->link_path
= malloc(link_info
.st_size
+ 1);
66 file
->link_path
[link_info
.st_size
] = '\0';
67 file
->link_path
[0] = '\0';
70 if (readlink(file_path
, file
->link_path
, link_info
.st_size
) == -1)
73 file
->link_path
= NULL
;
76 if (stat(file_path
, &info
) == -1) {
78 PRINT_ERRNO_AND_EXIT();
81 file
->type
= file_type
;
83 } else if (S_ISDIR(info
.st_mode
))
84 file
->type
= directory_type
;
86 file
->type
= file_type
;
88 if (file
->link
== TRUE
)
89 file
->info
= link_info
;
93 file
->name
= strdup(name
);
96 file
->show_dotfiles
= FALSE
;
98 file
->dotfiles
= NULL
;
107 gboolean
read_directory(GNode
*directory
)
110 struct dirent
*entry
;
112 char *path
= get_path(directory
);
115 if ((dir
= opendir(path
)) == NULL
) {
119 for (errno
= 0, i
= 0; (entry
= readdir(dir
)) != NULL
; ) {
120 if (!strcmp(entry
->d_name
, ".") || !strcmp(entry
->d_name
, ".."))
123 if ((new_file
= create_new_file(entry
->d_name
, path
, FALSE
)) == NULL
)
126 if (new_file
->name
[0] == '.') {
127 insert_sorted_in_dotfiles(directory
, new_file
);
130 insert_sorted_in_tree(directory
, new_file
);
136 if (closedir(dir
) == -1)
140 FILE(directory
)->read
= TRUE
;
142 add_watch_directory(directory
);
150 void free_element_data(gpointer element_data
, gpointer data
)
152 if (FILE((GNode
*) element_data
)->type
== directory_type
)
153 destroy_directory_content((GNode
*) element_data
);
154 free_node_data((GNode
*) element_data
, NULL
);
157 void destroy_dotfiles(GList
*dotfiles
)
159 g_list_foreach(dotfiles
, free_element_data
, NULL
);
160 g_list_free(dotfiles
);
163 gboolean
free_node_data(GNode
*node
, gpointer data
)
165 free(FILE(node
)->name
);
166 free(FILE(node
)->link_path
);
167 destroy_dotfiles(FILE(node
)->dotfiles
);
173 void destroy_directory_content(GNode
*directory
)
175 destroy_directory_content_real(directory
, TRUE
);
178 void destroy_directory_content_real(GNode
*directory
, gboolean remove_watch
)
180 GNode
*file_ptr
, *file_ptr2
;
183 if (FILE(directory
)->read
== TRUE
)
184 remove_watch_directory(directory
, remove_watch
);
186 for (file_ptr
= g_node_first_child(directory
); file_ptr
!= NULL
; ) {
187 file_ptr2
= file_ptr
;
188 file_ptr
= g_node_next_sibling(file_ptr
);
190 g_node_unlink(file_ptr2
);
191 g_node_traverse(file_ptr2
, G_PRE_ORDER
, G_TRAVERSE_ALL
, -1, free_node_data
, NULL
);
192 g_node_destroy(file_ptr2
);
194 destroy_dotfiles(FILE(directory
)->dotfiles
);
195 FILE(directory
)->dotfiles
= NULL
;
196 FILE(directory
)->read
= FALSE
;
199 void add_dotfiles(GNode
*directory
)
205 for (line_ptr
= g_list_next(FILE(directory
)->line
), position
= 0;
206 FILE(directory
)->dotfiles
!= NULL
; position
++) {
207 file_ptr
= NODE(FILE(directory
)->dotfiles
);
208 FILE(directory
)->dotfiles
= g_list_delete_link(FILE(directory
)->dotfiles
,
209 FILE(directory
)->dotfiles
);
210 g_node_insert(directory
, position
, file_ptr
);
211 lines
= g_list_insert_before(lines
, line_ptr
, file_ptr
);
212 FILE(file_ptr
)->line
= g_list_previous(line_ptr
);
213 if (FILE(file_ptr
)->type
== directory_type
&& FILE(file_ptr
)->open
== TRUE
)
214 add_directory_content(file_ptr
);
216 FILE(directory
)->show_dotfiles
= TRUE
;
219 void remove_dotfiles(GNode
*directory
)
222 GList
*line_ptr
, *line_ptr_aux
;
224 for (file_ptr
= g_node_first_child(directory
); file_ptr
!= NULL
&&
225 FILE(file_ptr
)->name
[0] == '.'; ) {
226 lines
= g_list_delete_link(lines
, FILE(file_ptr
)->line
);
227 FILE(directory
)->dotfiles
= g_list_insert(FILE(directory
)->dotfiles
, file_ptr
, -1);
228 FILE(file_ptr
)->line
= NULL
;
229 file_ptr
= g_node_next_sibling(file_ptr
);
230 g_node_unlink(NODE(g_list_last(FILE(directory
)->dotfiles
)));
232 for (line_ptr
= g_list_previous(FILE(file_ptr
)->line
);
233 line_ptr
!= FILE(directory
)->line
; ) {
234 line_ptr_aux
= line_ptr
;
235 line_ptr
= g_list_previous(line_ptr
);
236 FILE(NODE(line_ptr_aux
))->line
= NULL
;
237 lines
= g_list_delete_link(lines
, line_ptr_aux
);
240 FILE(directory
)->show_dotfiles
= FALSE
;
243 int file_cmp(File
*file1
, File
*file2
)
245 if (file1
->name
[0] == '.' && file2
->name
[0] != '.')
247 else if (file1
->name
[0] != '.' && file2
->name
[0] == '.')
249 else if (file1
->type
== file2
->type
)
250 return strcmp(file1
->name
, file2
->name
);
251 else if (file1
->type
== directory_type
)
257 int file_cmp_list(gconstpointer file1
, gconstpointer file2
)
259 return file_cmp(FILE((GNode
*) file1
), FILE((GNode
*) file2
));
262 void insert_sorted_in_dotfiles(GNode
*directory
, File
*file
)
264 FILE(directory
)->dotfiles
= g_list_insert_sorted(FILE(directory
)->dotfiles
,
265 g_node_new(file
), file_cmp_list
);
268 GNode
*insert_sorted_in_tree(GNode
*directory
, File
*file
)
270 GNode
*file_ptr
, *new_file
;
272 if (G_NODE_IS_LEAF(directory
)) {
273 g_node_append_data(directory
, file
);
274 return g_node_first_child(directory
);
275 } else if (file_cmp(file
, FILE(g_node_first_child(directory
))) < 0) {
276 g_node_prepend_data(directory
, file
);
277 return g_node_first_child(directory
);
279 for (file_ptr
= g_node_last_child(directory
); file_ptr
!= NULL
;
280 file_ptr
= g_node_prev_sibling(file_ptr
)) {
281 if (file_cmp(file
, FILE(file_ptr
)) > 0) {
282 new_file
= g_node_new(file
);
283 g_node_insert_after(directory
, file_ptr
, new_file
);
292 char *get_path(GNode
*file
)
295 GString
*path
= g_string_new(FILE(file
)->name
);
297 for (file_ptr
= file
->parent
; file_ptr
!= NULL
; file_ptr
= file_ptr
->parent
) {
298 g_string_prepend(path
, "/");
299 g_string_prepend(path
, FILE(file_ptr
)->name
);
302 return g_string_free(path
, FALSE
);
305 GNode
*get_next_file_real(GNode
*file
, gboolean go_deeper
)
307 GNode
*file_ptr
, *directory_ptr
;
309 if (go_deeper
&& (file_ptr
= g_node_first_child(file
)) != NULL
&& FILE(file
)->open
== TRUE
)
311 else if ((file_ptr
= g_node_next_sibling(file
)) != NULL
)
314 for (directory_ptr
= file
->parent
; directory_ptr
!= NULL
;
315 directory_ptr
= directory_ptr
->parent
) {
316 if ((file_ptr
= g_node_next_sibling(directory_ptr
)) != NULL
)
324 GNode
*get_previous_file(GNode
*file
)
328 if (G_NODE_IS_ROOT(file
))
330 else if (file
== g_node_first_sibling(file
))
332 else if (!G_NODE_IS_LEAF(file_ptr
= g_node_prev_sibling(file
)) &&
333 FILE(file_ptr
)->open
== TRUE
) {
335 file_ptr
= g_node_last_child(file_ptr
);
336 while (!G_NODE_IS_LEAF(file_ptr
) && FILE(file_ptr
)->open
== TRUE
);
342 GNode
*get_next_file(GNode
*file
)
344 return get_next_file_real(file
, TRUE
);
347 GNode
*get_next_file_not_deepper(GNode
*file
)
349 return get_next_file_real(file
, FALSE
);
352 char *get_file_info(GNode
*file
)
357 char mode
[11], mtime_str
[17], size_suffix
;
360 switch (FILE(file
)->info
.st_mode
& S_IFMT
) {
383 mode
[1] = (FILE(file
)->info
.st_mode
& S_IRUSR
) ? 'r' : '-';
384 mode
[2] = (FILE(file
)->info
.st_mode
& S_IWUSR
) ? 'w' : '-';
385 mode
[3] = (FILE(file
)->info
.st_mode
& S_IXUSR
) ? 'x' : '-';
387 mode
[4] = (FILE(file
)->info
.st_mode
& S_IRGRP
) ? 'r' : '-';
388 mode
[5] = (FILE(file
)->info
.st_mode
& S_IWGRP
) ? 'w' : '-';
389 mode
[6] = (FILE(file
)->info
.st_mode
& S_IXGRP
) ? 'x' : '-';
391 mode
[7] = (FILE(file
)->info
.st_mode
& S_IROTH
) ? 'r' : '-';
392 mode
[8] = (FILE(file
)->info
.st_mode
& S_IWOTH
) ? 'w' : '-';
393 mode
[9] = (FILE(file
)->info
.st_mode
& S_IXOTH
) ? 'x' : '-';
396 if (FILE(file
)->info
.st_mode
& S_ISUID
&& mode
[3] == 'x')
398 else if (FILE(file
)->info
.st_mode
& S_ISUID
&& mode
[3] == '-')
400 if (FILE(file
)->info
.st_mode
& S_ISGID
&& mode
[6] == 'x')
402 else if (FILE(file
)->info
.st_mode
& S_ISGID
&& mode
[6] == '-')
404 if (FILE(file
)->info
.st_mode
& S_ISVTX
&& mode
[9] == 'x')
406 else if (FILE(file
)->info
.st_mode
& S_ISVTX
&& mode
[9] == '-')
409 if ((pw
= getpwuid(FILE(file
)->info
.st_uid
)) == NULL
) {
411 struct passwd pw_unknown
;
413 pw_unknown
.pw_name
= "unknown";
419 } if ((grp
= getgrgid(FILE(file
)->info
.st_gid
)) == NULL
) {
421 struct group grp_unknown
;
423 grp_unknown
.gr_name
= "unknown";
431 if ((size
=(double) FILE(file
)->info
.st_size
/ (1024.0 * 1024.0 * 1024.0)) > 1.0)
433 else if ((size
=(double) FILE(file
)->info
.st_size
/ (1024.0 * 1024.0)) > 1.0)
435 else if ((size
=(double) FILE(file
)->info
.st_size
/ (1024.0)) > 1.0)
438 size
=(double) FILE(file
)->info
.st_size
;
442 if ((mtime
= localtime(&(FILE(file
)->info
.st_mtime
))) == NULL
) {
446 if (strftime(mtime_str
, sizeof(mtime_str
), "%Y-%m-%d %H:%M", mtime
) == 0) {
451 if (FILE(file
)->link
== TRUE
) {
452 if (size_suffix
== ' ')
453 return g_strdup_printf("%s %s %s %i %s %s -> %s", mode
, pw
->pw_name
, grp
->gr_name
,
454 (int) size
, mtime_str
, FILE(file
)->name
, FILE(file
)->link_path
);
456 return g_strdup_printf("%s %s %s %.2f%c %s %s -> %s", mode
, pw
->pw_name
, grp
->gr_name
,
457 size
, size_suffix
, mtime_str
, FILE(file
)->name
, FILE(file
)->link_path
);
459 if (size_suffix
== ' ')
460 return g_strdup_printf("%s %s %s %i %s %s", mode
, pw
->pw_name
, grp
->gr_name
,
461 (int) size
, mtime_str
, FILE(file
)->name
);
463 return g_strdup_printf("%s %s %s %.2f%c %s %s", mode
, pw
->pw_name
, grp
->gr_name
,
464 size
, size_suffix
, mtime_str
, FILE(file
)->name
);
This page took 0.648765 seconds and 4 git commands to generate.