]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/fs-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
14 #include <linux/magic.h>
18 #include "alloc-util.h"
19 #include "dirent-util.h"
27 #include "parse-util.h"
28 #include "path-util.h"
29 #include "process-util.h"
30 #include "stat-util.h"
31 #include "stdio-util.h"
32 #include "string-util.h"
34 #include "time-util.h"
35 #include "user-util.h"
38 int unlink_noerrno ( const char * path
) {
49 int rmdir_parents ( const char * path
, const char * stop
) {
58 /* Skip trailing slashes */
59 while ( l
> 0 && path
[ l
- 1 ] == '/' )
65 /* Skip last component */
66 while ( l
> 0 && path
[ l
- 1 ] != '/' )
69 /* Skip trailing slashes */
70 while ( l
> 0 && path
[ l
- 1 ] == '/' )
80 if ( path_startswith ( stop
, t
)) {
96 int rename_noreplace ( int olddirfd
, const char * oldpath
, int newdirfd
, const char * newpath
) {
100 ret
= renameat2 ( olddirfd
, oldpath
, newdirfd
, newpath
, RENAME_NOREPLACE
);
104 /* renameat2() exists since Linux 3.15, btrfs added support for it later.
105 * If it is not implemented, fallback to another method. */
106 if (! IN_SET ( errno
, EINVAL
, ENOSYS
))
109 /* The link()/unlink() fallback does not work on directories. But
110 * renameat() without RENAME_NOREPLACE gives the same semantics on
111 * directories, except when newpath is an *empty* directory. This is
113 ret
= fstatat ( olddirfd
, oldpath
, & buf
, AT_SYMLINK_NOFOLLOW
);
114 if ( ret
>= 0 && S_ISDIR ( buf
. st_mode
)) {
115 ret
= renameat ( olddirfd
, oldpath
, newdirfd
, newpath
);
116 return ret
>= 0 ? 0 : - errno
;
119 /* If it is not a directory, use the link()/unlink() fallback. */
120 ret
= linkat ( olddirfd
, oldpath
, newdirfd
, newpath
, 0 );
124 ret
= unlinkat ( olddirfd
, oldpath
, 0 );
126 /* backup errno before the following unlinkat() alters it */
128 ( void ) unlinkat ( newdirfd
, newpath
, 0 );
136 int readlinkat_malloc ( int fd
, const char * p
, char ** ret
) {
151 n
= readlinkat ( fd
, p
, c
, l
- 1 );
158 if (( size_t ) n
< l
- 1 ) {
169 int readlink_malloc ( const char * p
, char ** ret
) {
170 return readlinkat_malloc ( AT_FDCWD
, p
, ret
);
173 int readlink_value ( const char * p
, char ** ret
) {
174 _cleanup_free_
char * link
= NULL
;
178 r
= readlink_malloc ( p
, & link
);
182 value
= basename ( link
);
186 value
= strdup ( value
);
195 int readlink_and_make_absolute ( const char * p
, char ** r
) {
196 _cleanup_free_
char * target
= NULL
;
203 j
= readlink_malloc ( p
, & target
);
207 k
= file_in_same_dir ( p
, target
);
215 int chmod_and_chown ( const char * path
, mode_t mode
, uid_t uid
, gid_t gid
) {
218 /* Under the assumption that we are running privileged we
219 * first change the access mode and only then hand out
220 * ownership to avoid a window where access is too open. */
222 if ( mode
!= MODE_INVALID
)
223 if ( chmod ( path
, mode
) < 0 )
226 if ( uid
!= UID_INVALID
|| gid
!= GID_INVALID
)
227 if ( chown ( path
, uid
, gid
) < 0 )
233 int fchmod_umask ( int fd
, mode_t m
) {
238 r
= fchmod ( fd
, m
& (~ u
)) < 0 ? - errno
: 0 ;
244 int fd_warn_permissions ( const char * path
, int fd
) {
247 if ( fstat ( fd
, & st
) < 0 )
250 if ( st
. st_mode
& 0111 )
251 log_warning ( "Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway." , path
);
253 if ( st
. st_mode
& 0002 )
254 log_warning ( "Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway." , path
);
256 if ( getpid_cached () == 1 && ( st
. st_mode
& 0044 ) != 0044 )
257 log_warning ( "Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway." , path
);
262 int touch_file ( const char * path
, bool parents
, usec_t stamp
, uid_t uid
, gid_t gid
, mode_t mode
) {
263 char fdpath
[ STRLEN ( "/proc/self/fd/" ) + DECIMAL_STR_MAX ( int )];
264 _cleanup_close_
int fd
= - 1 ;
269 /* Note that touch_file() does not follow symlinks: if invoked on an existing symlink, then it is the symlink
270 * itself which is updated, not its target
272 * Returns the first error we encounter, but tries to apply as much as possible. */
275 ( void ) mkdir_parents ( path
, 0755 );
277 /* Initially, we try to open the node with O_PATH, so that we get a reference to the node. This is useful in
278 * case the path refers to an existing device or socket node, as we can open it successfully in all cases, and
279 * won't trigger any driver magic or so. */
280 fd
= open ( path
, O_PATH
| O_CLOEXEC
| O_NOFOLLOW
);
285 /* if the node doesn't exist yet, we create it, but with O_EXCL, so that we only create a regular file
286 * here, and nothing else */
287 fd
= open ( path
, O_WRONLY
| O_CREAT
| O_EXCL
| O_CLOEXEC
, IN_SET ( mode
, 0 , MODE_INVALID
) ? 0644 : mode
);
292 /* Let's make a path from the fd, and operate on that. With this logic, we can adjust the access mode,
293 * ownership and time of the file node in all cases, even if the fd refers to an O_PATH object â which is
294 * something fchown(), fchmod(), futimensat() don't allow. */
295 xsprintf ( fdpath
, "/proc/self/fd/%i" , fd
);
297 if ( mode
!= MODE_INVALID
)
298 if ( chmod ( fdpath
, mode
) < 0 )
301 if ( uid_is_valid ( uid
) || gid_is_valid ( gid
))
302 if ( chown ( fdpath
, uid
, gid
) < 0 && ret
>= 0 )
305 if ( stamp
!= USEC_INFINITY
) {
306 struct timespec ts
[ 2 ];
308 timespec_store (& ts
[ 0 ], stamp
);
310 r
= utimensat ( AT_FDCWD
, fdpath
, ts
, 0 );
312 r
= utimensat ( AT_FDCWD
, fdpath
, NULL
, 0 );
313 if ( r
< 0 && ret
>= 0 )
319 int touch ( const char * path
) {
320 return touch_file ( path
, false , USEC_INFINITY
, UID_INVALID
, GID_INVALID
, MODE_INVALID
);
323 int symlink_idempotent ( const char * from
, const char * to
) {
329 if ( symlink ( from
, to
) < 0 ) {
330 _cleanup_free_
char * p
= NULL
;
335 r
= readlink_malloc ( to
, & p
);
336 if ( r
== - EINVAL
) /* Not a symlink? In that case return the original error we encountered: -EEXIST */
338 if ( r
< 0 ) /* Any other error? In that case propagate it as is */
341 if (! streq ( p
, from
)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */
348 int symlink_atomic ( const char * from
, const char * to
) {
349 _cleanup_free_
char * t
= NULL
;
355 r
= tempfn_random ( to
, NULL
, & t
);
359 if ( symlink ( from
, t
) < 0 )
362 if ( rename ( t
, to
) < 0 ) {
370 int mknod_atomic ( const char * path
, mode_t mode
, dev_t dev
) {
371 _cleanup_free_
char * t
= NULL
;
376 r
= tempfn_random ( path
, NULL
, & t
);
380 if ( mknod ( t
, mode
, dev
) < 0 )
383 if ( rename ( t
, path
) < 0 ) {
391 int mkfifo_atomic ( const char * path
, mode_t mode
) {
392 _cleanup_free_
char * t
= NULL
;
397 r
= tempfn_random ( path
, NULL
, & t
);
401 if ( mkfifo ( t
, mode
) < 0 )
404 if ( rename ( t
, path
) < 0 ) {
412 int get_files_in_directory ( const char * path
, char *** list
) {
413 _cleanup_closedir_
DIR * d
= NULL
;
415 size_t bufsize
= 0 , n
= 0 ;
416 _cleanup_strv_free_
char ** l
= NULL
;
420 /* Returns all files in a directory in *list, and the number
421 * of files as return value. If list is NULL returns only the
428 FOREACH_DIRENT_ALL ( de
, d
, return - errno
) {
429 dirent_ensure_type ( d
, de
);
431 if (! dirent_is_file ( de
))
435 /* one extra slot is needed for the terminating NULL */
436 if (! GREEDY_REALLOC ( l
, bufsize
, n
+ 2 ))
439 l
[ n
] = strdup ( de
-> d_name
);
454 static int getenv_tmp_dir ( const char ** ret_path
) {
460 /* We use the same order of environment variables python uses in tempfile.gettempdir():
461 * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
462 FOREACH_STRING ( n
, "TMPDIR" , "TEMP" , "TMP" ) {
465 e
= secure_getenv ( n
);
468 if (! path_is_absolute ( e
)) {
472 if (! path_is_normalized ( e
)) {
489 /* Remember first error, to make this more debuggable */
501 static int tmp_dir_internal ( const char * def
, const char ** ret
) {
508 r
= getenv_tmp_dir (& e
);
514 k
= is_dir ( def
, true );
518 return r
< 0 ? r
: k
;
524 int var_tmp_dir ( const char ** ret
) {
526 /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
527 * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
528 * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
529 * making it a variable that overrides all temporary file storage locations. */
531 return tmp_dir_internal ( "/var/tmp" , ret
);
534 int tmp_dir ( const char ** ret
) {
536 /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
537 * backed by an in-memory file system: /tmp. */
539 return tmp_dir_internal ( "/tmp" , ret
);
542 int unlink_or_warn ( const char * filename
) {
543 if ( unlink ( filename
) < 0 && errno
!= ENOENT
)
544 /* If the file doesn't exist and the fs simply was read-only (in which
545 * case unlink() returns EROFS even if the file doesn't exist), don't
547 if ( errno
!= EROFS
|| access ( filename
, F_OK
) >= 0 )
548 return log_error_errno ( errno
, "Failed to remove \" %s \" : %m" , filename
);
553 int inotify_add_watch_fd ( int fd
, int what
, uint32_t mask
) {
554 char path
[ STRLEN ( "/proc/self/fd/" ) + DECIMAL_STR_MAX ( int ) + 1 ];
557 /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
558 xsprintf ( path
, "/proc/self/fd/%i" , what
);
560 r
= inotify_add_watch ( fd
, path
, mask
);
567 static bool noop_root ( const char * root
) {
568 return isempty ( root
) || path_equal ( root
, "/" );
571 static bool safe_transition ( const struct stat
* a
, const struct stat
* b
) {
572 /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
573 * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
574 * making us believe we read something safe even though it isn't safe in the specific context we open it in. */
576 if ( a
-> st_uid
== 0 ) /* Transitioning from privileged to unprivileged is always fine */
579 return a
-> st_uid
== b
-> st_uid
; /* Otherwise we need to stay within the same UID */
582 int chase_symlinks ( const char * path
, const char * original_root
, unsigned flags
, char ** ret
) {
583 _cleanup_free_
char * buffer
= NULL
, * done
= NULL
, * root
= NULL
;
584 _cleanup_close_
int fd
= - 1 ;
585 unsigned max_follow
= 32 ; /* how many symlinks to follow before giving up and returning ELOOP */
586 struct stat previous_stat
;
593 /* Either the file may be missing, or we return an fd to the final object, but both make no sense */
594 if (( flags
& ( CHASE_NONEXISTENT
| CHASE_OPEN
)) == ( CHASE_NONEXISTENT
| CHASE_OPEN
))
600 /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
601 * symlinks relative to a root directory, instead of the root of the host.
603 * Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following
604 * relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is
605 * assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first
606 * prefixed accordingly.
608 * Algorithmically this operates on two path buffers: "done" are the components of the path we already
609 * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
610 * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
611 * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
612 * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
615 * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
616 * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
617 * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
620 /* A root directory of "/" or "" is identical to none */
621 if ( noop_root ( original_root
))
622 original_root
= NULL
;
624 if (! original_root
&& ! ret
&& ( flags
& ( CHASE_NONEXISTENT
| CHASE_NO_AUTOFS
| CHASE_SAFE
| CHASE_OPEN
)) == CHASE_OPEN
) {
625 /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
626 * and doesn't care about any of the other special features we provide either. */
627 r
= open ( path
, O_PATH
| O_CLOEXEC
);
635 r
= path_make_absolute_cwd ( original_root
, & root
);
639 if ( flags
& CHASE_PREFIX_ROOT
) {
641 /* We don't support relative paths in combination with a root directory */
642 if (! path_is_absolute ( path
))
645 path
= prefix_roota ( root
, path
);
649 r
= path_make_absolute_cwd ( path
, & buffer
);
653 fd
= open ( "/" , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
657 if ( flags
& CHASE_SAFE
) {
658 if ( fstat ( fd
, & previous_stat
) < 0 )
664 _cleanup_free_
char * first
= NULL
;
665 _cleanup_close_
int child
= - 1 ;
669 /* Determine length of first component in the path */
670 n
= strspn ( todo
, "/" ); /* The slashes */
671 m
= n
+ strcspn ( todo
+ n
, "/" ); /* The entire length of the component */
673 /* Extract the first component. */
674 first
= strndup ( todo
, m
);
680 /* Empty? Then we reached the end. */
684 /* Just a single slash? Then we reached the end. */
685 if ( path_equal ( first
, "/" )) {
686 /* Preserve the trailing slash */
688 if ( flags
& CHASE_TRAIL_SLASH
)
689 if (! strextend (& done
, "/" , NULL
))
695 /* Just a dot? Then let's eat this up. */
696 if ( path_equal ( first
, "/." ))
699 /* Two dots? Then chop off the last bit of what we already found out. */
700 if ( path_equal ( first
, "/.." )) {
701 _cleanup_free_
char * parent
= NULL
;
702 _cleanup_close_
int fd_parent
= - 1 ;
704 /* If we already are at the top, then going up will not change anything. This is in-line with
705 * how the kernel handles this. */
706 if ( isempty ( done
) || path_equal ( done
, "/" ))
709 parent
= dirname_malloc ( done
);
713 /* Don't allow this to leave the root dir. */
715 path_startswith ( done
, root
) &&
716 ! path_startswith ( parent
, root
))
719 free_and_replace ( done
, parent
);
721 fd_parent
= openat ( fd
, ".." , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
725 if ( flags
& CHASE_SAFE
) {
726 if ( fstat ( fd_parent
, & st
) < 0 )
729 if (! safe_transition (& previous_stat
, & st
))
736 fd
= TAKE_FD ( fd_parent
);
741 /* Otherwise let's see what this is. */
742 child
= openat ( fd
, first
+ n
, O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
745 if ( errno
== ENOENT
&&
746 ( flags
& CHASE_NONEXISTENT
) &&
747 ( isempty ( todo
) || path_is_normalized ( todo
))) {
749 /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
750 * what we got so far. But don't allow this if the remaining path contains "../ or "./"
751 * or something else weird. */
753 /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
754 if ( streq_ptr ( done
, "/" ))
757 if (! strextend (& done
, first
, todo
, NULL
))
767 if ( fstat ( child
, & st
) < 0 )
769 if (( flags
& CHASE_SAFE
) &&
770 ! safe_transition (& previous_stat
, & st
))
775 if (( flags
& CHASE_NO_AUTOFS
) &&
776 fd_is_fs_type ( child
, AUTOFS_SUPER_MAGIC
) > 0 )
779 if ( S_ISLNK ( st
. st_mode
)) {
782 _cleanup_free_
char * destination
= NULL
;
784 /* This is a symlink, in this case read the destination. But let's make sure we don't follow
785 * symlinks without bounds. */
786 if (-- max_follow
<= 0 )
789 r
= readlinkat_malloc ( fd
, first
+ n
, & destination
);
792 if ( isempty ( destination
))
795 if ( path_is_absolute ( destination
)) {
797 /* An absolute destination. Start the loop from the beginning, but use the root
798 * directory as base. */
801 fd
= open ( root
?: "/" , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
805 if ( flags
& CHASE_SAFE
) {
806 if ( fstat ( fd
, & st
) < 0 )
809 if (! safe_transition (& previous_stat
, & st
))
817 /* Note that we do not revalidate the root, we take it as is. */
826 /* Prefix what's left to do with what we just read, and start the loop again, but
827 * remain in the current directory. */
828 joined
= strjoin ( destination
, todo
);
830 joined
= strjoin ( "/" , destination
, todo
);
835 todo
= buffer
= joined
;
840 /* If this is not a symlink, then let's just add the name we read to what we already verified. */
842 done
= TAKE_PTR ( first
);
844 /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
845 if ( streq ( done
, "/" ))
848 if (! strextend (& done
, first
, NULL
))
852 /* And iterate again, but go one directory further down. */
858 /* Special case, turn the empty string into "/", to indicate the root directory. */
865 * ret
= TAKE_PTR ( done
);
867 if ( flags
& CHASE_OPEN
) {
868 /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by
869 * opening /proc/self/fd/xyz. */
878 int chase_symlinks_and_open (
881 unsigned chase_flags
,
885 _cleanup_close_
int path_fd
= - 1 ;
886 _cleanup_free_
char * p
= NULL
;
889 if ( chase_flags
& CHASE_NONEXISTENT
)
892 if ( noop_root ( root
) && ! ret_path
&& ( chase_flags
& ( CHASE_NO_AUTOFS
| CHASE_SAFE
)) == 0 ) {
893 /* Shortcut this call if none of the special features of this call are requested */
894 r
= open ( path
, open_flags
);
901 path_fd
= chase_symlinks ( path
, root
, chase_flags
| CHASE_OPEN
, ret_path
? & p
: NULL
);
905 r
= fd_reopen ( path_fd
, open_flags
);
910 * ret_path
= TAKE_PTR ( p
);
915 int chase_symlinks_and_opendir (
918 unsigned chase_flags
,
922 char procfs_path
[ STRLEN ( "/proc/self/fd/" ) + DECIMAL_STR_MAX ( int )];
923 _cleanup_close_
int path_fd
= - 1 ;
924 _cleanup_free_
char * p
= NULL
;
929 if ( chase_flags
& CHASE_NONEXISTENT
)
932 if ( noop_root ( root
) && ! ret_path
&& ( chase_flags
& ( CHASE_NO_AUTOFS
| CHASE_SAFE
)) == 0 ) {
933 /* Shortcut this call if none of the special features of this call are requested */
942 path_fd
= chase_symlinks ( path
, root
, chase_flags
| CHASE_OPEN
, ret_path
? & p
: NULL
);
946 xsprintf ( procfs_path
, "/proc/self/fd/%i" , path_fd
);
947 d
= opendir ( procfs_path
);
952 * ret_path
= TAKE_PTR ( p
);
958 int access_fd ( int fd
, int mode
) {
959 char p
[ STRLEN ( "/proc/self/fd/" ) + DECIMAL_STR_MAX ( fd
) + 1 ];
962 /* Like access() but operates on an already open fd */
964 xsprintf ( p
, "/proc/self/fd/%i" , fd
);
972 int unlinkat_deallocate ( int fd
, const char * name
, int flags
) {
973 _cleanup_close_
int truncate_fd
= - 1 ;
977 /* Operates like unlinkat() but also deallocates the file contents if it is a regular file and there's no other
978 * link to it. This is useful to ensure that other processes that might have the file open for reading won't be
979 * able to keep the data pinned on disk forever. This call is particular useful whenever we execute clean-up
980 * jobs ("vacuuming"), where we want to make sure the data is really gone and the disk space released and
981 * returned to the free pool.
983 * Deallocation is preferably done by FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE (đ) if supported, which means
984 * the file won't change size. That's a good thing since we shouldn't needlessly trigger SIGBUS in other
985 * programs that have mmap()ed the file. (The assumption here is that changing file contents to all zeroes
986 * underneath those programs is the better choice than simply triggering SIGBUS in them which truncation does.)
987 * However if hole punching is not implemented in the kernel or file system we'll fall back to normal file
988 * truncation (đĒ), as our goal of deallocating the data space trumps our goal of being nice to readers (đ).
990 * Note that we attempt deallocation, but failure to succeed with that is not considered fatal, as long as the
991 * primary job â to delete the file â is accomplished. */
993 if (( flags
& AT_REMOVEDIR
) == 0 ) {
994 truncate_fd
= openat ( fd
, name
, O_WRONLY
| O_CLOEXEC
| O_NOCTTY
| O_NOFOLLOW
| O_NONBLOCK
);
995 if ( truncate_fd
< 0 ) {
997 /* If this failed because the file doesn't exist propagate the error right-away. Also,
998 * AT_REMOVEDIR wasn't set, and we tried to open the file for writing, which means EISDIR is
999 * returned when this is a directory but we are not supposed to delete those, hence propagate
1000 * the error right-away too. */
1001 if ( IN_SET ( errno
, ENOENT
, EISDIR
))
1004 if ( errno
!= ELOOP
) /* don't complain if this is a symlink */
1005 log_debug_errno ( errno
, "Failed to open file '%s' for deallocation, ignoring: %m" , name
);
1009 if ( unlinkat ( fd
, name
, flags
) < 0 )
1012 if ( truncate_fd
< 0 ) /* Don't have a file handle, can't do more âšī¸ */
1015 if ( fstat ( truncate_fd
, & st
) < 0 ) {
1016 log_debug_errno ( errno
, "Failed to stat file '%s' for deallocation, ignoring." , name
);
1020 if (! S_ISREG ( st
. st_mode
) || st
. st_blocks
== 0 || st
. st_nlink
> 0 )
1023 /* If this is a regular file, it actually took up space on disk and there are no other links it's time to
1024 * punch-hole/truncate this to release the disk space. */
1026 bs
= MAX ( st
. st_blksize
, 512 );
1027 l
= DIV_ROUND_UP ( st
. st_size
, bs
) * bs
; /* Round up to next block size */
1029 if ( fallocate ( truncate_fd
, FALLOC_FL_PUNCH_HOLE
| FALLOC_FL_KEEP_SIZE
, 0 , l
) >= 0 )
1030 return 0 ; /* Successfully punched a hole! đ */
1032 /* Fall back to truncation */
1033 if ( ftruncate ( truncate_fd
, 0 ) < 0 ) {
1034 log_debug_errno ( errno
, "Failed to truncate file to 0, ignoring: %m" );
1041 int fsync_directory_of_file ( int fd
) {
1042 _cleanup_free_
char * path
= NULL
, * dn
= NULL
;
1043 _cleanup_close_
int dfd
= - 1 ;
1046 r
= fd_verify_regular ( fd
);
1050 r
= fd_get_path ( fd
, & path
);
1052 log_debug ( "Failed to query /proc/self/fd/%d%s: %m" ,
1054 r
== - EOPNOTSUPP
? ", ignoring" : "" );
1056 if ( r
== - EOPNOTSUPP
)
1057 /* If /proc is not available, we're most likely running in some
1058 * chroot environment, and syncing the directory is not very
1059 * important in that case. Let's just silently do nothing. */
1065 if (! path_is_absolute ( path
))
1068 dn
= dirname_malloc ( path
);
1072 dfd
= open ( dn
, O_RDONLY
| O_CLOEXEC
| O_DIRECTORY
);