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 (stat(file_path
, &info
) == -1) {
47 PRINT_ERRNO_AND_EXIT();
50 file
->type
= file_type
;
53 } else if (S_ISDIR(info
.st_mode
)) {
54 file
->type
= directory_type
;
55 file
->no_info
= FALSE
;
57 file
->type
= file_type
;
58 file
->no_info
= FALSE
;
61 if (lstat(file_path
, &link_info
) == -1) {
63 file
->link_path
= NULL
;
65 } else if (S_ISLNK(link_info
.st_mode
)) {
66 if (link_info
.st_size
== 0)
67 link_info
.st_size
= PATH_MAX
;
69 file
->link_path
= malloc(link_info
.st_size
+ 1);
70 file
->link_path
[link_info
.st_size
] = '\0';
71 file
->link_path
[0] = '\0';
74 if (readlink(file_path
, file
->link_path
, link_info
.st_size
) == -1)
77 file
->link_path
= NULL
;
80 if (file
->link
== TRUE
) {
81 file
->no_info
= FALSE
;
82 file
->info
= link_info
;
83 } else if (file
->no_info
== FALSE
)
86 file
->name
= strdup(name
);
89 file
->show_dotfiles
= FALSE
;
91 file
->dotfiles
= NULL
;
99 gboolean
read_directory(GNode
*directory
)
102 struct dirent
*entry
;
104 char *path
= get_path(directory
);
106 if ((dir
= opendir(path
)) == NULL
) {
110 for (; (entry
= readdir(dir
)) != NULL
; ) {
111 if (!strcmp(entry
->d_name
, ".") || !strcmp(entry
->d_name
, ".."))
114 if ((new_file
= create_new_file(entry
->d_name
, path
, FALSE
)) == NULL
)
117 if (new_file
->name
[0] == '.')
118 insert_sorted_in_dotfiles(directory
, new_file
);
120 insert_sorted_in_tree(directory
, new_file
);
123 PRINT_ERRNO_AND_EXIT();
124 if (closedir(dir
) == -1)
125 PRINT_ERRNO_AND_EXIT();
127 FILE(directory
)->read
= TRUE
;
132 void free_element_data(gpointer element_data
, gpointer data
)
134 if (FILE((GNode
*) element_data
)->type
== directory_type
)
135 destroy_directory_content((GNode
*) element_data
);
136 free_node_data((GNode
*) element_data
, NULL
);
139 void destroy_dotfiles(GList
*dotfiles
)
141 g_list_foreach(dotfiles
, free_element_data
, NULL
);
142 g_list_free(dotfiles
);
145 gboolean
free_node_data(GNode
*node
, gpointer data
)
147 free(FILE(node
)->name
);
148 free(FILE(node
)->link_path
);
149 destroy_dotfiles(FILE(node
)->dotfiles
);
155 void destroy_directory_content(GNode
*directory
)
157 GNode
*file_ptr
, *file_ptr2
;
159 for (file_ptr
= g_node_first_child(directory
); file_ptr
!= NULL
; ) {
160 file_ptr2
= file_ptr
;
161 file_ptr
= g_node_next_sibling(file_ptr
);
163 g_node_unlink(file_ptr2
);
164 g_node_traverse(file_ptr2
, G_PRE_ORDER
, G_TRAVERSE_ALL
, -1, free_node_data
, NULL
);
165 g_node_destroy(file_ptr2
);
167 destroy_dotfiles(FILE(directory
)->dotfiles
);
168 FILE(directory
)->dotfiles
= NULL
;
169 FILE(directory
)->read
= FALSE
;
172 void add_dotfiles(GNode
*directory
)
178 for (line_ptr
= g_list_next(FILE(directory
)->line
), position
= 0;
179 FILE(directory
)->dotfiles
!= NULL
; position
++) {
180 file_ptr
= NODE(FILE(directory
)->dotfiles
);
181 FILE(directory
)->dotfiles
= g_list_delete_link(FILE(directory
)->dotfiles
,
182 FILE(directory
)->dotfiles
);
183 g_node_insert(directory
, position
, file_ptr
);
184 lines
= g_list_insert_before(lines
, line_ptr
, file_ptr
);
185 FILE(file_ptr
)->line
= g_list_previous(line_ptr
);
186 if (FILE(file_ptr
)->type
== directory_type
&& FILE(file_ptr
)->open
== TRUE
)
187 add_directory_content(file_ptr
);
189 FILE(directory
)->show_dotfiles
= TRUE
;
192 void remove_dotfiles(GNode
*directory
)
195 GList
*line_ptr
, *line_ptr_aux
;
197 for (file_ptr
= g_node_first_child(directory
); file_ptr
!= NULL
&&
198 FILE(file_ptr
)->name
[0] == '.'; ) {
199 lines
= g_list_delete_link(lines
, FILE(file_ptr
)->line
);
200 FILE(directory
)->dotfiles
= g_list_insert(FILE(directory
)->dotfiles
, file_ptr
, -1);
201 FILE(file_ptr
)->line
= NULL
;
202 file_ptr
= g_node_next_sibling(file_ptr
);
203 g_node_unlink(NODE(g_list_last(FILE(directory
)->dotfiles
)));
205 for (line_ptr
= g_list_previous(FILE(file_ptr
)->line
);
206 line_ptr
!= FILE(directory
)->line
; ) {
207 line_ptr_aux
= line_ptr
;
208 line_ptr
= g_list_previous(line_ptr
);
209 FILE(NODE(line_ptr_aux
))->line
= NULL
;
210 lines
= g_list_delete_link(lines
, line_ptr_aux
);
213 FILE(directory
)->show_dotfiles
= FALSE
;
216 int file_cmp(File
*file1
, File
*file2
)
218 if (file1
->type
== file2
->type
)
219 return strcmp(file1
->name
, file2
->name
);
220 else if (file1
->type
== directory_type
)
226 int file_cmp_list(gconstpointer file1
, gconstpointer file2
)
228 return file_cmp(FILE((GNode
*) file1
), FILE((GNode
*) file2
));
231 void insert_sorted_in_dotfiles(GNode
*directory
, File
*file
)
233 FILE(directory
)->dotfiles
= g_list_insert_sorted(FILE(directory
)->dotfiles
,
234 g_node_new(file
), file_cmp_list
);
237 void insert_sorted_in_tree(GNode
*directory
, File
*file
)
241 if (G_NODE_IS_LEAF(directory
))
242 g_node_append_data(directory
, file
);
243 else if (file_cmp(file
, FILE(g_node_first_child(directory
))) < 0)
244 g_node_prepend_data(directory
, file
);
246 for (file_ptr
= g_node_last_child(directory
); file_ptr
!= NULL
;
247 file_ptr
= g_node_prev_sibling(file_ptr
)) {
248 if (file_cmp(file
, FILE(file_ptr
)) > 0) {
249 g_node_insert_after(directory
, file_ptr
, g_node_new(file
));
256 char *get_path(GNode
*file
)
259 GString
*path
= g_string_new(FILE(file
)->name
);
261 for (file_ptr
= file
->parent
; file_ptr
!= NULL
; file_ptr
= file_ptr
->parent
) {
262 g_string_prepend(path
, "/");
263 g_string_prepend(path
, FILE(file_ptr
)->name
);
266 return g_string_free(path
, FALSE
);
269 GNode
*get_next_file__real(GNode
*file
, gboolean go_deeper
)
271 GNode
*file_ptr
, *directory_ptr
;
273 if (go_deeper
&& (file_ptr
= g_node_first_child(file
)) != NULL
&& FILE(file
)->open
== TRUE
)
275 else if ((file_ptr
= g_node_next_sibling(file
)) != NULL
)
278 for (directory_ptr
= file
->parent
; directory_ptr
!= NULL
;
279 directory_ptr
= directory_ptr
->parent
) {
280 if ((file_ptr
= g_node_next_sibling(directory_ptr
)) != NULL
)
288 GNode
*get_previous_file(GNode
*file
)
292 if (G_NODE_IS_ROOT(file
))
294 else if (file
== g_node_first_sibling(file
))
296 else if (!G_NODE_IS_LEAF(file_ptr
= g_node_prev_sibling(file
)) &&
297 FILE(file_ptr
)->open
== TRUE
) {
299 file_ptr
= g_node_last_child(file_ptr
);
300 while (!G_NODE_IS_LEAF(file_ptr
) && FILE(file_ptr
)->open
== TRUE
);
306 GNode
*get_next_file(GNode
*file
)
308 return get_next_file__real(file
, TRUE
);
311 GNode
*get_next_file_not_deepper(GNode
*file
)
313 return get_next_file__real(file
, FALSE
);
316 char *get_file_info(GNode
*file
)
321 char mode
[11], mtime_str
[17], size_suffix
;
324 switch (FILE(file
)->info
.st_mode
& S_IFMT
) {
347 mode
[1] = (FILE(file
)->info
.st_mode
& S_IRUSR
) ? 'r' : '-';
348 mode
[2] = (FILE(file
)->info
.st_mode
& S_IWUSR
) ? 'w' : '-';
349 mode
[3] = (FILE(file
)->info
.st_mode
& S_IXUSR
) ? 'x' : '-';
351 mode
[4] = (FILE(file
)->info
.st_mode
& S_IRGRP
) ? 'r' : '-';
352 mode
[5] = (FILE(file
)->info
.st_mode
& S_IWGRP
) ? 'w' : '-';
353 mode
[6] = (FILE(file
)->info
.st_mode
& S_IXGRP
) ? 'x' : '-';
355 mode
[7] = (FILE(file
)->info
.st_mode
& S_IROTH
) ? 'r' : '-';
356 mode
[8] = (FILE(file
)->info
.st_mode
& S_IWOTH
) ? 'w' : '-';
357 mode
[9] = (FILE(file
)->info
.st_mode
& S_IXOTH
) ? 'x' : '-';
360 if (FILE(file
)->info
.st_mode
& S_ISUID
&& mode
[3] == 'x')
362 else if (FILE(file
)->info
.st_mode
& S_ISUID
&& mode
[3] == '-')
364 if (FILE(file
)->info
.st_mode
& S_ISGID
&& mode
[6] == 'x')
366 else if (FILE(file
)->info
.st_mode
& S_ISGID
&& mode
[6] == '-')
368 if (FILE(file
)->info
.st_mode
& S_ISVTX
&& mode
[9] == 'x')
370 else if (FILE(file
)->info
.st_mode
& S_ISVTX
&& mode
[9] == '-')
373 if ((pw
= getpwuid(FILE(file
)->info
.st_uid
)) == NULL
) {
376 } if ((grp
= getgrgid(FILE(file
)->info
.st_gid
)) == NULL
) {
381 if ((size
=(double) FILE(file
)->info
.st_size
/ (1024.0 * 1024.0 * 1024.0)) > 1.0)
383 else if ((size
=(double) FILE(file
)->info
.st_size
/ (1024.0 * 1024.0)) > 1.0)
385 else if ((size
=(double) FILE(file
)->info
.st_size
/ (1024.0)) > 1.0)
388 size
=(double) FILE(file
)->info
.st_size
;
392 if ((mtime
= localtime(&(FILE(file
)->info
.st_mtime
))) == NULL
) {
396 if (strftime(mtime_str
, sizeof(mtime_str
), "%Y-%m-%d %H:%M", mtime
) == 0) {
401 if (FILE(file
)->link
== TRUE
) {
402 if (size_suffix
== ' ')
403 return g_strdup_printf("%s %s %s %i %s %s -> %s", mode
, pw
->pw_name
, grp
->gr_name
,
404 (int) size
, mtime_str
, FILE(file
)->name
, FILE(file
)->link_path
);
406 return g_strdup_printf("%s %s %s %.2f%c %s %s -> %s", mode
, pw
->pw_name
, grp
->gr_name
,
407 size
, size_suffix
, mtime_str
, FILE(file
)->name
, FILE(file
)->link_path
);
409 if (size_suffix
== ' ')
410 return g_strdup_printf("%s %s %s %i %s %s", mode
, pw
->pw_name
, grp
->gr_name
,
411 (int) size
, mtime_str
, FILE(file
)->name
);
413 return g_strdup_printf("%s %s %s %.2f%c %s %s", mode
, pw
->pw_name
, grp
->gr_name
,
414 size
, size_suffix
, mtime_str
, FILE(file
)->name
);
This page took 1.287906 seconds and 4 git commands to generate.