aboutsummaryrefslogtreecommitdiffstats
path: root/wrapper.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2014-06-25 11:49:48 -0700
committerJunio C Hamano <gitster@pobox.com>2014-06-25 11:49:48 -0700
commit1881d2b88c4b889dcb95782ad4bc5395808438e9 (patch)
treecab7b82ccfc98e89b355c3dc209b7ec6656e1b93 /wrapper.c
parent85785df6d6db50ff37d0ff1878c16ad69a063f6a (diff)
parent426ddeead6112955dfb50ccf9bb4af05d1ca9082 (diff)
downloadgit-1881d2b88c4b889dcb95782ad4bc5395808438e9.tar.gz
Merge branch 'ym/fix-opportunistic-index-update-race' into maint
"git status", even though it is a read-only operation, tries to update the index with refreshed lstat(2) info to optimize future accesses to the working tree opportunistically, but this could race with a "read-write" operation that modify the index while it is running. Detect such a race and avoid overwriting the index. * ym/fix-opportunistic-index-update-race: read-cache.c: verify index file before we opportunistically update it wrapper.c: add xpread() similar to xread()
Diffstat (limited to 'wrapper.c')
-rw-r--r--wrapper.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/wrapper.c b/wrapper.c
index 0cc56368bd..bc1bfb8600 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -174,6 +174,24 @@ ssize_t xwrite(int fd, const void *buf, size_t len)
}
}
+/*
+ * xpread() is the same as pread(), but it automatically restarts pread()
+ * operations with a recoverable error (EAGAIN and EINTR). xpread() DOES
+ * NOT GUARANTEE that "len" bytes is read even if the data is available.
+ */
+ssize_t xpread(int fd, void *buf, size_t len, off_t offset)
+{
+ ssize_t nr;
+ if (len > MAX_IO_SIZE)
+ len = MAX_IO_SIZE;
+ while (1) {
+ nr = pread(fd, buf, len, offset);
+ if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+ continue;
+ return nr;
+ }
+}
+
ssize_t read_in_full(int fd, void *buf, size_t count)
{
char *p = buf;
@@ -214,6 +232,26 @@ ssize_t write_in_full(int fd, const void *buf, size_t count)
return total;
}
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
+{
+ char *p = buf;
+ ssize_t total = 0;
+
+ while (count > 0) {
+ ssize_t loaded = xpread(fd, p, count, offset);
+ if (loaded < 0)
+ return -1;
+ if (loaded == 0)
+ return total;
+ count -= loaded;
+ p += loaded;
+ total += loaded;
+ offset += loaded;
+ }
+
+ return total;
+}
+
int xdup(int fd)
{
int ret = dup(fd);