22 * Copyright (c) 2005, Junio C Hamano
33 */
44
5- /*
6- * State diagram and cleanup
7- * -------------------------
8- *
9- * This module keeps track of all locked files in `lock_file_list` for
10- * use at cleanup. This list and the `lock_file` objects that comprise
11- * it must be kept in self-consistent states at all time, because the
12- * program can be interrupted any time by a signal, in which case the
13- * signal handler will walk through the list attempting to clean up
14- * any open lock files.
15- *
16- * The possible states of a `lock_file` object are as follows:
17- *
18- * - Uninitialized. In this state the object's `on_list` field must be
19- * zero but the rest of its contents need not be initialized. As
20- * soon as the object is used in any way, it is irrevocably
21- * registered in `lock_file_list`, and `on_list` is set.
22- *
23- * - Locked, lockfile open (after `hold_lock_file_for_update()`,
24- * `hold_lock_file_for_append()`, or `reopen_lock_file()`). In this
25- * state:
26- *
27- * - the lockfile exists
28- * - `active` is set
29- * - `filename` holds the filename of the lockfile
30- * - `fd` holds a file descriptor open for writing to the lockfile
31- * - `fp` holds a pointer to an open `FILE` object if and only if
32- * `fdopen_lock_file()` has been called on the object
33- * - `owner` holds the PID of the process that locked the file
34- *
35- * - Locked, lockfile closed (after successful `close_lock_file()`).
36- * Same as the previous state, except that the lockfile is closed
37- * and `fd` is -1.
38- *
39- * - Unlocked (after `commit_lock_file()`, `commit_lock_file_to()`,
40- * `rollback_lock_file()`, a failed attempt to lock, or a failed
41- * `close_lock_file()`). In this state:
42- *
43- * - `active` is unset
44- * - `filename` is empty (usually, though there are transitory
45- * states in which this condition doesn't hold). Client code should
46- * *not* rely on the filename being empty in this state.
47- * - `fd` is -1
48- * - the object is left registered in the `lock_file_list`, and
49- * `on_list` is set.
50- *
51- * A lockfile is owned by the process that created it. The `lock_file`
52- * has an `owner` field that records the owner's PID. This field is
53- * used to prevent a forked process from closing a lockfile created by
54- * its parent.
55- */
56-
575#include "cache.h"
586#include "lockfile.h"
59- #include "sigchain.h"
60-
61- static struct lock_file * volatile lock_file_list ;
62-
63- static void remove_lock_files (int skip_fclose )
64- {
65- pid_t me = getpid ();
66-
67- while (lock_file_list ) {
68- if (lock_file_list -> owner == me ) {
69- /* fclose() is not safe to call in a signal handler */
70- if (skip_fclose )
71- lock_file_list -> fp = NULL ;
72- rollback_lock_file (lock_file_list );
73- }
74- lock_file_list = lock_file_list -> next ;
75- }
76- }
77-
78- static void remove_lock_files_on_exit (void )
79- {
80- remove_lock_files (0 );
81- }
82-
83- static void remove_lock_files_on_signal (int signo )
84- {
85- remove_lock_files (1 );
86- sigchain_pop (signo );
87- raise (signo );
88- }
897
908/*
919 * path = absolute or relative path name
@@ -154,60 +72,17 @@ static void resolve_symlink(struct strbuf *path)
15472/* Make sure errno contains a meaningful value on error */
15573static int lock_file (struct lock_file * lk , const char * path , int flags )
15674{
157- size_t pathlen = strlen (path );
158-
159- if (!lock_file_list ) {
160- /* One-time initialization */
161- sigchain_push_common (remove_lock_files_on_signal );
162- atexit (remove_lock_files_on_exit );
163- }
75+ int fd ;
76+ struct strbuf filename = STRBUF_INIT ;
16477
165- if (lk -> active )
166- die ("BUG: cannot lock_file(\"%s\") using active struct lock_file" ,
167- path );
168- if (!lk -> on_list ) {
169- /* Initialize *lk and add it to lock_file_list: */
170- lk -> fd = -1 ;
171- lk -> fp = NULL ;
172- lk -> active = 0 ;
173- lk -> owner = 0 ;
174- strbuf_init (& lk -> filename , pathlen + LOCK_SUFFIX_LEN );
175- lk -> next = lock_file_list ;
176- lock_file_list = lk ;
177- lk -> on_list = 1 ;
178- } else if (lk -> filename .len ) {
179- /* This shouldn't happen, but better safe than sorry. */
180- die ("BUG: lock_file(\"%s\") called with improperly-reset lock_file object" ,
181- path );
182- }
78+ strbuf_addstr (& filename , path );
79+ if (!(flags & LOCK_NO_DEREF ))
80+ resolve_symlink (& filename );
18381
184- if (flags & LOCK_NO_DEREF ) {
185- strbuf_add_absolute_path (& lk -> filename , path );
186- } else {
187- struct strbuf resolved_path = STRBUF_INIT ;
188-
189- strbuf_add (& resolved_path , path , pathlen );
190- resolve_symlink (& resolved_path );
191- strbuf_add_absolute_path (& lk -> filename , resolved_path .buf );
192- strbuf_release (& resolved_path );
193- }
194-
195- strbuf_addstr (& lk -> filename , LOCK_SUFFIX );
196- lk -> fd = open (lk -> filename .buf , O_RDWR | O_CREAT | O_EXCL , 0666 );
197- if (lk -> fd < 0 ) {
198- strbuf_reset (& lk -> filename );
199- return -1 ;
200- }
201- lk -> owner = getpid ();
202- lk -> active = 1 ;
203- if (adjust_shared_perm (lk -> filename .buf )) {
204- int save_errno = errno ;
205- error ("cannot fix permission bits on %s" , lk -> filename .buf );
206- rollback_lock_file (lk );
207- errno = save_errno ;
208- return -1 ;
209- }
210- return lk -> fd ;
82+ strbuf_addstr (& filename , LOCK_SUFFIX );
83+ fd = create_tempfile (& lk -> tempfile , filename .buf );
84+ strbuf_release (& filename );
85+ return fd ;
21186}
21287
21388static int sleep_microseconds (long us )
@@ -353,109 +228,17 @@ int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
353228 return fd ;
354229}
355230
356- FILE * fdopen_lock_file (struct lock_file * lk , const char * mode )
357- {
358- if (!lk -> active )
359- die ("BUG: fdopen_lock_file() called for unlocked object" );
360- if (lk -> fp )
361- die ("BUG: fdopen_lock_file() called twice for file '%s'" , lk -> filename .buf );
362-
363- lk -> fp = fdopen (lk -> fd , mode );
364- return lk -> fp ;
365- }
366-
367- const char * get_lock_file_path (struct lock_file * lk )
368- {
369- if (!lk -> active )
370- die ("BUG: get_lock_file_path() called for unlocked object" );
371- return lk -> filename .buf ;
372- }
373-
374- int get_lock_file_fd (struct lock_file * lk )
375- {
376- if (!lk -> active )
377- die ("BUG: get_lock_file_fd() called for unlocked object" );
378- return lk -> fd ;
379- }
380-
381- FILE * get_lock_file_fp (struct lock_file * lk )
382- {
383- if (!lk -> active )
384- die ("BUG: get_lock_file_fp() called for unlocked object" );
385- return lk -> fp ;
386- }
387-
388231char * get_locked_file_path (struct lock_file * lk )
389232{
390- if (!lk -> active )
391- die ("BUG: get_locked_file_path() called for unlocked object" );
392- if (lk -> filename .len <= LOCK_SUFFIX_LEN ||
393- strcmp (lk -> filename .buf + lk -> filename .len - LOCK_SUFFIX_LEN , LOCK_SUFFIX ))
233+ struct strbuf ret = STRBUF_INIT ;
234+
235+ strbuf_addstr (& ret , get_tempfile_path (& lk -> tempfile ));
236+ if (ret .len <= LOCK_SUFFIX_LEN ||
237+ strcmp (ret .buf + ret .len - LOCK_SUFFIX_LEN , LOCK_SUFFIX ))
394238 die ("BUG: get_locked_file_path() called for malformed lock object" );
395239 /* remove ".lock": */
396- return xmemdupz (lk -> filename .buf , lk -> filename .len - LOCK_SUFFIX_LEN );
397- }
398-
399- int close_lock_file (struct lock_file * lk )
400- {
401- int fd = lk -> fd ;
402- FILE * fp = lk -> fp ;
403- int err ;
404-
405- if (fd < 0 )
406- return 0 ;
407-
408- lk -> fd = -1 ;
409- if (fp ) {
410- lk -> fp = NULL ;
411-
412- /*
413- * Note: no short-circuiting here; we want to fclose()
414- * in any case!
415- */
416- err = ferror (fp ) | fclose (fp );
417- } else {
418- err = close (fd );
419- }
420-
421- if (err ) {
422- int save_errno = errno ;
423- rollback_lock_file (lk );
424- errno = save_errno ;
425- return -1 ;
426- }
427-
428- return 0 ;
429- }
430-
431- int reopen_lock_file (struct lock_file * lk )
432- {
433- if (0 <= lk -> fd )
434- die (_ ("BUG: reopen a lockfile that is still open" ));
435- if (!lk -> active )
436- die (_ ("BUG: reopen a lockfile that has been committed" ));
437- lk -> fd = open (lk -> filename .buf , O_WRONLY );
438- return lk -> fd ;
439- }
440-
441- int commit_lock_file_to (struct lock_file * lk , const char * path )
442- {
443- if (!lk -> active )
444- die ("BUG: attempt to commit unlocked object to \"%s\"" , path );
445-
446- if (close_lock_file (lk ))
447- return -1 ;
448-
449- if (rename (lk -> filename .buf , path )) {
450- int save_errno = errno ;
451- rollback_lock_file (lk );
452- errno = save_errno ;
453- return -1 ;
454- }
455-
456- lk -> active = 0 ;
457- strbuf_reset (& lk -> filename );
458- return 0 ;
240+ strbuf_setlen (& ret , ret .len - LOCK_SUFFIX_LEN );
241+ return strbuf_detach (& ret , NULL );
459242}
460243
461244int commit_lock_file (struct lock_file * lk )
@@ -471,15 +254,3 @@ int commit_lock_file(struct lock_file *lk)
471254 free (result_path );
472255 return 0 ;
473256}
474-
475- void rollback_lock_file (struct lock_file * lk )
476- {
477- if (!lk -> active )
478- return ;
479-
480- if (!close_lock_file (lk )) {
481- unlink_or_warn (lk -> filename .buf );
482- lk -> active = 0 ;
483- strbuf_reset (& lk -> filename );
484- }
485- }
0 commit comments