Have a constant extern refspec for "--tags"
[git/gitweb.git] / lockfile.c
blobe9e0095e9f98f9a05d2f88f5e97766930a99d89d
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)
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);
20 lock_file_list = lock_file_list->next;
24 static void remove_lock_file_on_signal(int signo)
26 remove_lock_file();
27 signal(SIGINT, SIG_DFL);
28 raise(signo);
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');
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--;
52 * then go backwards until I hit a slash, or the beginning of
53 * the string
55 while (r > p && *(r-1) != '/')
56 r--;
57 return r;
61 /* We allow "recursive" symbolic links. Only within reason, though */
62 #define MAXDEPTH 5
65 * p = path that may be a symlink
66 * s = full size of p
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.
76 * Always returns p.
79 static char *resolve_symlink(char *p, size_t s)
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;
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;
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;
106 } else {
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)
113 strcpy(r, link);
114 else {
115 warning("%s: symlink too long", p);
116 return p;
120 return 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);
135 if (0 <= lk->fd) {
136 if (!lock_file_list) {
137 signal(SIGINT, remove_lock_file_on_signal);
138 atexit(remove_lock_file);
140 lk->owner = getpid();
141 if (!lk->on_list) {
142 lk->next = lock_file_list;
143 lock_file_list = lk;
144 lk->on_list = 1;
146 if (adjust_shared_perm(lk->filename))
147 return error("cannot fix permission bits on %s",
148 lk->filename);
150 else
151 lk->filename[0] = 0;
152 return lk->fd;
155 int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on_error)
157 int fd = lock_file(lk, path);
158 if (fd < 0 && die_on_error)
159 die("unable to create '%s.lock': %s", path, strerror(errno));
160 return fd;
163 int hold_lock_file_for_append(struct lock_file *lk, const char *path, int die_on_error)
165 int fd, orig_fd;
167 fd = lock_file(lk, path);
168 if (fd < 0) {
169 if (die_on_error)
170 die("unable to create '%s.lock': %s", path, strerror(errno));
171 return fd;
174 orig_fd = open(path, O_RDONLY);
175 if (orig_fd < 0) {
176 if (errno != ENOENT) {
177 if (die_on_error)
178 die("cannot open '%s' for copying", path);
179 close(fd);
180 return error("cannot open '%s' for copying", path);
182 } else if (copy_fd(orig_fd, fd)) {
183 if (die_on_error)
184 exit(128);
185 close(fd);
186 return -1;
188 return fd;
191 int close_lock_file(struct lock_file *lk)
193 int fd = lk->fd;
194 lk->fd = -1;
195 return close(fd);
198 int commit_lock_file(struct lock_file *lk)
200 char result_file[PATH_MAX];
201 size_t i;
202 if (lk->fd >= 0 && close_lock_file(lk))
203 return -1;
204 strcpy(result_file, lk->filename);
205 i = strlen(result_file) - 5; /* .lock */
206 result_file[i] = 0;
207 if (rename(lk->filename, result_file))
208 return -1;
209 lk->filename[0] = 0;
210 return 0;
213 int hold_locked_index(struct lock_file *lk, int die_on_error)
215 return hold_lock_file_for_update(lk, get_index_file(), die_on_error);
218 void set_alternate_index_output(const char *name)
220 alternate_index_output = name;
223 int commit_locked_index(struct lock_file *lk)
225 if (alternate_index_output) {
226 if (lk->fd >= 0 && close_lock_file(lk))
227 return -1;
228 if (rename(lk->filename, alternate_index_output))
229 return -1;
230 lk->filename[0] = 0;
231 return 0;
233 else
234 return commit_lock_file(lk);
237 void rollback_lock_file(struct lock_file *lk)
239 if (lk->filename[0]) {
240 if (lk->fd >= 0)
241 close(lk->fd);
242 unlink(lk->filename);
244 lk->filename[0] = 0;