resolve_symlink(): take a strbuf parameter
authorMichael Haggerty <mhagger@alum.mit.edu>
Wed, 1 Oct 2014 10:28:34 +0000 (12:28 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 1 Oct 2014 20:51:29 +0000 (13:51 -0700)
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>
lockfile.c
index cc9b9cbaf8c7dee11c31509bfd3a435dd3fa2b2c..5f5bcfffbe25b6145f1683a989399f44880b3d5d 100644 (file)
@@ -109,58 +109,47 @@ static char *last_path_elm(char *p)
 #define MAXDEPTH 5
 
 /*
- * p = path that may be a symlink
- * s = full size of p
+ * path contains a path that might be a symlink.
  *
- * If p is a symlink, attempt to overwrite p with a path to the real
- * file or directory (which may or may not exist), following a chain of
- * symlinks if necessary.  Otherwise, leave p unmodified.
+ * If path is a symlink, attempt to overwrite it with a path to the
+ * real file or directory (which may or may not exist), following a
+ * chain of symlinks if necessary.  Otherwise, leave path unmodified.
  *
- * This is a best-effort routine.  If an error occurs, p will either be
- * left unmodified or will name a different symlink in a symlink chain
- * that started with p's initial contents.
- *
- * Always returns p.
+ * This is a best-effort routine.  If an error occurs, path will
+ * either be left unmodified or will name a different symlink in a
+ * symlink chain that started with the original path.
  */
-
-static char *resolve_symlink(char *p, size_t s)
+static void resolve_symlink(struct strbuf *path)
 {
        int depth = MAXDEPTH;
        static struct strbuf link = STRBUF_INIT;
 
        while (depth--) {
-               if (strbuf_readlink(&link, p, strlen(p)) < 0)
+               if (strbuf_readlink(&link, path->buf, path->len) < 0)
                        break;
 
-               if (is_absolute_path(link.buf)) {
+               if (is_absolute_path(link.buf))
                        /* absolute path simply replaces p */
-                       if (link.len < s)
-                               strcpy(p, link.buf);
-                       else {
-                               warning("%s: symlink too long", p);
-                               break;
-                       }
-               } else {
+                       strbuf_reset(path);
+               else {
                        /*
                         * link is a relative path, so replace the
                         * last element of p with it.
                         */
-                       char *r = (char *)last_path_elm(p);
-                       if (r - p + link.len < s)
-                               strcpy(r, link.buf);
-                       else {
-                               warning("%s: symlink too long", p);
-                               break;
-                       }
+                       char *r = last_path_elm(path->buf);
+                       strbuf_setlen(path, r - path->buf);
                }
+
+               strbuf_addbuf(path, &link);
        }
        strbuf_reset(&link);
-       return p;
 }
 
 /* Make sure errno contains a meaningful value on error */
 static int lock_file(struct lock_file *lk, const char *path, int flags)
 {
+       size_t pathlen = strlen(path);
+
        if (!lock_file_list) {
                /* One-time initialization */
                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)
                lk->fd = -1;
                lk->active = 0;
                lk->owner = 0;
-               strbuf_init(&lk->filename, PATH_MAX);
+               strbuf_init(&lk->filename, pathlen + LOCK_SUFFIX_LEN);
                lk->next = lock_file_list;
                lock_file_list = lk;
                lk->on_list = 1;
@@ -185,11 +174,9 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
                    path);
        }
 
-       strbuf_addstr(&lk->filename, path);
-       if (!(flags & LOCK_NODEREF)) {
-               resolve_symlink(lk->filename.buf, lk->filename.alloc);
-               strbuf_setlen(&lk->filename, strlen(lk->filename.buf));
-       }
+       strbuf_add(&lk->filename, path, pathlen);
+       if (!(flags & LOCK_NODEREF))
+               resolve_symlink(&lk->filename);
        strbuf_addstr(&lk->filename, LOCK_SUFFIX);
        lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666);
        if (lk->fd < 0) {