|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2011 Willem Dijkstra
|
|
|
+ * Copyright (c) 2012 Willem Dijkstra
|
|
|
* All rights reserved.
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -39,52 +39,18 @@
|
|
|
|
|
|
#include "error.h"
|
|
|
#include "platform.h"
|
|
|
+#include "diskname.h"
|
|
|
|
|
|
-/*
|
|
|
- * checkdisk(spath, dpath, maxlen)
|
|
|
- *
|
|
|
- * Determine that <spath> exists, and return the device name that was referenced
|
|
|
- * (/dev/sdx) when <spath> is a link in <dpath>, observing <dpath>'s <maxlen>.
|
|
|
- */
|
|
|
-static size_t
|
|
|
-checkdisk(const char *spath, char *dpath, size_t maxlen)
|
|
|
+void
|
|
|
+initdisknamectx(struct disknamectx *c, const char *spath, char *dpath, size_t dmaxlen)
|
|
|
{
|
|
|
- char diskname[MAX_PATH_LEN];
|
|
|
- char *r;
|
|
|
- struct stat buffer;
|
|
|
- size_t result;
|
|
|
-
|
|
|
- bzero(diskname, MAX_PATH_LEN);
|
|
|
- bzero(&buffer, sizeof(struct stat));
|
|
|
-
|
|
|
- if (lstat(spath, &buffer)) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* Walk one link, if it is there */
|
|
|
- if (S_ISLNK(buffer.st_mode)) {
|
|
|
- if ((r = realpath(spath, NULL))) {
|
|
|
- strlcpy(diskname, r, sizeof(diskname));
|
|
|
- free(r);
|
|
|
- }
|
|
|
- bzero(&buffer, sizeof(struct stat));
|
|
|
- if (lstat(diskname, &buffer)) {
|
|
|
- fatal("diskbyname: '%.200s' = '%.200s' cannot be examined: %.200s", spath, diskname, strerror(errno));
|
|
|
- }
|
|
|
- } else
|
|
|
- strlcpy(diskname, spath, sizeof(diskname));
|
|
|
+ bzero(c, sizeof(struct disknamectx));
|
|
|
+ c->spath = spath;
|
|
|
+ c->dpath = dpath;
|
|
|
+ c->maxlen = dmaxlen;
|
|
|
|
|
|
- /*
|
|
|
- * No more links from here; also note the lack of further checks on the
|
|
|
- * stat structure. For linux we should now be looking at a block device,
|
|
|
- * for FreeBSD this should be a character device.
|
|
|
- */
|
|
|
- if (!S_ISLNK(buffer.st_mode)) {
|
|
|
- result = strlcpy(dpath, diskname, maxlen);
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
+ if (c->dpath != NULL)
|
|
|
+ bzero(c->dpath, c->maxlen);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -93,32 +59,53 @@ checkdisk(const char *spath, char *dpath, size_t maxlen)
|
|
|
* Resolve a logical disk name <spath> to it's block device name
|
|
|
* <dpath>. <dpath> is preallocated and can hold <maxlen> characters. <spath>
|
|
|
* can refer to a disk via 1) an absolute path or 2) a diskname relative to
|
|
|
- * /dev in various forms defined in platform specific DISK_PATHS.
|
|
|
+ * /dev in various forms.
|
|
|
*/
|
|
|
-size_t
|
|
|
-diskbyname(const char *spath, char *dpath, size_t maxlen)
|
|
|
+char *
|
|
|
+nextdiskname(struct disknamectx *c)
|
|
|
{
|
|
|
- char diskname[MAX_PATH_LEN];
|
|
|
- size_t size;
|
|
|
+ char *r;
|
|
|
+ struct stat buffer;
|
|
|
#ifdef DISK_PATHS
|
|
|
- char *l[] = DISK_PATHS;
|
|
|
+ char *l[] = DISK_PATHS;
|
|
|
#else
|
|
|
char *l[] = { "/dev/%s", NULL };
|
|
|
#endif
|
|
|
- int i;
|
|
|
|
|
|
- if (spath == NULL)
|
|
|
- return 0;
|
|
|
+ if ((c->spath == NULL) || (c->dpath == NULL) || (l[c->i] == NULL))
|
|
|
+ return NULL;
|
|
|
|
|
|
- if (strchr(spath, '/') == spath)
|
|
|
- return checkdisk(spath, dpath, maxlen);
|
|
|
+ bzero(c->dpath, c->maxlen);
|
|
|
|
|
|
- for (i = 0; l[i] != NULL; i++) {
|
|
|
- bzero(diskname, sizeof(diskname));
|
|
|
- snprintf(diskname, sizeof(diskname), l[i], spath);
|
|
|
- if ((size = checkdisk(diskname, dpath, maxlen)))
|
|
|
- return size;
|
|
|
+ /* do not play with absolute paths, just return it once */
|
|
|
+ if (c->spath[0] == '/') {
|
|
|
+ if (c->i == 0) {
|
|
|
+ strlcpy(c->dpath, c->spath, c->maxlen);
|
|
|
+ c->i++;
|
|
|
+ return c->dpath;
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ /* prepare the next pathname */
|
|
|
+ snprintf(c->dpath, c->maxlen, l[c->i], c->spath);
|
|
|
+
|
|
|
+ if ((c->link == 0) &&
|
|
|
+ (lstat(c->dpath, &buffer) == 0)) {
|
|
|
+ /* return the real path of a link, but only dereference once */
|
|
|
+ if (S_ISLNK(buffer.st_mode)) {
|
|
|
+ if ((r = realpath(c->dpath, NULL))) {
|
|
|
+ strlcpy(c->dpath, r, c->maxlen);
|
|
|
+ free(r);
|
|
|
+ c->link = 1;
|
|
|
+
|
|
|
+ return c->dpath;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ c->link = 0;
|
|
|
+ c->i++;
|
|
|
+
|
|
|
+ return c->dpath;
|
|
|
}
|