Commit Diff


commit - 82223ffcc5f64af285d0eac132024ef478ca6bd2
commit + 3d35a492f8fdcff7a6389058d0fcb635ea34a355
blob - cb77d0174b7784f5caab2a896af314562e4951aa
blob + f58f283d5b4a7296a4bc31daa1735068b298bb47
--- lib/worktree.c
+++ 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);