{"thread":{"id":"12608","subject":"[PATCH 1/2] Add a lockfile function to append to a file","startedAt":"2008-03-09T22:46:35Z","lastAt":"2008-03-09T22:46:35Z","messageCount":1,"participants":["Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"71533","messageId":"alpine.LNX.1.00.0803091842030.19665@iabervon.org","threadId":"12608","inReplyTo":null,"subject":"[PATCH 1/2] Add a lockfile function to append to a file","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-03-09T22:46:35Z","receivedAt":"2008-03-09T22:46:35Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This takes care of copying the original contents into the replacement\nfile after the lock is held, so that concurrent additions can't miss\neach other's changes.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n---\nThese two together replace [PATCH 5/11] from my earlier series; the \nlockfile API turned out not to have anything for O_APPEND (for the simple \nreason that it always creates a new replacement file). But appending is an \nobvious logical operation to support internally, especially since it \nactually has a clear semantics by itself for avoiding races.\n\n cache.h    |    1 +\n lockfile.c |   17 +++++++++++++++++\n 2 files changed, 18 insertions(+), 0 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 2a1e7ec..4a113b0 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -391,6 +391,7 @@ struct lock_file {\n \tchar filename[PATH_MAX];\n };\n extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);\n+extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);\n extern int commit_lock_file(struct lock_file *);\n \n extern int hold_locked_index(struct lock_file *, int);\ndiff --git a/lockfile.c b/lockfile.c\nindex 663f18f..95fd3d1 100644\n--- a/lockfile.c\n+++ b/lockfile.c\n@@ -160,6 +160,23 @@ int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on\n \treturn fd;\n }\n \n+int hold_lock_file_for_append(struct lock_file *lk, const char *path, int die_on_error)\n+{\n+\tint fd = lock_file(lk, path);\n+\tstruct stat st;\n+\tif (!stat(path, &st)) {\n+\t\tint orig_fd = open(path, O_RDONLY);\n+\t\tsize_t mmap_size = xsize_t(st.st_size);\n+\t\tvoid *mmap = xmmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE,\n+\t\t\t\t   orig_fd, 0);\n+\t\twrite_or_die(fd, mmap, mmap_size);\n+\t\tmunmap(mmap, mmap_size);\n+\t}\n+\tif (fd < 0 && die_on_error)\n+\t\tdie(\"unable to create '%s.lock': %s\", path, strerror(errno));\n+\treturn fd;\n+}\n+\n int close_lock_file(struct lock_file *lk)\n {\n \tint fd = lk->fd;\n-- \n1.5.4.3.610.gea6cd\n"}]}