105
|
1 /*
|
196
|
2 * Geeqie
|
105
|
3 * (C) 2006 John Ellis
|
475
|
4 * Copyright (C) 2008 The Geeqie Team
|
105
|
5 *
|
|
6 * Author: John Ellis
|
|
7 *
|
|
8 * This software is released under the GNU General Public License (GNU GPL).
|
|
9 * Please read the included file COPYING for more information.
|
|
10 * This software comes with no warranty of any kind, use at your own risk!
|
|
11 */
|
|
12
|
281
|
13 #include "main.h"
|
105
|
14 #include "pan-types.h"
|
|
15
|
|
16 #include "ui_fileops.h"
|
|
17
|
|
18
|
|
19 /*
|
|
20 *-----------------------------------------------------------------------------
|
|
21 * date functions
|
|
22 *-----------------------------------------------------------------------------
|
|
23 */
|
|
24
|
|
25 gint pan_date_compare(time_t a, time_t b, PanDateLengthType length)
|
|
26 {
|
|
27 struct tm ta;
|
|
28 struct tm tb;
|
|
29
|
|
30 if (length == PAN_DATE_LENGTH_EXACT) return (a == b);
|
|
31
|
|
32 if (!localtime_r(&a, &ta) ||
|
|
33 !localtime_r(&b, &tb)) return FALSE;
|
|
34
|
|
35 if (ta.tm_year != tb.tm_year) return FALSE;
|
|
36 if (length == PAN_DATE_LENGTH_YEAR) return TRUE;
|
|
37
|
|
38 if (ta.tm_mon != tb.tm_mon) return FALSE;
|
|
39 if (length == PAN_DATE_LENGTH_MONTH) return TRUE;
|
|
40
|
|
41 if (length == PAN_DATE_LENGTH_WEEK) return (ta.tm_yday / 7 == tb.tm_yday / 7);
|
|
42
|
|
43 if (ta.tm_mday != tb.tm_mday) return FALSE;
|
|
44 if (length == PAN_DATE_LENGTH_DAY) return TRUE;
|
|
45
|
|
46 return (ta.tm_hour == tb.tm_hour);
|
|
47 }
|
|
48
|
|
49 gint pan_date_value(time_t d, PanDateLengthType length)
|
|
50 {
|
|
51 struct tm td;
|
|
52
|
|
53 if (!localtime_r(&d, &td)) return -1;
|
|
54
|
|
55 switch (length)
|
|
56 {
|
|
57 case PAN_DATE_LENGTH_DAY:
|
|
58 return td.tm_mday;
|
|
59 break;
|
|
60 case PAN_DATE_LENGTH_WEEK:
|
|
61 return td.tm_wday;
|
|
62 break;
|
|
63 case PAN_DATE_LENGTH_MONTH:
|
|
64 return td.tm_mon + 1;
|
|
65 break;
|
|
66 case PAN_DATE_LENGTH_YEAR:
|
|
67 return td.tm_year + 1900;
|
|
68 break;
|
|
69 case PAN_DATE_LENGTH_EXACT:
|
|
70 default:
|
|
71 break;
|
|
72 }
|
|
73
|
|
74 return -1;
|
|
75 }
|
|
76
|
|
77 gchar *pan_date_value_string(time_t d, PanDateLengthType length)
|
|
78 {
|
|
79 struct tm td;
|
|
80 gchar buf[128];
|
|
81 gchar *format = NULL;
|
|
82
|
|
83 if (!localtime_r(&d, &td)) return g_strdup("");
|
|
84
|
|
85 switch (length)
|
|
86 {
|
|
87 case PAN_DATE_LENGTH_DAY:
|
|
88 return g_strdup_printf("%d", td.tm_mday);
|
|
89 break;
|
|
90 case PAN_DATE_LENGTH_WEEK:
|
|
91 format = "%A %e";
|
|
92 break;
|
|
93 case PAN_DATE_LENGTH_MONTH:
|
|
94 format = "%B %Y";
|
|
95 break;
|
|
96 case PAN_DATE_LENGTH_YEAR:
|
|
97 return g_strdup_printf("%d", td.tm_year + 1900);
|
|
98 break;
|
|
99 case PAN_DATE_LENGTH_EXACT:
|
|
100 default:
|
|
101 return g_strdup(text_from_time(d));
|
|
102 break;
|
|
103 }
|
|
104
|
|
105
|
|
106 if (format && strftime(buf, sizeof(buf), format, &td) > 0)
|
|
107 {
|
|
108 gchar *ret = g_locale_to_utf8(buf, -1, NULL, NULL, NULL);
|
|
109 if (ret) return ret;
|
|
110 }
|
|
111
|
|
112 return g_strdup("");
|
|
113 }
|
|
114
|
|
115 time_t pan_date_to_time(gint year, gint month, gint day)
|
|
116 {
|
|
117 struct tm lt;
|
|
118
|
|
119 lt.tm_sec = 0;
|
|
120 lt.tm_min = 0;
|
|
121 lt.tm_hour = 0;
|
|
122 lt.tm_mday = (day >= 1 && day <= 31) ? day : 1;
|
|
123 lt.tm_mon = (month >= 1 && month <= 12) ? month - 1 : 0;
|
|
124 lt.tm_year = year - 1900;
|
|
125 lt.tm_isdst = 0;
|
|
126
|
|
127 return mktime(<);
|
|
128 }
|
|
129
|
|
130
|
|
131 /*
|
|
132 *-----------------------------------------------------------------------------
|
|
133 * folder validation
|
|
134 *-----------------------------------------------------------------------------
|
|
135 */
|
|
136
|
|
137 gint pan_is_link_loop(const gchar *s)
|
|
138 {
|
|
139 gchar *sl;
|
|
140 struct stat st;
|
|
141 gint ret = FALSE;
|
|
142
|
|
143 sl = path_from_utf8(s);
|
|
144
|
|
145 if (lstat(sl, &st) == 0 && S_ISLNK(st.st_mode))
|
|
146 {
|
|
147 gchar *buf;
|
|
148 gint l;
|
|
149
|
|
150 buf = g_malloc(st.st_size + 1);
|
|
151 l = readlink(sl, buf, st.st_size);
|
|
152 if (l == st.st_size)
|
|
153 {
|
|
154 buf[l] = '\0';
|
|
155
|
|
156 parse_out_relatives(buf);
|
|
157 l = strlen(buf);
|
|
158
|
|
159 parse_out_relatives(sl);
|
|
160
|
|
161 if (buf[0] == '/')
|
|
162 {
|
|
163 if (strncmp(sl, buf, l) == 0 &&
|
|
164 (sl[l] == '\0' || sl[l] == '/' || l == 1)) ret = TRUE;
|
|
165 }
|
|
166 else
|
|
167 {
|
|
168 gchar *link_path;
|
|
169
|
|
170 link_path = concat_dir_and_file(sl, buf);
|
|
171 parse_out_relatives(link_path);
|
|
172
|
|
173 if (strncmp(sl, link_path, l) == 0 &&
|
|
174 (sl[l] == '\0' || sl[l] == '/' || l == 1)) ret = TRUE;
|
|
175
|
|
176 g_free(link_path);
|
|
177 }
|
|
178 }
|
|
179
|
|
180 g_free(buf);
|
|
181 }
|
|
182
|
|
183 g_free(sl);
|
|
184
|
|
185 return ret;
|
|
186 }
|
|
187
|
|
188 gint pan_is_ignored(const gchar *s, gint ignore_symlinks)
|
|
189 {
|
|
190 struct stat st;
|
|
191 const gchar *n;
|
|
192
|
|
193 if (!lstat_utf8(s, &st)) return TRUE;
|
|
194
|
|
195 #if 0
|
|
196 /* normal filesystems have directories with some size or block allocation,
|
|
197 * special filesystems (like linux /proc) set both to zero.
|
|
198 * enable this check if you enable listing the root "/" folder
|
|
199 */
|
|
200 if (st.st_size == 0 && st.st_blocks == 0) return TRUE;
|
|
201 #endif
|
|
202
|
|
203 if (S_ISLNK(st.st_mode) && (ignore_symlinks || pan_is_link_loop(s))) return TRUE;
|
|
204
|
|
205 n = filename_from_path(s);
|
283
|
206 if (n && strcmp(n, GQ_RC_DIR) == 0) return TRUE;
|
105
|
207
|
|
208 return FALSE;
|
|
209 }
|
|
210
|
|
211 GList *pan_list_tree(const gchar *path, SortType sort, gint ascend,
|
|
212 gint ignore_symlinks)
|
|
213 {
|
|
214 GList *flist = NULL;
|
|
215 GList *dlist = NULL;
|
|
216 GList *result;
|
|
217 GList *folders;
|
|
218
|
|
219 filelist_read(path, &flist, &dlist);
|
|
220 if (sort != SORT_NONE)
|
|
221 {
|
|
222 flist = filelist_sort(flist, sort, ascend);
|
|
223 dlist = filelist_sort(dlist, sort, ascend);
|
|
224 }
|
|
225
|
|
226 result = flist;
|
|
227 folders = dlist;
|
|
228 while (folders)
|
|
229 {
|
|
230 FileData *fd;
|
|
231
|
|
232 fd = folders->data;
|
|
233 folders = g_list_remove(folders, fd);
|
|
234
|
|
235 if (!pan_is_ignored(fd->path, ignore_symlinks) &&
|
|
236 filelist_read(fd->path, &flist, &dlist))
|
|
237 {
|
|
238 if (sort != SORT_NONE)
|
|
239 {
|
|
240 flist = filelist_sort(flist, sort, ascend);
|
|
241 dlist = filelist_sort(dlist, sort, ascend);
|
|
242 }
|
|
243
|
|
244 result = g_list_concat(result, flist);
|
|
245 folders = g_list_concat(dlist, folders);
|
|
246 }
|
|
247
|
138
|
248 file_data_unref(fd);
|
105
|
249 }
|
|
250
|
|
251 return result;
|
|
252 }
|