Code

git config: don't allow multiple variable types
[git.git] / lockfile.c
1 /*
2  * Copyright (c) 2005, Junio C Hamano
3  */
4 #include "cache.h"
5 #include "sigchain.h"
7 static struct lock_file *lock_file_list;
8 static const char *alternate_index_output;
10 static void remove_lock_file(void)
11 {
12         pid_t me = getpid();
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);
20                 }
21                 lock_file_list = lock_file_list->next;
22         }
23 }
25 static void remove_lock_file_on_signal(int signo)
26 {
27         remove_lock_file();
28         sigchain_pop(signo);
29         raise(signo);
30 }
32 /*
33  * p = absolute or relative path name
34  *
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.
37  */
38 static char *last_path_elm(char *p)
39 {
40         /* r starts pointing to null at the end of the string */
41         char *r = strchr(p, '\0');
43         if (r == p)
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 == '/')
50                 r--;
52         /*
53          * then go backwards until I hit a slash, or the beginning of
54          * the string
55          */
56         while (r > p && *(r-1) != '/')
57                 r--;
58         return r;
59 }
62 /* We allow "recursive" symbolic links. Only within reason, though */
63 #define MAXDEPTH 5
65 /*
66  * p = path that may be a symlink
67  * s = full size of p
68  *
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.
72  *
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.
76  *
77  * Always returns p.
78  */
80 static char *resolve_symlink(char *p, size_t s)
81 {
82         int depth = MAXDEPTH;
84         while (depth--) {
85                 char link[PATH_MAX];
86                 int link_len = readlink(p, link, sizeof(link));
87                 if (link_len < 0) {
88                         /* not a symlink anymore */
89                         return p;
90                 }
91                 else if (link_len < sizeof(link))
92                         /* readlink() never null-terminates */
93                         link[link_len] = '\0';
94                 else {
95                         warning("%s: symlink too long", p);
96                         return p;
97                 }
99                 if (is_absolute_path(link)) {
100                         /* absolute path simply replaces p */
101                         if (link_len < s)
102                                 strcpy(p, link);
103                         else {
104                                 warning("%s: symlink too long", p);
105                                 return p;
106                         }
107                 } else {
108                         /*
109                          * link is a relative path, so I must replace the
110                          * last element of p with it.
111                          */
112                         char *r = (char*)last_path_elm(p);
113                         if (r - p + link_len < s)
114                                 strcpy(r, link);
115                         else {
116                                 warning("%s: symlink too long", p);
117                                 return p;
118                         }
119                 }
120         }
121         return p;
125 static int lock_file(struct lock_file *lk, const char *path, int flags)
127         if (strlen(path) >= sizeof(lk->filename))
128                 return -1;
129         strcpy(lk->filename, path);
130         /*
131          * subtract 5 from size to make sure there's room for adding
132          * ".lock" for the lock file name
133          */
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);
138         if (0 <= lk->fd) {
139                 if (!lock_file_list) {
140                         sigchain_push_common(remove_lock_file_on_signal);
141                         atexit(remove_lock_file);
142                 }
143                 lk->owner = getpid();
144                 if (!lk->on_list) {
145                         lk->next = lock_file_list;
146                         lock_file_list = lk;
147                         lk->on_list = 1;
148                 }
149                 if (adjust_shared_perm(lk->filename))
150                         return error("cannot fix permission bits on %s",
151                                      lk->filename);
152         }
153         else
154                 lk->filename[0] = 0;
155         return lk->fd;
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));
163         return fd;
166 int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
168         int fd, orig_fd;
170         fd = lock_file(lk, path, flags);
171         if (fd < 0) {
172                 if (flags & LOCK_DIE_ON_ERROR)
173                         die("unable to create '%s.lock': %s", path, strerror(errno));
174                 return fd;
175         }
177         orig_fd = open(path, O_RDONLY);
178         if (orig_fd < 0) {
179                 if (errno != ENOENT) {
180                         if (flags & LOCK_DIE_ON_ERROR)
181                                 die("cannot open '%s' for copying", path);
182                         close(fd);
183                         return error("cannot open '%s' for copying", path);
184                 }
185         } else if (copy_fd(orig_fd, fd)) {
186                 if (flags & LOCK_DIE_ON_ERROR)
187                         exit(128);
188                 close(fd);
189                 return -1;
190         }
191         return fd;
194 int close_lock_file(struct lock_file *lk)
196         int fd = lk->fd;
197         lk->fd = -1;
198         return close(fd);
201 int commit_lock_file(struct lock_file *lk)
203         char result_file[PATH_MAX];
204         size_t i;
205         if (lk->fd >= 0 && close_lock_file(lk))
206                 return -1;
207         strcpy(result_file, lk->filename);
208         i = strlen(result_file) - 5; /* .lock */
209         result_file[i] = 0;
210         if (rename(lk->filename, result_file))
211                 return -1;
212         lk->filename[0] = 0;
213         return 0;
216 int hold_locked_index(struct lock_file *lk, int die_on_error)
218         return hold_lock_file_for_update(lk, get_index_file(),
219                                          die_on_error
220                                          ? LOCK_DIE_ON_ERROR
221                                          : 0);
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))
233                         return -1;
234                 if (rename(lk->filename, alternate_index_output))
235                         return -1;
236                 lk->filename[0] = 0;
237                 return 0;
238         }
239         else
240                 return commit_lock_file(lk);
243 void rollback_lock_file(struct lock_file *lk)
245         if (lk->filename[0]) {
246                 if (lk->fd >= 0)
247                         close(lk->fd);
248                 unlink(lk->filename);
249         }
250         lk->filename[0] = 0;