Changeset View
Changeset View
Standalone View
Standalone View
stand/userboot/userboot/devicename.c
Show All 32 Lines | |||||
#include "bootstrap.h" | #include "bootstrap.h" | ||||
#include "disk.h" | #include "disk.h" | ||||
#include "libuserboot.h" | #include "libuserboot.h" | ||||
#if defined(USERBOOT_ZFS_SUPPORT) | #if defined(USERBOOT_ZFS_SUPPORT) | ||||
#include "libzfs.h" | #include "libzfs.h" | ||||
#endif | #endif | ||||
static int userboot_parsedev(struct disk_devdesc **dev, const char *devspec, | static int userboot_parsedev(struct devdesc **dev, const char *devspec, | ||||
const char **path); | const char **path); | ||||
/* | /* | ||||
* Point (dev) at an allocated device specifier for the device matching the | * Point (dev) at an allocated device specifier for the device matching the | ||||
* path in (devspec). If it contains an explicit device specification, | * path in (devspec). If it contains an explicit device specification, | ||||
* use that. If not, use the default device. | * use that. If not, use the default device. | ||||
*/ | */ | ||||
int | int | ||||
userboot_getdev(void **vdev, const char *devspec, const char **path) | userboot_getdev(void **vdev, const char *devspec, const char **path) | ||||
{ | { | ||||
struct disk_devdesc **dev = (struct disk_devdesc **)vdev; | struct devdesc **dev = (struct devdesc **)vdev; | ||||
int rv; | int rv; | ||||
/* | /* | ||||
* If it looks like this is just a path and no | * If it looks like this is just a path and no | ||||
* device, go with the current device. | * device, go with the current device. | ||||
*/ | */ | ||||
if ((devspec == NULL) || | if ((devspec == NULL) || | ||||
(devspec[0] == '/') || | (devspec[0] == '/') || | ||||
Show All 21 Lines | |||||
* is parsed according to the rules applied to the device type. | * is parsed according to the rules applied to the device type. | ||||
* | * | ||||
* For disk-type devices, the syntax is: | * For disk-type devices, the syntax is: | ||||
* | * | ||||
* disk<unit>[s<slice>][<partition>]: | * disk<unit>[s<slice>][<partition>]: | ||||
* | * | ||||
*/ | */ | ||||
static int | static int | ||||
userboot_parsedev(struct disk_devdesc **dev, const char *devspec, | userboot_parsedev(struct devdesc **dev, const char *devspec, | ||||
const char **path) | const char **path) | ||||
{ | { | ||||
struct disk_devdesc *idev; | struct devdesc *idev; | ||||
struct devsw *dv; | struct devsw *dv; | ||||
int i, unit, err; | int i, unit, err; | ||||
const char *cp; | const char *cp; | ||||
const char *np; | const char *np; | ||||
/* minimum length check */ | /* minimum length check */ | ||||
if (strlen(devspec) < 2) | if (strlen(devspec) < 2) | ||||
return (EINVAL); | return (EINVAL); | ||||
Show All 12 Lines | userboot_parsedev(struct devdesc **dev, const char *devspec, | ||||
err = 0; | err = 0; | ||||
np = (devspec + strlen(dv->dv_name)); | np = (devspec + strlen(dv->dv_name)); | ||||
switch (dv->dv_type) { | switch (dv->dv_type) { | ||||
case DEVT_NONE: /* XXX what to do here? Do we care? */ | case DEVT_NONE: /* XXX what to do here? Do we care? */ | ||||
break; | break; | ||||
case DEVT_DISK: | case DEVT_DISK: | ||||
err = disk_parsedev(idev, np, path); | free(idev); | ||||
err = disk_parsedev(&idev, np, path); | |||||
if (err != 0) | if (err != 0) | ||||
goto fail; | goto fail; | ||||
break; | break; | ||||
case DEVT_CD: | case DEVT_CD: | ||||
case DEVT_NET: | case DEVT_NET: | ||||
unit = 0; | unit = 0; | ||||
if (*np && (*np != ':')) { | if (*np && (*np != ':')) { | ||||
/* get unit number if present */ | /* get unit number if present */ | ||||
unit = strtol(np, (char **)&cp, 0); | unit = strtol(np, (char **)&cp, 0); | ||||
if (cp == np) { | if (cp == np) { | ||||
err = EUNIT; | err = EUNIT; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
} else { | } else { | ||||
cp = np; | cp = np; | ||||
} | } | ||||
if (*cp && (*cp != ':')) { | if (*cp && (*cp != ':')) { | ||||
err = EINVAL; | err = EINVAL; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
idev->dd.d_unit = unit; | idev->d_unit = unit; | ||||
if (path != NULL) | if (path != NULL) | ||||
*path = (*cp == 0) ? cp : cp + 1; | *path = (*cp == 0) ? cp : cp + 1; | ||||
break; | break; | ||||
case DEVT_ZFS: | case DEVT_ZFS: | ||||
#if defined(USERBOOT_ZFS_SUPPORT) | #if defined(USERBOOT_ZFS_SUPPORT) | ||||
/* XXX assumes sizeof disk_devdesc >= sizeof zfs_devdesc */ | |||||
err = zfs_parsedev((struct zfs_devdesc *)idev, np, path); | err = zfs_parsedev((struct zfs_devdesc *)idev, np, path); | ||||
if (err != 0) | if (err != 0) | ||||
goto fail; | goto fail; | ||||
break; | break; | ||||
#else | #else | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
#endif | #endif | ||||
default: | default: | ||||
err = EINVAL; | err = EINVAL; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
idev->dd.d_dev = dv; | idev->d_dev = dv; | ||||
if (dev == NULL) { | if (dev == NULL) { | ||||
free(idev); | free(idev); | ||||
} else { | } else { | ||||
*dev = idev; | *dev = idev; | ||||
} | } | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
free(idev); | free(idev); | ||||
return (err); | return (err); | ||||
} | } | ||||
/* | /* | ||||
* Set currdev to suit the value being supplied in (value) | * Set currdev to suit the value being supplied in (value) | ||||
*/ | */ | ||||
int | int | ||||
userboot_setcurrdev(struct env_var *ev, int flags, const void *value) | userboot_setcurrdev(struct env_var *ev, int flags, const void *value) | ||||
{ | { | ||||
struct disk_devdesc *ncurr; | struct devdesc *ncurr; | ||||
int rv; | int rv; | ||||
if ((rv = userboot_parsedev(&ncurr, value, NULL)) != 0) | if ((rv = userboot_parsedev(&ncurr, value, NULL)) != 0) | ||||
return (rv); | return (rv); | ||||
free(ncurr); | free(ncurr); | ||||
return (mount_currdev(ev, flags, value)); | return (mount_currdev(ev, flags, value)); | ||||
} | } |