FreeBSD/cddl/contrib/opensolaris/cmd/zpool/zpool_vdev.c
/*
 * Create a leaf vdev.  Determine if this is a file or a device.  If it's a
 * device, fill in the device id to make a complete nvlist.  Valid forms for a
 * leaf vdev are:
 *
 * 	/dev/dsk/xxx	Complete disk path
 * 	/xxx		Full path to file
 * 	xxx		Shorthand for /dev/dsk/xxx
 */
Create a leaf vdev.  Determine if this is a file or a device.  If it's a
device, fill in the device id to make a complete nvlist.  Valid forms for a
leaf vdev are.


Create a leaf vdev . Determine if this is a file or a device . If it ' s a device fill in the device id to make a complete nvlist . Valid forms for a leaf vdev are .
static nvlist_t *
make_leaf_vdev(const char *arg, uint64_t is_log)
{
	char path[MAXPATHLEN];
	struct stat64 statbuf;
	nvlist_t *vdev = NULL;
	char *type = NULL;
	boolean_t wholedisk = B_FALSE;
	if (arg[0] == '/') {
		wholedisk = is_whole_disk(arg);
		if (!wholedisk && (stat64(arg, &statbuf) != 0)) {
			(void) fprintf(stderr,
			    gettext("cannot open '%s': %s\n"),
			    arg, strerror(errno));
			return (NULL);
		}
		(void) strlcpy(path, arg, sizeof (path));
	} else {
		if (strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
			strlcpy(path, arg, sizeof (path));
		else
			snprintf(path, sizeof (path), "%s%s", _PATH_DEV, arg);
		wholedisk = is_whole_disk(path);
		if (!wholedisk && (stat64(path, &statbuf) != 0)) {
			if (errno == ENOENT) {
				(void) fprintf(stderr,
				    gettext("cannot open '%s': no such "
				    "GEOM provider\n"), arg);
				(void) fprintf(stderr,
				    gettext("must be a full path or "
				    "shorthand device name\n"));
				return (NULL);
			} else {
				(void) fprintf(stderr,
				    gettext("cannot open '%s': %s\n"),
				    path, strerror(errno));
				return (NULL);
			}
		}
	}
#ifdef __FreeBSD__
	if (S_ISCHR(statbuf.st_mode)) {
		statbuf.st_mode &= ~S_IFCHR;
		statbuf.st_mode |= S_IFBLK;
		wholedisk = B_FALSE;
	}
#endif
	if (wholedisk || S_ISBLK(statbuf.st_mode)) {
		type = VDEV_TYPE_DISK;
	} else if (S_ISREG(statbuf.st_mode)) {
		type = VDEV_TYPE_FILE;
	} else {
		(void) fprintf(stderr, gettext("cannot use '%s': must be a "
		    "GEOM provider or regular file\n"), path);
		return (NULL);
	}
	verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
	verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
	verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
	verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
	if (strcmp(type, VDEV_TYPE_DISK) == 0)
		verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
		    (uint64_t)wholedisk) == 0);
#ifdef have_devid
	if (S_ISBLK(statbuf.st_mode) && !wholedisk) {
		int fd;
		ddi_devid_t devid;
		char *minor = NULL, *devid_str = NULL;
		if ((fd = open(path, O_RDONLY)) < 0) {
			(void) fprintf(stderr, gettext("cannot open '%s': "
			    "%s\n"), path, strerror(errno));
			nvlist_free(vdev);
			return (NULL);
		}
		if (devid_get(fd, &devid) == 0) {
			if (devid_get_minor_name(fd, &minor) == 0 &&
			    (devid_str = devid_str_encode(devid, minor)) !=
			    NULL) {
				verify(nvlist_add_string(vdev,
				    ZPOOL_CONFIG_DEVID, devid_str) == 0);
			}
			if (devid_str != NULL)
				devid_str_free(devid_str);
			if (minor != NULL)
				devid_str_free(minor);
			devid_free(devid);
		}
		(void) close(fd);
	}
