1/*
2* Copyright (c) 2005, Junio C Hamano
3*/
4#include "cache.h"
56
static struct lock_file *lock_file_list;
7static const char *alternate_index_output;
89
static void remove_lock_file(void)
10{
11pid_t me = getpid();
1213
while (lock_file_list) {
14if (lock_file_list->owner == me &&
15lock_file_list->filename[0])
16unlink(lock_file_list->filename);
17lock_file_list = lock_file_list->next;
18}
19}
2021
static void remove_lock_file_on_signal(int signo)
22{
23remove_lock_file();
24signal(SIGINT, SIG_DFL);
25raise(signo);
26}
2728
/*
29* p = absolute or relative path name
30*
31* Return a pointer into p showing the beginning of the last path name
32* element. If p is empty or the root directory ("/"), just return p.
33*/
34static char *last_path_elm(char *p)
35{
36/* r starts pointing to null at the end of the string */
37char *r = strchr(p, '\0');
3839
if (r == p)
40return p; /* just return empty string */
4142
r--; /* back up to last non-null character */
4344
/* back up past trailing slashes, if any */
45while (r > p && *r == '/')
46r--;
4748
/*
49* then go backwards until I hit a slash, or the beginning of
50* the string
51*/
52while (r > p && *(r-1) != '/')
53r--;
54return r;
55}
5657
58
/* We allow "recursive" symbolic links. Only within reason, though */
59#define MAXDEPTH 5
6061
/*
62* p = path that may be a symlink
63* s = full size of p
64*
65* If p is a symlink, attempt to overwrite p with a path to the real
66* file or directory (which may or may not exist), following a chain of
67* symlinks if necessary. Otherwise, leave p unmodified.
68*
69* This is a best-effort routine. If an error occurs, p will either be
70* left unmodified or will name a different symlink in a symlink chain
71* that started with p's initial contents.
72*
73* Always returns p.
74*/
7576
static char *resolve_symlink(char *p, size_t s)
77{
78int depth = MAXDEPTH;
7980
while (depth--) {
81char link[PATH_MAX];
82int link_len = readlink(p, link, sizeof(link));
83if (link_len < 0) {
84/* not a symlink anymore */
85return p;
86}
87else if (link_len < sizeof(link))
88/* readlink() never null-terminates */
89link[link_len] = '\0';
90else {
91warning("%s: symlink too long", p);
92return p;
93}
9495
if (link[0] == '/') {
96/* absolute path simply replaces p */
97if (link_len < s)
98strcpy(p, link);
99else {
100warning("%s: symlink too long", p);
101return p;
102}
103} else {
104/*
105* link is a relative path, so I must replace the
106* last element of p with it.
107*/
108char *r = (char*)last_path_elm(p);
109if (r - p + link_len < s)
110strcpy(r, link);
111else {
112warning("%s: symlink too long", p);
113return p;
114}
115}
116}
117return p;
118}
119120
121
static int lock_file(struct lock_file *lk, const char *path)
122{
123int fd;
124125
if (strlen(path) >= sizeof(lk->filename)) return -1;
126strcpy(lk->filename, path);
127/*
128* subtract 5 from size to make sure there's room for adding
129* ".lock" for the lock file name
130*/
131resolve_symlink(lk->filename, sizeof(lk->filename)-5);
132strcat(lk->filename, ".lock");
133fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
134if (0 <= fd) {
135if (!lock_file_list) {
136signal(SIGINT, remove_lock_file_on_signal);
137atexit(remove_lock_file);
138}
139lk->owner = getpid();
140if (!lk->on_list) {
141lk->next = lock_file_list;
142lock_file_list = lk;
143lk->on_list = 1;
144}
145if (adjust_shared_perm(lk->filename))
146return error("cannot fix permission bits on %s",
147lk->filename);
148}
149else
150lk->filename[0] = 0;
151return fd;
152}
153154
int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on_error)
155{
156int fd = lock_file(lk, path);
157if (fd < 0 && die_on_error)
158die("unable to create '%s.lock': %s", path, strerror(errno));
159return fd;
160}
161162
int commit_lock_file(struct lock_file *lk)
163{
164char result_file[PATH_MAX];
165int i;
166strcpy(result_file, lk->filename);
167i = strlen(result_file) - 5; /* .lock */
168result_file[i] = 0;
169i = rename(lk->filename, result_file);
170lk->filename[0] = 0;
171return i;
172}
173174
int hold_locked_index(struct lock_file *lk, int die_on_error)
175{
176return hold_lock_file_for_update(lk, get_index_file(), die_on_error);
177}
178179
void set_alternate_index_output(const char *name)
180{
181alternate_index_output = name;
182}
183184
int commit_locked_index(struct lock_file *lk)
185{
186if (alternate_index_output) {
187int result = rename(lk->filename, alternate_index_output);
188lk->filename[0] = 0;
189return result;
190}
191else
192return commit_lock_file(lk);
193}
194195
void rollback_lock_file(struct lock_file *lk)
196{
197if (lk->filename[0])
198unlink(lk->filename);
199lk->filename[0] = 0;
200}