OpenCoverage

renameat2.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/renameat2.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* Rename a file relative to open directories.-
2 Copyright (C) 2009-2018 Free Software Foundation, Inc.-
3-
4 This program is free software: you can redistribute it and/or modify-
5 it under the terms of the GNU General Public License as published by-
6 the Free Software Foundation; either version 3 of the License, or-
7 (at your option) any later version.-
8-
9 This program is distributed in the hope that it will be useful,-
10 but WITHOUT ANY WARRANTY; without even the implied warranty of-
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
12 GNU General Public License for more details.-
13-
14 You should have received a copy of the GNU General Public License-
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */-
16-
17/* written by Eric Blake and Paul Eggert */-
18-
19#include <config.h>-
20-
21#include "renameat2.h"-
22-
23#include <errno.h>-
24#include <stdio.h>-
25#include <sys/stat.h>-
26#include <unistd.h>-
27-
28#ifdef __linux__-
29# include <sys/syscall.h>-
30#endif-
31-
32static int-
33errno_fail (int e)-
34{-
35 errno = e;-
36 return -1;
never executed: return -1;
0
37}-
38-
39#if HAVE_RENAMEAT-
40-
41# include <stdbool.h>-
42# include <stdlib.h>-
43# include <string.h>-
44-
45# include "dirname.h"-
46# include "openat.h"-
47-
48#else-
49# include "openat-priv.h"-
50-
51static int-
52rename_noreplace (char const *src, char const *dst)-
53{-
54 /* This has a race between the call to lstat and the call to rename. */-
55 struct stat st;-
56 return (lstat (dst, &st) == 0 || errno == EOVERFLOW ? errno_fail (EEXIST)-
57 : errno == ENOENT ? rename (src, dst)-
58 : -1);-
59}-
60#endif-
61-
62#undef renameat-
63-
64/* Rename FILE1, in the directory open on descriptor FD1, to FILE2, in-
65 the directory open on descriptor FD2. If possible, do it without-
66 changing the working directory. Otherwise, resort to using-
67 save_cwd/fchdir, then rename/restore_cwd. If either the save_cwd or-
68 the restore_cwd fails, then give a diagnostic and exit nonzero.-
69-
70 Obey FLAGS when doing the renaming. If FLAGS is zero, this-
71 function is equivalent to renameat (FD1, SRC, FD2, DST). */-
72-
73int-
74renameat2 (int fd1, char const *src, int fd2, char const *dst,-
75 unsigned int flags)-
76{-
77 int ret_val = -1;-
78 int err = EINVAL;-
79-
80#ifdef SYS_renameat2-
81 ret_val = syscall (SYS_renameat2, fd1, src, fd2, dst, flags);-
82 err = errno;-
83#elif defined RENAME_EXCL-
84 if (! (flags & ~(RENAME_EXCHANGE | RENAME_NOREPLACE)))-
85 {-
86 ret_val = renameatx_np (fd1, src, fd2, dst,-
87 ((flags & RENAME_EXCHANGE ? RENAME_SWAP : 0)-
88 | (flags & RENAME_NOREPLACE ? RENAME_EXCL : 0)));-
89 err = errno;-
90 }-
91#endif-
92-
93 if (! (ret_val < 0 && (err == EINVAL || err == ENOSYS || err == ENOTSUP)))
ret_val < 0Description
TRUEevaluated 8513 times by 2 tests
Evaluated by:
  • mv
  • shred
FALSEevaluated 168 times by 4 tests
Evaluated by:
  • cp
  • ginstall
  • mv
  • shred
err == 22Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • mv
FALSEevaluated 8509 times by 2 tests
Evaluated by:
  • mv
  • shred
err == 38Description
TRUEnever evaluated
FALSEevaluated 8509 times by 2 tests
Evaluated by:
  • mv
  • shred
err == 95Description
TRUEnever evaluated
FALSEevaluated 8509 times by 2 tests
Evaluated by:
  • mv
  • shred
0-8513
94 return ret_val;
executed 8677 times by 4 tests: return ret_val;
Executed by:
  • cp
  • ginstall
  • mv
  • shred
8677
95-
96#if HAVE_RENAMEAT-
97 {-
98 size_t src_len;-
99 size_t dst_len;-
100 char *src_temp = (char *) src;-
101 char *dst_temp = (char *) dst;-
102 bool src_slash;-
103 bool dst_slash;-
104 int rename_errno = ENOTDIR;-
105 struct stat src_st;-
106 struct stat dst_st;-
107 bool dst_found_nonexistent = false;-
108-
109 if (flags != 0)
flags != 0Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • mv
FALSEnever evaluated
0-4
110 {-
111 /* RENAME_NOREPLACE is the only flag currently supported. */-
112 if (flags & ~RENAME_NOREPLACE)
flags & ~ (1 << 0)Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • mv
0-4
113 return errno_fail (ENOTSUP);
never executed: return errno_fail ( 95 );
0
114 else-
115 {-
116 /* This has a race between the call to lstatat and the calls to-
117 renameat below. */-
118 if (lstatat (fd2, dst, &dst_st) == 0 || errno == EOVERFLOW)
lstatat (fd2, ... &dst_st) == 0Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • mv
(*__errno_location ()) == 75Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • mv
0-4
119 return errno_fail (EEXIST);
never executed: return errno_fail ( 17 );
0
120 if (errno != ENOENT)
(*__errno_location ()) != 2Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • mv
0-4
121 return -1;
never executed: return -1;
0
122 dst_found_nonexistent = true;-
123 }
executed 4 times by 1 test: end of block
Executed by:
  • mv
4
124 }-
125-
126 /* Let strace see any ENOENT failure. */-
127 src_len = strlen (src);-
128 dst_len = strlen (dst);-
129 if (!src_len || !dst_len)
!src_lenDescription
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • mv
!dst_lenDescription
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • mv
0-4
130 return renameat (fd1, src, fd2, dst);
never executed: return renameat (fd1, src, fd2, dst);
0
131-
132 src_slash = src[src_len - 1] == '/';-
133 dst_slash = dst[dst_len - 1] == '/';-
134 if (!src_slash && !dst_slash)
!src_slashDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • mv
FALSEnever evaluated
!dst_slashDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • mv
FALSEnever evaluated
0-4
135 return renameat (fd1, src, fd2, dst);
executed 4 times by 1 test: return renameat (fd1, src, fd2, dst);
Executed by:
  • mv
4
136-
137 /* Presence of a trailing slash requires directory semantics. If-
138 the source does not exist, or if the destination cannot be turned-
139 into a directory, give up now. Otherwise, strip trailing slashes-
140 before calling rename. */-
141 if (lstatat (fd1, src, &src_st))
lstatat (fd1, src, &src_st)Description
TRUEnever evaluated
FALSEnever evaluated
0
142 return -1;
never executed: return -1;
0
143 if (dst_found_nonexistent)
dst_found_nonexistentDescription
TRUEnever evaluated
FALSEnever evaluated
0
144 {-
145 if (!S_ISDIR (src_st.st_mode))
! (((( src_st.... == (0040000))Description
TRUEnever evaluated
FALSEnever evaluated
0
146 return errno_fail (ENOENT);
never executed: return errno_fail ( 2 );
0
147 }
never executed: end of block
0
148 else if (lstatat (fd2, dst, &dst_st))
lstatat (fd2, dst, &dst_st)Description
TRUEnever evaluated
FALSEnever evaluated
0
149 {-
150 if (errno != ENOENT || !S_ISDIR (src_st.st_mode))
(*__errno_location ()) != 2Description
TRUEnever evaluated
FALSEnever evaluated
! (((( src_st.... == (0040000))Description
TRUEnever evaluated
FALSEnever evaluated
0
151 return -1;
never executed: return -1;
0
152 }
never executed: end of block
0
153 else if (!S_ISDIR (dst_st.st_mode))
! (((( dst_st.... == (0040000))Description
TRUEnever evaluated
FALSEnever evaluated
0
154 return errno_fail (ENOTDIR);
never executed: return errno_fail ( 20 );
0
155 else if (!S_ISDIR (src_st.st_mode))
! (((( src_st.... == (0040000))Description
TRUEnever evaluated
FALSEnever evaluated
0
156 return errno_fail (EISDIR);
never executed: return errno_fail ( 21 );
0
157-
158# if RENAME_TRAILING_SLASH_SOURCE_BUG-
159 /* See the lengthy comment in rename.c why Solaris 9 is forced to-
160 GNU behavior, while Solaris 10 is left with POSIX behavior,-
161 regarding symlinks with trailing slash. */-
162 ret_val = -1;-
163 if (src_slash)-
164 {-
165 src_temp = strdup (src);-
166 if (!src_temp)-
167 {-
168 /* Rather than rely on strdup-posix, we set errno ourselves. */-
169 rename_errno = ENOMEM;-
170 goto out;-
171 }-
172 strip_trailing_slashes (src_temp);-
173 if (lstatat (fd1, src_temp, &src_st))-
174 {-
175 rename_errno = errno;-
176 goto out;-
177 }-
178 if (S_ISLNK (src_st.st_mode))-
179 goto out;-
180 }-
181 if (dst_slash)-
182 {-
183 dst_temp = strdup (dst);-
184 if (!dst_temp)-
185 {-
186 rename_errno = ENOMEM;-
187 goto out;-
188 }-
189 strip_trailing_slashes (dst_temp);-
190 if (lstatat (fd2, dst_temp, &dst_st))-
191 {-
192 if (errno != ENOENT)-
193 {-
194 rename_errno = errno;-
195 goto out;-
196 }-
197 }-
198 else if (S_ISLNK (dst_st.st_mode))-
199 goto out;-
200 }-
201# endif /* RENAME_TRAILING_SLASH_SOURCE_BUG */-
202-
203 /* renameat does not honor trailing / on Solaris 10. Solve it in a-
204 similar manner to rename. No need to worry about bugs not present-
205 on Solaris, since all other systems either lack renameat or honor-
206 trailing slash correctly. */-
207-
208 ret_val = renameat (fd1, src_temp, fd2, dst_temp);-
209 rename_errno = errno;-
210 goto out;
never executed: goto out;
0
211 out:-
212 if (src_temp != src)
src_temp != srcDescription
TRUEnever evaluated
FALSEnever evaluated
0
213 free (src_temp);
never executed: free (src_temp);
0
214 if (dst_temp != dst)
dst_temp != dstDescription
TRUEnever evaluated
FALSEnever evaluated
0
215 free (dst_temp);
never executed: free (dst_temp);
0
216 errno = rename_errno;-
217 return ret_val;
never executed: return ret_val;
0
218 }-
219#else /* !HAVE_RENAMEAT */-
220-
221 /* RENAME_NOREPLACE is the only flag currently supported. */-
222 if (flags & ~RENAME_NOREPLACE)-
223 return errno_fail (ENOTSUP);-
224 return at_func2 (fd1, src, fd2, dst, flags ? rename_noreplace : rename);-
225-
226#endif /* !HAVE_RENAMEAT */-
227}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2