2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 // IWYU pragma: no_include <features.h>
31 #include "main-defines.h"
32 #include "ui-fileops.h"
36 *-----------------------------------------------------------------------------
38 *-----------------------------------------------------------------------------
41 gboolean pan_date_compare(time_t a, time_t b, PanDateLengthType length)
46 if (length == PAN_DATE_LENGTH_EXACT) return (a == b);
48 if (!localtime_r(&a, &ta) ||
49 !localtime_r(&b, &tb)) return FALSE;
51 if (ta.tm_year != tb.tm_year) return FALSE;
52 if (length == PAN_DATE_LENGTH_YEAR) return TRUE;
54 if (ta.tm_mon != tb.tm_mon) return FALSE;
55 if (length == PAN_DATE_LENGTH_MONTH) return TRUE;
57 if (length == PAN_DATE_LENGTH_WEEK) return (ta.tm_yday / 7 == tb.tm_yday / 7);
59 if (ta.tm_mday != tb.tm_mday) return FALSE;
60 if (length == PAN_DATE_LENGTH_DAY) return TRUE;
62 return (ta.tm_hour == tb.tm_hour);
65 gint pan_date_value(time_t d, PanDateLengthType length)
69 if (!localtime_r(&d, &td)) return -1;
73 case PAN_DATE_LENGTH_DAY:
76 case PAN_DATE_LENGTH_WEEK:
79 case PAN_DATE_LENGTH_MONTH:
82 case PAN_DATE_LENGTH_YEAR:
83 return td.tm_year + 1900;
85 case PAN_DATE_LENGTH_EXACT:
93 #if defined(__GLIBC_PREREQ)
94 # if __GLIBC_PREREQ(2, 27)
95 # define HAS_GLIBC_STRFTIME_EXTENSIONS
99 gchar *pan_date_value_string(time_t d, PanDateLengthType length)
103 const gchar *format = nullptr;
105 if (!localtime_r(&d, &td)) return g_strdup("");
109 case PAN_DATE_LENGTH_DAY:
110 return g_strdup_printf("%d", td.tm_mday);
112 case PAN_DATE_LENGTH_WEEK:
115 case PAN_DATE_LENGTH_MONTH:
116 #if defined(HAS_GLIBC_STRFTIME_EXTENSIONS) || defined(__FreeBSD__)
122 case PAN_DATE_LENGTH_YEAR:
123 return g_strdup_printf("%d", td.tm_year + 1900);
125 case PAN_DATE_LENGTH_EXACT:
127 return g_strdup(text_from_time(d));
132 if (format && strftime(buf, sizeof(buf), format, &td) > 0)
134 gchar *ret = g_locale_to_utf8(buf, -1, nullptr, nullptr, nullptr);
141 time_t pan_date_to_time(gint year, gint month, gint day)
148 lt.tm_mday = (day >= 1 && day <= 31) ? day : 1;
149 lt.tm_mon = (month >= 1 && month <= 12) ? month - 1 : 0;
150 lt.tm_year = year - 1900;
158 *-----------------------------------------------------------------------------
160 *-----------------------------------------------------------------------------
163 gboolean pan_is_link_loop(const gchar *s)
167 gboolean ret = FALSE;
169 sl = path_from_utf8(s);
171 if (lstat(sl, &st) == 0 && S_ISLNK(st.st_mode))
176 buf = static_cast<gchar *>(g_malloc(st.st_size + 1));
177 l = readlink(sl, buf, st.st_size);
182 parse_out_relatives(buf);
185 parse_out_relatives(sl);
187 if (buf[0] == G_DIR_SEPARATOR)
189 if (strncmp(sl, buf, l) == 0 &&
190 (sl[l] == '\0' || sl[l] == G_DIR_SEPARATOR || l == 1)) ret = TRUE;
196 link_path = g_build_filename(sl, buf, NULL);
197 parse_out_relatives(link_path);
199 if (strncmp(sl, link_path, l) == 0 &&
200 (sl[l] == '\0' || sl[l] == G_DIR_SEPARATOR || l == 1)) ret = TRUE;
214 gboolean pan_is_ignored(const gchar *s, gboolean ignore_symlinks)
219 if (!lstat_utf8(s, &st)) return TRUE;
222 /* normal filesystems have directories with some size or block allocation,
223 * special filesystems (like linux /proc) set both to zero.
224 * enable this check if you enable listing the root "/" folder
226 if (st.st_size == 0 && st.st_blocks == 0) return TRUE;
229 if (S_ISLNK(st.st_mode) && (ignore_symlinks || pan_is_link_loop(s))) return TRUE;
231 n = filename_from_path(s);
232 if (n && strcmp(n, GQ_RC_DIR) == 0) return TRUE;
237 GList *pan_list_tree(FileData *dir_fd, SortType sort, gboolean ascend, gboolean case_sensitive,
238 gboolean ignore_symlinks)
245 filelist_read(dir_fd, &flist, &dlist);
246 if (sort != SORT_NONE)
248 flist = filelist_sort(flist, sort, ascend, case_sensitive);
249 dlist = filelist_sort(dlist, sort, ascend, case_sensitive);
258 fd = static_cast<FileData *>(folders->data);
259 folders = g_list_remove(folders, fd);
261 if (!pan_is_ignored(fd->path, ignore_symlinks) &&
262 filelist_read(fd, &flist, &dlist))
264 if (sort != SORT_NONE)
266 flist = filelist_sort(flist, sort, ascend, case_sensitive);
267 dlist = filelist_sort(dlist, sort, ascend, case_sensitive);
270 result = g_list_concat(result, flist);
271 folders = g_list_concat(dlist, folders);
279 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */