Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library 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 GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : */
22 : :
23 : : #ifndef __G_LOCAL_FILE_INFO_H__
24 : : #define __G_LOCAL_FILE_INFO_H__
25 : :
26 : : /* Needed for statx() */
27 : : #ifndef _GNU_SOURCE
28 : : #define _GNU_SOURCE
29 : : #endif
30 : :
31 : : #include <fcntl.h>
32 : : #include <gio/gfileinfo.h>
33 : : #include <gio/gfile.h>
34 : : #include <glib/glib-private.h>
35 : : #include <glib/gstdio.h>
36 : : #include <glib/gstdioprivate.h>
37 : : #include <sys/stat.h>
38 : : #include <sys/types.h>
39 : :
40 : : #ifdef HAVE_STATX
41 : : #include <sys/sysmacros.h>
42 : : #endif
43 : :
44 : : G_BEGIN_DECLS
45 : :
46 : : typedef struct
47 : : {
48 : : gboolean writable;
49 : : gboolean is_sticky;
50 : : gboolean has_trash_dir;
51 : : /* owner should be uid_t but it breaks compliance with MS-Windows */
52 : : int owner;
53 : : dev_t device;
54 : : ino_t inode;
55 : : gpointer extra_data;
56 : : GDestroyNotify free_extra_data;
57 : : } GLocalParentFileInfo;
58 : :
59 : : #ifdef HAVE_STATX
60 : : #define GLocalFileStat struct statx
61 : :
62 : : typedef enum
63 : : {
64 : : G_LOCAL_FILE_STAT_FIELD_TYPE = STATX_TYPE,
65 : : G_LOCAL_FILE_STAT_FIELD_MODE = STATX_MODE,
66 : : G_LOCAL_FILE_STAT_FIELD_NLINK = STATX_NLINK,
67 : : G_LOCAL_FILE_STAT_FIELD_UID = STATX_UID,
68 : : G_LOCAL_FILE_STAT_FIELD_GID = STATX_GID,
69 : : G_LOCAL_FILE_STAT_FIELD_ATIME = STATX_ATIME,
70 : : G_LOCAL_FILE_STAT_FIELD_MTIME = STATX_MTIME,
71 : : G_LOCAL_FILE_STAT_FIELD_CTIME = STATX_CTIME,
72 : : G_LOCAL_FILE_STAT_FIELD_INO = STATX_INO,
73 : : G_LOCAL_FILE_STAT_FIELD_SIZE = STATX_SIZE,
74 : : G_LOCAL_FILE_STAT_FIELD_BLOCKS = STATX_BLOCKS,
75 : : G_LOCAL_FILE_STAT_FIELD_BTIME = STATX_BTIME,
76 : : } GLocalFileStatField;
77 : :
78 : : #define G_LOCAL_FILE_STAT_FIELD_BASIC_STATS STATX_BASIC_STATS
79 : : #define G_LOCAL_FILE_STAT_FIELD_ALL STATX_ALL
80 : :
81 : : static inline int
82 : 1358 : g_local_file_statx (int dirfd,
83 : : const char *pathname,
84 : : int flags,
85 : : GLocalFileStatField mask,
86 : : GLocalFileStatField mask_required,
87 : : GLocalFileStat *stat_buf)
88 : : {
89 : : int retval;
90 : :
91 : : /* Allow the caller to set mask_required==G_LOCAL_FILE_STAT_FIELD_ALL as a
92 : : * shortcut for saying it’s equal to @mask. */
93 : 1358 : mask_required &= mask;
94 : :
95 : 1358 : retval = statx (dirfd, pathname, flags, mask, stat_buf);
96 : 1358 : if (retval == 0 && (stat_buf->stx_mask & mask_required) != mask_required)
97 : : {
98 : : /* Not all required fields could be returned. */
99 : 0 : errno = ERANGE;
100 : 0 : return -1;
101 : : }
102 : :
103 : 1358 : return retval;
104 : : }
105 : :
106 : : static inline int
107 : 571 : g_local_file_fstat (int fd,
108 : : GLocalFileStatField mask,
109 : : GLocalFileStatField mask_required,
110 : : GLocalFileStat *stat_buf)
111 : : {
112 : 571 : return g_local_file_statx (fd, "", AT_EMPTY_PATH, mask, mask_required, stat_buf);
113 : : }
114 : :
115 : : static inline int
116 : 76 : g_local_file_fstatat (int fd,
117 : : const char *path,
118 : : int flags,
119 : : GLocalFileStatField mask,
120 : : GLocalFileStatField mask_required,
121 : : GLocalFileStat *stat_buf)
122 : : {
123 : 76 : return g_local_file_statx (fd, path, flags, mask, mask_required, stat_buf);
124 : : }
125 : :
126 : : static inline int
127 : 700 : g_local_file_lstat (const char *path,
128 : : GLocalFileStatField mask,
129 : : GLocalFileStatField mask_required,
130 : : GLocalFileStat *stat_buf)
131 : : {
132 : 700 : return g_local_file_statx (AT_FDCWD, path,
133 : : AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT,
134 : : mask, mask_required, stat_buf);
135 : : }
136 : :
137 : : static inline int
138 : 11 : g_local_file_stat (const char *path,
139 : : GLocalFileStatField mask,
140 : : GLocalFileStatField mask_required,
141 : : GLocalFileStat *stat_buf)
142 : : {
143 : 11 : return g_local_file_statx (AT_FDCWD, path,
144 : : AT_NO_AUTOMOUNT | AT_STATX_SYNC_AS_STAT,
145 : : mask, mask_required, stat_buf);
146 : : }
147 : :
148 : 1785 : inline static gboolean _g_stat_has_field (const GLocalFileStat *buf, GLocalFileStatField field) { return buf->stx_mask & field; }
149 : :
150 : 3805 : inline static guint16 _g_stat_mode (const GLocalFileStat *buf) { return buf->stx_mode; }
151 : 750 : inline static guint32 _g_stat_nlink (const GLocalFileStat *buf) { return buf->stx_nlink; }
152 : 1645 : inline static dev_t _g_stat_dev (const GLocalFileStat *buf) { return makedev (buf->stx_dev_major, buf->stx_dev_minor); }
153 : 861 : inline static guint64 _g_stat_ino (const GLocalFileStat *buf) { return buf->stx_ino; }
154 : 984 : inline static guint64 _g_stat_size (const GLocalFileStat *buf) { return buf->stx_size; }
155 : :
156 : 893 : inline static guint32 _g_stat_uid (const GLocalFileStat *buf) { return buf->stx_uid; }
157 : 825 : inline static guint32 _g_stat_gid (const GLocalFileStat *buf) { return buf->stx_gid; }
158 : 708 : inline static dev_t _g_stat_rdev (const GLocalFileStat *buf) { return makedev (buf->stx_rdev_major, buf->stx_rdev_minor); }
159 : 708 : inline static guint32 _g_stat_blksize (const GLocalFileStat *buf) { return buf->stx_blksize; }
160 : :
161 : 1416 : inline static guint64 _g_stat_blocks (const GLocalFileStat *buf) { return buf->stx_blocks; }
162 : :
163 : 708 : inline static gint64 _g_stat_atime (const GLocalFileStat *buf) { return buf->stx_atime.tv_sec; }
164 : 708 : inline static gint64 _g_stat_ctime (const GLocalFileStat *buf) { return buf->stx_ctime.tv_sec; }
165 : 1185 : inline static gint64 _g_stat_mtime (const GLocalFileStat *buf) { return buf->stx_mtime.tv_sec; }
166 : 1416 : inline static guint32 _g_stat_atim_nsec (const GLocalFileStat *buf) { return buf->stx_atime.tv_nsec; }
167 : 1416 : inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return buf->stx_ctime.tv_nsec; }
168 : 2154 : inline static guint32 _g_stat_mtim_nsec (const GLocalFileStat *buf) { return buf->stx_mtime.tv_nsec; }
169 : :
170 : : #else /* if !HAVE_STATX */
171 : :
172 : : #ifdef G_OS_WIN32
173 : : /* We want 64-bit file size, file ID and symlink support */
174 : : #define GLocalFileStat GWin32PrivateStat
175 : : #else
176 : : #define GLocalFileStat struct stat
177 : : #endif
178 : :
179 : : /* If the system doesn’t have statx() support, emulate it using traditional
180 : : * stat(). It supports fields %G_LOCAL_FILE_STAT_FIELD_BASIC_STATS only, and
181 : : * always returns all of them. */
182 : : typedef enum
183 : : {
184 : : G_LOCAL_FILE_STAT_FIELD_TYPE = (1 << 0),
185 : : G_LOCAL_FILE_STAT_FIELD_MODE = (1 << 1),
186 : : G_LOCAL_FILE_STAT_FIELD_NLINK = (1 << 2),
187 : : G_LOCAL_FILE_STAT_FIELD_UID = (1 << 3),
188 : : G_LOCAL_FILE_STAT_FIELD_GID = (1 << 4),
189 : : G_LOCAL_FILE_STAT_FIELD_ATIME = (1 << 5),
190 : : G_LOCAL_FILE_STAT_FIELD_MTIME = (1 << 6),
191 : : G_LOCAL_FILE_STAT_FIELD_CTIME = (1 << 7),
192 : : G_LOCAL_FILE_STAT_FIELD_INO = (1 << 8),
193 : : G_LOCAL_FILE_STAT_FIELD_SIZE = (1 << 9),
194 : : G_LOCAL_FILE_STAT_FIELD_BLOCKS = (1 << 10),
195 : : G_LOCAL_FILE_STAT_FIELD_BTIME = (1 << 11),
196 : : } GLocalFileStatField;
197 : :
198 : : #define G_LOCAL_FILE_STAT_FIELD_BASIC_STATS \
199 : : (G_LOCAL_FILE_STAT_FIELD_TYPE | G_LOCAL_FILE_STAT_FIELD_MODE | \
200 : : G_LOCAL_FILE_STAT_FIELD_NLINK | G_LOCAL_FILE_STAT_FIELD_UID | \
201 : : G_LOCAL_FILE_STAT_FIELD_GID | G_LOCAL_FILE_STAT_FIELD_ATIME | \
202 : : G_LOCAL_FILE_STAT_FIELD_MTIME | G_LOCAL_FILE_STAT_FIELD_CTIME | \
203 : : G_LOCAL_FILE_STAT_FIELD_INO | G_LOCAL_FILE_STAT_FIELD_SIZE | \
204 : : G_LOCAL_FILE_STAT_FIELD_BLOCKS)
205 : : #define G_LOCAL_FILE_STAT_FIELD_ALL (G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME)
206 : :
207 : : static inline int
208 : : g_local_file_fstat (int fd,
209 : : GLocalFileStatField mask,
210 : : GLocalFileStatField mask_required,
211 : : GLocalFileStat *stat_buf)
212 : : {
213 : : if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask))
214 : : {
215 : : /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */
216 : : errno = ERANGE;
217 : : return -1;
218 : : }
219 : :
220 : : #ifdef G_OS_WIN32
221 : : return GLIB_PRIVATE_CALL (g_win32_fstat) (fd, stat_buf);
222 : : #else
223 : : return fstat (fd, stat_buf);
224 : : #endif
225 : : }
226 : :
227 : : static inline int
228 : : g_local_file_fstatat (int fd,
229 : : const char *path,
230 : : int flags,
231 : : GLocalFileStatField mask,
232 : : GLocalFileStatField mask_required,
233 : : GLocalFileStat *stat_buf)
234 : : {
235 : : if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask))
236 : : {
237 : : /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */
238 : : errno = ERANGE;
239 : : return -1;
240 : : }
241 : :
242 : : #if !defined(G_OS_WIN32) && defined(AT_FDCWD)
243 : : return fstatat (fd, path, stat_buf, flags);
244 : : #else
245 : : /* Currently not supported on Windows or macOS < 10.10 */
246 : : errno = ENOSYS;
247 : : return -1;
248 : : #endif
249 : : }
250 : :
251 : : static inline int
252 : : g_local_file_lstat (const char *path,
253 : : GLocalFileStatField mask,
254 : : GLocalFileStatField mask_required,
255 : : GLocalFileStat *stat_buf)
256 : : {
257 : : if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask))
258 : : {
259 : : /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */
260 : : errno = ERANGE;
261 : : return -1;
262 : : }
263 : :
264 : : #ifdef G_OS_WIN32
265 : : return GLIB_PRIVATE_CALL (g_win32_lstat_utf8) (path, stat_buf);
266 : : #else
267 : : return g_lstat (path, stat_buf);
268 : : #endif
269 : : }
270 : :
271 : : static inline int
272 : : g_local_file_stat (const char *path,
273 : : GLocalFileStatField mask,
274 : : GLocalFileStatField mask_required,
275 : : GLocalFileStat *stat_buf)
276 : : {
277 : : if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask))
278 : : {
279 : : /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */
280 : : errno = ERANGE;
281 : : return -1;
282 : : }
283 : :
284 : : #ifdef G_OS_WIN32
285 : : return GLIB_PRIVATE_CALL (g_win32_stat_utf8) (path, stat_buf);
286 : : #else
287 : : return stat (path, stat_buf);
288 : : #endif
289 : : }
290 : :
291 : : inline static gboolean _g_stat_has_field (const GLocalFileStat *buf, GLocalFileStatField field) { return (G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & field) == field; }
292 : :
293 : : #ifndef G_OS_WIN32
294 : : inline static mode_t _g_stat_mode (const GLocalFileStat *buf) { return buf->st_mode; }
295 : : inline static nlink_t _g_stat_nlink (const GLocalFileStat *buf) { return buf->st_nlink; }
296 : : #else
297 : : inline static guint16 _g_stat_mode (const GLocalFileStat *buf) { return buf->st_mode; }
298 : : inline static guint32 _g_stat_nlink (const GLocalFileStat *buf) { return buf->st_nlink; }
299 : : #endif
300 : : inline static dev_t _g_stat_dev (const GLocalFileStat *buf) { return buf->st_dev; }
301 : : inline static ino_t _g_stat_ino (const GLocalFileStat *buf) { return buf->st_ino; }
302 : : inline static goffset _g_stat_size (const GLocalFileStat *buf) { return buf->st_size; }
303 : :
304 : : #ifndef G_OS_WIN32
305 : : inline static uid_t _g_stat_uid (const GLocalFileStat *buf) { return buf->st_uid; }
306 : : inline static gid_t _g_stat_gid (const GLocalFileStat *buf) { return buf->st_gid; }
307 : : inline static dev_t _g_stat_rdev (const GLocalFileStat *buf) { return buf->st_rdev; }
308 : : inline static blksize_t _g_stat_blksize (const GLocalFileStat *buf) { return buf->st_blksize; }
309 : : #else
310 : : inline static guint16 _g_stat_uid (const GLocalFileStat *buf) { return buf->st_uid; }
311 : : inline static guint16 _g_stat_gid (const GLocalFileStat *buf) { return buf->st_gid; }
312 : : #endif
313 : :
314 : : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
315 : : inline static blkcnt_t _g_stat_blocks (const GLocalFileStat *buf) { return buf->st_blocks; }
316 : : #endif
317 : :
318 : : #ifndef G_OS_WIN32
319 : : inline static guint64 _g_stat_atime (const GLocalFileStat *buf) { return buf->st_atime; }
320 : : inline static guint64 _g_stat_ctime (const GLocalFileStat *buf) { return buf->st_ctime; }
321 : : inline static guint64 _g_stat_mtime (const GLocalFileStat *buf) { return buf->st_mtime; }
322 : : #else
323 : : inline static guint64 _g_stat_atime (const GLocalFileStat *buf) { return buf->st_atim.tv_sec; }
324 : : inline static guint64 _g_stat_ctime (const GLocalFileStat *buf) { return buf->st_ctim.tv_sec; }
325 : : inline static guint64 _g_stat_mtime (const GLocalFileStat *buf) { return buf->st_mtim.tv_sec; }
326 : : #endif
327 : : #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) || defined(G_OS_WIN32)
328 : : inline static guint32 _g_stat_atim_nsec (const GLocalFileStat *buf) { return buf->st_atim.tv_nsec; }
329 : : inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return buf->st_ctim.tv_nsec; }
330 : : inline static guint32 _g_stat_mtim_nsec (const GLocalFileStat *buf) { return buf->st_mtim.tv_nsec; }
331 : : #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
332 : : inline static guint32 _g_stat_atim_nsec (const GLocalFileStat *buf) { return buf->st_atimensec; }
333 : : inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return buf->st_ctimensec; }
334 : : inline static guint32 _g_stat_mtim_nsec (const GLocalFileStat *buf) { return buf->st_mtimensec; }
335 : : #else
336 : : inline static guint32 _g_stat_atim_nsec (const GLocalFileStat *buf) { return 0; }
337 : : inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return 0; }
338 : : inline static guint32 _g_stat_mtim_nsec (const GLocalFileStat *buf) { return 0; }
339 : : #endif
340 : :
341 : : #endif /* !HAVE_STATX */
342 : :
343 : : #define G_LOCAL_FILE_INFO_NOSTAT_ATTRIBUTES \
344 : : G_FILE_ATTRIBUTE_STANDARD_NAME "," \
345 : : G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," \
346 : : G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME "," \
347 : : G_FILE_ATTRIBUTE_STANDARD_COPY_NAME
348 : :
349 : : gboolean _g_local_file_has_trash_dir (const char *dirname,
350 : : dev_t dir_dev);
351 : : #ifdef G_OS_UNIX
352 : : gboolean _g_local_file_is_lost_found_dir (const char *path,
353 : : dev_t path_dev);
354 : : #endif
355 : : void _g_local_file_info_get_parent_info (const char *dir,
356 : : GFileAttributeMatcher *attribute_matcher,
357 : : GLocalParentFileInfo *parent_info);
358 : : void _g_local_file_info_free_parent_info (GLocalParentFileInfo *parent_info);
359 : : void _g_local_file_info_get_nostat (GFileInfo *info,
360 : : const char *basename,
361 : : const char *path,
362 : : GFileAttributeMatcher *attribute_matcher);
363 : : GFileInfo *_g_local_file_info_get (const char *basename,
364 : : const char *path,
365 : : GFileAttributeMatcher *attribute_matcher,
366 : : GFileQueryInfoFlags flags,
367 : : GLocalParentFileInfo *parent_info,
368 : : GError **error);
369 : : GFileInfo *_g_local_file_info_get_from_fd (int fd,
370 : : const char *attributes,
371 : : GError **error);
372 : : char * _g_local_file_info_create_etag (GLocalFileStat *statbuf);
373 : : gboolean _g_local_file_info_set_attribute (char *filename,
374 : : const char *attribute,
375 : : GFileAttributeType type,
376 : : gpointer value_p,
377 : : GFileQueryInfoFlags flags,
378 : : GCancellable *cancellable,
379 : : GError **error);
380 : : gboolean _g_local_file_info_set_attributes (char *filename,
381 : : GFileInfo *info,
382 : : GFileQueryInfoFlags flags,
383 : : GCancellable *cancellable,
384 : : GError **error);
385 : :
386 : : G_END_DECLS
387 : :
388 : : #endif /* __G_FILE_LOCAL_FILE_INFO_H__ */
|