avoid opening the file in get_file_status() if possible
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
diff --git a/lib/worktree.c b/lib/worktree.c
index cb77d01..f58f283 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -1127,24 +1127,25 @@ get_file_status(unsigned char *status, struct stat *sb,
* race conditions if filesystem paths change beneath our feet.
*/
if (dirfd != -1) {
- fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW);
- if (fd == -1 && errno != ENOENT)
- return got_error_from_errno2("openat", abspath);
+ if (fstatat(dirfd, de_name, sb, AT_SYMLINK_NOFOLLOW) == -1) {
+ err = got_error_from_errno2("fstatat", abspath);
+ goto done;
+ }
} else {
fd = open(abspath, O_RDONLY | O_NOFOLLOW);
if (fd == -1 && errno != ENOENT)
return got_error_from_errno2("open", abspath);
- }
- if (fd == -1 || fstat(fd, sb) == -1) {
- if (errno == ENOENT) {
- if (got_fileindex_entry_has_file_on_disk(ie))
- *status = GOT_STATUS_MISSING;
- else
- *status = GOT_STATUS_DELETE;
+ if (fd == -1 || fstat(fd, sb) == -1) {
+ if (errno == ENOENT) {
+ if (got_fileindex_entry_has_file_on_disk(ie))
+ *status = GOT_STATUS_MISSING;
+ else
+ *status = GOT_STATUS_DELETE;
+ goto done;
+ }
+ err = got_error_from_errno2("fstat", abspath);
goto done;
}
- err = got_error_from_errno2("fstat", abspath);
- goto done;
}
if (!S_ISREG(sb->st_mode)) {
@@ -1174,6 +1175,12 @@ get_file_status(unsigned char *status, struct stat *sb,
if (err)
goto done;
+ if (dirfd != -1) {
+ fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW);
+ if (fd == -1 && errno != ENOENT)
+ return got_error_from_errno2("openat", abspath);
+ }
+
f = fdopen(fd, "r");
if (f == NULL) {
err = got_error_from_errno2("fopen", abspath);