Code

Merge branch 'maint'
[git.git] / lockfile.c
1 /*
2  * Copyright (c) 2005, Junio C Hamano
3  */
4 #include "cache.h"
6 static struct lock_file *lock_file_list;
7 static const char *alternate_index_output;
9 static void remove_lock_file(void)
10 {
11         pid_t me = getpid();
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);
19                 }
20                 lock_file_list = lock_file_list->next;
21         }
22 }
24 static void remove_lock_file_on_signal(int signo)
25 {
26         remove_lock_file();
27         signal(signo, SIG_DFL);
28         raise(signo);
29 }
31 /*
32  * p = absolute or relative path name
33  *
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.
36  */
37 static char *last_path_elm(char *p)
38 {
39         /* r starts pointing to null at the end of the string */
40         char *r = strchr(p, '\0');
42         if (r == p)
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 == '/')
49                 r--;
51         /*
52          * then go backwards until I hit a slash, or the beginning of
53          * the string
54          */
55         while (r > p && *(r-1) != '/')
56                 r--;
57         return r;
58 }
61 /* We allow "recursive" symbolic links. Only within reason, though */
62 #define MAXDEPTH 5
64 /*
65  * p = path that may be a symlink
66  * s = full size of p
67  *
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.
71  *
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.
75  *
76  * Always returns p.
77  */
79 static char *resolve_symlink(char *p, size_t s)
80 {
81         int depth = MAXDEPTH;
83         while (depth--) {
84                 char link[PATH_MAX];
85                 int link_len = readlink(p, link, sizeof(link));
86                 if (link_len < 0) {
87                         /* not a symlink anymore */
88                         return p;
89                 }
90                 else if (link_len < sizeof(link))
91                         /* readlink() never null-terminates */
92                         link[link_len] = '\0';
93                 else {
94                         warning("%s: symlink too long", p);
95                         return p;
96                 }
98                 if (is_absolute_path(link)) {
99                         /* absolute path simply replaces p */
100                         if (link_len < s)
101                                 strcpy(p, link);
102                         else {
103                                 warning("%s: symlink too long", p);
104                                 return p;
105                         }
106                 } else {
107                         /*
108                          * link is a relative path, so I must replace the
109                          * last element of p with it.
110                          */
111                         char *r = (char*)last_path_elm(p);
112                         if (r - p + link_len < s)
113                                 strcpy(r, link);
114                         else {
115                                 warning("%s: symlink too long", p);
116                                 return p;
117                         }
118                 }
119         }
120         return p;
124 static int lock_file(struct lock_file *lk, const char *path, int flags)
126         if (strlen(path) >= sizeof(lk->filename))
127                 return -1;
128         strcpy(lk->filename, path);
129         /*
130          * subtract 5 from size to make sure there's room for adding
131          * ".lock" for the lock file name
132          */
133         if (!(flags & LOCK_NODEREF))
134                 resolve_symlink(lk->filename, sizeof(lk->filename)-5);
135         strcat(lk->filename, ".lock");
136         lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
137         if (0 <= lk->fd) {
138                 if (!lock_file_list) {
139                         signal(SIGINT, remove_lock_file_on_signal);
140                         signal(SIGHUP, remove_lock_file_on_signal);
141                         signal(SIGTERM, remove_lock_file_on_signal);
142                         signal(SIGQUIT, remove_lock_file_on_signal);
143                         signal(SIGPIPE, remove_lock_file_on_signal);
144                         atexit(remove_lock_file);
145                 }
146                 lk->owner = getpid();
147                 if (!lk->on_list) {
148                         lk->next = lock_file_list;
149                         lock_file_list = lk;
150                         lk->on_list = 1;
151                 }
152                 if (adjust_shared_perm(lk->filename))
153                         return error("cannot fix permission bits on %s",
154                                      lk->filename);
155         }
156         else
157                 lk->filename[0] = 0;
158         return lk->fd;
161 int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
163         int fd = lock_file(lk, path, flags);
164         if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
165                 die("unable to create '%s.lock': %s", path, strerror(errno));
166         return fd;
169 int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
171         int fd, orig_fd;
173         fd = lock_file(lk, path, flags);
174         if (fd < 0) {
175                 if (flags & LOCK_DIE_ON_ERROR)
176                         die("unable to create '%s.lock': %s", path, strerror(errno));
177                 return fd;
178         }
180         orig_fd = open(path, O_RDONLY);
181         if (orig_fd < 0) {
182                 if (errno != ENOENT) {
183                         if (flags & LOCK_DIE_ON_ERROR)
184                                 die("cannot open '%s' for copying", path);
185                         close(fd);
186                         return error("cannot open '%s' for copying", path);
187                 }
188         } else if (copy_fd(orig_fd, fd)) {
189                 if (flags & LOCK_DIE_ON_ERROR)
190                         exit(128);
191                 close(fd);
192                 return -1;
193         }
194         return fd;
197 int close_lock_file(struct lock_file *lk)
199         int fd = lk->fd;
200         lk->fd = -1;
201         return close(fd);
204 int commit_lock_file(struct lock_file *lk)
206         char result_file[PATH_MAX];
207         size_t i;
208         if (lk->fd >= 0 && close_lock_file(lk))
209                 return -1;
210         strcpy(result_file, lk->filename);
211         i = strlen(result_file) - 5; /* .lock */
212         result_file[i] = 0;
213         if (rename(lk->filename, result_file))
214                 return -1;
215         lk->filename[0] = 0;
216         return 0;
219 int hold_locked_index(struct lock_file *lk, int die_on_error)
221         return hold_lock_file_for_update(lk, get_index_file(),
222                                          die_on_error
223                                          ? LOCK_DIE_ON_ERROR
224                                          : 0);
227 void set_alternate_index_output(const char *name)
229         alternate_index_output = name;
232 int commit_locked_index(struct lock_file *lk)
234         if (alternate_index_output) {
235                 if (lk->fd >= 0 && close_lock_file(lk))
236                         return -1;
237                 if (rename(lk->filename, alternate_index_output))
238                         return -1;
239                 lk->filename[0] = 0;
240                 return 0;
241         }
242         else
243                 return commit_lock_file(lk);
246 void rollback_lock_file(struct lock_file *lk)
248         if (lk->filename[0]) {
249                 if (lk->fd >= 0)
250                         close(lk->fd);
251                 unlink(lk->filename);
252         }
253         lk->filename[0] = 0;