Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libutil - use a private buffer to resolve symlinks, the ...



details:   https://anonhg.NetBSD.org/src/rev/4b24b0aa9f68
branches:  trunk
changeset: 332220:4b24b0aa9f68
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Fri Sep 12 07:59:36 2014 +0000

description:
- use a private buffer to resolve symlinks, the previous code was broken
- factored out symlink handling
- handle relative symlinks now
- handle device paths that do not contain a '/'.

diffstat:

 lib/libutil/getdiskrawname.c |  74 ++++++++++++++++++++++++++++++-------------
 1 files changed, 51 insertions(+), 23 deletions(-)

diffs (132 lines):

diff -r d660df601c28 -r 4b24b0aa9f68 lib/libutil/getdiskrawname.c
--- a/lib/libutil/getdiskrawname.c      Fri Sep 12 04:10:24 2014 +0000
+++ b/lib/libutil/getdiskrawname.c      Fri Sep 12 07:59:36 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: getdiskrawname.c,v 1.2 2013/12/22 14:31:51 mlelstv Exp $       */
+/*     $NetBSD: getdiskrawname.c,v 1.3 2014/09/12 07:59:36 mlelstv Exp $       */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: getdiskrawname.c,v 1.2 2013/12/22 14:31:51 mlelstv Exp $");
+__RCSID("$NetBSD: getdiskrawname.c,v 1.3 2014/09/12 07:59:36 mlelstv Exp $");
 
 #include <sys/stat.h>
 
@@ -37,25 +37,51 @@
 #include <string.h>
 #include <errno.h>
 #include <util.h>
+#include <limits.h>
 #include <unistd.h>
 
+static const char *
+resolve_link(char *buf, size_t bufsiz, const char *name)
+{
+       const char *dp;
+       ssize_t nlen, dlen;
+
+       dlen = readlink(name, buf, bufsiz-1);
+       if (dlen == -1)
+               return name;
+
+       buf[dlen] = '\0';
+
+       if (buf[0] != '/') {
+               dp = strrchr(name, '/');
+               if (dp != NULL) {
+                       nlen = dp - name + 1;
+                       if (nlen + 1 > PATH_MAX)
+                               return NULL;
+                       if (nlen + dlen + 1 > PATH_MAX)
+                               return NULL;
+
+                       memmove(buf+nlen, buf, dlen+1);
+                       memcpy(buf, name, nlen);
+               }
+       }
+
+       return buf;
+}
+
 const char *
 getdiskrawname(char *buf, size_t bufsiz, const char *name)
 {
-       const char *dp = strrchr(name, '/');
+       const char *dp;
        struct stat st;
-       ssize_t len;
+       char dest[PATH_MAX];
 
-       if (dp == NULL) {
+       if ((name = resolve_link(dest, sizeof(dest), name)) == NULL) {
                errno = EINVAL;
                return NULL;
        }
 
-       len = readlink(name, buf, bufsiz-1);
-       if (len > 0) {
-               buf[len] = '\0';
-               name = buf;
-       }
+       dp = strrchr(name, '/');
 
        if (stat(name, &st) == -1)
                return NULL;
@@ -65,7 +91,10 @@
                return NULL;
        }
 
-       (void)snprintf(buf, bufsiz, "%.*s/r%s", (int)(dp - name), name, dp + 1);
+       if (dp != NULL)
+               (void)snprintf(buf, bufsiz, "%.*s/r%s", (int)(dp - name), name, dp + 1);
+       else
+               (void)snprintf(buf, bufsiz, "r%s", name);
 
        return buf;
 }
@@ -75,17 +104,18 @@
 {
        const char *dp;
        struct stat st;
-       ssize_t len;
+       char dest[PATH_MAX];
 
-       if ((dp = strrchr(name, '/')) == NULL) {
+       if ((name = resolve_link(dest, sizeof(dest), name)) == NULL) {
                errno = EINVAL;
                return NULL;
        }
 
-       len = readlink(name, buf, bufsiz-1);
-       if (len > 0) {
-               buf[len] = '\0';
-               name = buf;
+       dp = strrchr(name, '/');
+
+       if ((dp != NULL && dp[1] != 'r') || (dp == NULL && name[0] != 'r')) {
+               errno = EINVAL;
+               return NULL;
        }
 
        if (stat(name, &st) == -1)
@@ -96,12 +126,10 @@
                return NULL;
        }
 
-       if (dp[1] != 'r') {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       (void)snprintf(buf, bufsiz, "%.*s/%s", (int)(dp - name), name, dp + 2);
+       if (dp != NULL)
+               (void)snprintf(buf, bufsiz, "%.*s/%s", (int)(dp - name), name, dp + 2);
+       else
+               (void)snprintf(buf, bufsiz, "%s", name + 1);
 
        return buf;
 }



Home | Main Index | Thread Index | Old Index