2 * Copyright (c) 2005, Junio C Hamano
6 static struct lock_file
*lock_file_list
;
7 static const char *alternate_index_output
;
9 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 if (lock_file_list
->fd
>= 0)
17 close(lock_file_list
->fd
);
18 unlink(lock_file_list
->filename
);
20 lock_file_list
= lock_file_list
->next
;
24 static void remove_lock_file_on_signal(int signo
)
27 signal(signo
, SIG_DFL
);
32 * p = absolute or relative path name
34 * Return a pointer into p showing the beginning of the last path name
35 * element. If p is empty or the root directory ("/"), just return p.
37 static char *last_path_elm(char *p
)
39 /* r starts pointing to null at the end of the string */
40 char *r
= strchr(p
, '\0');
43 return p
; /* just return empty string */
45 r
--; /* back up to last non-null character */
47 /* back up past trailing slashes, if any */
48 while (r
> p
&& *r
== '/')
52 * then go backwards until I hit a slash, or the beginning of
55 while (r
> p
&& *(r
-1) != '/')
61 /* We allow "recursive" symbolic links. Only within reason, though */
65 * p = path that may be a symlink
68 * If p is a symlink, attempt to overwrite p with a path to the real
69 * file or directory (which may or may not exist), following a chain of
70 * symlinks if necessary. Otherwise, leave p unmodified.
72 * This is a best-effort routine. If an error occurs, p will either be
73 * left unmodified or will name a different symlink in a symlink chain
74 * that started with p's initial contents.
79 static char *resolve_symlink(char *p
, size_t s
)
85 int link_len
= readlink(p
, link
, sizeof(link
));
87 /* not a symlink anymore */
90 else if (link_len
< sizeof(link
))
91 /* readlink() never null-terminates */
92 link
[link_len
] = '\0';
94 warning("%s: symlink too long", p
);
98 if (is_absolute_path(link
)) {
99 /* absolute path simply replaces p */
103 warning("%s: symlink too long", p
);
108 * link is a relative path, so I must replace the
109 * last element of p with it.
111 char *r
= (char*)last_path_elm(p
);
112 if (r
- p
+ link_len
< s
)
115 warning("%s: symlink too long", p
);
124 static int lock_file(struct lock_file
*lk
, const char *path
)
126 if (strlen(path
) >= sizeof(lk
->filename
)) return -1;
127 strcpy(lk
->filename
, path
);
129 * subtract 5 from size to make sure there's room for adding
130 * ".lock" for the lock file name
132 resolve_symlink(lk
->filename
, sizeof(lk
->filename
)-5);
133 strcat(lk
->filename
, ".lock");
134 lk
->fd
= open(lk
->filename
, O_RDWR
| O_CREAT
| O_EXCL
, 0666);
136 if (!lock_file_list
) {
137 signal(SIGINT
, remove_lock_file_on_signal
);
138 signal(SIGHUP
, remove_lock_file_on_signal
);
139 signal(SIGTERM
, remove_lock_file_on_signal
);
140 signal(SIGQUIT
, remove_lock_file_on_signal
);
141 atexit(remove_lock_file
);
143 lk
->owner
= getpid();
145 lk
->next
= lock_file_list
;
149 if (adjust_shared_perm(lk
->filename
))
150 return error("cannot fix permission bits on %s",
158 int hold_lock_file_for_update(struct lock_file
*lk
, const char *path
, int die_on_error
)
160 int fd
= lock_file(lk
, path
);
161 if (fd
< 0 && die_on_error
)
162 die("unable to create '%s.lock': %s", path
, strerror(errno
));
166 int hold_lock_file_for_append(struct lock_file
*lk
, const char *path
, int die_on_error
)
170 fd
= lock_file(lk
, path
);
173 die("unable to create '%s.lock': %s", path
, strerror(errno
));
177 orig_fd
= open(path
, O_RDONLY
);
179 if (errno
!= ENOENT
) {
181 die("cannot open '%s' for copying", path
);
183 return error("cannot open '%s' for copying", path
);
185 } else if (copy_fd(orig_fd
, fd
)) {
194 int close_lock_file(struct lock_file
*lk
)
201 int commit_lock_file(struct lock_file
*lk
)
203 char result_file
[PATH_MAX
];
205 if (lk
->fd
>= 0 && close_lock_file(lk
))
207 strcpy(result_file
, lk
->filename
);
208 i
= strlen(result_file
) - 5; /* .lock */
210 if (rename(lk
->filename
, result_file
))
216 int hold_locked_index(struct lock_file
*lk
, int die_on_error
)
218 return hold_lock_file_for_update(lk
, get_index_file(), die_on_error
);
221 void set_alternate_index_output(const char *name
)
223 alternate_index_output
= name
;
226 int commit_locked_index(struct lock_file
*lk
)
228 if (alternate_index_output
) {
229 if (lk
->fd
>= 0 && close_lock_file(lk
))
231 if (rename(lk
->filename
, alternate_index_output
))
237 return commit_lock_file(lk
);
240 void rollback_lock_file(struct lock_file
*lk
)
242 if (lk
->filename
[0]) {
245 unlink(lk
->filename
);