Esempio n. 1
0
/* Get details about a file. */
int
get_file_details(
	ctx_t *c,		/* ARGSUSED */
	char *fsname,
	sqm_lst_t *files,
	sqm_lst_t **status)
{
	int rval, mntfd;
	node_t *fil;
	char mountpt[MAXPATHLEN+1];
	char details[MAXPATHLEN+1];
	struct stat64 sout;
	char *filstat;

	if (strlen(fsname) != 0) {
		rval = getfsmountpt(fsname, mountpt, sizeof (mountpt));
		if (rval != 0) {
			return (rval);
		}
	} else {
		/* No FS specified, use root */
		strlcpy(mountpt, "/", sizeof (mountpt));
	}

	mntfd = open64(mountpt, O_RDONLY);
	if (mntfd < 0)
		return (samrerr(SE_NOT_A_DIR, mountpt));

	*status = lst_create();	/* Return results in this list */
	if (*status == NULL) {
		close(mntfd);
		return (-1);	/* If allocation failed, samerr is set */
	}

	fil = files->head;	/* Walk through list of files */
	while (fil != NULL) {

		memset(&sout, 0, sizeof (sout));
		rval = fstatat64(mntfd, fil->data, &sout, 0);
		if (rval) {
			filstat = copystr(""); /* File doesn't exist */
		} else {
			snprintf(
			    details, sizeof (details),
			    "size=%lld,created=%lu,modified=%lu",
			    sout.st_size, sout.st_ctim.tv_sec,
			    sout.st_mtim.tv_sec);
			filstat = copystr(details);
		}

		lst_append(*status, filstat);

		fil = fil->next; /* And check next file */
	}

	close(mntfd);
	return (0);
}
Esempio n. 2
0
int
vn_openat(char *path, enum uio_seg x1, int flags, int mode,
          vnode_t **vpp, enum create x2, mode_t x3, vnode_t *startvp,
          int pfd)
{
    int save_errno, fd, stflags = 0;
    mode_t old_umask;
    struct stat64 st;

    if (flags & FNOFOLLOW)
        stflags |= AT_SYMLINK_NOFOLLOW;

    if (!(flags & FCREAT) && fstatat64(pfd, path, &st, stflags) == -1)
        return (errno);

    if (flags & FCREAT)
        old_umask = umask(0);

    if (!(flags & FCREAT) && S_ISBLK(st.st_mode)) {
        flags |= O_DIRECT;
        if (flags & FWRITE)
            flags |= O_EXCL;
    }

    /*
     * The construct 'flags - FREAD' conveniently maps combinations of
     * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
     */
    fd = openat64(pfd, path, flags - FREAD, mode);
    save_errno = errno;

    if (flags & FCREAT)
        umask(old_umask);

    if (fd == -1)
        return (save_errno);

    /* isfromfd */
    return (vn_fromfd(fd, path, flags, vpp, startvp != rootdir));
}
Esempio n. 3
0
int util::rm_r(int dfd, const char * path)
{
	DIR * dir;
	struct stat64 st;
	struct dirent * ent;
	int fd, copy, r = fstatat64(dfd, path, &st, AT_SYMLINK_NOFOLLOW);
	if(r < 0)
		return r;
	if(!S_ISDIR(st.st_mode))
		return unlinkat(dfd, path, 0);
	fd = openat(dfd, path, O_RDONLY);
	if(fd < 0)
		return fd;
	copy = dup(fd);
	if(copy < 0)
	{
		close(fd);
		return copy;
	}
	dir = fdopendir(copy);
	if(!dir)
	{
		close(copy);
		close(fd);
		return -1;
	}
	while((ent = readdir(dir)))
	{
		if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
			continue;
		r = rm_r(fd, ent->d_name);
		if(r < 0)
			break;
	}
	closedir(dir);
	close(fd);
	if(r < 0)
		return r;
	return unlinkat(dfd, path, AT_REMOVEDIR);
}
Esempio n. 4
0
static void
zpool_open_func(void *arg)
{
	rdsk_node_t *rn = arg;
#ifdef __APPLE__
	struct stat statbuf;
#else
	struct stat64 statbuf;
#endif
	nvlist_t *config;
	int num_labels;
	int fd;

	if (rn->rn_nozpool)
		return;
#if defined (__linux__) || defined (__APPLE__)
	/*
	 * Skip devices with well known prefixes there can be side effects
	 * when opening devices which need to be avoided.
	 *
	 * core     - Symlink to /proc/kcore
	 * fd*      - Floppy interface.
	 * fuse     - Fuse control device.
	 * hpet     - High Precision Event Timer
	 * lp*      - Printer interface.
	 * parport* - Parallel port interface.
	 * ppp      - Generic PPP driver.
	 * random   - Random device
	 * rtc      - Real Time Clock
	 * tty*     - Generic serial interface.
	 * urandom  - Random device.
	 * usbmon*  - USB IO monitor.
	 * vcs*     - Virtual console memory.
	 * watchdog - Watchdog must be closed in a special way.
	 */
	if ((strncmp(rn->rn_name, "core", 4) == 0) ||
	    (strncmp(rn->rn_name, "fd", 2) == 0) ||
	    (strncmp(rn->rn_name, "fuse", 4) == 0) ||
	    (strncmp(rn->rn_name, "hpet", 4) == 0) ||
	    (strncmp(rn->rn_name, "lp", 2) == 0) ||
	    (strncmp(rn->rn_name, "parport", 7) == 0) ||
	    (strncmp(rn->rn_name, "ppp", 3) == 0) ||
	    (strncmp(rn->rn_name, "random", 6) == 0) ||
	    (strncmp(rn->rn_name, "rtc", 3) == 0) ||
	    (strncmp(rn->rn_name, "tty", 3) == 0) ||
	    (strncmp(rn->rn_name, "urandom", 7) == 0) ||
	    (strncmp(rn->rn_name, "usbmon", 6) == 0) ||
	    (strncmp(rn->rn_name, "vcs", 3) == 0) ||
#ifdef __APPLE__
		(strncmp(rn->rn_name, "pty", 3) == 0) || // lots, skip for speed
		(strncmp(rn->rn_name, "com", 3) == 0) || // /dev/com_digidesign_semiface
#endif
	    (strncmp(rn->rn_name, "watchdog", 8) == 0))
		return;

	/*
	 * Ignore failed stats.  We only want regular files and block devices.
	 */
	if (fstatat64(rn->rn_dfd, rn->rn_name, &statbuf, 0) != 0 ||
	    (!S_ISREG(statbuf.st_mode) && !S_ISBLK(statbuf.st_mode)))
		return;

#ifdef __APPLE__
	/* It is desirable to skip optical media as well, as they are
	 * also called /dev/diskX
	 */
	if (is_optical_media((char *)rn->rn_name))
		return;
#endif

	if ((fd = openat64(rn->rn_dfd, rn->rn_name, O_RDONLY)) < 0) {
		/* symlink to a device that's no longer there */
		if (errno == ENOENT)
			nozpool_all_slices(rn->rn_avl, rn->rn_name);
		return;
	}

#else /* LINUX, APPLE -> IllumOS */

	if ((fd = openat64(rn->rn_dfd, rn->rn_name, O_RDONLY)) < 0) {
		/* symlink to a device that's no longer there */
		if (errno == ENOENT)
			nozpool_all_slices(rn->rn_avl, rn->rn_name);
		return;
	}
	/*
	 * Ignore failed stats.  We only want regular
	 * files, character devs and block devs.
	 */
	if (fstat64(fd, &statbuf) != 0 ||
	    (!S_ISREG(statbuf.st_mode) &&
	    !S_ISCHR(statbuf.st_mode) &&
	    !S_ISBLK(statbuf.st_mode))) {
		(void) close(fd);
		return;
	}
#endif
	/* this file is too small to hold a zpool */
	if (S_ISREG(statbuf.st_mode) &&
	    statbuf.st_size < SPA_MINDEVSIZE) {
		(void) close(fd);
		return;
	} else if (!S_ISREG(statbuf.st_mode)) {
		/*
		 * Try to read the disk label first so we don't have to
		 * open a bunch of minor nodes that can't have a zpool.
		 */
		check_slices(rn->rn_avl, fd, rn->rn_name);
	}

#ifdef __APPLE__
	int32_t blksz = 0;
	if (S_ISBLK(statbuf.st_mode) &&
		(ioctl(fd, DKIOCGETBLOCKSIZE, &blksz) || blksz == 0)) {
		if (strncmp(rn->rn_name, "vn", 2) != 0)
			fprintf(stderr, "device '%s' failed to report blocksize -- skipping\r\n",
					rn->rn_name);
		close(fd);
		return;
	}

	struct sigaction sact;
	sigemptyset(&sact.sa_mask);
	sact.sa_flags = 0;
	sact.sa_handler = signal_alarm;
	sigaction(SIGALRM, &sact, NULL);

	if (setjmp(buffer) != 0) {
		printf("ZFS: Warning, timeout reading device '%s'\n", rn->rn_name);
		close(fd);
		return;
	}

	alarm(20);
#endif

	if ((zpool_read_label(fd, &config, &num_labels)) != 0) {
#ifdef __APPLE__
		alarm(0);
#endif
		(void) close(fd);
		(void) no_memory(rn->rn_hdl);
		return;
	}

#ifdef __APPLE__
	alarm(0);
#endif

	if (num_labels == 0) {
		(void) close(fd);
		nvlist_free(config);
		return;
	}

	(void) close(fd);

	rn->rn_config = config;
	rn->rn_num_labels = num_labels;
}
Esempio n. 5
0
static int
do_test (void)
{
  /* fdopendir takes over the descriptor, make a copy.  */
  int dupfd = dup (dir_fd);
  if (dupfd == -1)
    {
      puts ("dup failed");
      return 1;
    }
  if (lseek (dupfd, 0, SEEK_SET) != 0)
    {
      puts ("1st lseek failed");
      return 1;
    }

  /* The directory should be empty safe the . and .. files.  */
  DIR *dir = fdopendir (dupfd);
  if (dir == NULL)
    {
      puts ("fdopendir failed");
      return 1;
    }
  struct dirent64 *d;
  while ((d = readdir64 (dir)) != NULL)
    if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
      {
	printf ("temp directory contains file \"%s\"\n", d->d_name);
	return 1;
      }
  closedir (dir);

  /* Try to create a file.  */
  int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
  if (fd == -1)
    {
      if (errno == ENOSYS)
	{
	  puts ("*at functions not supported");
	  return 0;
	}

      puts ("file creation failed");
      return 1;
    }
  write (fd, "hello", 5);
  puts ("file created");

  struct stat64 st1;
  if (fstat64 (fd, &st1) != 0)
    {
      puts ("fstat64 failed");
      return 1;
    }

  close (fd);

  if (linkat (dir_fd, "some-file", dir_fd, "another-file", 0) != 0)
    {
      puts ("symlinkat failed");
      return 1;
    }

  struct stat64 st2;
  if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
    {
      puts ("fstatat64 failed");
      return 1;
    }
  if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
    {
      puts ("file changed after symlinkat");
      return 1;
    }

  if (fstatat64 (dir_fd, "another-file", &st2, AT_SYMLINK_NOFOLLOW) != 0)
    {
      puts ("2nd fstatat64 failed");
      return 1;
    }
  if (S_ISLNK (st2.st_mode))
    {
      puts ("2nd fstatat64 shows file is a symlink");
      return 1;
    }
  if (st1.st_dev != st2.st_dev
      || st1.st_ino != st2.st_ino
      || st1.st_size != st2.st_size)
    {
      puts ("stat results for linked file do not match");
      return 1;
    }

  if (fstatat64 (dir_fd, "another-file", &st2, 0) != 0)
    {
      puts ("3rd fstatat64 failed");
      return 1;
    }
  if (st1.st_dev != st2.st_dev
      || st1.st_ino != st2.st_ino
      || st1.st_size != st2.st_size)
    {
      puts ("stat results do not match");
      return 1;
    }

  if (unlinkat (dir_fd, "another-file", 0) != 0)
    {
      puts ("unlinkat failed");
      return 1;
    }
  if (unlinkat (dir_fd, "some-file", 0) != 0)
    {
      puts ("2nd unlinkat failed");
      return 1;
    }

  close (dir_fd);

  return 0;
}
Esempio n. 6
0
/*
 * Given a list of directories to search, find all pools stored on disk.  This
 * includes partial pools which are not available to import.  If no args are
 * given (argc is 0), then the default directory (/dev/dsk) is searched.
 * poolname or guid (but not both) are provided by the caller when trying
 * to import a specific pool.
 */
