2 * Copyright (c) 2005, Junio C Hamano
7 static struct lock_file *lock_file_list;
8 static const char *alternate_index_output;
10 static void remove_lock_file(void)
14 while (lock_file_list) {
15 if (lock_file_list->owner == me &&
16 lock_file_list->filename[0]) {
17 if (lock_file_list->fd >= 0)
18 close(lock_file_list->fd);
19 unlink(lock_file_list->filename);
21 lock_file_list = lock_file_list->next;
25 static void remove_lock_file_on_signal(int signo)
33 * p = absolute or relative path name
35 * Return a pointer into p showing the beginning of the last path name
36 * element. If p is empty or the root directory ("/"), just return p.
38 static char *last_path_elm(char *p)
40 /* r starts pointing to null at the end of the string */
41 char *r = strchr(p, '\0');
44 return p; /* just return empty string */
46 r--; /* back up to last non-null character */
48 /* back up past trailing slashes, if any */
49 while (r > p && *r == '/')
53 * then go backwards until I hit a slash, or the beginning of
56 while (r > p && *(r-1) != '/')
62 /* We allow "recursive" symbolic links. Only within reason, though */
66 * p = path that may be a symlink
69 * If p is a symlink, attempt to overwrite p with a path to the real
70 * file or directory (which may or may not exist), following a chain of
71 * symlinks if necessary. Otherwise, leave p unmodified.
73 * This is a best-effort routine. If an error occurs, p will either be
74 * left unmodified or will name a different symlink in a symlink chain
75 * that started with p's initial contents.
80 static char *resolve_symlink(char *p, size_t s)
86 int link_len = readlink(p, link, sizeof(link));
88 /* not a symlink anymore */
91 else if (link_len < sizeof(link))
92 /* readlink() never null-terminates */
93 link[link_len] = '\0';
95 warning("%s: symlink too long", p);
99 if (is_absolute_path(link)) {
100 /* absolute path simply replaces p */
104 warning("%s: symlink too long", p);
109 * link is a relative path, so I must replace the
110 * last element of p with it.
112 char *r = (char*)last_path_elm(p);
113 if (r - p + link_len < s)
116 warning("%s: symlink too long", p);
125 static int lock_file(struct lock_file *lk, const char *path, int flags)
127 if (strlen(path) >= sizeof(lk->filename))
129 strcpy(lk->filename, path);
131 * subtract 5 from size to make sure there's room for adding
132 * ".lock" for the lock file name
134 if (!(flags & LOCK_NODEREF))
135 resolve_symlink(lk->filename, sizeof(lk->filename)-5);
136 strcat(lk->filename, ".lock");
137 lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
139 if (!lock_file_list) {
140 sigchain_push_common(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 flags)
160 int fd = lock_file(lk, path, flags);
161 if (fd < 0 && (flags & LOCK_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 flags)
170 fd = lock_file(lk, path, flags);
172 if (flags & LOCK_DIE_ON_ERROR)
173 die("unable to create '%s.lock': %s", path, strerror(errno));
177 orig_fd = open(path, O_RDONLY);
179 if (errno != ENOENT) {
180 if (flags & LOCK_DIE_ON_ERROR)
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)) {
186 if (flags & LOCK_DIE_ON_ERROR)
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(),
224 void set_alternate_index_output(const char *name)
226 alternate_index_output = name;
229 int commit_locked_index(struct lock_file *lk)
231 if (alternate_index_output) {
232 if (lk->fd >= 0 && close_lock_file(lk))
234 if (rename(lk->filename, alternate_index_output))
240 return commit_lock_file(lk);
243 void rollback_lock_file(struct lock_file *lk)
245 if (lk->filename[0]) {
248 unlink(lk->filename);