resolve_symlink(): take a strbuf parameter
Change resolve_symlink() to take a strbuf rather than a string as parameter. This simplifies the code and removes an arbitrary pathname length restriction. It also means that lock_file's filename field no longer needs to be initialized to a large size. Helped-by: Torsten Bögershausen <tboegi@web.de> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Haggerty committed
Oct 1, 2014 at 12:28 UTC
6cad805332e3c3a60993f062afd8d896920689ab
1 file changed
+22
-35
lockfile.c
+22
-35
@@ -109,58 +109,47 @@ static char *last_path_elm(char *p)
109
#define MAXDEPTH 5
110
111
/*
112
- * p = path that may be a symlink
113
- * s = full size of p
112
+ * path contains a path that might be a symlink.
113
*
115
- * If p is a symlink, attempt to overwrite p with a path to the real
116
- * file or directory (which may or may not exist), following a chain of
117
- * symlinks if necessary. Otherwise, leave p unmodified.
114
+ * If path is a symlink, attempt to overwrite it with a path to the
115
+ * real file or directory (which may or may not exist), following a
116
+ * chain of symlinks if necessary. Otherwise, leave path unmodified.
117
*
119
- * This is a best-effort routine. If an error occurs, p will either be
120
- * left unmodified or will name a different symlink in a symlink chain
121
- * that started with p's initial contents.
122
- *
123
- * Always returns p.
118
+ * This is a best-effort routine. If an error occurs, path will
119
+ * either be left unmodified or will name a different symlink in a
120
+ * symlink chain that started with the original path.
121
*/
125
-
126
-static char *resolve_symlink(char *p, size_t s)
122
+static void resolve_symlink(struct strbuf *path)
123
{
124
int depth = MAXDEPTH;
125
static struct strbuf link = STRBUF_INIT;
126
127
while (depth--) {
132
- if (strbuf_readlink(&link, p, strlen(p)) < 0)
128
+ if (strbuf_readlink(&link, path->buf, path->len) < 0)
129
break;
130
135
- if (is_absolute_path(link.buf)) {
131
+ if (is_absolute_path(link.buf))
132
/* absolute path simply replaces p */
137
- if (link.len < s)
138
- strcpy(p, link.buf);
139
- else {
140
- warning("%s: symlink too long", p);
141
- break;
142
- }
143
- } else {
133
+ strbuf_reset(path);
134
+ else {
135
/*
136
* link is a relative path, so replace the
137
* last element of p with it.
138
*/
148
- char *r = (char *)last_path_elm(p);
149
- if (r - p + link.len < s)
150
- strcpy(r, link.buf);
151
- else {
152
- warning("%s: symlink too long", p);
153
- break;
154
- }
139
+ char *r = last_path_elm(path->buf);
140
+ strbuf_setlen(path, r - path->buf);
141
}
142
+
143
+ strbuf_addbuf(path, &link);
144
}
145
strbuf_reset(&link);
158
- return p;
146
}
147
148
/* Make sure errno contains a meaningful value on error */
149
static int lock_file(struct lock_file *lk, const char *path, int flags)
150
{
151
+ size_t pathlen = strlen(path);
152
+
153
if (!lock_file_list) {
154
/* One-time initialization */
155
sigchain_push_common(remove_lock_file_on_signal);
@@ -175,7 +164,7 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
164
lk->fd = -1;
165
lk->active = 0;
166
lk->owner = 0;
178
- strbuf_init(&lk->filename, PATH_MAX);
167
+ strbuf_init(&lk->filename, pathlen + LOCK_SUFFIX_LEN);
168
lk->next = lock_file_list;
169
lock_file_list = lk;
170
lk->on_list = 1;
@@ -185,11 +174,9 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
174
path);
175
}
176
188
- strbuf_addstr(&lk->filename, path);
189
- if (!(flags & LOCK_NODEREF)) {
190
- resolve_symlink(lk->filename.buf, lk->filename.alloc);
191
- strbuf_setlen(&lk->filename, strlen(lk->filename.buf));
192
- }
177
+ strbuf_add(&lk->filename, path, pathlen);
178
+ if (!(flags & LOCK_NODEREF))
179
+ resolve_symlink(&lk->filename);
180
strbuf_addstr(&lk->filename, LOCK_SUFFIX);
181
lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666);
182
if (lk->fd < 0) {