commit efdd40df00214d30ba88fa63c6a0cb3ef414088d from: Stefan Sperling date: Sat Jul 27 13:30:49 2019 UTC do a single open(2) call in get_file_status() commit - 6a263307756fdbb961b0d9d309edbacfb18a4fe3 commit + efdd40df00214d30ba88fa63c6a0cb3ef414088d blob - 08d2a404aeb438f0119da97f048a5a3735aa51c1 blob + bd32578a672cd5a5329ff0248325ae7f4012e663 --- lib/worktree.c +++ lib/worktree.c @@ -1041,6 +1041,7 @@ get_file_status(unsigned char *status, struct stat *sb const struct got_error *err = NULL; struct got_object_id id; size_t hdrlen; + int fd; FILE *f = NULL; uint8_t fbuf[8192]; struct got_blob_object *blob = NULL; @@ -1048,7 +1049,8 @@ get_file_status(unsigned char *status, struct stat *sb *status = GOT_STATUS_NO_CHANGE; - if (lstat(abspath, sb) == -1) { + fd = open(abspath, O_RDONLY | O_NOFOLLOW); + if (fd == -1) { if (errno == ENOENT) { if (ie) { if (got_fileindex_entry_has_file_on_disk(ie)) @@ -1062,38 +1064,44 @@ get_file_status(unsigned char *status, struct stat *sb sb->st_mode = GOT_DEFAULT_FILE_MODE; return NULL; } - return got_error_from_errno2("lstat", abspath); + return got_error_from_errno2("fopen", abspath); } + if (fstat(fd, sb) == -1) { + err = got_error_from_errno2("fstat", abspath); + goto done; + } + if (!S_ISREG(sb->st_mode)) { *status = GOT_STATUS_OBSTRUCTED; - return NULL; + goto done; } if (ie == NULL) - return NULL; + goto done; if (!got_fileindex_entry_has_file_on_disk(ie)) { *status = GOT_STATUS_DELETE; - return NULL; + goto done; } else if (!got_fileindex_entry_has_blob(ie)) { *status = GOT_STATUS_ADD; - return NULL; + goto done; } if (!stat_info_differs(ie, sb)) - return NULL; + goto done; memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1)); err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf)); if (err) - return err; + goto done; - f = fopen(abspath, "r"); + f = fdopen(fd, "r"); if (f == NULL) { - err = got_error_from_errno2("fopen", abspath); + err = got_error_from_errno2("fdopen", abspath); goto done; } + fd = -1; hdrlen = got_object_blob_get_hdrlen(blob); for (;;) { const uint8_t *bbuf = got_object_blob_get_read_buf(blob); @@ -1134,6 +1142,8 @@ get_file_status(unsigned char *status, struct stat *sb done: if (blob) got_object_blob_close(blob); + if (fd != -1 && close(fd) == -1 && err == NULL) + err = got_error_from_errno2("close", abspath); if (f) fclose(f); return err;