static nvlist_t *
zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
{
	int i, num_labels, dirs = iarg->paths;
	DIR *dirp = NULL;
	struct dirent *dp;
	char path[MAXPATHLEN];
	char *end, **dir = iarg->path;
	size_t pathleft;
	struct stat statbuf;
	nvlist_t *ret = NULL, *config;
	int fd;
	pool_list_t pools = { 0 };
	pool_entry_t *pe, *penext;
	vdev_entry_t *ve, *venext;
	config_entry_t *ce, *cenext;
	name_entry_t *ne, *nenext;

	verify(iarg->poolname == NULL || iarg->guid == 0);

	if (dirs == 0) {
#ifdef HAVE_LIBBLKID
		/* Use libblkid to scan all device for their type */
		if (zpool_find_import_blkid(hdl, &pools) == 0)
			goto skip_scanning;

		(void) zfs_error_fmt(hdl, EZFS_BADCACHE,
		    dgettext(TEXT_DOMAIN, "blkid failure falling back "
		    "to manual probing"));
#endif /* HAVE_LIBBLKID */

		dir = zpool_default_import_path;
		dirs = DEFAULT_IMPORT_PATH_SIZE;
	}

	/*
	 * Go through and read the label configuration information from every
	 * possible device, organizing the information according to pool GUID
	 * and toplevel GUID.
	 */
	for (i = 0; i < dirs; i++) {
		char *rdsk;
		int dfd;

		/* use realpath to normalize the path */
		if (realpath(dir[i], path) == 0) {

			/* it is safe to skip missing search paths */
			if (errno == ENOENT)
				continue;

			zfs_error_aux(hdl, strerror(errno));
			(void) zfs_error_fmt(hdl, EZFS_BADPATH,
			    dgettext(TEXT_DOMAIN, "cannot open '%s'"), dir[i]);
			goto error;
		}
		end = &path[strlen(path)];
		*end++ = '/';
		*end = 0;
		pathleft = &path[sizeof (path)] - end;

		/*
		 * Using raw devices instead of block devices when we're
		 * reading the labels skips a bunch of slow operations during
		 * close(2) processing, so we replace /dev/dsk with /dev/rdsk.
		 */
		if (strcmp(path, "/dev/dsk/") == 0)
			rdsk = "/dev/rdsk/";
		else
			rdsk = path;

		if ((dfd = open(rdsk, O_RDONLY)) < 0 ||
		    (dirp = fdopendir(dfd)) == NULL) {
			zfs_error_aux(hdl, strerror(errno));
			(void) zfs_error_fmt(hdl, EZFS_BADPATH,
			    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
			    rdsk);
			goto error;
		}

		/*
		 * This is not MT-safe, but we have no MT consumers of libzfs
		 */
		while ((dp = readdir(dirp)) != NULL) {
			const char *name = dp->d_name;
			if (name[0] == '.' &&
			    (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
				continue;

			/*
			 * Skip checking devices with well known prefixes:
			 * watchdog - A special close is required to avoid
			 *            triggering it and resetting the system.
			 * fuse     - Fuse control device.
			 * ppp      - Generic PPP driver.
			 * tty*     - Generic serial interface.
			 * vcs*     - Virtual console memory.
			 * parport* - Parallel port interface.
			 * lp*      - Printer interface.
			 * fd*      - Floppy interface.
			 * hpet     - High Precision Event Timer, crashes qemu
			 *            when accessed from a virtual machine.
			 * core     - Symlink to /proc/kcore, causes a crash
			 *            when access from Xen dom0.
			 */
			if ((strncmp(name, "watchdog", 8) == 0) ||
			    (strncmp(name, "fuse", 4) == 0) ||
			    (strncmp(name, "ppp", 3) == 0) ||
			    (strncmp(name, "tty", 3) == 0) ||
			    (strncmp(name, "vcs", 3) == 0) ||
			    (strncmp(name, "parport", 7) == 0) ||
			    (strncmp(name, "lp", 2) == 0) ||
			    (strncmp(name, "fd", 2) == 0) ||
			    (strncmp(name, "hpet", 4) == 0) ||
#ifdef __APPLE__
				(strncmp(name, "pty", 3) == 0) || // lots, skip for speed
				(strncmp(name, "com", 3) == 0) || // /dev/com_digidesign_semiface
#endif
			    (strncmp(name, "core", 4) == 0))
				continue;

			/*
			 * Ignore failed stats.  We only want regular
			 * files and block devices.
			 */
			if ((fstatat64(dfd, name, &statbuf, 0) != 0) ||
			    (!S_ISREG(statbuf.st_mode) &&
			    !S_ISBLK(statbuf.st_mode)))
				continue;

#ifdef __APPLE__
			/* It is desirable to skip optical media as well, as they are
			 * also called /dev/diskX
			 */
			if (is_optical_media((char *)name))
				continue;
#endif

			if ((fd = openat64(dfd, name, O_RDONLY)) < 0)
				continue;

			int32_t blksz = 0;
			if (S_ISBLK(statbuf.st_mode) &&
				(ioctl(fd, DKIOCGETBLOCKSIZE, &blksz) || blksz == 0)) {
				if (strncmp(name, "vn", 2) != 0)
					fprintf(stderr, "device '%s' failed to report blocksize -- skipping\r\n",
							name);
				close(fd);
				continue;
			}

#ifdef __APPLE__
			struct sigaction sact;
			sigemptyset(&sact.sa_mask);
			sact.sa_flags = 0;
			sact.sa_handler = signal_alarm;
			sigaction(SIGALRM, &sact, NULL);

			if (setjmp(buffer) != 0) {
				printf("ZFS: Warning, timeout reading device '%s'\n", name);
				close(fd);
				continue;
			}

			alarm(20);
#endif

			if ((zpool_read_label(fd, &config, NULL)) != 0) {
#ifdef __APPLE__
				alarm(0);
#endif
				(void) close(fd);
				(void) no_memory(hdl);
				goto error;
			}
#ifdef __APPLE__
			alarm(0);
#endif

			(void) close(fd);

			if (config != NULL) {
				boolean_t matched = B_TRUE;
				char *pname;

				if ((iarg->poolname != NULL) &&
				    (nvlist_lookup_string(config,
				    ZPOOL_CONFIG_POOL_NAME, &pname) == 0)) {

					if (strcmp(iarg->poolname, pname))
						matched = B_FALSE;

				} else if (iarg->guid != 0) {
					uint64_t this_guid;

					matched = nvlist_lookup_uint64(config,
					    ZPOOL_CONFIG_POOL_GUID,
					    &this_guid) == 0 &&
					    iarg->guid == this_guid;
				}
				if (!matched) {
					nvlist_free(config);
					config = NULL;
					continue;
				}
				/* use the non-raw path for the config */
				(void) strlcpy(end, name, pathleft);
				if (add_config(hdl, &pools, path, i+1,
				    num_labels, config))
					goto error;
			}
		}

		(void) closedir(dirp);
		dirp = NULL;
	}

#ifdef HAVE_LIBBLKID
skip_scanning:
#endif
	ret = get_configs(hdl, &pools, iarg->can_be_active);

error:
	for (pe = pools.pools; pe != NULL; pe = penext) {
		penext = pe->pe_next;
		for (ve = pe->pe_vdevs; ve != NULL; ve = venext) {
			venext = ve->ve_next;
			for (ce = ve->ve_configs; ce != NULL; ce = cenext) {
				cenext = ce->ce_next;
				if (ce->ce_config)
					nvlist_free(ce->ce_config);
				free(ce);
			}
			free(ve);
		}
		free(pe);
	}

	for (ne = pools.names; ne != NULL; ne = nenext) {
		nenext = ne->ne_next;
		if (ne->ne_name)
			free(ne->ne_name);
		free(ne);
	}

	if (dirp)
		(void) closedir(dirp);

	return (ret);
}
Esempio n. 7
0
static void
zpool_open_func(void *arg)
{
	rdsk_node_t *rn = arg;
	struct stat64 statbuf;
	nvlist_t *config;
	int num_labels;
	int fd;

	if (rn->rn_nozpool)
		return;
#ifdef __linux__
	/*
	 * Skip devices with well known prefixes there can be side effects
	 * when opening devices which need to be avoided.
	 *
	 * core     - Symlink to /proc/kcore
	 * fd*      - Floppy interface.
	 * fuse     - Fuse control device.
	 * hpet     - High Precision Event Timer
	 * lp*      - Printer interface.
	 * parport* - Parallel port interface.
	 * ppp      - Generic PPP driver.
	 * random   - Random device
	 * rtc      - Real Time Clock
	 * tty*     - Generic serial interface.
	 * urandom  - Random device.
	 * usbmon*  - USB IO monitor.
	 * vcs*     - Virtual console memory.
	 * watchdog - Watchdog must be closed in a special way.
	 */
	if ((strncmp(rn->rn_name, "core", 4) == 0) ||
	    (strncmp(rn->rn_name, "fd", 2) == 0) ||
	    (strncmp(rn->rn_name, "fuse", 4) == 0) ||
	    (strncmp(rn->rn_name, "hpet", 4) == 0) ||
	    (strncmp(rn->rn_name, "lp", 2) == 0) ||
	    (strncmp(rn->rn_name, "parport", 7) == 0) ||
	    (strncmp(rn->rn_name, "ppp", 3) == 0) ||
	    (strncmp(rn->rn_name, "random", 6) == 0) ||
	    (strncmp(rn->rn_name, "rtc", 3) == 0) ||
	    (strncmp(rn->rn_name, "tty", 3) == 0) ||
	    (strncmp(rn->rn_name, "urandom", 7) == 0) ||
	    (strncmp(rn->rn_name, "usbmon", 6) == 0) ||
	    (strncmp(rn->rn_name, "vcs", 3) == 0) ||
	    (strncmp(rn->rn_name, "watchdog", 8) == 0))
		return;

	/*
	 * Ignore failed stats.  We only want regular files and block devices.
	 */
	if (fstatat64(rn->rn_dfd, rn->rn_name, &statbuf, 0) != 0 ||
	    (!S_ISREG(statbuf.st_mode) && !S_ISBLK(statbuf.st_mode)))
		return;

	if ((fd = openat64(rn->rn_dfd, rn->rn_name, O_RDONLY)) < 0) {
		/* symlink to a device that's no longer there */
		if (errno == ENOENT)
			nozpool_all_slices(rn->rn_avl, rn->rn_name);
		return;
	}
#else
	if ((fd = openat64(rn->rn_dfd, rn->rn_name, O_RDONLY)) < 0) {
		/* symlink to a device that's no longer there */
		if (errno == ENOENT)
			nozpool_all_slices(rn->rn_avl, rn->rn_name);
		return;
	}
	/*
	 * Ignore failed stats.  We only want regular
	 * files, character devs and block devs.
	 */
	if (fstat64(fd, &statbuf) != 0 ||
	    (!S_ISREG(statbuf.st_mode) &&
	    !S_ISCHR(statbuf.st_mode) &&
	    !S_ISBLK(statbuf.st_mode))) {
		(void) close(fd);
		return;
	}
#endif
	/* this file is too small to hold a zpool */
	if (S_ISREG(statbuf.st_mode) &&
	    statbuf.st_size < SPA_MINDEVSIZE) {
		(void) close(fd);
		return;
	} else if (!S_ISREG(statbuf.st_mode)) {
		/*
		 * Try to read the disk label first so we don't have to
		 * open a bunch of minor nodes that can't have a zpool.
		 */
		check_slices(rn->rn_avl, fd, rn->rn_name);
	}

	if ((zpool_read_label(fd, &config, &num_labels)) != 0) {
		(void) close(fd);
		(void) no_memory(rn->rn_hdl);
		return;
	}

	if (num_labels == 0) {
		(void) close(fd);
		nvlist_free(config);
		return;
	}

	(void) close(fd);

	rn->rn_config = config;
	rn->rn_num_labels = num_labels;
}
Esempio n. 8
0
static int
do_test (void)
{
  /* fdopendir takes over the descriptor, make a copy.  */
  int dupfd = dup (dir_fd);
  if (dupfd == -1)
    {
      puts ("dup failed");
      return 1;
    }
  if (lseek (dupfd, 0, SEEK_SET) != 0)
    {
      puts ("1st lseek failed");
      return 1;
    }

  /* The directory should be empty safe the . and .. files.  */
  DIR *dir = fdopendir (dupfd);
  if (dir == NULL)
    {
      puts ("fdopendir failed");
      return 1;
    }
  struct dirent64 *d;
  while ((d = readdir64 (dir)) != NULL)
    if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
      {
	printf ("temp directory contains file \"%s\"\n", d->d_name);
	return 1;
      }
  closedir (dir);

  /* Create a new fifo.  */
  int e = mknodat (dir_fd, "some-fifo", 0777 | S_IFIFO, 0);
  if (e == -1)
    {
      if (errno == ENOSYS)
	{
	  puts ("*at functions not supported");
	  return 0;
	}

      puts ("fifo creation failed");
      return 1;
    }

  struct stat64 st1;
  if (fstatat64 (dir_fd, "some-fifo", &st1, 0) != 0)
    {
      puts ("fstat64 failed");
      return 1;
    }
  if (!S_ISFIFO (st1.st_mode))
    {
      puts ("mknodat did not create a fifo");
      return 1;
    }

  dupfd = dup (dir_fd);
  if (dupfd == -1)
    {
      puts ("dup failed");
      return 1;
    }
  if (lseek (dupfd, 0, SEEK_SET) != 0)
    {
      puts ("1st lseek failed");
      return 1;
    }

  dir = fdopendir (dupfd);
  if (dir == NULL)
    {
      puts ("2nd fdopendir failed");
      return 1;
    }
  bool has_some_fifo = false;
  while ((d = readdir64 (dir)) != NULL)
    if (strcmp (d->d_name, "some-fifo") == 0)
      {
	has_some_fifo = true;
#ifdef _DIRENT_HAVE_D_TYPE
	if (d->d_type != DT_UNKNOWN && d->d_type != DT_FIFO)
	  {
	    puts ("d_type for some-fifo wrong");
	    return 1;
	  }
#endif
      }
    else if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
      {
	printf ("temp directory contains file \"%s\"\n", d->d_name);
	return 1;
      }
  closedir (dir);

  if (!has_some_fifo)
    {
      puts ("some-fifo not in directory list");
      return 1;
    }

  if (unlinkat (dir_fd, "some-fifo", 0) != 0)
    {
      puts ("unlinkat failed");
      return 1;
    }

  close (dir_fd);

  return 0;
}
Esempio n. 9
0
int stat(const char *file_name, struct stat *buf)
{
	return fstatat64(AT_FDCWD, file_name, buf, 0);
}
Esempio n. 10
0
static int
do_test (void)
{
  /* fdopendir takes over the descriptor, make a copy.  */
  int dupfd = dup (dir_fd);
  if (dupfd == -1)
    {
      puts ("dup failed");
      return 1;
    }
  if (lseek (dupfd, 0, SEEK_SET) != 0)
    {
      puts ("1st lseek failed");
      return 1;
    }

  /* The directory should be empty safe the . and .. files.  */
  DIR *dir = fdopendir (dupfd);
  if (dir == NULL)
    {
      puts ("fdopendir failed");
      return 1;
    }
  struct dirent64 *d;
  while ((d = readdir64 (dir)) != NULL)
    if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
      {
	printf ("temp directory contains file \"%s\"\n", d->d_name);
	return 1;
      }
  closedir (dir);

  /* Try to create a file.  */
  int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
  if (fd == -1)
    {
      if (errno == ENOSYS)
	{
	  puts ("*at functions not supported");
	  return 0;
	}

      puts ("file creation failed");
      return 1;
    }
  write (fd, "hello", 5);
  puts ("file created");

  struct stat64 st1;

  /* Before closing the file, try using this file descriptor to open
     another file.  This must fail.  */
  if (fstatat64 (fd, "some-file", &st1, 0) != -1)
    {
      puts ("fstatatat using descriptor for normal file worked");
      return 1;
    }
  if (errno == ENOSYS)
    {
	  puts ("fstatat function not supported");
      return 0;
    }
  else if (errno != ENOTDIR)
    {
      puts ("error for fstatat using descriptor for normal file not ENOTDIR ");
      return 1;
    }

  if (fstat64 (fd, &st1) != 0)
    {
      puts ("fstat64 failed");
      return 1;
    }

  close (fd);

  struct stat64 st2;
  if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
    {
      puts ("fstatat64 failed");
      return 1;
    }

  if (st1.st_dev != st2.st_dev
      || st1.st_ino != st2.st_ino
      || st1.st_size != st2.st_size)
    {
      puts ("stat results do not match");
      return 1;
    }

  if (unlinkat (dir_fd, "some-file", 0) != 0)
    {
      puts ("unlinkat failed");
      return 1;
    }

  if (fstatat64 (dir_fd, "some-file", &st2, 0) == 0)
    {
      puts ("second fstatat64 succeeded");
      return 1;
    }
  if (errno != ENOENT)
    {
      puts ("second fstatat64 did not fail with ENOENT");
      return 1;
    }

  /* Create a file descriptor which is closed again right away.  */
  int dir_fd2 = dup (dir_fd);
  if (dir_fd2 == -1)
    {
      puts ("dup failed");
      return 1;
    }
  close (dir_fd2);

  if (fstatat64 (dir_fd2, "some-file", &st1, 0) != -1)
    {
      puts ("fstatat64 using closed descriptor worked");
      return 1;
    }
  if (errno != EBADF)
    {
      puts ("error for fstatat using closed descriptor not EBADF ");
      return 1;
    }

  close (dir_fd);

  if (fstatat64 (-1, "some-file", &st1, 0) != -1)
    {
      puts ("fstatat64 using invalid descriptor worked");
      return 1;
    }
  if (errno != EBADF)
    {
      puts ("error for fstatat using invalid descriptor not EBADF ");
      return 1;
    }

  return 0;
}
Esempio n. 11
0
static int
do_test (void)
{
    /* fdopendir takes over the descriptor, make a copy.  */
    int dupfd = dup (dir_fd);
    if (dupfd == -1)
    {
        puts ("dup failed");
        return 1;
    }
    if (lseek (dupfd, 0, SEEK_SET) != 0)
    {
        puts ("1st lseek failed");
        return 1;
    }

    /* The directory should be empty safe the . and .. files.  */
    DIR *dir = fdopendir (dupfd);
    if (dir == NULL)
    {
        puts ("fdopendir failed");
        return 1;
    }
    struct dirent64 *d;
    while ((d = readdir64 (dir)) != NULL)
        if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
        {
            printf ("temp directory contains file \"%s\"\n", d->d_name);
            return 1;
        }
    closedir (dir);

    /* Try to create a file.  */
    int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
    if (fd == -1)
    {
        if (errno == ENOSYS)
        {
            puts ("*at functions not supported");
            return 0;
        }

        puts ("file creation failed");
        return 1;
    }
    write (fd, "hello", 5);
    puts ("file created");

    struct stat64 st1;
    if (fstat64 (fd, &st1) != 0)
    {
        puts ("fstat64 failed");
        return 1;
    }

    close (fd);

    struct timeval tv[2];
    tv[0].tv_sec = st1.st_atime + 1;
    tv[0].tv_usec = 0;
    tv[1].tv_sec = st1.st_mtime + 1;
    tv[1].tv_usec = 0;
    if (futimesat (dir_fd, "some-file", tv) != 0)
    {
        puts ("futimesat failed");
        return 1;
    }

    struct stat64 st2;
    if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
    {
        puts ("fstatat64 failed");
        return 1;
    }

    if (st2.st_mtime != tv[1].tv_sec
#ifdef _STATBUF_ST_NSEC
            || st2.st_mtim.tv_nsec != 0
#endif
       )
    {
        puts ("stat shows different mtime");
        return 1;
    }


    if (unlinkat (dir_fd, "some-file", 0) != 0)
    {
        puts ("unlinkat failed");
        return 1;
    }

    close (dir_fd);

    return 0;
}
Esempio n. 12
0
/*
 * Given a list of directories to search, find all pools stored on disk.  This
 * includes partial pools which are not available to import.  If no args are
 * given (argc is 0), then the default directory (/dev/dsk) is searched.
 * poolname or guid (but not both) are provided by the caller when trying
 * to import a specific pool.
 */
static nvlist_t *
zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
{
	int i, dirs = iarg->paths;
	DIR *dirp = NULL;
	struct dirent64 *dp;
	char path[MAXPATHLEN];
	char *end, **dir = iarg->path;
	size_t pathleft;
	struct stat64 statbuf;
	nvlist_t *ret = NULL, *config;
	static char *default_dir = DISK_ROOT;
	int fd;
	pool_list_t pools = { 0 };
	pool_entry_t *pe, *penext;
	vdev_entry_t *ve, *venext;
	config_entry_t *ce, *cenext;
	name_entry_t *ne, *nenext;

	verify(iarg->poolname == NULL || iarg->guid == 0);

	if (dirs == 0) {
#ifdef HAVE_LIBBLKID
		/* Use libblkid to scan all device for their type */
		if (zpool_find_import_blkid(hdl, &pools) == 0)
			goto skip_scanning;

		(void) zfs_error_fmt(hdl, EZFS_BADCACHE,
		    dgettext(TEXT_DOMAIN, "blkid failure falling back "
		    "to manual probing"));
#endif /* HAVE_LIBBLKID */
		dirs = 1;
		dir = &default_dir;
	}

	/*
	 * Go through and read the label configuration information from every
	 * possible device, organizing the information according to pool GUID
	 * and toplevel GUID.
	 */
	for (i = 0; i < dirs; i++) {
		char *rdsk;
		int dfd;

		/* use realpath to normalize the path */
		if (realpath(dir[i], path) == 0) {
			(void) zfs_error_fmt(hdl, EZFS_BADPATH,
			    dgettext(TEXT_DOMAIN, "cannot open '%s'"), dir[i]);
			goto error;
		}
		end = &path[strlen(path)];
		*end++ = '/';
		*end = 0;
		pathleft = &path[sizeof (path)] - end;

		/*
		 * Using raw devices instead of block devices when we're
		 * reading the labels skips a bunch of slow operations during
		 * close(2) processing, so we replace /dev/dsk with /dev/rdsk.
		 */
		if (strcmp(path, "/dev/dsk/") == 0)
			rdsk = "/dev/rdsk/";
		else
			rdsk = path;

		if ((dfd = open64(rdsk, O_RDONLY)) < 0 ||
		    (dirp = fdopendir(dfd)) == NULL) {
			zfs_error_aux(hdl, strerror(errno));
			(void) zfs_error_fmt(hdl, EZFS_BADPATH,
			    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
			    rdsk);
			goto error;
		}

		/*
		 * This is not MT-safe, but we have no MT consumers of libzfs
		 */
		while ((dp = readdir64(dirp)) != NULL) {
			const char *name = dp->d_name;
			if (name[0] == '.' &&
			    (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
				continue;

			/*
			 * Skip checking devices with well known prefixes:
			 * watchdog - A special close is required to avoid
			 *            triggering it and resetting the system.
			 * fuse     - Fuse control device.
			 * ppp      - Generic PPP driver.
			 * tty*     - Generic serial interface.
			 * vcs*     - Virtual console memory.
			 * parport* - Parallel port interface.
			 * lp*      - Printer interface.
			 * fd*      - Floppy interface.
			 * hpet     - High Precision Event Timer, crashes qemu
			 *            when accessed from a virtual machine.
			 * core     - Symlink to /proc/kcore, causes a crash
			 *            when access from Xen dom0.
			 */
			if ((strncmp(name, "watchdog", 8) == 0) ||
			    (strncmp(name, "fuse", 4) == 0)     ||
			    (strncmp(name, "ppp", 3) == 0)      ||
			    (strncmp(name, "tty", 3) == 0)      ||
			    (strncmp(name, "vcs", 3) == 0)      ||
			    (strncmp(name, "parport", 7) == 0)  ||
			    (strncmp(name, "lp", 2) == 0)       ||
			    (strncmp(name, "fd", 2) == 0)       ||
			    (strncmp(name, "hpet", 4) == 0)     ||
			    (strncmp(name, "core", 4) == 0))
				continue;

			/*
			 * Ignore failed stats.  We only want regular
			 * files and block devices.
			 */
			if ((fstatat64(dfd, name, &statbuf, 0) != 0) ||
			    (!S_ISREG(statbuf.st_mode) &&
			    !S_ISBLK(statbuf.st_mode)))
				continue;

			if ((fd = openat64(dfd, name, O_RDONLY)) < 0)
				continue;

			if ((zpool_read_label(fd, &config)) != 0) {
				(void) close(fd);
				(void) no_memory(hdl);
				goto error;
			}

			(void) close(fd);

			if (config != NULL) {
				boolean_t matched = B_TRUE;

				if (iarg->poolname != NULL) {
					char *pname;

					matched = nvlist_lookup_string(config,
					    ZPOOL_CONFIG_POOL_NAME,
					    &pname) == 0 &&
					    strcmp(iarg->poolname, pname) == 0;
				} else if (iarg->guid != 0) {
					uint64_t this_guid;

					matched = nvlist_lookup_uint64(config,
					    ZPOOL_CONFIG_POOL_GUID,
					    &this_guid) == 0 &&
					    iarg->guid == this_guid;
				}
				if (!matched) {
					nvlist_free(config);
					config = NULL;
					continue;
				}
				/* use the non-raw path for the config */
				(void) strlcpy(end, name, pathleft);
				if (add_config(hdl, &pools, path, config) != 0)
					goto error;
			}
		}

		(void) closedir(dirp);
		dirp = NULL;
	}

#ifdef HAVE_LIBBLKID
skip_scanning:
#endif
	ret = get_configs(hdl, &pools, iarg->can_be_active);

error:
	for (pe = pools.pools; pe != NULL; pe = penext) {
		penext = pe->pe_next;
		for (ve = pe->pe_vdevs; ve != NULL; ve = venext) {
			venext = ve->ve_next;
			for (ce = ve->ve_configs; ce != NULL; ce = cenext) {
				cenext = ce->ce_next;
				if (ce->ce_config)
					nvlist_free(ce->ce_config);
				free(ce);
			}
			free(ve);
		}
		free(pe);
	}

	for (ne = pools.names; ne != NULL; ne = nenext) {
		nenext = ne->ne_next;
		if (ne->ne_name)
			free(ne->ne_name);
		free(ne);
	}

	if (dirp)
		(void) closedir(dirp);

	return (ret);
}