#endif
	return (vdev);
}
static nvlist_t * make_leaf_vdev ( const char * arg , uint64_t is_log ) { char path [ MAXPATHLEN ] ; struct stat64 statbuf ; nvlist_t * vdev = NULL ; char * type = NULL ; boolean_t wholedisk = B_FALSE ; if ( arg [ 0 ] == ' ' ) { wholedisk = is_whole_disk ( arg ) ; if ( ! wholedisk && ( stat64 ( arg , & statbuf ) != 0 ) ) { ( void ) fprintf ( stderr , gettext ( " \n " ) , arg , strerror ( errno ) ) ; return ( NULL ) ; } ( void ) strlcpy ( path , arg , sizeof ( path ) ) ; } else { if ( strncmp ( arg , _PATH_DEV , sizeof ( _PATH_DEV ) - 1 ) == 0 ) strlcpy ( path , arg , sizeof ( path ) ) ; else snprintf ( path , sizeof ( path ) , " " , _PATH_DEV , arg ) ; wholedisk = is_whole_disk ( path ) ; if ( ! wholedisk && ( stat64 ( path , & statbuf ) != 0 ) ) { if ( errno == ENOENT ) { ( void ) fprintf ( stderr , gettext ( " " " \n " ) , arg ) ; ( void ) fprintf ( stderr , gettext ( " " " \n " ) ) ; return ( NULL ) ; } else { ( void ) fprintf ( stderr , gettext ( " \n " ) , path , strerror ( errno ) ) ; return ( NULL ) ; } } } #ifdef __FreeBSD__ if ( S_ISCHR ( statbuf . st_mode ) ) { statbuf . st_mode &= ~ S_IFCHR ; statbuf . st_mode |= S_IFBLK ; wholedisk = B_FALSE ; } #endif if ( wholedisk || S_ISBLK ( statbuf . st_mode ) ) { type = VDEV_TYPE_DISK ; } else if ( S_ISREG ( statbuf . st_mode ) ) { type = VDEV_TYPE_FILE ; } else { ( void ) fprintf ( stderr , gettext ( " " " \n " ) , path ) ; return ( NULL ) ; } verify ( nvlist_alloc ( & vdev , NV_UNIQUE_NAME , 0 ) == 0 ) ; verify ( nvlist_add_string ( vdev , ZPOOL_CONFIG_PATH , path ) == 0 ) ; verify ( nvlist_add_string ( vdev , ZPOOL_CONFIG_TYPE , type ) == 0 ) ; verify ( nvlist_add_uint64 ( vdev , ZPOOL_CONFIG_IS_LOG , is_log ) == 0 ) ; if ( strcmp ( type , VDEV_TYPE_DISK ) == 0 ) verify ( nvlist_add_uint64 ( vdev , ZPOOL_CONFIG_WHOLE_DISK , ( uint64_t ) wholedisk ) == 0 ) ; #ifdef have_devid if ( S_ISBLK ( statbuf . st_mode ) && ! wholedisk ) { int fd ; ddi_devid_t devid ; char * minor = NULL , * devid_str = NULL ; if ( ( fd = open ( path , O_RDONLY ) ) < 0 ) { ( void ) fprintf ( stderr , gettext ( " " " \n " ) , path , strerror ( errno ) ) ; nvlist_free ( vdev ) ; return ( NULL ) ; } if ( devid_get ( fd , & devid ) == 0 ) { if ( devid_get_minor_name ( fd , & minor ) == 0 && ( devid_str = devid_str_encode ( devid , minor ) ) != NULL ) { verify ( nvlist_add_string ( vdev , ZPOOL_CONFIG_DEVID , devid_str ) == 0 ) ; } if ( devid_str != NULL ) devid_str_free ( devid_str ) ; if ( minor != NULL ) devid_str_free ( minor ) ; devid_free ( devid ) ; } ( void ) close ( fd ) ; } #endif return ( vdev ) ; }
Create a leaf vdev.
Create a leaf vdev .
/*
	 * Determine what type of vdev this is, and put the full path into
	 * 'path'.  We detect whether this is a device of file afterwards by
	 * checking the st_mode of the file.
	 */ /*
		 * Complete device or file path.  Exact type is determined by
		 * examining the file descriptor afterwards.
		 */ /*
		 * This may be a short path for a device, or it could be total
		 * gibberish.  Check to see if it's a known device in
		 * /dev/dsk/.  As part of this check, see if we've been given a
		 * an entire disk (minus the slice number).
		 */ /*
			 * If we got ENOENT, then the user gave us
			 * gibberish, so try to direct them with a
			 * reasonable error message.  Otherwise,
			 * regurgitate strerror() since it's the best we
			 * can do.
			 */ /*
	 * Determine whether this is a device or a file.
	 */ /*
	 * Finally, we have the complete device or file, and we know that it is
	 * acceptable to use.  Construct the nvlist to describe this vdev.  All
	 * vdevs have a 'path' element, and devices also have a 'devid' element.
	 */ /*
	 * For a whole disk, defer getting its devid until after labeling it.
	 */ /*
		 * Get the devid for the device.
		 */