summaryrefslogtreecommitdiff
path: root/lib/libutil
diff options
context:
space:
mode:
authormlelstv <mlelstv@NetBSD.org>2014-09-12 07:59:36 +0000
committermlelstv <mlelstv@NetBSD.org>2014-09-12 07:59:36 +0000
commit7ea191e42eb36928d5f6d702fefdaf5a97643ce3 (patch)
tree90c16bb4c25c8c5fabc86e08b20103fcb1b662a7 /lib/libutil
parenta743bc13d6ba077a292bfd809b539e3dd523d71e (diff)
- 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 (limited to 'lib/libutil')
-rw-r--r--lib/libutil/getdiskrawname.c74
1 files changed, 51 insertions, 23 deletions
diff --git a/lib/libutil/getdiskrawname.c b/lib/libutil/getdiskrawname.c
index ed1c21a40dc..d3089d52aa2 100644
--- a/lib/libutil/getdiskrawname.c
+++ b/lib/libutil/getdiskrawname.c
@@ -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 @@ __RCSID("$NetBSD: getdiskrawname.c,v 1.2 2013/12/22 14:31:51 mlelstv Exp $");
#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 @@ getdiskrawname(char *buf, size_t bufsiz, const char *name)
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 @@ getdiskcookedname(char *buf, size_t bufsiz, const char *name)
{
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 @@ getdiskcookedname(char *buf, size_t bufsiz, const char *name)
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;
}