@matheusbsbs / matheus-bagliano / commits / d6cf61bfd4
Fork 0

close_lock_file(): new function in the lockfile API

The lockfile API is a handy way to obtain a file that is cleaned up if you die(). But sometimes you would need this sequence to work: 1. hold_lock_file_for_update() to get a file descriptor for writing; 2. write the contents out, without being able to decide if the results should be committed or rolled back; 3. do something else that makes the decision --- and this "something else" needs the lockfile not to have an open file descriptor for writing (e.g. Windows do not want a open file to be renamed); 4. call commit_lock_file() or rollback_lock_file() as appropriately. This adds close_lock_file() you can call between step 2 and 3 in the above sequence. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Casey committed Jan 16, 2008 at 11:05 UTC d6cf61bfd4bccffcc8b095f8469dbe749d70abdf
3 files changed +35 -12
Documentation/technical/api-lockfile.txt
+12 -3
@@ -37,7 +37,8 @@ commit_lock_file::
37 Take a pointer to the `struct lock_file` initialized
38 with an earlier call to `hold_lock_file_for_update()`,
39 close the file descriptor and rename the lockfile to its
40 - final destination.
40 + final destination. Returns 0 upon success, a negative
41 + value on failure to close(2) or rename(2).
42
43 rollback_lock_file::
44
@@ -45,6 +46,12 @@ rollback_lock_file::
46 with an earlier call to `hold_lock_file_for_update()`,
47 close the file descriptor and remove the lockfile.
48
49 +close_lock_file::
50 + Take a pointer to the `struct lock_file` initialized
51 + with an earlier call to `hold_lock_file_for_update()`,
52 + and close the file descriptor. Returns 0 upon success,
53 + a negative value on failure to close(2).
54 +
55 Because the structure is used in an `atexit(3)` handler, its
56 storage has to stay throughout the life of the program. It
57 cannot be an auto variable allocated on the stack.
@@ -54,8 +61,10 @@ done writing to the file descriptor. If you do not call either
61 and simply `exit(3)` from the program, an `atexit(3)` handler
62 will close and remove the lockfile.
63
57 -You should not close the file descriptor you obtained from
58 -`hold_lock_file_for_update` function yourself. The `struct
64 +If you need to close the file descriptor you obtained from
65 +`hold_lock_file_for_update` function yourself, do so by calling
66 +`close_lock_file()`. You should never call `close(2)` yourself!
67 +Otherwise the `struct
68 lock_file` structure still remembers that the file descriptor
69 needs to be closed, and a later call to `commit_lock_file()` or
70 `rollback_lock_file()` will result in duplicate calls to
cache.h
+1 -1
@@ -308,7 +308,7 @@ extern int commit_lock_file(struct lock_file *);
308 extern int hold_locked_index(struct lock_file *, int);
309 extern int commit_locked_index(struct lock_file *);
310 extern void set_alternate_index_output(const char *);
311 -
311 +extern int close_lock_file(struct lock_file *);
312 extern void rollback_lock_file(struct lock_file *);
313 extern int delete_ref(const char *, const unsigned char *sha1);
314
lockfile.c
+22 -8
@@ -13,7 +13,8 @@ static void remove_lock_file(void)
13 while (lock_file_list) {
14 if (lock_file_list->owner == me &&
15 lock_file_list->filename[0]) {
16 - close(lock_file_list->fd);
16 + if (lock_file_list->fd >= 0)
17 + close(lock_file_list->fd);
18 unlink(lock_file_list->filename);
19 }
20 lock_file_list = lock_file_list->next;
@@ -159,17 +160,26 @@ int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on
160 return fd;
161 }
162
163 +int close_lock_file(struct lock_file *lk)
164 +{
165 + int fd = lk->fd;
166 + lk->fd = -1;
167 + return close(fd);
168 +}
169 +
170 int commit_lock_file(struct lock_file *lk)
171 {
172 char result_file[PATH_MAX];
165 - int i;
166 - close(lk->fd);
173 + size_t i;
174 + if (lk->fd >= 0 && close_lock_file(lk))
175 + return -1;
176 strcpy(result_file, lk->filename);
177 i = strlen(result_file) - 5; /* .lock */
178 result_file[i] = 0;
170 - i = rename(lk->filename, result_file);
179 + if (rename(lk->filename, result_file))
180 + return -1;
181 lk->filename[0] = 0;
172 - return i;
182 + return 0;
183 }
184
185 int hold_locked_index(struct lock_file *lk, int die_on_error)
@@ -185,9 +195,12 @@ void set_alternate_index_output(const char *name)
195 int commit_locked_index(struct lock_file *lk)
196 {
197 if (alternate_index_output) {
188 - int result = rename(lk->filename, alternate_index_output);
198 + if (lk->fd >= 0 && close_lock_file(lk))
199 + return -1;
200 + if (rename(lk->filename, alternate_index_output))
201 + return -1;
202 lk->filename[0] = 0;
190 - return result;
203 + return 0;
204 }
205 else
206 return commit_lock_file(lk);
@@ -196,7 +209,8 @@ int commit_locked_index(struct lock_file *lk)
209 void rollback_lock_file(struct lock_file *lk)
210 {
211 if (lk->filename[0]) {
199 - close(lk->fd);
212 + if (lk->fd >= 0)
213 + close(lk->fd);
214 unlink(lk->filename);
215 }
216 lk->filename[0] = 0;