Line Flow Count Block(s) Source
1 - /*
2 - * Copyright (C) the libgit2 contributors. All rights reserved.
3 - *
4 - * This file is part of libgit2, distributed under the GNU GPL v2 with
5 - * a Linking Exception. For full terms see the included COPYING file.
6 - */
7 -
8 - #include "futils.h"
9 -
10 - #include "global.h"
11 - #include "strmap.h"
12 - #include <ctype.h>
13 - #if GIT_WIN32
14 - #include "win32/findfile.h"
15 - #endif
16 -
17 5288 2 int git_futils_mkpath2file(const char *file_path, const mode_t mode)
18 - {
19 5288 2 return git_futils_mkdir(
20 - file_path, mode,
21 - GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR);
22 - }
23 -
24 6695 2 int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode)
25 - {
26 - int fd;
27 - mode_t mask;
28 -
29 6695 2,3 p_umask(mask = p_umask(0));
30 -
31 6695 4 git_buf_sets(path_out, filename);
32 6695 5 git_buf_puts(path_out, "_git2_XXXXXX");
33 -
34 6695 6,7 if (git_buf_oom(path_out))
35 ##### 8 return -1;
36 -
37 6695 9,10 if ((fd = p_mkstemp(path_out->ptr)) < 0) {
38 ##### 11 git_error_set(GIT_ERROR_OS,
39 - "failed to create temporary file '%s'", path_out->ptr);
40 ##### 12 return -1;
41 - }
42 -
43 6695 13,14 if (p_chmod(path_out->ptr, (mode & ~mask))) {
44 ##### 15 git_error_set(GIT_ERROR_OS,
45 - "failed to set permissions on file '%s'", path_out->ptr);
46 ##### 16 return -1;
47 - }
48 -
49 6695 17 return fd;
50 - }
51 -
52 73 2 int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode)
53 - {
54 - int fd;
55 -
56 73 2,3 if (git_futils_mkpath2file(path, dirmode) < 0)
57 ##### 4 return -1;
58 -
59 73 5 fd = p_creat(path, mode);
60 73 6 if (fd < 0) {
61 ##### 7 git_error_set(GIT_ERROR_OS, "failed to create file '%s'", path);
62 ##### 8 return -1;
63 - }
64 -
65 73 9 return fd;
66 - }
67 -
68 10325 2 int git_futils_creat_locked(const char *path, const mode_t mode)
69 - {
70 10325 2 int fd = p_open(path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC,
71 - mode);
72 -
73 10326 3 if (fd < 0) {
74 3 4 int error = errno;
75 3 5 git_error_set(GIT_ERROR_OS, "failed to create locked file '%s'", path);
76 3 6 switch (error) {
77 - case EEXIST:
78 3 7 return GIT_ELOCKED;
79 - case ENOENT:
80 ##### 8 return GIT_ENOTFOUND;
81 - default:
82 ##### 9 return -1;
83 - }
84 - }
85 -
86 10323 10 return fd;
87 - }
88 -
89 3494 2 int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode)
90 - {
91 3494 2,3 if (git_futils_mkpath2file(path, dirmode) < 0)
92 ##### 4 return -1;
93 -
94 3493 5 return git_futils_creat_locked(path, mode);
95 - }
96 -
97 128386 2 int git_futils_open_ro(const char *path)
98 - {
99 128386 2 int fd = p_open(path, O_RDONLY);
100 128430 3 if (fd < 0)
101 1 4,5 return git_path_set_error(errno, path, "open");
102 128429 6 return fd;
103 - }
104 -
105 117 2 int git_futils_truncate(const char *path, int mode)
106 - {
107 117 2 int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
108 117 3 if (fd < 0)
109 ##### 4,5 return git_path_set_error(errno, path, "open");
110 -
111 117 6 close(fd);
112 117 7 return 0;
113 - }
114 -
115 435 2 int git_futils_filesize(uint64_t *out, git_file fd)
116 - {
117 - struct stat sb;
118 -
119 435 2,3 if (p_fstat(fd, &sb)) {
120 ##### 4 git_error_set(GIT_ERROR_OS, "failed to stat file descriptor");
121 ##### 5 return -1;
122 - }
123 -
124 435 6 if (sb.st_size < 0) {
125 ##### 7 git_error_set(GIT_ERROR_INVALID, "invalid file size");
126 ##### 8 return -1;
127 - }
128 -
129 435 9 *out = sb.st_size;
130 435 9 return 0;
131 - }
132 -
133 18094 2 mode_t git_futils_canonical_mode(mode_t raw_mode)
134 - {
135 18094 2 if (S_ISREG(raw_mode))
136 16692 3-6 return S_IFREG | GIT_PERMS_CANONICAL(raw_mode);
137 1402 7 else if (S_ISLNK(raw_mode))
138 41 8 return S_IFLNK;
139 1361 9 else if (S_ISGITLINK(raw_mode))
140 194 10 return S_IFGITLINK;
141 1167 11 else if (S_ISDIR(raw_mode))
142 1164 12 return S_IFDIR;
143 - else
144 3 13 return 0;
145 - }
146 -
147 104229 2 int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
148 - {
149 104229 2 ssize_t read_size = 0;
150 - size_t alloc_len;
151 -
152 104229 2 git_buf_clear(buf);
153 -
154 104343 3,4 if (!git__is_ssizet(len)) {
155 ##### 5 git_error_set(GIT_ERROR_INVALID, "read too large");
156 46 6 return -1;
157 - }
158 -
159 104343 7-13 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
160 104508 14,15 if (git_buf_grow(buf, alloc_len) < 0)
161 ##### 16 return -1;
162 -
163 - /* p_read loops internally to read len bytes */
164 104508 17 read_size = p_read(fd, buf->ptr, len);
165 -
166 104487 18 if (read_size != (ssize_t)len) {
167 ##### 19 git_error_set(GIT_ERROR_OS, "failed to read descriptor");
168 ##### 20 git_buf_dispose(buf);
169 ##### 21 return -1;
170 - }
171 -
172 104487 22 buf->ptr[read_size] = '\0';
173 104487 22 buf->size = read_size;
174 -
175 104487 22 return 0;
176 - }
177 -
178 - 2 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files)int git_futils_readbuffer_updated(
179 - git_buf *out, const char *path, git_oid *checksum, int *updated)
180 - {
181 - int error;
182 - git_file fd;
183 - struct stat st;
184 - 2 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) git_buf buf = GIT_BUF_INIT;
185 - git_oid checksum_new;
186 -
187 - 2-5 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) assert(out && path && *path);
188 -
189 - 6 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (updated != NULL)
190 - 7 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) *updated = 0;
191 -
192 - 8,9 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (p_stat(path, &st) < 0)
193 - 10,11 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) return git_path_set_error(errno, path, "stat");
194 -
195 -
196 - 12 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (S_ISDIR(st.st_mode)) {
197 - 13 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_INVALID, "requested file is a directory");
198 - 14 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) return GIT_ENOTFOUND;
199 - }
200 -
201 - 15,16 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (!git__is_sizet(st.st_size+1)) {
202 - 17 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_OS, "invalid regular file stat for '%s'", path);
203 - 18 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) return -1;
204 - }
205 -
206 - 19,20 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if ((fd = git_futils_open_ro(path)) < 0)
207 - 21 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) return fd;
208 -
209 - 22,23 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (git_futils_readbuffer_fd(&buf, fd, (size_t)st.st_size) < 0) {
210 - 24 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) p_close(fd);
211 - 25 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) return -1;
212 - }
213 -
214 - 26 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) p_close(fd);
215 -
216 - 27 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (checksum) {
217 - 28,29 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) {
218 - 30 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) git_buf_dispose(&buf);
219 - 31 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) return error;
220 - }
221 -
222 - /*
223 - * If we were given a checksum, we only want to use it if it's different
224 - */
225 - 32,33 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (!git_oid__cmp(checksum, &checksum_new)) {
226 - 34 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) git_buf_dispose(&buf);
227 - 35 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (updated)
228 - 36 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) *updated = 0;
229 -
230 - 37 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) return 0;
231 - }
232 -
233 - 38 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) git_oid_cpy(checksum, &checksum_new);
234 - }
235 -
236 - /*
237 - * If we're here, the file did change, or the user didn't have an old version
238 - */
239 - 39 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) if (updated != NULL)
240 - 40 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) *updated = 1;
241 -
242 - 41 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) git_buf_swap(out, &buf);
243 - 42 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) git_buf_dispose(&buf);
244 -
245 - 43 suppressed: function cannot be solved git_futils_readbuffer_updated (automatic due to inconsistent arc counts in .gcda files) return 0;
246 - }
247 -
248 144636 2 int git_futils_readbuffer(git_buf *buf, const char *path)
249 - {
250 144636 2 return git_futils_readbuffer_updated(buf, path, NULL, NULL);
251 - }
252 -
253 2386 2 int git_futils_writebuffer(
254 - const git_buf *buf, const char *path, int flags, mode_t mode)
255 - {
256 2386 2 int fd, do_fsync = 0, error = 0;
257 -
258 2386 2 if (!flags)
259 505 3 flags = O_CREAT | O_TRUNC | O_WRONLY;
260 -
261 2386 4 if ((flags & O_FSYNC) != 0)
262 2 5 do_fsync = 1;
263 -
264 2386 6 flags &= ~O_FSYNC;
265 -
266 2386 6 if (!mode)
267 13 7 mode = GIT_FILEMODE_BLOB;
268 -
269 2386 8,9 if ((fd = p_open(path, flags, mode)) < 0) {
270 ##### 10 git_error_set(GIT_ERROR_OS, "could not open '%s' for writing", path);
271 ##### 11 return fd;
272 - }
273 -
274 2386 12-15 if ((error = p_write(fd, git_buf_cstr(buf), git_buf_len(buf))) < 0) {
275 ##### 16 git_error_set(GIT_ERROR_OS, "could not write to '%s'", path);
276 ##### 17 (void)p_close(fd);
277 ##### 18 return error;
278 - }
279 -
280 2386 19-21 if (do_fsync && (error = p_fsync(fd)) < 0) {
281 ##### 22 git_error_set(GIT_ERROR_OS, "could not fsync '%s'", path);
282 ##### 23 p_close(fd);
283 ##### 24 return error;
284 - }
285 -
286 2386 25,26 if ((error = p_close(fd)) < 0) {
287 ##### 27 git_error_set(GIT_ERROR_OS, "error while closing '%s'", path);
288 ##### 28 return error;
289 - }
290 -
291 2386 29,30 if (do_fsync && (flags & O_CREAT))
292 2 31 error = git_futils_fsync_parent(path);
293 -
294 2386 32 return error;
295 - }
296 -
297 ##### 2 int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode)
298 - {
299 ##### 2,3 if (git_futils_mkpath2file(to, dirmode) < 0)
300 ##### 4 return -1;
301 -
302 ##### 5,6 if (p_rename(from, to) < 0) {
303 ##### 7 git_error_set(GIT_ERROR_OS, "failed to rename '%s' to '%s'", from, to);
304 ##### 8 return -1;
305 - }
306 -
307 ##### 9 return 0;
308 - }
309 -
310 5335 2 int git_futils_mmap_ro(git_map *out, git_file fd, off64_t begin, size_t len)
311 - {
312 5335 2 return p_mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin);
313 - }
314 -
315 49 2 int git_futils_mmap_ro_file(git_map *out, const char *path)
316 - {
317 49 2 git_file fd = git_futils_open_ro(path);
318 - uint64_t len;
319 - int result;
320 -
321 49 3 if (fd < 0)
322 ##### 4 return fd;
323 -
324 49 5,6 if ((result = git_futils_filesize(&len, fd)) < 0)
325 ##### 7 goto out;
326 -
327 49 8,9 if (!git__is_sizet(len)) {
328 ##### 10 git_error_set(GIT_ERROR_OS, "file `%s` too large to mmap", path);
329 ##### 11 result = -1;
330 ##### 11 goto out;
331 - }
332 -
333 49 12 result = git_futils_mmap_ro(out, fd, 0, (size_t)len);
334 - out:
335 49 13 p_close(fd);
336 49 14 return result;
337 - }
338 -
339 5335 2 void git_futils_mmap_free(git_map *out)
340 - {
341 5335 2 p_munmap(out);
342 5335 3 }
343 -
344 6709 2 GIT_INLINE(int) mkdir_validate_dir(
345 - const char *path,
346 - struct stat *st,
347 - mode_t mode,
348 - uint32_t flags,
349 - struct git_futils_mkdir_options *opts)
350 - {
351 - /* with exclusive create, existing dir is an error */
352 6709 2 if ((flags & GIT_MKDIR_EXCL) != 0) {
353 8 3 git_error_set(GIT_ERROR_FILESYSTEM,
354 - "failed to make directory '%s': directory exists", path);
355 8 4 return GIT_EEXISTS;
356 - }
357 -
358 6701 5-7 if ((S_ISREG(st->st_mode) && (flags & GIT_MKDIR_REMOVE_FILES)) ||
359 6701 7,8 (S_ISLNK(st->st_mode) && (flags & GIT_MKDIR_REMOVE_SYMLINKS))) {
360 ##### 9,10 if (p_unlink(path) < 0) {
361 ##### 11-14 git_error_set(GIT_ERROR_OS, "failed to remove %s '%s'",
362 ##### 11 S_ISLNK(st->st_mode) ? "symlink" : "file", path);
363 ##### 15 return GIT_EEXISTS;
364 - }
365 -
366 ##### 16 opts->perfdata.mkdir_calls++;
367 -
368 ##### 16,17,20 if (p_mkdir(path, mode) < 0) {
369 ##### 18 git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", path);
370 ##### 19 return GIT_EEXISTS;
371 - }
372 - }
373 -
374 6701 21 else if (S_ISLNK(st->st_mode)) {
375 - /* Re-stat the target, make sure it's a directory */
376 ##### 22 opts->perfdata.stat_calls++;
377 -
378 ##### 22,23 if (p_stat(path, st) < 0) {
379 ##### 24 git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", path);
380 ##### 25 return GIT_EEXISTS;
381 - }
382 - }
383 -
384 6701 26 else if (!S_ISDIR(st->st_mode)) {
385 ##### 27 git_error_set(GIT_ERROR_FILESYSTEM,
386 - "failed to make directory '%s': directory exists", path);
387 ##### 28 return GIT_EEXISTS;
388 - }
389 -
390 6701 29 return 0;
391 - }
392 -
393 14579 2 GIT_INLINE(int) mkdir_validate_mode(
394 - const char *path,
395 - struct stat *st,
396 - bool terminal_path,
397 - mode_t mode,
398 - uint32_t flags,
399 - struct git_futils_mkdir_options *opts)
400 - {
401 14579 2-4 if (((terminal_path && (flags & GIT_MKDIR_CHMOD) != 0) ||
402 14555 4,5 (flags & GIT_MKDIR_CHMOD_PATH) != 0) && st->st_mode != mode) {
403 -
404 35 6 opts->perfdata.chmod_calls++;
405 -
406 35 6,7 if (p_chmod(path, mode) < 0) {
407 ##### 8 git_error_set(GIT_ERROR_OS, "failed to set permissions on '%s'", path);
408 ##### 9 return -1;
409 - }
410 - }
411 -
412 14579 10 return 0;
413 - }
414 -
415 16583 2 GIT_INLINE(int) mkdir_canonicalize(
416 - git_buf *path,
417 - uint32_t flags)
418 - {
419 - ssize_t root_len;
420 -
421 16583 2 if (path->size == 0) {
422 ##### 3 git_error_set(GIT_ERROR_OS, "attempt to create empty path");
423 ##### 4 return -1;
424 - }
425 -
426 - /* Trim trailing slashes (except the root) */
427 16583 5,6 if ((root_len = git_path_root(path->ptr)) < 0)
428 2634 7 root_len = 0;
429 - else
430 13949 8 root_len++;
431 -
432 20005 9,11,12 while (path->size > (size_t)root_len && path->ptr[path->size - 1] == '/')
433 3422 10 path->ptr[--path->size] = '\0';
434 -
435 - /* if we are not supposed to made the last element, truncate it */
436 16583 13 if ((flags & GIT_MKDIR_SKIP_LAST2) != 0) {
437 ##### 14 git_path_dirname_r(path, path->ptr);
438 ##### 15 flags |= GIT_MKDIR_SKIP_LAST;
439 - }
440 16583 16 if ((flags & GIT_MKDIR_SKIP_LAST) != 0) {
441 11659 17 git_path_dirname_r(path, path->ptr);
442 - }
443 -
444 - /* We were either given the root path (or trimmed it to
445 - * the root), we don't have anything to do.
446 - */
447 16583 18 if (path->size <= (size_t)root_len)
448 ##### 19 git_buf_clear(path);
449 -
450 16583 20 return 0;
451 - }
452 -
453 6927 2 int git_futils_mkdir(
454 - const char *path,
455 - mode_t mode,
456 - uint32_t flags)
457 - {
458 6927 2 git_buf make_path = GIT_BUF_INIT, parent_path = GIT_BUF_INIT;
459 - const char *relative;
460 6927 2 struct git_futils_mkdir_options opts = { 0 };
461 - struct stat st;
462 6927 2 size_t depth = 0;
463 6927 2 int len = 0, root_len, error;
464 -
465 6927 2-5 if ((error = git_buf_puts(&make_path, path)) < 0 ||
466 6927 6,7 (error = mkdir_canonicalize(&make_path, flags)) < 0 ||
467 6927 6,8 (error = git_buf_puts(&parent_path, make_path.ptr)) < 0 ||
468 6927 8 make_path.size == 0)
469 - goto done;
470 -
471 6927 9 root_len = git_path_root(make_path.ptr);
472 -
473 - /* find the first parent directory that exists. this will be used
474 - * as the base to dirname_relative.
475 - */
476 8575 10,31 for (relative = make_path.ptr; parent_path.size; ) {
477 8575 11 error = p_lstat(parent_path.ptr, &st);
478 -
479 8575 12 if (error == 0) {
480 6229 13 break;
481 2346 14,15 } else if (errno != ENOENT) {
482 2 16 git_error_set(GIT_ERROR_OS, "failed to stat '%s'", parent_path.ptr);
483 2 17 error = -1;
484 2 17 goto done;
485 - }
486 -
487 2344 18 depth++;
488 -
489 - /* examine the parent of the current path */
490 2344 18,19 if ((len = git_path_dirname_r(&parent_path, parent_path.ptr)) < 0) {
491 ##### 20 error = len;
492 ##### 20 goto done;
493 - }
494 -
495 2344 21,22 assert(len);
496 -
497 - /*
498 - * We've walked all the given path's parents and it's either relative
499 - * (the parent is simply '.') or rooted (the length is less than or
500 - * equal to length of the root path). The path may be less than the
501 - * root path length on Windows, where `C:` == `C:/`.
502 - */
503 2344 23-25 if ((len == 1 && parent_path.ptr[0] == '.') ||
504 2006 26,27 (len == 1 && parent_path.ptr[0] == '/') ||
505 - len <= root_len) {
506 338 28 relative = make_path.ptr;
507 338 28 break;
508 - }
509 -
510 2006 29 relative = make_path.ptr + len + 1;
511 -
512 - /* not recursive? just make this directory relative to its parent. */
513 2006 29 if ((flags & GIT_MKDIR_PATH) == 0)
514 358 30 break;
515 - }
516 -
517 - /* we found an item at the location we're trying to create,
518 - * validate it.
519 - */
520 6925 32 if (depth == 0) {
521 5358 33 error = mkdir_validate_dir(make_path.ptr, &st, mode, flags, &opts);
522 -
523 5358 34 if (!error)
524 5353 35 error = mkdir_validate_mode(
525 5353 35 make_path.ptr, &st, true, mode, flags, &opts);
526 -
527 5358 36 goto done;
528 - }
529 -
530 - /* we already took `SKIP_LAST` and `SKIP_LAST2` into account when
531 - * canonicalizing `make_path`.
532 - */
533 1567 37 flags &= ~(GIT_MKDIR_SKIP_LAST2 | GIT_MKDIR_SKIP_LAST);
534 -
535 1567 37-40 error = git_futils_mkdir_relative(relative,
536 1567 37 parent_path.size ? parent_path.ptr : NULL, mode, flags, &opts);
537 -
538 - done:
539 6927 41 git_buf_dispose(&make_path);
540 6926 42 git_buf_dispose(&parent_path);
541 6926 43 return error;
542 - }
543 -
544 117 2 int git_futils_mkdir_r(const char *path, const mode_t mode)
545 - {
546 117 2 return git_futils_mkdir(path, mode, GIT_MKDIR_PATH);
547 - }
548 -
549 9656 2 int git_futils_mkdir_relative(
550 - const char *relative_path,
551 - const char *base,
552 - mode_t mode,
553 - uint32_t flags,
554 - struct git_futils_mkdir_options *opts)
555 - {
556 9656 2 git_buf make_path = GIT_BUF_INIT;
557 9656 2 ssize_t root = 0, min_root_len;
558 9656 2 char lastch = '/', *tail;
559 - struct stat st;
560 9656 2 struct git_futils_mkdir_options empty_opts = {0};
561 - int error;
562 -
563 9656 2 if (!opts)
564 5169 3 opts = &empty_opts;
565 -
566 - /* build path and find "root" where we should start calling mkdir */
567 9656 4,5 if (git_path_join_unrooted(&make_path, relative_path, base, &root) < 0)
568 ##### 6 return -1;
569 -
570 9656 7-9 if ((error = mkdir_canonicalize(&make_path, flags)) < 0 ||
571 9656 9 make_path.size == 0)
572 - goto done;
573 -
574 - /* if we are not supposed to make the whole path, reset root */
575 9656 10 if ((flags & GIT_MKDIR_PATH) == 0)
576 663 11,12 root = git_buf_rfind(&make_path, '/');
577 -
578 - /* advance root past drive name or network mount prefix */
579 9656 13 min_root_len = git_path_root(make_path.ptr);
580 9656 14 if (root < min_root_len)
581 ##### 15 root = min_root_len;
582 11649 16,18,19 while (root >= 0 && make_path.ptr[root] == '/')
583 1993 17 ++root;
584 -
585 - /* clip root to make_path length */
586 9656 20 if (root > (ssize_t)make_path.size)
587 8 21 root = (ssize_t)make_path.size; /* i.e. NUL byte of string */
588 9656 22 if (root < 0)
589 5 23 root = 0;
590 -
591 - /* walk down tail of path making each directory */
592 19128 24,75,76 for (tail = &make_path.ptr[root]; *tail; *tail = lastch) {
593 9481 25 bool mkdir_attempted = false;
594 -
595 - /* advance tail to include next path component */
596 11910 25,27 while (*tail == '/')
597 2429 26 tail++;
598 49644 28,30,31 while (*tail && *tail != '/')
599 40163 29 tail++;
600 -
601 - /* truncate path at next component */
602 9481 32 lastch = *tail;
603 9481 32 *tail = '\0';
604 9481 32 st.st_mode = 0;
605 -
606 9481 32-34 if (opts->dir_map && git_strmap_exists(opts->dir_map, make_path.ptr))
607 246 35 continue;
608 -
609 - /* See what's going on with this path component */
610 9235 36 opts->perfdata.stat_calls++;
611 -
612 - retry_lstat:
613 9235 37,38 if (p_lstat(make_path.ptr, &st) < 0) {
614 7884 39-41 if (mkdir_attempted || errno != ENOENT) {
615 ##### 42 git_error_set(GIT_ERROR_OS, "cannot access component in path '%s'", make_path.ptr);
616 ##### 43 error = -1;
617 ##### 43 goto done;
618 - }
619 -
620 7884 44 git_error_clear();
621 7884 45 opts->perfdata.mkdir_calls++;
622 7884 45 mkdir_attempted = true;
623 7884 45,46 if (p_mkdir(make_path.ptr, mode) < 0) {
624 6 47,48 if (errno == EEXIST)
625 ##### 49 goto retry_lstat;
626 6 50 git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", make_path.ptr);
627 6 51 error = -1;
628 6 51 goto done;
629 - }
630 - } else {
631 1351 52,53 if ((error = mkdir_validate_dir(
632 1351 52 make_path.ptr, &st, mode, flags, opts)) < 0)
633 3 54 goto done;
634 - }
635 -
636 - /* chmod if requested and necessary */
637 9226 55,55,56 if ((error = mkdir_validate_mode(
638 9226 55 make_path.ptr, &st, (lastch == '\0'), mode, flags, opts)) < 0)
639 ##### 57 goto done;
640 -
641 9226 58,59 if (opts->dir_map && opts->pool) {
642 - char *cache_path;
643 - size_t alloc_size;
644 -
645 192 60-66,74 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, make_path.size, 1);
646 192 67 cache_path = git_pool_malloc(opts->pool, alloc_size);
647 192 68,69 GIT_ERROR_CHECK_ALLOC(cache_path);
648 -
649 192 70 memcpy(cache_path, make_path.ptr, make_path.size + 1);
650 -
651 192 70,71 if ((error = git_strmap_set(opts->dir_map, cache_path, cache_path)) < 0)
652 192 72,73 goto done;
653 - }
654 - }
655 -
656 9647 77 error = 0;
657 -
658 - /* check that full path really is a directory if requested & needed */
659 9647 77,78 if ((flags & GIT_MKDIR_VERIFY_DIR) != 0 &&
660 - lastch != '\0') {
661 2573 79 opts->perfdata.stat_calls++;
662 -
663 2573 79-81 if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) {
664 ##### 82 git_error_set(GIT_ERROR_OS, "path is not a directory '%s'",
665 - make_path.ptr);
666 ##### 83 error = GIT_ENOTFOUND;
667 - }
668 - }
669 -
670 - done:
671 9656 84 git_buf_dispose(&make_path);
672 9656 85 return error;
673 - }
674 -
675 - typedef struct {
676 - const char *base;
677 - size_t baselen;
678 - uint32_t flags;
679 - int depth;
680 - } futils__rmdir_data;
681 -
682 - #define FUTILS_MAX_DEPTH 100
683 -
684 3 2 static int futils__error_cannot_rmdir(const char *path, const char *filemsg)
685 - {
686 3 2 if (filemsg)
687 3 3 git_error_set(GIT_ERROR_OS, "could not remove directory '%s': %s",
688 - path, filemsg);
689 - else
690 ##### 4 git_error_set(GIT_ERROR_OS, "could not remove directory '%s'", path);
691 -
692 3 5 return -1;
693 - }
694 -
695 8 2 static int futils__rm_first_parent(git_buf *path, const char *ceiling)
696 - {
697 8 2 int error = GIT_ENOTFOUND;
698 - struct stat st;
699 -
700 24 2,19 while (error == GIT_ENOTFOUND) {
701 16 3 git_buf_rtruncate_at_char(path, '/');
702 -
703 16 4-6 if (!path->size || git__prefixcmp(path->ptr, ceiling) != 0)
704 ##### 7 error = 0;
705 16 8,9 else if (p_lstat_posixly(path->ptr, &st) == 0) {
706 8 10,11 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
707 8 12 error = p_unlink(path->ptr);
708 ##### 13 else if (!S_ISDIR(st.st_mode))
709 8 14,15 error = -1; /* fail to remove non-regular file */
710 8 16,17 } else if (errno != ENOTDIR)
711 ##### 18 error = -1;
712 - }
713 -
714 8 20 if (error)
715 ##### 21 futils__error_cannot_rmdir(path->ptr, "cannot remove parent");
716 -
717 8 22 return error;
718 - }
719 -
720 7768 2 static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
721 - {
722 7768 2 int error = 0;
723 7768 2 futils__rmdir_data *data = opaque;
724 - struct stat st;
725 -
726 7768 2 if (data->depth > FUTILS_MAX_DEPTH)
727 ##### 3 error = futils__error_cannot_rmdir(
728 ##### 3 path->ptr, "directory nesting too deep");
729 -
730 7768 4,5 else if ((error = p_lstat_posixly(path->ptr, &st)) < 0) {
731 2164 6,7 if (errno == ENOENT)
732 2156 8 error = 0;
733 8 9,10 else if (errno == ENOTDIR) {
734 - /* asked to remove a/b/c/d/e and a/b is a normal file */
735 8 11 if ((data->flags & GIT_RMDIR_REMOVE_BLOCKERS) != 0)
736 8 12 error = futils__rm_first_parent(path, data->base);
737 - else
738 8 13,14 futils__error_cannot_rmdir(
739 ##### 13 path->ptr, "parent is not directory");
740 - }
741 - else
742 2164 15-17 error = git_path_set_error(errno, path->ptr, "rmdir");
743 - }
744 -
745 5604 18 else if (S_ISDIR(st.st_mode)) {
746 1991 19 data->depth++;
747 -
748 1991 19 error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data);
749 -
750 1991 20 data->depth--;
751 -
752 1991 20 if (error < 0)
753 2 21 return error;
754 -
755 1989 22,23 if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0)
756 4 24 return error;
757 -
758 1985 25,26 if ((error = p_rmdir(path->ptr)) < 0) {
759 7 27,29 if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 &&
760 7 28,30-33 (errno == ENOTEMPTY || errno == EEXIST || errno == EBUSY))
761 7 34 error = 0;
762 - else
763 1985 35-37 error = git_path_set_error(errno, path->ptr, "rmdir");
764 - }
765 - }
766 -
767 3613 38 else if ((data->flags & GIT_RMDIR_REMOVE_FILES) != 0) {
768 2531 39,40 if (p_unlink(path->ptr) < 0)
769 2531 41-43 error = git_path_set_error(errno, path->ptr, "remove");
770 - }
771 -
772 1082 44 else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0)
773 3 45 error = futils__error_cannot_rmdir(path->ptr, "still present");
774 -
775 7762 46 return error;
776 - }
777 -
778 2207 2 static int futils__rmdir_empty_parent(void *opaque, const char *path)
779 - {
780 2207 2 futils__rmdir_data *data = opaque;
781 2207 2 int error = 0;
782 -
783 2207 2 if (strlen(path) <= data->baselen)
784 930 3 error = GIT_ITEROVER;
785 -
786 1277 4,5 else if (p_rmdir(path) < 0) {
787 1157 6 int en = errno;
788 -
789 1157 7,8 if (en == ENOENT || en == ENOTDIR) {
790 - /* do nothing */
791 30 9,10 } else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0 &&
792 - en == EBUSY) {
793 ##### 11,12 error = git_path_set_error(errno, path, "rmdir");
794 30 13-15 } else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) {
795 30 16 error = GIT_ITEROVER;
796 - } else {
797 ##### 17,18 error = git_path_set_error(errno, path, "rmdir");
798 - }
799 - }
800 -
801 2207 19 return error;
802 - }
803 -
804 4007 2 int git_futils_rmdir_r(
805 - const char *path, const char *base, uint32_t flags)
806 - {
807 - int error;
808 4007 2 git_buf fullpath = GIT_BUF_INIT;
809 - futils__rmdir_data data;
810 -
811 - /* build path and find "root" where we should start calling mkdir */
812 4007 2,3 if (git_path_join_unrooted(&fullpath, path, base, NULL) < 0)
813 ##### 4 return -1;
814 -
815 4007 5 memset(&data, 0, sizeof(data));
816 4007 5-7 data.base = base ? base : "";
817 4007 8-10 data.baselen = base ? strlen(base) : 0;
818 4007 11 data.flags = flags;
819 -
820 4007 11 error = futils__rmdir_recurs_foreach(&data, &fullpath);
821 -
822 - /* remove now-empty parents if requested */
823 4007 12,13 if (!error && (flags & GIT_RMDIR_EMPTY_PARENTS) != 0)
824 960 14 error = git_path_walk_up(
825 - &fullpath, base, futils__rmdir_empty_parent, &data);
826 -
827 4007 15 if (error == GIT_ITEROVER) {
828 960 16 git_error_clear();
829 960 17 error = 0;
830 - }
831 -
832 4007 18 git_buf_dispose(&fullpath);
833 -
834 4007 19 return error;
835 - }
836 -
837 1 2 int git_futils_fake_symlink(const char *target, const char *path)
838 - {
839 1 2 int retcode = GIT_ERROR;
840 1 2 int fd = git_futils_creat_withpath(path, 0755, 0644);
841 1 3 if (fd >= 0) {
842 1 4 retcode = p_write(fd, target, strlen(target));
843 1 5 p_close(fd);
844 - }
845 1 6 return retcode;
846 - }
847 -
848 2057 2 static int cp_by_fd(int ifd, int ofd, bool close_fd_when_done)
849 - {
850 2057 2 int error = 0;
851 - char buffer[FILEIO_BUFSIZE];
852 2057 2 ssize_t len = 0;
853 -
854 4025 2,4-6 while (!error && (len = p_read(ifd, buffer, sizeof(buffer))) > 0)
855 - /* p_write() does not have the same semantics as write(). It loops
856 - * internally and will return 0 when it has completed writing.
857 - */
858 1968 3 error = p_write(ofd, buffer, len);
859 -
860 2057 7 if (len < 0) {
861 ##### 8 git_error_set(GIT_ERROR_OS, "read error while copying file");
862 ##### 9 error = (int)len;
863 - }
864 -
865 2057 10 if (error < 0)
866 ##### 11 git_error_set(GIT_ERROR_OS, "write error while copying file");
867 -
868 2057 12 if (close_fd_when_done) {
869 2057 13 p_close(ifd);
870 2057 14 p_close(ofd);
871 - }
872 -
873 2057 15 return error;
874 - }
875 -
876 2057 2 int git_futils_cp(const char *from, const char *to, mode_t filemode)
877 - {
878 - int ifd, ofd;
879 -
880 2057 2,3 if ((ifd = git_futils_open_ro(from)) < 0)
881 ##### 4 return ifd;
882 -
883 2057 5,6 if ((ofd = p_open(to, O_WRONLY | O_CREAT | O_EXCL, filemode)) < 0) {
884 ##### 7 p_close(ifd);
885 ##### 8,9 return git_path_set_error(errno, to, "open for writing");
886 - }
887 -
888 2057 10 return cp_by_fd(ifd, ofd, true);
889 - }
890 -
891 5570 2 int git_futils_touch(const char *path, time_t *when)
892 - {
893 - struct p_timeval times[2];
894 - int ret;
895 -
896 5570 2-4 times[0].tv_sec = times[1].tv_sec = when ? *when : time(NULL);
897 5570 5 times[0].tv_usec = times[1].tv_usec = 0;
898 -
899 5570 5 ret = p_utimes(path, times);
900 -
901 5570 6 return (ret < 0) ? git_path_set_error(errno, path, "touch") : 0;
902 - }
903 -
904 7 2 static int cp_link(const char *from, const char *to, size_t link_size)
905 - {
906 7 2 int error = 0;
907 - ssize_t read_len;
908 - char *link_data;
909 - size_t alloc_size;
910 -
911 7 2-8 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, link_size, 1);
912 7 9 link_data = git__malloc(alloc_size);
913 7 10,11 GIT_ERROR_CHECK_ALLOC(link_data);
914 -
915 7 12 read_len = p_readlink(from, link_data, link_size);
916 7 13 if (read_len != (ssize_t)link_size) {
917 ##### 14 git_error_set(GIT_ERROR_OS, "failed to read symlink data for '%s'", from);
918 ##### 15 error = -1;
919 - }
920 - else {
921 7 16 link_data[read_len] = '\0';
922 -
923 7 16,17 if (p_symlink(link_data, to) < 0) {
924 ##### 18 git_error_set(GIT_ERROR_OS, "could not symlink '%s' as '%s'",
925 - link_data, to);
926 ##### 19 error = -1;
927 - }
928 - }
929 -
930 7 20 git__free(link_data);
931 7 21 return error;
932 - }
933 -
934 - typedef struct {
935 - const char *to_root;
936 - git_buf to;
937 - ssize_t from_prefix;
938 - uint32_t flags;
939 - uint32_t mkdir_flags;
940 - mode_t dirmode;
941 - } cp_r_info;
942 -
943 - #define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10)
944 -
945 1220 2 static int _cp_r_mkdir(cp_r_info *info, git_buf *from)
946 - {
947 1220 2 int error = 0;
948 -
949 - /* create root directory the first time we need to create a directory */
950 1220 2 if ((info->flags & GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT) == 0) {
951 30 3-6 error = git_futils_mkdir(
952 - info->to_root, info->dirmode,
953 30 3 (info->flags & GIT_CPDIR_CHMOD_DIRS) ? GIT_MKDIR_CHMOD : 0);
954 -
955 30 7 info->flags |= GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT;
956 - }
957 -
958 - /* create directory with root as base to prevent excess chmods */
959 1220 8 if (!error)
960 1220 9,9 error = git_futils_mkdir_relative(
961 1220 9 from->ptr + info->from_prefix, info->to_root,
962 - info->dirmode, info->mkdir_flags, NULL);
963 -
964 1220 10 return error;
965 - }
966 -
967 2211 2 static int _cp_r_callback(void *ref, git_buf *from)
968 - {
969 2211 2 int error = 0;
970 2211 2 cp_r_info *info = ref;
971 - struct stat from_st, to_st;
972 2211 2 bool exists = false;
973 -
974 2211 2,4 if ((info->flags & GIT_CPDIR_COPY_DOTFILES) == 0 &&
975 2138 3 from->ptr[git_path_basename_offset(from)] == '.')
976 2 5 return 0;
977 -
978 2209 6,7 if ((error = git_buf_joinpath(
979 2209 6 &info->to, info->to_root, from->ptr + info->from_prefix)) < 0)
980 ##### 8 return error;
981 -
982 2209 9,10 if (!(error = git_path_lstat(info->to.ptr, &to_st)))
983 64 11 exists = true;
984 2145 12 else if (error != GIT_ENOTFOUND)
985 ##### 13 return error;
986 - else {
987 2145 14 git_error_clear();
988 2145 15 error = 0;
989 - }
990 -
991 2209 16,17 if ((error = git_path_lstat(from->ptr, &from_st)) < 0)
992 ##### 18 return error;
993 -
994 2209 19 if (S_ISDIR(from_st.st_mode)) {
995 988 20 mode_t oldmode = info->dirmode;
996 -
997 - /* if we are not chmod'ing, then overwrite dirmode */
998 988 20 if ((info->flags & GIT_CPDIR_CHMOD_DIRS) == 0)
999 984 21 info->dirmode = from_st.st_mode;
1000 -
1001 - /* make directory now if CREATE_EMPTY_DIRS is requested and needed */
1002 988 22,23 if (!exists && (info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) != 0)
1003 10 24 error = _cp_r_mkdir(info, from);
1004 -
1005 - /* recurse onto target directory */
1006 988 25-27 if (!error && (!exists || S_ISDIR(to_st.st_mode)))
1007 988 28 error = git_path_direach(from, 0, _cp_r_callback, info);
1008 -
1009 988 29 if (oldmode != 0)
1010 985 30 info->dirmode = oldmode;
1011 -
1012 988 31 return error;
1013 - }
1014 -
1015 1221 32 if (exists) {
1016 ##### 33 if ((info->flags & GIT_CPDIR_OVERWRITE) == 0)
1017 ##### 34 return 0;
1018 -
1019 ##### 35,36 if (p_unlink(info->to.ptr) < 0) {
1020 ##### 37 git_error_set(GIT_ERROR_OS, "cannot overwrite existing file '%s'",
1021 - info->to.ptr);
1022 ##### 38 return GIT_EEXISTS;
1023 - }
1024 - }
1025 -
1026 - /* Done if this isn't a regular file or a symlink */
1027 1221 39,40 if (!S_ISREG(from_st.st_mode) &&
1028 9 40,41 (!S_ISLNK(from_st.st_mode) ||
1029 9 41 (info->flags & GIT_CPDIR_COPY_SYMLINKS) == 0))
1030 2 42 return 0;
1031 -
1032 - /* Make container directory on demand if needed */
1033 1219 43-45 if ((info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0 &&
1034 - (error = _cp_r_mkdir(info, from)) < 0)
1035 ##### 46 return error;
1036 -
1037 - /* make symlink or regular file */
1038 1219 47 if (info->flags & GIT_CPDIR_LINK_FILES) {
1039 1039 48,49 if ((error = p_link(from->ptr, info->to.ptr)) < 0)
1040 1039 50,51 git_error_set(GIT_ERROR_OS, "failed to link '%s'", from->ptr);
1041 180 52 } else if (S_ISLNK(from_st.st_mode)) {
1042 7 53 error = cp_link(from->ptr, info->to.ptr, (size_t)from_st.st_size);
1043 - } else {
1044 173 54 mode_t usemode = from_st.st_mode;
1045 -
1046 173 54 if ((info->flags & GIT_CPDIR_SIMPLE_TO_MODE) != 0)
1047 32 55-58 usemode = GIT_PERMS_FOR_WRITE(usemode);
1048 -
1049 173 59 error = git_futils_cp(from->ptr, info->to.ptr, usemode);
1050 - }
1051 -
1052 1219 60 return error;
1053 - }
1054 -
1055 35 2 int git_futils_cp_r(
1056 - const char *from,
1057 - const char *to,
1058 - uint32_t flags,
1059 - mode_t dirmode)
1060 - {
1061 - int error;
1062 35 2 git_buf path = GIT_BUF_INIT;
1063 - cp_r_info info;
1064 -
1065 35 2,3 if (git_buf_joinpath(&path, from, "") < 0) /* ensure trailing slash */
1066 ##### 4 return -1;
1067 -
1068 35 5 memset(&info, 0, sizeof(info));
1069 35 5 info.to_root = to;
1070 35 5 info.flags = flags;
1071 35 5 info.dirmode = dirmode;
1072 35 5 info.from_prefix = path.size;
1073 35 5 git_buf_init(&info.to, 0);
1074 -
1075 - /* precalculate mkdir flags */
1076 35 6 if ((flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0) {
1077 - /* if not creating empty dirs, then use mkdir to create the path on
1078 - * demand right before files are copied.
1079 - */
1080 33 7 info.mkdir_flags = GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST;
1081 33 7 if ((flags & GIT_CPDIR_CHMOD_DIRS) != 0)
1082 33 8,9 info.mkdir_flags |= GIT_MKDIR_CHMOD_PATH;
1083 - } else {
1084 - /* otherwise, we will do simple mkdir as directories are encountered */
1085 2 10-13 info.mkdir_flags =
1086 2 10 ((flags & GIT_CPDIR_CHMOD_DIRS) != 0) ? GIT_MKDIR_CHMOD : 0;
1087 - }
1088 -
1089 35 14 error = _cp_r_callback(&info, &path);
1090 -
1091 35 15 git_buf_dispose(&path);
1092 35 16 git_buf_dispose(&info.to);
1093 -
1094 35 17 return error;
1095 - }
1096 -
1097 - 2 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files)int git_futils_filestamp_check(
1098 - git_futils_filestamp *stamp, const char *path)
1099 - {
1100 - struct stat st;
1101 -
1102 - /* if the stamp is NULL, then always reload */
1103 - 2 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) if (stamp == NULL)
1104 - 3 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) return 1;
1105 -
1106 - 4,5 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) if (p_stat(path, &st) < 0)
1107 - 6 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) return GIT_ENOTFOUND;
1108 -
1109 - 7,8 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) if (stamp->mtime.tv_sec == st.st_mtime &&
1110 - #if defined(GIT_USE_NSEC)
1111 - 8,9 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) stamp->mtime.tv_nsec == st.st_mtime_nsec &&
1112 - #endif
1113 - 9,10 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) stamp->size == (uint64_t)st.st_size &&
1114 - 10 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) stamp->ino == (unsigned int)st.st_ino)
1115 - 11 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) return 0;
1116 -
1117 - 12 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) stamp->mtime.tv_sec = st.st_mtime;
1118 - #if defined(GIT_USE_NSEC)
1119 - 12 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) stamp->mtime.tv_nsec = st.st_mtime_nsec;
1120 - #endif
1121 - 12 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) stamp->size = (uint64_t)st.st_size;
1122 - 12 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) stamp->ino = (unsigned int)st.st_ino;
1123 -
1124 - 12 suppressed: function cannot be solved git_futils_filestamp_check (automatic due to inconsistent arc counts in .gcda files) return 1;
1125 - }
1126 -
1127 6747 2 void git_futils_filestamp_set(
1128 - git_futils_filestamp *target, const git_futils_filestamp *source)
1129 - {
1130 6747 2,3 assert(target);
1131 -
1132 6747 4 if (source)
1133 1776 5 memcpy(target, source, sizeof(*target));
1134 - else
1135 4971 6 memset(target, 0, sizeof(*target));
1136 6747 7 }
1137 -
1138 -
1139 15217 2 void git_futils_filestamp_set_from_stat(
1140 - git_futils_filestamp *stamp, struct stat *st)
1141 - {
1142 15217 2 if (st) {
1143 15217 3 stamp->mtime.tv_sec = st->st_mtime;
1144 - #if defined(GIT_USE_NSEC)
1145 15217 3 stamp->mtime.tv_nsec = st->st_mtime_nsec;
1146 - #else
1147 - stamp->mtime.tv_nsec = 0;
1148 - #endif
1149 15217 3 stamp->size = (uint64_t)st->st_size;
1150 15217 3 stamp->ino = (unsigned int)st->st_ino;
1151 - } else {
1152 ##### 4 memset(stamp, 0, sizeof(*stamp));
1153 - }
1154 15217 5 }
1155 -
1156 13 2 int git_futils_fsync_dir(const char *path)
1157 - {
1158 - #ifdef GIT_WIN32
1159 - GIT_UNUSED(path);
1160 - return 0;
1161 - #else
1162 13 2 int fd, error = -1;
1163 -
1164 13 2,3 if ((fd = p_open(path, O_RDONLY)) < 0) {
1165 ##### 4 git_error_set(GIT_ERROR_OS, "failed to open directory '%s' for fsync", path);
1166 ##### 5 return -1;
1167 - }
1168 -
1169 13 6,7 if ((error = p_fsync(fd)) < 0)
1170 ##### 8 git_error_set(GIT_ERROR_OS, "failed to fsync directory '%s'", path);
1171 -
1172 13 9 p_close(fd);
1173 13 10 return error;
1174 - #endif
1175 - }
1176 -
1177 13 2 int git_futils_fsync_parent(const char *path)
1178 - {
1179 - char *parent;
1180 - int error;
1181 -
1182 13 2,3 if ((parent = git_path_dirname(path)) == NULL)
1183 ##### 4 return -1;
1184 -
1185 13 5 error = git_futils_fsync_dir(parent);
1186 13 6 git__free(parent);
1187 13 7 return error;
1188 - }