Esempio n. 1
0
/* returns the free disk space (in GB) remaining in the filesystem used by the
 * storage system */
float fs_free_disk_gb(const char *kb)
{
    #if (defined (__SVR4) && defined (__sun))
    struct statvfs64 buf;
    #else
    struct statfs buf;
    #endif
    char *mdfn = g_strdup_printf(FS_MD_FILE, kb);

    #if (defined (__SVR4) && defined (__sun))
    if (statvfs64(mdfn, &buf) == -1) {
    #else
    if (statfs(mdfn, &buf) == -1) {
    #endif
        fs_error(LOG_ERR, "cannot statfs('%s'): %s", mdfn, strerror(errno));
        g_free(mdfn);

        return 50.0;
    }
    g_free(mdfn);

    return (double)(buf.f_bavail * buf.f_bsize) / (1024.0*1024.0*1024.0);
}

/* returns the percentage of disk space remaining in the filesystem used by the
 * storage system */
float fs_free_disk(const char *kb)
{
    #if (defined (__SVR4) && defined (__sun))
    struct statvfs64 buf;
    #else
    struct statfs buf;
    #endif
    char *mdfn = g_strdup_printf(FS_MD_FILE, kb);

    #if (defined (__SVR4) && defined (__sun))
    if (statvfs64(mdfn, &buf) == -1) {
    #else
    if (statfs(mdfn, &buf) == -1) {
    #endif
        fs_error(LOG_ERR, "cannot statfs('%s'): %s", mdfn, strerror(errno));
        g_free(mdfn);

        return 50.0;
    }

    g_free(mdfn);
    float used_pc = (buf.f_blocks - buf.f_bavail) * 100.0 / buf.f_blocks;

    return 100.0 - used_pc;
}
Esempio n. 2
0
void some_func() {
  struct statvfs64 st;
  statvfs64(&st);
// Check that even if there is a structure with redefined name before the
// pragma, subsequent function name redefined properly. PR5172, Comment 11.
// CHECK:  call i32 @statvfs(%struct.statvfs64* %st)
}
Esempio n. 3
0
/*
 * Returns true if the specified directory is empty.  If we can't open the
 * directory at all, return true so that the mount can fail with a more
 * informative error message.
 */
static boolean_t
dir_is_empty(const char *dirname)
{
	struct statvfs64 st;

	/*
	 * If the statvfs call fails or the filesystem is not a ZFS
	 * filesystem, fall back to the slow path which uses readdir.
	 */
	if ((statvfs64(dirname, &st) != 0) ||
	    (strcmp(st.f_basetype, "zfs") != 0)) {
		return (dir_is_empty_readdir(dirname));
	}

	/*
	 * At this point, we know the provided path is on a ZFS
	 * filesystem, so we can use stat instead of readdir to
	 * determine if the directory is empty or not. We try to avoid
	 * using readdir because that requires opening "dirname"; this
	 * open file descriptor can potentially end up in a child
	 * process if there's a concurrent fork, thus preventing the
	 * zfs_mount() from otherwise succeeding (the open file
	 * descriptor inherited by the child process will cause the
	 * parent's mount to fail with EBUSY). The performance
	 * implications of replacing the open, read, and close with a
	 * single stat is nice; but is not the main motivation for the
	 * added complexity.
	 */
	return (dir_is_empty_stat(dirname));
}
Esempio n. 4
0
/*
 * Get information for file system on remote host.  Set offline flag
 * to include the size of all SAM-FS offline files in the capacity.
 */
int
SamrftStatvfs(
	SamrftImpl_t *rftd,
	char *path,
	boolean_t offlineFiles,
	struct statvfs64 *buf)
{
	int error;
	int rc = -1;

	if (rftd->remotehost) {
		SendCommand(rftd, "%s %s %d", SAMRFT_CMD_STATVFS,
		    path, offlineFiles);
		if (GetReply(rftd) >= 0) {
			rc = GetStatvfsReply(rftd, buf, &error);
		}
	} else {
		fsize_t offlineFileSize;

		rc = statvfs64(path, buf);
		if (rc == 0 && (strcmp(buf->f_basetype, "samfs") == 0) &&
		    offlineFiles == B_TRUE) {
			offlineFileSize = DiskVolsOfflineFiles(path);
			/*
			 * Adjust capacity to include size of offline files.
			 */
			buf->f_blocks += offlineFileSize / buf->f_frsize;
		}
	}
	return (rc);
}
Esempio n. 5
0
uint64_t getfsutil_size(char *dirname)
{
	struct statvfs64 fsdata;
	statvfs64(dirname, &fsdata);

	return (fsdata.f_blocks - fsdata.f_bfree) * fsdata.f_bsize;
}
Esempio n. 6
0
IFileInfo::size_type FileContainer::freeSpace() const
{
	struct statvfs64 info;

	if (statvfs64(m_path.as<QByteArray>(), &info) == -1)
		return 0;
	else
		return info.f_bsize * info.f_bfree;
}
Esempio n. 7
0
/* !!!! check portability */
float getfsutil(char *dirname)
{
	struct statvfs64 fsdata;

	statvfs64(dirname, &fsdata);

/* 	return (float)(fsdata.f_blocks-fsdata.f_bfree)/ */
/* 		(float)(fsdata.f_blocks-fsdata.f_bfree+fsdata.f_bavail); */
	return (float) (((float)(fsdata.f_blocks - fsdata.f_bfree)) /
			((float)fsdata.f_blocks));
}
Esempio n. 8
0
int
statfs64(char *path, struct statfs64 *buf)
{
	int ret;
	struct statvfs64 vbuf;

	if ((long)buf == -1L) {
		errno = EFAULT;
		return (-1);
	}

	if ((ret = statvfs64(path, &vbuf)) != -1)
		cnvtvfs64(buf, &vbuf);
	return (ret);
}
Esempio n. 9
0
void DriveManager::RetrievePathInfo(PathInfo& PathInfo)
{
    //HACK: Used to to give Linux some time while mounting new drives is in progress
    usleep(500000);

    struct statvfs64 fiData;

    if(statvfs64(PathInfo.DrivePath.c_str(), &fiData) < 0)
    {
        return;
    }

    PathInfo.TotalSpace = (fiData.f_blocks * fiData.f_frsize) / 1024 / 1024;
    PathInfo.UsedSpace = PathInfo.TotalSpace - ((fiData.f_bfree * fiData.f_frsize) / 1024 / 1024);
    PathInfo.SpaceUnit = "MB";
}
Esempio n. 10
0
int CollectorSolaris::getHostFilesystemUsage(const char *path, ULONG *total, ULONG *used, ULONG *available)
{
    struct statvfs64 stats;
    const unsigned _MB = 1024 * 1024;

    if (statvfs64(path, &stats) == -1)
    {
        LogRel(("Failed to collect %s filesystem usage: errno=%d.\n", path, errno));
        return VERR_ACCESS_DENIED;
    }
    uint64_t cbBlock = stats.f_frsize ? stats.f_frsize : stats.f_bsize;
    *total = (ULONG)(getZfsTotal(cbBlock * stats.f_blocks, stats.f_basetype, path) / _MB);
    LogFlowThisFunc(("f_blocks=%llu.\n", stats.f_blocks));
    *used  = (ULONG)(cbBlock * (stats.f_blocks - stats.f_bfree) / _MB);
    *available = (ULONG)(cbBlock * stats.f_bavail / _MB);

    return VINF_SUCCESS;
}
Esempio n. 11
0
long long get_freespace(void)
{
	struct mntent *mnt;
	char *table = MOUNTED;
	FILE *fp;
	long long ret = 0;

	fp = setmntent (table, "r");
	if(!fp)
		return(-1);
	while ((mnt = getmntent (fp)))
	{
		if(strstr(mnt->mnt_dir, "/mnt/target") != NULL) {
			struct statvfs64 buf;

			statvfs64(mnt->mnt_dir, &buf);
			ret += buf.f_bavail * buf.f_bsize;
		}
	}
	return(ret);
}
Esempio n. 12
0
static int
fsys_stat(int n)
{
	struct statvfs64 svfsb;
	struct fstable *fs_tab;

	if (n == BADFSYS)
		return (1);

	fs_tab = get_fs_entry(n);

	/*
	 * At this point, we know we need information
	 * about a particular filesystem, so we can do the
	 * statvfs() now.  For performance reasons, we only want to
	 * stat the filesystem once, at the first time we need to,
	 * and so we can key on whether or not we have the
	 * block size for that filesystem.
	 */
	if (fs_tab->bsize != 0)
		return (0);

	if (statvfs64(fs_tab->name, &svfsb)) {
		logerr(gettext(WRN_STATVFS), fs_tab->name);
		return (1);
	}

	/*
	 * statvfs returns number of fragment size blocks
	 * so will change this to number of 512 byte blocks
	 */
	fs_tab->bsize  = svfsb.f_bsize;
	fs_tab->frsize = svfsb.f_frsize;
	fs_tab->bfree  = ((svfsb.f_frsize > 0) ?
	    howmany(svfsb.f_frsize, DEV_BSIZE) :
	    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bavail;
	fs_tab->ffree  = (svfsb.f_favail > 0) ? svfsb.f_favail : svfsb.f_ffree;
	return (0);
}
Esempio n. 13
0
	bool FreeDiskSpace(const QString & path,Uint64 & bytes_free)
	{
#ifdef HAVE_STATVFS
#ifdef HAVE_STATVFS64
		struct statvfs64 stfs;
		if (statvfs64(QFile::encodeName(path), &stfs) == 0)
#else
		struct statvfs stfs;
		if (statvfs(QFile::encodeName(path), &stfs) == 0)
#endif
		{
			if (stfs.f_blocks == 0) // if this is 0, then we are using gvfs
				return false;

			bytes_free = ((Uint64)stfs.f_bavail) * ((Uint64)stfs.f_frsize);
			return true;
		}
		else
		{
			Out(SYS_GEN|LOG_DEBUG) << "Error : statvfs for " << path << " failed :  "
				<< QString(strerror(errno)) << endl;

			return false;
		}
#elif defined(Q_WS_WIN)
#ifdef UNICODE
		LPCWSTR tpath = (LPCWSTR)path.utf16();
#else
		const char *tpath = path.toLocal8Bit();
#endif
		if(GetDiskFreeSpaceEx(tpath, (PULARGE_INTEGER)&bytes_free, NULL, NULL)) {
			return true;
		} else {
			return false;
		}
#else
		return false;
#endif
	}
Esempio n. 14
0
qint64 Utility::freeDiskSpace(const QString &path, bool *ok)
{
#ifdef Q_OS_MAC
    struct statvfs stat;
    statvfs(path.toUtf8().data(), &stat);
    return (qint64) stat.f_bavail * stat.f_frsize;
#elif defined(Q_OS_UNIX)
    Q_UNUSED(ok)
    struct statvfs64 stat;
    statvfs64(path.toUtf8().data(), &stat);
    return (qint64) stat.f_bavail * stat.f_frsize;
#elif defined(Q_OS_WIN)
    ULARGE_INTEGER freeBytes;
    freeBytes.QuadPart = 0L;
    QString drive = QDir().absoluteFilePath(path).left(2);
    if( !GetDiskFreeSpaceEx( reinterpret_cast<const wchar_t *>(drive.utf16()), &freeBytes, NULL, NULL ) ) {
        if (ok) *ok = false;
    }
    return freeBytes.QuadPart;
#else
    if (ok) *ok = false;
    return 0;
#endif
}
Esempio n. 15
0
int
main(int argc, char *argv[])
{
	struct utsname utsbuf;
	struct statvfs64 svfsb;
	struct cfent	**eptlist;
	FILE	*fp;
	VFP_T	*vfp;
	int	i, c, n, eptnum, found,
		part, nparts, npkgs, objects;
	char	buf[MAX_PKG_PARAM_LENGTH];
	char	temp[MAX_PKG_PARAM_LENGTH];
	char	param[MAX_PKG_PARAM_LENGTH];
	char	*pt, *value, *pkginst, *tmpdir, *abi_sym_ptr,
		**cmdparam;
	char	*pkgname;
	char	*pkgvers;
	char	*pkgarch;
	char	*pkgcat;
	void	(*func)();
	time_t	clock;
	fsblkcnt_t	bsize = 0;
	fsblkcnt_t	frsize = 0;
	struct cl_attr	**allclass = NULL;
	struct cl_attr	**order;

	/* initialize locale environment */

	(void) setlocale(LC_ALL, "");

#if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) textdomain(TEXT_DOMAIN);

	/* initialize program name */

	(void) set_prog_name(argv[0]);

	/* tell spmi zones interface how to access package output functions */

	z_set_output_functions(echo, echoDebug, progerr);

	func = sigset(SIGINT, trap);
	if (func != SIG_DFL)
		func = sigset(SIGINT, func);
	func = sigset(SIGHUP, trap);
	setmapmode(MAPBUILD);	/* variable binding */
	if (func != SIG_DFL)
		func = sigset(SIGHUP, func);

	environ = NULL;
	while ((c = getopt(argc, argv, "osnp:l:r:b:d:f:a:v:?")) != EOF) {
		switch (c) {
		    case 'n':
			nflag++;
			break;

		    case 's':
			sflag++;
			break;

		    case 'o':
			overwrite++;
			break;

		    case 'p':
			putparam("PSTAMP", optarg);
			break;

		    case 'l':
			llimit = atol(optarg);
			break;

		    case 'r':
			pt = strtok(optarg, " \t\n, ");
			n = 0;
			do {
				rootlist[n++] = flex_device(pt, 0);
				if (n >= NROOT) {
					progerr(gettext(ERR_NROOT), NROOT);
					quit(1);
				}
			} while (pt = strtok(NULL, " \t\n, "));
			rootlist[n] = NULL;
			break;

		    case 'b':
			basedir = optarg;
			break;

		    case 'f':
			protofile = optarg;
			break;

		    case 'd':
			device = flex_device(optarg, 1);
			break;

		    case 'a':
			putparam("ARCH", optarg);
			break;

		    case 'v':
			putparam("VERSION", optarg);
			break;

		    default:
			usage();
		}
	}

	/*
	 * Store command line variable assignments for later
	 * incorporation into the environment.
	 */
	cmdparam = &argv[optind];

	/* Skip past equates. */
	while (argv[optind] && strchr(argv[optind], '='))
		optind++;

	/* Confirm that the instance name is valid */
	if ((pkginst = argv[optind]) != NULL) {
		if (pkgnmchk(pkginst, "all", 0)) {
			progerr(gettext(ERR_PKGINST), pkginst);
			quit(1);
		}
		argv[optind++] = NULL;
	}
	if (optind != argc)
		usage();

	tmpdir = getenv("TMPDIR");
	if (tmpdir == NULL)
		tmpdir = P_tmpdir;

	/* bug id 4244631, not ABI compliant */
	abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
	if (abi_sym_ptr && (strncasecmp(abi_sym_ptr, "TRUE", 4) == 0)) {
		set_nonABI_symlinks();
	}

	if (device == NULL) {
		device = devattr(SPOOLDEV, "pathname");
		if (device == NULL) {
			progerr(gettext(ERR_DEVICE), SPOOLDEV);
			exit(99);
		}
	}

	if (protofile == NULL) {
		if (access("prototype", 0) == 0)
			protofile = "prototype";
		else if (access("Prototype", 0) == 0)
			protofile = "Prototype";
		else {
			progerr(gettext(ERR_PROTOTYPE));
			quit(1);
		}
	}

	if (devtype(device, &pkgdev)) {
		progerr(gettext(ERR_BADDEV), device);
		quit(1);
	}
	if (pkgdev.norewind) {
		/* initialize datastream */
		progerr(gettext(ERR_DSTREAM), device);
		quit(1);
	}
	if (pkgdev.mount) {
		if (n = pkgmount(&pkgdev, NULL, 0, 0, 1))
			quit(n);
	}

	/*
	 * convert prototype file to a pkgmap, while locating
	 * package objects in the current environment
	 */
	t_pkgmap = tempnam(tmpdir, "tmpmap");
	if (t_pkgmap == NULL) {
		progerr(gettext(ERR_TEMP), errno);
		exit(99);
	}

	(void) fprintf(stderr, gettext(MSG_PROTOTYPE));
	if (n = mkpkgmap(t_pkgmap, protofile, cmdparam)) {
		progerr(gettext(ERR_BUILD));
		quit(1);
	}

	setmapmode(MAPNONE);	/* All appropriate variables are now bound */

	if (vfpOpen(&vfp, t_pkgmap, "r", VFP_NEEDNOW) != 0) {
		progerr(gettext(ERR_TEMP), errno);
		quit(99);
	}

	eptlist = procmap(vfp, 0, NULL);

	if (eptlist == NULL) {
		quit(1);
	}

	(void) vfpClose(&vfp);

	/* Validate the zone attributes in pkginfo, before creation */
	if (!valid_zone_attr(eptlist)) {
		progerr(ERR_PKGINFO_INVALID_OPTION_COMB);
		quit(1);
	}

	(void) fprintf(stderr, gettext(MSG_PKGINFO));
	pt = NULL;
	for (i = 0; eptlist[i]; i++) {
		ckmissing(eptlist[i]->path, eptlist[i]->ftype);
		if (eptlist[i]->ftype != 'i')
			continue;
		if (strcmp(eptlist[i]->path, "pkginfo") == 0)
			svept = eptlist[i];
	}
	if (svept == NULL) {
		progerr(gettext(ERR_NOPKGINFO));
		quit(99);
	}
	eptnum = i;

	/*
	 * process all parameters from the pkginfo file
	 * and place them in the execution environment
	 */

	if ((fp = fopen(svept->ainfo.local, "r")) == NULL) {
		progerr(gettext(ERR_RDPKGINFO), svept->ainfo.local);
		quit(99);
	}
	param[0] = '\0';
	while (value = fpkgparam(fp, param)) {
		if (getenv(param) == NULL)
			putparam(param, value);
		free((void *)value);
		param[0] = '\0';
	}
	(void) fclose(fp);

	/* add command line variables */
	while (*cmdparam && (value = strchr(*cmdparam, '=')) != NULL) {
		*value = NULL;	/* terminate the parameter */
		value++;	/* value is now the value (not '=') */
		putparam(*cmdparam++, value);  /* store it in environ */
	}

	/* make sure parameters are valid */
	(void) time(&clock);
	if (pt = getenv("PKG")) {
		if (pkgnmchk(pt, NULL, 0) || strchr(pt, '.')) {
			progerr(gettext(ERR_PKGABRV), pt);
			quit(1);
		}
		if (pkginst == NULL)
			pkginst = pt;
	} else {
		progerr(gettext(ERR_NOPARAM), "PKG", svept->path);
		quit(1);
	}
	/*
	 * verify consistency between PKG parameter and pkginst
	 */
	(void) snprintf(param, sizeof (param), "%s.*", pt);
	if (pkgnmchk(pkginst, param, 0)) {
		progerr(gettext(ERR_PKGMTCH), pt, pkginst);
		quit(1);
	}

	/*
	 * *********************************************************************
	 * this feature is removed starting with Solaris 10 - there is no built
	 * in list of packages that should be run "the old way"
	 * *********************************************************************
	 */

#ifdef	ALLOW_EXCEPTION_PKG_LIST
	/* Until 2.9, set it from the execption list */
	if (exception_pkg(pkginst, LINK))
		set_nonABI_symlinks();
#endif

	if ((pkgname = getenv("NAME")) == NULL) {
		progerr(gettext(ERR_NOPARAM), "NAME", svept->path);
		quit(1);
	}
	if (ckparam("NAME", pkgname))
		quit(1);
	if ((pkgvers = getenv("VERSION")) == NULL) {
		/* XXX - I18n */
		/* LINTED do not use cftime(); use strftime instead */
		(void) cftime(buf, "\045m/\045d/\045Y", &clock);
		(void) snprintf(temp, sizeof (temp),
			gettext("Dev Release %s"), buf);
		putparam("VERSION", temp);
		pkgvers = getenv("VERSION");
		logerr(gettext(WRN_SETPARAM), "VERSION", temp);
	}
	if (ckparam("VERSION", pkgvers))
		quit(1);
	if ((pkgarch = getenv("ARCH")) == NULL) {
		(void) uname(&utsbuf);
		putparam("ARCH", utsbuf.machine);
		pkgarch = getenv("ARCH");
		logerr(gettext(WRN_SETPARAM), "ARCH", utsbuf.machine);
	}
	if (ckparam("ARCH", pkgarch))
		quit(1);
	if (getenv("PSTAMP") == NULL) {
		/* use octal value of '%' to fight sccs expansion */
		/* XXX - I18n */
		/* LINTED do not use cftime(); use strftime instead */
		(void) cftime(buf, "\045Y\045m\045d\045H\045M\045S", &clock);
		(void) uname(&utsbuf);
		(void) snprintf(temp, sizeof (temp), "%s%s",
			utsbuf.nodename, buf);
		putparam("PSTAMP", temp);
		logerr(gettext(WRN_SETPARAM), "PSTAMP", temp);
	}
	if ((pkgcat = getenv("CATEGORY")) == NULL) {
		progerr(gettext(ERR_NOPARAM), "CATEGORY", svept->path);
		quit(1);
	}
	if (ckparam("CATEGORY", pkgcat))
		quit(1);

	/*
	 * warn user of classes listed in package which do
	 * not appear in CLASSES variable in pkginfo file
	 */
	objects = 0;
	for (i = 0; eptlist[i]; i++) {
		if (eptlist[i]->ftype != 'i') {
			objects++;
			addlist(&allclass, eptlist[i]->pkg_class);
		}
	}

	if ((pt = getenv("CLASSES")) == NULL) {
		if (allclass && *allclass) {
			cl_setl(allclass);
			cl_putl("CLASSES", allclass);
			logerr(gettext(WRN_SETPARAM), "CLASSES",
			    getenv("CLASSES"));
		}
	} else {
		cl_sets(qstrdup(pt));
		if (allclass && *allclass) {
			for (i = 0; allclass[i]; i++) {
				found = 0;
				if (cl_idx(allclass[i]->name) != -1) {
					found++;
					break;
				}
				if (!found) {
					logerr(gettext(WRN_CLASSES),
					    (char *)allclass[i]);
				}
			}
		}
	}

	(void) fprintf(stderr, gettext(MSG_VOLUMIZE), objects);
	order = (struct cl_attr **)0;
	if (pt = getenv("ORDER")) {
		pt = qstrdup(pt);
		(void) setlist(&order, pt);
		cl_putl("ORDER", order);
	}

	/* stat the intended output filesystem to get blocking information */
	if (pkgdev.dirname == NULL) {
		progerr(gettext(ERR_WHATVFS), device);
		quit(99);
	}
	if (statvfs64(pkgdev.dirname, &svfsb)) {
		progerr(gettext(ERR_STATVFS), pkgdev.dirname);
		quit(99);
	}

	if (bsize == 0) {
		bsize = svfsb.f_bsize;
	}
	if (frsize == 0) {
		frsize = svfsb.f_frsize;
	}
	if (limit == 0)
		/*
		 * bavail is in terms of fragment size blocks - change
		 * to 512 byte blocks
		 */
		limit = (((long)frsize > 0) ?
			howmany(frsize, DEV_BSIZE) :
			howmany(bsize, DEV_BSIZE)) * svfsb.f_bavail;
	if (ilimit == 0) {
		ilimit = (svfsb.f_favail > 0) ?
		    svfsb.f_favail : svfsb.f_ffree;
	}

	nparts = splpkgmap(eptlist, eptnum, (char **)order, bsize, frsize,
	    &limit, &ilimit, &llimit);

	if (nparts <= 0) {
		progerr(gettext(ERR_SPLIT));
		quit(1);
	}

	if (nflag) {
		for (i = 0; eptlist[i]; i++)
			(void) ppkgmap(eptlist[i], stdout);
		exit(0);
		/*NOTREACHED*/
	}

	(void) snprintf(pkgloc, sizeof (pkgloc), "%s/%s",
			pkgdev.dirname, pkginst);
	if (!isdir(pkgloc) && !overwrite) {
		progerr(gettext(ERR_OVERWRITE), pkgloc);
		quit(1);
	}

	/* output all environment install parameters */
	t_pkginfo = tempnam(tmpdir, "pkginfo");
	if ((fp = fopen(t_pkginfo, "w")) == NULL) {
		progerr(gettext(ERR_TEMP), errno);
		exit(99);
	}
	for (i = 0; environ[i]; i++) {
		if (isupper(*environ[i])) {
			(void) fputs(environ[i], fp);
			(void) fputc('\n', fp);
		}
	}
	(void) fclose(fp);

	started++;
	(void) rrmdir(pkgloc);
	if (mkdir(pkgloc, 0755)) {
		progerr(gettext(ERR_MKDIR), pkgloc);
		quit(1);
	}

	/* determine how many packages already reside on the medium */
	pkgdir = pkgdev.dirname;
	npkgs = 0;
	while (pt = fpkginst("all", NULL, NULL))
		npkgs++;
	(void) fpkginst(NULL); /* free resource usage */

	if (nparts > 1) {
		if (pkgdev.mount && npkgs) {
			progerr(gettext(ERR_ONEVOL));
			quit(1);
		}
	}

	/*
	 *  update pkgmap entry for pkginfo file, since it may
	 *  have changed due to command line or failure to
	 *  specify all neccessary parameters
	 */
	for (i = 0; eptlist[i]; i++) {
		if (eptlist[i]->ftype != 'i')
			continue;
		if (strcmp(eptlist[i]->path, "pkginfo") == 0) {
			svept = eptlist[i];
			svept->ftype = '?';
			svept->ainfo.local = t_pkginfo;
			(void) cverify(0, &svept->ftype, t_pkginfo,
				&svept->cinfo, 1);
			svept->ftype = 'i';
			break;
		}
	}

	if (nparts > 1)
		(void) fprintf(stderr, gettext(MSG_PACKAGEM), nparts);
	else
		(void) fprintf(stderr, gettext(MSG_PACKAGE1));

	for (part = 1; part <= nparts; part++) {
		if ((part > 1) && pkgdev.mount) {
			if (pkgumount(&pkgdev)) {
				progerr(gettext(ERR_UMOUNT), pkgdev.mount);
				quit(99);
			}
			if (n = pkgmount(&pkgdev, NULL, part, nparts, 1))
				quit(n);
			(void) rrmdir(pkgloc);
			if (mkdir(pkgloc, 0555)) {
				progerr(gettext(ERR_MKDIR), pkgloc);
				quit(99);
			}
		}
		outvol(eptlist, eptnum, part, nparts);

		/* Validate (as much as possible) the control scripts. */
		if (part == 1) {
			char inst_path[PATH_MAX];

			(void) fprintf(stderr, gettext(MSG_VALSCRIPTS));
			(void) snprintf(inst_path, sizeof (inst_path),
					"%s/install", pkgloc);
			checkscripts(inst_path, 0);
		}
	}

	quit(0);
	/*NOTREACHED*/
}
Esempio n. 16
0
static int
pkgxfer(char *srcinst, int options)
{
	int	r;
	struct pkginfo info;
	FILE	*fp, *pp;
	char	*pt, *src, *dst;
	char	dstdir[PATH_MAX],
		temp[PATH_MAX],
		srcdir[PATH_MAX],
		cmd[CMDSIZE],
		pkgname[NON_ABI_NAMELNGTH];
	int	i, n, part, nparts, maxpartsize, curpartcnt, iscomp;
	char	volnos[128], tmpvol[128];
	struct	statvfs64 svfsb;
	longlong_t free_blocks;
	struct	stat	srcstat;

	info.pkginst = NULL; /* required initialization */

	/*
	 * when this routine is entered, the first part of
	 * the package to transfer is already available in
	 * the directory indicated by 'src' --- unless the
	 * source device is a datstream, in which case only
	 * the pkginfo and pkgmap files are available in 'src'
	 */
	src = srcdev.dirname;
	dst = dstdev.dirname;

	if (!(options & PT_SILENT))
		(void) fprintf(stderr, pkg_gt(MSG_TRANSFER), srcinst);
	(void) strlcpy(dstinst, srcinst, sizeof (dstinst));

	if (!(options & PT_ODTSTREAM)) {
		/* destination is a (possibly mounted) directory */
		(void) snprintf(dstdir, sizeof (dstdir),
		    "%s/%s", dst, dstinst);

		/*
		 * need to check destination directory to assure
		 * that we will not be duplicating a package which
		 * already resides there (though we are allowed to
		 * overwrite the same version)
		 */
		pkgdir = src;
		if (fpkginfo(&info, srcinst)) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_NOEXISTS), srcinst);
			(void) fpkginfo(&info, NULL);
			return (1);
		}
		pkgdir = dst;

		(void) strlcpy(temp, srcinst, sizeof (temp));
		if (pt = strchr(temp, '.'))
			*pt = '\0';
		(void) strlcat(temp, ".*", sizeof (temp));

		if (pt = fpkginst(temp, info.arch, info.version)) {
			/*
			 * the same instance already exists, although
			 * its pkgid might be different
			 */
			if (options & PT_OVERWRITE) {
				(void) strlcpy(dstinst, pt, sizeof (dstinst));
				(void) snprintf(dstdir, sizeof (dstdir),
				    "%s/%s", dst, dstinst);
			} else {
				progerr(pkg_gt(ERR_TRANSFER));
				logerr(pkg_gt(MSG_DUPVERS), srcinst);
				(void) fpkginfo(&info, NULL);
				(void) fpkginst(NULL);
				return (2);
			}
		} else if (options & PT_RENAME) {
			/*
			 * find next available instance by appending numbers
			 * to the package abbreviation until the instance
			 * does not exist in the destination directory
			 */
			if (pt = strchr(temp, '.'))
				*pt = '\0';
			for (i = 2; (access(dstdir, 0) == 0); i++) {
				(void) snprintf(dstinst, sizeof (dstinst),
				    "%s.%d", temp, i);
				(void) snprintf(dstdir, sizeof (dstdir),
				    "%s/%s", dst, dstinst);
			}
		} else if (options & PT_OVERWRITE) {
			/*
			 * we're allowed to overwrite, but there seems
			 * to be no valid package to overwrite, and we are
			 * not allowed to rename the destination, so act
			 * as if we weren't given permission to overwrite
			 * --- this keeps us from removing a destination
			 * instance which is named the same as the source
			 * instance, but really reflects a different pkg!
			 */
			options &= (~PT_OVERWRITE);
		}
		(void) fpkginfo(&info, NULL);
		(void) fpkginst(NULL);

		if (ckoverwrite(dst, dstinst, options))
			return (2);

		if (isdir(dstdir) && mkdir(dstdir, 0755)) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_MKDIR), dstdir);
			return (1);
		}

		(void) snprintf(srcdir, sizeof (srcdir),
		    "%s/%s", src, srcinst);
		if (stat(srcdir, &srcstat) != -1) {
			if (chmod(dstdir, (srcstat.st_mode & S_IAMB)) == -1) {
				progerr(pkg_gt(ERR_TRANSFER));
				logerr(pkg_gt(MSG_CHMODDIR), dstdir);
				return (1);
			}
		} else {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_STATDIR), srcdir);
			return (1);
		}
	}

	if (!(options & PT_SILENT) && strcmp(dstinst, srcinst))
		(void) fprintf(stderr, pkg_gt(MSG_RENAME), dstinst);

	(void) snprintf(srcdir, sizeof (srcdir), "%s/%s", src, srcinst);
	if (chdir(srcdir)) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_CHDIR), srcdir);
		return (1);
	}

	if (ids_name) {	/* unpack the datatstream into a directory */
		/*
		 * transfer pkginfo & pkgmap first
		 */
		(void) snprintf(cmd, sizeof (cmd),
		    "%s -pudm %s", CPIOPROC, dstdir);
		if ((pp = epopen(cmd, "w")) == NULL) {
			rpterr();
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_POPEN), cmd, errno);
			return (1);
		}
		(void) fprintf(pp, "%s\n%s\n", PKGINFO, PKGMAP);

		(void) sighold(SIGINT);
		(void) sighold(SIGHUP);
		r = epclose(pp);
		(void) sigrelse(SIGINT);
		(void) sigrelse(SIGHUP);

		if (r != 0) {
			rpterr();
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_PCLOSE), cmd, errno);
			return (1);
		}

		if (options & PT_INFO_ONLY)
			return (0); /* don't transfer objects */

		if (chdir(dstdir)) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_CHDIR), dstdir);
			return (1);
		}

		/*
		 * for each part of the package, use cpio() to
		 * unpack the archive into the destination directory
		 */
		nparts = ds_findpkg(srcdev.cdevice, srcinst);
		if (nparts < 0) {
			progerr(pkg_gt(ERR_TRANSFER));
			return (1);
		}
		for (part = 1; part <= nparts; /* void */) {
			if (ds_getpkg(srcdev.cdevice, part, dstdir)) {
				progerr(pkg_gt(ERR_TRANSFER));
				return (1);
			}
			part++;
			if (dstdev.mount) {
				(void) chdir("/");
				if (pkgumount(&dstdev))
					return (1);
				if (part <= nparts) {
					if (n = pkgmount(&dstdev, NULL, part+1,
					    nparts, 1))
						return (n);
					if (ckoverwrite(dst, dstinst, options))
						return (1);
					if (isdir(dstdir) &&
					    mkdir(dstdir, 0755)) {
						progerr(
						    pkg_gt(ERR_TRANSFER));
						logerr(pkg_gt(MSG_MKDIR),
						    dstdir);
						return (1);
					}
					/*
					 * since volume is removable, each part
					 * must contain a duplicate of the
					 * pkginfo file to properly identify the
					 * volume
					 */
					if (chdir(srcdir)) {
						progerr(
						    pkg_gt(ERR_TRANSFER));
						logerr(pkg_gt(MSG_CHDIR),
						    srcdir);
						return (1);
					}
					if ((pp = epopen(cmd, "w")) == NULL) {
						rpterr();
						progerr(
						    pkg_gt(ERR_TRANSFER));
						logerr(pkg_gt(MSG_POPEN),
						    cmd, errno);
						return (1);
					}
					(void) fprintf(pp, "pkginfo");

					(void) sighold(SIGINT);
					(void) sighold(SIGHUP);
					r = epclose(pp);
					(void) sigrelse(SIGINT);
					(void) sigrelse(SIGHUP);

					if (r != 0) {
						rpterr();
						progerr(
						    pkg_gt(ERR_TRANSFER));
						logerr(pkg_gt(MSG_PCLOSE),
						    cmd, errno);
						return (1);
					}
					if (chdir(dstdir)) {
						progerr(
						    pkg_gt(ERR_TRANSFER));
						logerr(pkg_gt(MSG_CHDIR),
						    dstdir);
						return (1);
					}
				}
			}
		}
		return (0);
	}

	if ((fp = fopen(PKGMAP, "r")) == NULL) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
		return (1);
	}

	nparts = 1;
	if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
		return (1);
	else
		(void) fclose(fp);

	if (srcdev.mount) {
		if (ckvolseq(srcdir, 1, nparts)) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_SEQUENCE));
			return (1);
		}
	}

	/* write each part of this package */
	if (options & PT_ODTSTREAM) {
		char line[128];
		(void) mgets(line, 128);
		curpartcnt = -1;
		/* LINTED E_SEC_SCANF_UNBOUNDED_COPY */
		if (sscanf(line, "%s %d %d %[ 0-9]", pkgname, &nparts,
		    &maxpartsize, volnos) == 4) {
			(void) sscanf(volnos,
			    "%d %[ 0-9]", &curpartcnt, tmpvol);
			(void) strlcpy(volnos, tmpvol, sizeof (volnos));
		}
	}

	for (part = 1; part <= nparts; /* void */) {
		if (curpartcnt == 0 && (options & PT_ODTSTREAM)) {
			char prompt[128];
			int index;
			ds_volno++;
			(void) ds_close(0);
			(void) sprintf(prompt,
			    pkg_gt("Insert %%v %d of %d into %%p"),
			    ds_volno, ds_volcnt);
			if (n = getvol(ods_name, NULL, DM_FORMAT, prompt))
				return (n);
			if ((ds_fd = open(dstdev.cdevice, O_WRONLY)) < 0) {
				progerr(pkg_gt(ERR_TRANSFER));
				logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
				    errno);
				return (1);
			}
			if (ds_ginit(dstdev.cdevice) < 0) {
				progerr(pkg_gt(ERR_TRANSFER));
				logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
				    errno);
				(void) ds_close(0);
				return (1);
			}

			(void) sscanf(volnos, "%d %[ 0-9]", &index, tmpvol);
			(void) strlcpy(volnos, tmpvol, sizeof (volnos));
			curpartcnt += index;
		}

		if (options & PT_INFO_ONLY)
			nparts = 0;

		if (part == 1) {
			(void) snprintf(cmd, sizeof (cmd),
			    "find %s %s", PKGINFO, PKGMAP);
			if (nparts && (isdir(INSTALL) == 0)) {
				(void) strlcat(cmd, " ", sizeof (cmd));
				(void) strlcat(cmd, INSTALL, sizeof (cmd));
			}
		} else
			(void) snprintf(cmd, sizeof (cmd), "find %s", PKGINFO);

		if (nparts > 1) {
			(void) snprintf(temp, sizeof (temp),
			    "%s.%d", RELOC, part);
			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
				(void) strlcat(cmd, " ", sizeof (cmd));
				(void) strlcat(cmd, temp, sizeof (cmd));
			}
			(void) snprintf(temp, sizeof (temp),
			    "%s.%d", ROOT, part);
			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
				(void) strlcat(cmd, " ", sizeof (cmd));
				(void) strlcat(cmd, temp, sizeof (cmd));
			}
			(void) snprintf(temp, sizeof (temp),
			    "%s.%d", ARCHIVE, part);
			if (isdir(temp) == 0) {
				(void) strlcat(cmd, " ", sizeof (cmd));
				(void) strlcat(cmd, temp, sizeof (cmd));
			}
		} else if (nparts) {
			for (i = 0; reloc_names[i] != NULL; i++) {
				if (iscpio(reloc_names[i], &iscomp) ||
				    isdir(reloc_names[i]) == 0) {
					(void) strlcat(cmd, " ", sizeof (cmd));
					(void) strlcat(cmd, reloc_names[i],
					    sizeof (cmd));
				}
			}
			for (i = 0; root_names[i] != NULL; i++) {
				if (iscpio(root_names[i], &iscomp) ||
				    isdir(root_names[i]) == 0) {
					(void) strlcat(cmd, " ", sizeof (cmd));
					(void) strlcat(cmd, root_names[i],
					    sizeof (cmd));
				}
			}
			if (isdir(ARCHIVE) == 0) {
				(void) strlcat(cmd, " ", sizeof (cmd));
				(void) strlcat(cmd, ARCHIVE, sizeof (cmd));
			}
		}
		if (options & PT_ODTSTREAM) {
			(void) snprintf(cmd + strlen(cmd),
			    sizeof (cmd) - strlen(cmd),
			    " -print | %s -ocD -C %d",
			    CPIOPROC, (int)BLK_SIZE);
		} else {
			if (statvfs64(dstdir, &svfsb) == -1) {
				progerr(pkg_gt(ERR_TRANSFER));
				logerr(pkg_gt(MSG_STATVFS), dstdir, errno);
				return (1);
			}

			free_blocks = (((long)svfsb.f_frsize > 0) ?
			    howmany(svfsb.f_frsize, DEV_BSIZE) :
			    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bavail;

			if ((has_comp_size ? compressedsize : maxpartsize) >
			    free_blocks) {
				progerr(pkg_gt(ERR_TRANSFER));
				logerr(pkg_gt(MSG_NOSPACE),
				    has_comp_size ?
				    (long)compressedsize : (long)maxpartsize,
				    free_blocks);
				return (1);
			}
			(void) snprintf(cmd + strlen(cmd),
			    sizeof (cmd) - strlen(cmd),
			    " -print | %s -pdum %s",
			    CPIOPROC, dstdir);
		}

		n = esystem(cmd, -1, (options & PT_ODTSTREAM) ? ds_fd : -1);
		if (n) {
			rpterr();
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
			return (1);
		}

		part++;
		if (srcdev.mount && (nparts > 1)) {
			/* unmount current source volume */
			(void) chdir("/");
			if (pkgumount(&srcdev))
				return (1);
			/* loop until volume is mounted successfully */
			while (part <= nparts) {
				/* read only */
				n = pkgmount(&srcdev, NULL, part, nparts, 1);
				if (n)
					return (n);
				if (chdir(srcdir)) {
					progerr(pkg_gt(ERR_TRANSFER));
					logerr(pkg_gt(MSG_CORRUPT));
					(void) chdir("/");
					(void) pkgumount(&srcdev);
					continue;
				}
				if (ckvolseq(srcdir, part, nparts)) {
					(void) chdir("/");
					(void) pkgumount(&srcdev);
					continue;
				}
				break;
			}
		}
		if (!(options & PT_ODTSTREAM) && dstdev.mount) {
			/* unmount current volume */
			if (pkgumount(&dstdev))
				return (1);
			/* loop until next volume is mounted successfully */
			while (part <= nparts) {
				/* writable */
				n = pkgmount(&dstdev, NULL, part, nparts, 1);
				if (n)
					return (n);
				if (ckoverwrite(dst, dstinst, options))
					continue;
				if (isdir(dstdir) && mkdir(dstdir, 0755)) {
					progerr(pkg_gt(ERR_TRANSFER));
					logerr(pkg_gt(MSG_MKDIR), dstdir);
					continue;
				}
				break;
			}
		}

		if ((options & PT_ODTSTREAM) && part <= nparts) {
			if (curpartcnt >= 0 && part > curpartcnt) {
				char prompt[128];
				int index;
				ds_volno++;
				if (ds_close(0))
					return (1);
				(void) sprintf(prompt,
				    pkg_gt("Insert %%v %d of %d into %%p"),
				    ds_volno, ds_volcnt);
				if (n = getvol(ods_name, NULL, DM_FORMAT,
				    prompt))
					return (n);
				if ((ds_fd = open(dstdev.cdevice, 1)) < 0) {
					progerr(pkg_gt(ERR_TRANSFER));
					logerr(pkg_gt(MSG_OPEN),
					    dstdev.cdevice, errno);
					return (1);
				}
				if (ds_ginit(dstdev.cdevice) < 0) {
					progerr(pkg_gt(ERR_TRANSFER));
					logerr(pkg_gt(MSG_OPEN),
					    dstdev.cdevice, errno);
					(void) ds_close(0);
					return (1);
				}

				(void) sscanf(volnos, "%d %[ 0-9]", &index,
				    tmpvol);
				(void) strlcpy(volnos, tmpvol, sizeof (volnos));
				curpartcnt += index;
			}
		}

	}
	return (0);
}
Esempio n. 17
0
/*
 * Execute command.
 */
void
DoCommand(
	Client_t *cli)
{
	int rc;
	char *cmd_name;
	char *lasts;
	char *msg;

	rc = 0;
	SetErrno = 0;

	msg = cli->cmdbuf;
	/*
	 * Extract command name.
	 */
/* LINTED improper pointer/integer combination */
	cmd_name = strtok_r(msg, " ", &lasts);

	if (strcmp(cmd_name, SAMRFT_CMD_CONNECT) == 0) {
		SendReply(cli, "%s %d %d", SAMRFT_CMD_CONNECT, 0, 0);

	} else if (strcmp(cmd_name, SAMRFT_CMD_CONFIG) == 0) {
		char *hostname;
		int blksize;
		int tcpwindowsize;

		hostname = getString(&lasts);
		blksize = GetCfgBlksize();
		tcpwindowsize = GetCfgTcpWindowsize();

		SamStrdup(cli->hostname, hostname);
		rc = CreateCrew(cli, 1, blksize);

		SendReply(cli, "%s %d %d %d %d",
		    SAMRFT_CMD_CONFIG, rc, 1, blksize, tcpwindowsize);

	} else if (strcmp(cmd_name, SAMRFT_CMD_OPEN) == 0) {
		char *filename;
		int oflag;
		SamrftCreateAttr_t creat;

		filename = getString(&lasts);
		oflag = getInteger(&lasts);

		if (getInteger(&lasts)) {
			(void) memset((char *)&creat, 0,
			    sizeof (SamrftCreateAttr_t));
			creat.mode = getInteger(&lasts);
			creat.uid = getInteger(&lasts);
			creat.gid = getInteger(&lasts);
			rc = OpenFile(cli, filename, oflag, &creat);
		} else {
			rc = OpenFile(cli, filename, oflag, NULL);
		}

		SendReply(cli, "%s %d %d", SAMRFT_CMD_OPEN, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_DPORT) == 0) {
		struct sockaddr_in data;
		int seqnum;
		char *addr = (char *)&data.sin_addr;
		char *port = (char *)&data.sin_port;

		(void) memset((char *)&data, 0, sizeof (struct sockaddr_in));
		data.sin_family = AF_INET;

		seqnum = getInteger(&lasts);

		/*
		 * Addr.
		 */
		addr[0] = getInteger(&lasts);
		addr[1] = getInteger(&lasts);
		addr[2] = getInteger(&lasts);
		addr[3] = getInteger(&lasts);

		/*
		 * Port.
		 */
		port[0] = getInteger(&lasts);
		port[1] = getInteger(&lasts);

		rc = InitDataConnection(cli, "r", seqnum,
		    data.sin_family, (struct sockaddr *)&data);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_DPORT, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_DPORT6) == 0) {
		struct sockaddr_in6 data;
		struct sockaddr_in *data4 = (struct sockaddr_in *)&data;
		int i;
		int seqnum;
		char *addr;
		char *port;

		(void) memset((char *)&data, 0, sizeof (struct sockaddr_in6));

		seqnum = getInteger(&lasts);

		/*
		 * Address family.
		 */
		data.sin6_family = getInteger(&lasts);
		if (data.sin6_family == AF_INET6) {
			addr = (char *)&data.sin6_addr;
			port = (char *)&data.sin6_port;
		} else {
			addr = (char *)&data4->sin_addr;
			port = (char *)&data4->sin_port;
		}

		/*
		 * Addr.
		 */
		for (i = 0; i < 16; i++) {
			addr[i] = getInteger(&lasts);
		}

		/*
		 * Port.
		 */
		port[0] = getInteger(&lasts);
		port[1] = getInteger(&lasts);

		rc = InitDataConnection(cli, "r", seqnum,
		    data.sin6_family, (struct sockaddr *)&data);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_DPORT6, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_STOR) == 0) {
		fsize_t nbytes;

		nbytes = getLongLong(&lasts);
		rc = ReceiveData(cli, nbytes);

	} else if (strcmp(cmd_name, SAMRFT_CMD_SEND) == 0) {
		size_t nbytes;

		nbytes = getInteger(&lasts);

		rc = ReceiveData(cli, nbytes);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_SEND, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_RECV) == 0) {
		size_t nbytes;

		nbytes = getInteger(&lasts);

		/*
		 * Process receive command from client.  Send data from local
		 * file over data sockets to the client process.
		 */
		rc = SendData(cli, nbytes);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_RECV, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_SEEK) == 0) {
		off64_t setpos;
		int whence;
		off64_t offset;

		setpos = getLongLong(&lasts);
		whence = getInteger(&lasts);

		rc = SeekFile(cli, setpos, whence, &offset);
		SendReply(cli, "%s %d %d %lld", SAMRFT_CMD_SEEK,
		    rc, errno, offset);

	} else if (strcmp(cmd_name, SAMRFT_CMD_FLOCK) == 0) {
		int type;

		type = getInteger(&lasts);

		rc = FlockFile(cli, type);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_FLOCK, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_ARCHIVEOP) == 0) {
		char *path;
		char *ops;

		path = getString(&lasts);
		ops = getString(&lasts);

		rc = sam_archive(path, ops);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_ARCHIVEOP, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_CLOSE) == 0) {

		rc = CloseFile(cli);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_CLOSE, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_UNLINK) == 0) {
		char *name;

		name = getString(&lasts);

		rc = UnlinkFile(cli, name);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_UNLINK, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_DISCONN) == 0) {

		Trace(TR_DEBUG, "RFT disconnect, no reply: '%s'", cli->cmdbuf);
		CleanupCrew(cli);
		cli->disconnect = 1;

		/*
		 * No reply.
		 */

	} else if (strcmp(cmd_name, SAMRFT_CMD_ISMOUNTED) == 0) {
		int mounted;
		char *mount_point;

		mount_point = getString(&lasts);

		mounted = IsMounted(cli, mount_point);
		SendReply(cli, "%s %d", SAMRFT_CMD_ISMOUNTED, mounted);

	} else if (strcmp(cmd_name, SAMRFT_CMD_STAT) == 0) {
		struct stat64 buf;
		char *filename;

		filename = getString(&lasts);

		(void) memset(&buf, 0, sizeof (buf));
		rc = stat64(filename, &buf);
		SendReply(cli, "%s %d %d %d %d %d %lld",
		    SAMRFT_CMD_STAT, rc, errno,
		    buf.st_mode, buf.st_uid, buf.st_gid, buf.st_size);

	} else if (strcmp(cmd_name, SAMRFT_CMD_STATVFS) == 0) {
		struct statvfs64 buf;
		char *mount_point;
		int offlineFiles;
		fsize_t offlineFileSize;

		mount_point = getString(&lasts);
		offlineFiles = getInteger(&lasts);

		(void) memset(&buf, 0, sizeof (buf));
		rc = statvfs64(mount_point, &buf);

		if (rc == 0 && (strcmp(buf.f_basetype, "samfs") == 0) &&
		    offlineFiles == B_TRUE) {
			offlineFileSize = DiskVolsOfflineFiles(mount_point);
			/*
			 * Adjust capacity to include size of offline files.
			 */
			buf.f_blocks += offlineFileSize / buf.f_frsize;
		}

		SendReply(cli, "%s %d %d %lld %lld %ld %s",
		    SAMRFT_CMD_STATVFS, rc, errno,
		    buf.f_bfree, buf.f_blocks, buf.f_frsize, buf.f_basetype);

	} else if (strcmp(cmd_name, SAMRFT_CMD_SPACEUSED) == 0) {
		char *path;
		fsize_t spaceUsed;

		path = getString(&lasts);

		spaceUsed = DiskVolsAccumSpaceUsed(path);

		SendReply(cli, "%s %d %d %lld",
		    SAMRFT_CMD_SPACEUSED, rc, errno, spaceUsed);

	} else if (strcmp(cmd_name, SAMRFT_CMD_MKDIR) == 0) {
		char *dirname;
		int mode, uid, gid;

		dirname = getString(&lasts);
		mode = getInteger(&lasts);
		uid = getInteger(&lasts);
		gid = getInteger(&lasts);

		rc = MkDir(cli, dirname, mode, uid, gid);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_MKDIR, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_OPENDIR) == 0) {
		char *dirname;
		int dirp;

		dirname = getString(&lasts);

		rc = OpenDir(cli, dirname, &dirp);
		SendReply(cli, "%s %d %d %d", SAMRFT_CMD_OPENDIR,
		    rc, errno, dirp);

	} else if (strcmp(cmd_name, SAMRFT_CMD_READDIR) == 0) {
		int dirp;
		SamrftReaddirInfo_t dir_info;

		dirp = getInteger(&lasts);

		rc = ReadDir(cli, dirp, &dir_info);
		if (rc == 0) {
			SendReply(cli, "%s %d %d %s %d", SAMRFT_CMD_READDIR,
			    rc, errno, dir_info.name, dir_info.isdir);
		} else {
			SendReply(cli, "%s %d %d", SAMRFT_CMD_READDIR,
			    rc, errno);
		}

	} else if (strcmp(cmd_name, SAMRFT_CMD_CLOSEDIR) == 0) {
		int dirp;

		dirp = getInteger(&lasts);

		CloseDir(cli, dirp);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_CLOSEDIR, 0, 0);

	} else if (strcmp(cmd_name, SAMRFT_CMD_RMDIR) == 0) {
		char *dirname;

		dirname = getString(&lasts);

		rc = RmDir(cli, dirname);
		SendReply(cli, "%s %d %d", SAMRFT_CMD_CLOSEDIR, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_LOADVOL) == 0) {
		struct sam_rminfo rb;
		int oflag;

		/*
		 * Create sam_rminfo structure used to create
		 * a removable-media file.
		 */
		(void) memset(&rb, 0, sizeof (rb));

		rb.flags = getInteger(&lasts);

		(void) strncpy(rb.file_id,  getString(&lasts),
		    sizeof (rb.file_id));
		(void) strncpy(rb.owner_id, getString(&lasts),
		    sizeof (rb.owner_id));
		(void) strncpy(rb.group_id, getString(&lasts),
		    sizeof (rb.group_id));

		rb.n_vsns = 1;
		(void) strncpy(rb.media, getString(&lasts), sizeof (rb.media));
		(void) strncpy(rb.section[0].vsn, getString(&lasts),
		    sizeof (rb.section[0].vsn));

		oflag = getInteger(&lasts);

		rc = LoadVol(cli, &rb, oflag);

		SendReply(cli, "%s %d %d", SAMRFT_CMD_LOADVOL, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_GETVOLINFO) == 0) {
		struct sam_rminfo getrm;
		int eq;

		rc = GetVolInfo(cli, &getrm, &eq);

		SendReply(cli, "%s %d %d %d %lld %d", SAMRFT_CMD_GETVOLINFO,
		    rc, errno, getrm.block_size, getrm.position, eq);

	} else if (strcmp(cmd_name, SAMRFT_CMD_SEEKVOL) == 0) {
		int block;

		block = getInteger(&lasts);

		rc = SeekVol(cli, block);

		SendReply(cli, "%s %d %d", SAMRFT_CMD_SEEKVOL, rc, errno);

	} else if (strcmp(cmd_name, SAMRFT_CMD_UNLOADVOL) == 0) {
		struct sam_ioctl_rmunload unload;

		/*
		 * Create sam_rmunload structure used to unload
		 * a removable-media file.
		 */
		(void) memset(&unload, 0, sizeof (unload));

		unload.flags = getInteger(&lasts);

		rc = UnloadVol(cli, &unload);

		SendReply(cli, "%s %d %d %lld", SAMRFT_CMD_UNLOADVOL,
		    rc, errno, unload.position);
	} else {
		Trace(TR_ERR, "Unknown RFT command: %s", cmd_name);
	}
}
TEST(sys_statvfs, statvfs64) {
  struct statvfs64 sb;
  ASSERT_EQ(0, statvfs64("/proc", &sb));
  Check(sb);
}
Esempio n. 19
0
/*
 * This function installs the database lock, opens the contents file for
 * reading and creates and opens the temporary contents file for read/write.
 * It returns 1 if successful, 0 otherwise.
 */
int
ocfile(PKGserver *server, VFP_T **r_tmpvfp, fsblkcnt_t map_blks)
{
	struct	stat64	statb, statl;
	struct	statvfs64	svfsb;
	fsblkcnt_t free_blocks;
	fsblkcnt_t need_blocks;
	fsblkcnt_t log_blocks;
	VFP_T		*tmpvfp = (VFP_T *)NULL;
	char		contents[PATH_MAX];
	char		logfile[PATH_MAX];
	int		n;
	off_t		cdiff_alloc;
	PKGserver	newserver;

	/* establish package administration contents directory location */

	if (pkgadm_dir == NULL) {
		if (set_cfdir(NULL) != 0) {
			progerr(gettext(ERR_CFDIR));
			return (0);
		}
	}

	/* Lock the file for exclusive access */

	if (!pkgWlock(1)) {
		progerr(gettext(ERR_NOLOCK));
		return (0);
	}

	if (*server != NULL) {
		vfpTruncate(*r_tmpvfp);
		(void) vfpClearModified(*r_tmpvfp);

		return (1);
	}

	newserver = pkgopenserver(NULL, pkgadm_dir, B_FALSE);

	/* The error has been reported. */
	if (newserver == NULL)
		return (0);

	/* reset return VFP/FILE pointers */

	(*r_tmpvfp) = (VFP_T *)NULL;

	/* determine path to the primary contents file */
	(void) snprintf(contents, sizeof (contents), "%s/contents", pkgadm_dir);

	/*
	 * Check and see if there is enough space for the packaging commands
	 * to back up the contents file, if there is not, then do not allow
	 * execution to continue by failing the ocfile() call.
	 */

	/* Get the contents file size */

	if (stat64(contents, &statb) == -1) {
		int	lerrno = errno;

		progerr(gettext(ERR_NOCFILE), contents);
		logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
		pkgcloseserver(newserver);
		return (0);
	}

	/* Get the filesystem space */

	if (statvfs64(contents, &svfsb) == -1) {
		int	lerrno = errno;

		progerr(gettext(ERR_NOSTATV), contents);
		logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
		pkgcloseserver(newserver);
		return (0);
	}

	free_blocks = (((fsblkcnt_t)svfsb.f_frsize > 0) ?
	    howmany(svfsb.f_frsize, DEV_BSIZE) :
	    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree;

	/* determine blocks used by the logfile */
	(void) snprintf(logfile, sizeof (logfile), "%s/" PKGLOG, pkgadm_dir);

	if (stat64(logfile, &statl) == -1)
		log_blocks = 0;
	else
		log_blocks = nblk(statl.st_size, svfsb.f_bsize, svfsb.f_frsize);

	/*
	 * Calculate the number of blocks we need to be able to operate on
	 * the contents file and the log file.
	 * When adding a package (map_blks > 0), we add the size of the
	 * pkgmap file times 1.5 as the pkgmap is a bit smaller then the
	 * lines added to the contents file.  That data is written both to
	 * the new contents file and the log file (2 * 1.5 * map_blks).
	 * The new contents file is limited by the size of the current
	 * contents file and the increased log file.
	 * If we're removing a package, then the log might grow to the size
	 * of the full contents file but then the new contents file would
	 * be zero and so we only need to add the size of the contents file.
	 */
	need_blocks = map_blks * 3 +
	    /* Current log file */
	    log_blocks +
	    /* Current contents file */
	    nblk(statb.st_size, svfsb.f_bsize, svfsb.f_frsize);

	if ((need_blocks + 10) > free_blocks) {
		progerr(gettext(ERR_CFBACK), contents);
		progerr(gettext(ERR_CFBACK1), need_blocks, free_blocks,
		    DEV_BSIZE);
		pkgcloseserver(newserver);
		return (0);
	}

	/*
	 * open the temporary contents file without a path name - this causes
	 * the "vfp" to be opened on in-memory storage only, the size of which
	 * is set following a successful return - this causes the temporary
	 * contents file to be maintained in memory only - if no changes are
	 * made as the primary contents file is processed, the in memory data
	 * is discarded and not written to the disk.
	 */

	if (vfpOpen(&tmpvfp, (char *)NULL, "w", VFP_NONE) != 0) {
		int	lerrno = errno;

		progerr(gettext(ERR_NOTMPOPEN));
		logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
		pkgcloseserver(newserver);
		return (0);
	}

	/*
	 * set size of allocation for temporary contents file - this sets the
	 * size of the in-memory buffer associated with the open vfp.
	 * We only store the new and changed entries.
	 * We allocate memory depending on the size of the pkgmap; it's not
	 * completely right but <some value + * 1.5 * map_blks * DEV_BSIZE>
	 * seems fine (an install adds the size if the name of the package.)
	 */

	cdiff_alloc = map_blks * DEV_BSIZE;
	cdiff_alloc += cdiff_alloc/2;
	if (cdiff_alloc < 1000000)
		cdiff_alloc += 1000000;

	if (vfpSetSize(tmpvfp, cdiff_alloc) != 0) {
		int	lerrno = errno;

		progerr(gettext(ERR_NOTMPOPEN));
		logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
		(void) vfpClose(&tmpvfp);
		pkgcloseserver(newserver);
		return (0);
	}

	/* set return ->s to open server/vfps */

	(*r_tmpvfp) = tmpvfp;
	*server = newserver;

	return (1);	/* All OK */
}
Esempio n. 20
0
/*
 * We have an array of entities that are potentially stat-able.  Using
 * the name (e_name) of the entity, attempt to construct a ksname suitable
 * for use by kstat_lookup(3kstat) and fill it into the e_ksname member.
 *
 * We check the e_name against the list of file system types.  If there is
 * no match then test to see if the path is valid.  If the path is valid,
 * then determine the mountpoint.
 */
void
set_ksnames(entity_t *entities, int nentities, char **fstypes, int nfstypes)
{
	int		i, j;
	struct statvfs64 statvfsbuf;

	for (i = 0; i < nentities; i++) {
		entity_t	*ep = &entities[i];

		/* Check the name against the list of fstypes */
		for (j = 1; j < nfstypes; j++) {
			if (fstypes[j] && ep->e_name &&
			    strcmp(ep->e_name, fstypes[j]) == 0) {
				/* It's a file system type */
				ep->e_type = ENTYPE_FSTYPE;
				(void) snprintf(ep->e_ksname, KSTAT_STRLEN,
				    "%s%s", VOPSTATS_STR, ep->e_name);
				/* Now allocate the vopstats array */
				ep->e_vs = calloc(VS_SIZE, sizeof (vopstats_t));
				if (entities[i].e_vs == NULL) {
					perror("calloc() fstype vopstats");
					exit(1);
				}
				break;
			}
		}
		if (j < nfstypes)	/* Found it! */
			continue;

		/*
		 * If the entity in the exception list of fstypes, then
		 * null out the entry so it isn't displayed and move along.
		 */
		if (is_exception(ep->e_name)) {
			ep->e_ksname[0] = 0;
			continue;
		}

		/* If we didn't find it, see if it's a path */
		if (ep->e_name == NULL || statvfs64(ep->e_name, &statvfsbuf)) {
			/* Error - Make sure the entry is nulled out */
			ep->e_ksname[0] = 0;
			continue;
		}
		(void) snprintf(ep->e_ksname, KSTAT_STRLEN, "%s%lx",
		    VOPSTATS_STR, statvfsbuf.f_fsid);
		ep->e_fsid = statvfsbuf.f_fsid;
		if (set_mntpt(ep)) {
			(void) fprintf(stderr,
			    gettext("Can't determine type of \"%s\"\n"),
			    ep->e_name ? ep->e_name : gettext("<NULL>"));
		} else {
			ep->e_type = ENTYPE_MNTPT;
		}

		/* Now allocate the vopstats array */
		ep->e_vs = calloc(VS_SIZE, sizeof (vopstats_t));
		if (entities[i].e_vs == NULL) {
			perror("calloc() vopstats array");
			exit(1);
		}
	}
}
Esempio n. 21
0
/*
 * set_mntpt() looks at the entity's name (e_name) and finds its
 * mountpoint.  To do this, we need to build a list of mountpoints
 * from /etc/mnttab.  We only need to do this once and we don't do it
 * if we don't need to look at any mountpoints.
 * Returns 0 on success, non-zero if it couldn't find a mount-point.
 */
int
set_mntpt(entity_t *ep)
{
	static struct mnt {
		struct mnt	*m_next;
		char		*m_mntpt;
		ulong_t		m_fsid;	/* From statvfs(), set only as needed */
	} *mnt_list = NULL;	/* Linked list of mount-points */
	struct mnt *mntp;
	struct statvfs64 statvfsbuf;
	char *original_name = ep->e_name;
	char path[PATH_MAX];

	if (original_name == NULL)		/* Shouldn't happen */
		return (1);

	/* We only set up mnt_list the first time this is called */
	if (mnt_list == NULL) {
		FILE *fp;
		struct mnttab mnttab;

		if ((fp = fopen(MNTTAB, "r")) == NULL) {
			perror(MNTTAB);
			return (1);
		}
		resetmnttab(fp);
		/*
		 * We insert at the front of the list so that when we
		 * search entries we'll have the last mounted entries
		 * first in the list so that we can match the longest
		 * mountpoint.
		 */
		while (getmntent(fp, &mnttab) == 0) {
			if ((mntp = malloc(sizeof (*mntp))) == NULL) {
				perror("malloc() mount list");
				return (1);
			}
			mntp->m_mntpt = strdup(mnttab.mnt_mountp);
			mntp->m_next = mnt_list;
			mnt_list = mntp;
		}
		(void) fclose(fp);
	}

	if (realpath(original_name, path) == NULL) {
		perror(original_name);
		return (1);
	}

	/*
	 * Now that we have the path, walk through the mnt_list and
	 * look for the first (best) match.
	 */
	for (mntp = mnt_list; mntp; mntp = mntp->m_next) {
		if (strncmp(path, mntp->m_mntpt, strlen(mntp->m_mntpt)) == 0) {
			if (mntp->m_fsid == 0) {
				if (statvfs64(mntp->m_mntpt, &statvfsbuf)) {
					/* Can't statvfs so no match */
					continue;
				} else {
					mntp->m_fsid = statvfsbuf.f_fsid;
				}
			}

			if (ep->e_fsid != mntp->m_fsid) {
				/* No match - Move on */
				continue;
			}

			break;
		}
	}

	if (mntp == NULL) {
		(void) fprintf(stderr, gettext(
		    "Can't find mount point for %s\n"), path);
		return (1);
	}

	ep->e_name = strdup(mntp->m_mntpt);
	free(original_name);
	return (0);
}
Esempio n. 22
0
/* this does all of the system specific guff to get the free disk space.
   It is derived from code in the GNU fileutils package, but has been
   considerably mangled for use here 

   results are returned in *dfree and *dsize, in 512 byte units
*/
int sys_fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize, SMB_BIG_UINT *bsize)
{
#ifdef STAT_STATFS3_OSF1
#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512)
	struct statfs fsd;

	if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
		return -1;
#endif /* STAT_STATFS3_OSF1 */
	
#ifdef STAT_STATFS2_FS_DATA	/* Ultrix */
#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)1024, (SMB_BIG_UINT)512)	
	struct fs_data fsd;
	
	if (statfs (path, &fsd) != 1)
		return -1;
	
	(*dsize) = CONVERT_BLOCKS (fsd.fd_req.btot);
	(*dfree) = CONVERT_BLOCKS (fsd.fd_req.bfreen);
#endif /* STAT_STATFS2_FS_DATA */
	
#ifdef STAT_STATFS2_BSIZE	/* 4.3BSD, SunOS 4, HP-UX, AIX */
#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512)
	struct statfs fsd;
	
	if (statfs (path, &fsd) < 0)
		return -1;
	
#ifdef STATFS_TRUNCATES_BLOCK_COUNTS
	/* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
	   struct statfs are truncated to 2GB.  These conditions detect that
	   truncation, presumably without botching the 4.1.1 case, in which
	   the values are not truncated.  The correct counts are stored in
	   undocumented spare fields.  */
	if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0) {
		fsd.f_blocks = fsd.f_spare[0];
		fsd.f_bfree = fsd.f_spare[1];
		fsd.f_bavail = fsd.f_spare[2];
	}
#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
#endif /* STAT_STATFS2_BSIZE */
	

#ifdef STAT_STATFS2_FSIZE	/* 4.4BSD */
#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512)
	
	struct statfs fsd;
	
	if (statfs (path, &fsd) < 0)
		return -1;
#endif /* STAT_STATFS2_FSIZE */
	
#ifdef STAT_STATFS4		/* SVR3, Dynix, Irix, AIX */
# if _AIX || defined(_CRAY)
#  define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512)
#  ifdef _CRAY
#   define f_bavail f_bfree
#  endif
# else
#  define CONVERT_BLOCKS(B) ((SMB_BIG_UINT)B)
#  ifndef _SEQUENT_		/* _SEQUENT_ is DYNIX/ptx */
#   ifndef DOLPHIN		/* DOLPHIN 3.8.alfa/7.18 has f_bavail */
#    define f_bavail f_bfree
#   endif
#  endif
# endif
	
	struct statfs fsd;

	if (statfs (path, &fsd, sizeof fsd, 0) < 0)
		return -1;
	/* Empirically, the block counts on most SVR3 and SVR3-derived
	   systems seem to always be in terms of 512-byte blocks,
	   no matter what value f_bsize has.  */

#endif /* STAT_STATFS4 */

#if defined(STAT_STATVFS) || defined(STAT_STATVFS64)		/* SVR4 */
# define CONVERT_BLOCKS(B) \
	adjust_blocks ((SMB_BIG_UINT)(B), fsd.f_frsize ? (SMB_BIG_UINT)fsd.f_frsize : (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)fsd.f_bsize)

#ifdef STAT_STATVFS64
	struct statvfs64 fsd;
	if (statvfs64(path, &fsd) < 0) return -1;
#else
	struct statvfs fsd;
	if (statvfs(path, &fsd) < 0) return -1;
#endif

	/* f_frsize isn't guaranteed to be supported.  */

#endif /* STAT_STATVFS */

#ifndef CONVERT_BLOCKS
	/* we don't have any dfree code! */
	return -1;
#else
#if !defined(STAT_STATFS2_FS_DATA)
	/* !Ultrix */
	(*bsize) = fsd.f_bsize;
	(*dsize) = CONVERT_BLOCKS (fsd.f_blocks);
	(*dfree) = CONVERT_BLOCKS (fsd.f_bavail);
#endif /* not STAT_STATFS2_FS_DATA */
#endif

	return 0;
}
Esempio n. 23
0
/* Fill in the fields of FSP with information about space usage for
   the file system on which FILE resides.
   DISK is the device on which FILE is mounted, for space-getting
   methods that need to know it.
   Return 0 if successful, -1 if not.  When returning -1, ensure that
   ERRNO is either a system error value, or zero if DISK is NULL
   on a system that requires a non-NULL value.  */
int
get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
{
#ifdef STAT_STATVFS     /* POSIX, except pre-2.6.36 glibc/Linux */

  if (statvfs_works ())
    {
      struct statvfs vfsd;

      if (statvfs (file, &vfsd) < 0)
        return -1;

      /* f_frsize isn't guaranteed to be supported.  */
      fsp->fsu_blocksize = (vfsd.f_frsize
                            ? PROPAGATE_ALL_ONES (vfsd.f_frsize)
                            : PROPAGATE_ALL_ONES (vfsd.f_bsize));

      fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks);
      fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree);
      fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail);
      fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0;
      fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files);
      fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree);
      return 0;
    }

#endif

#if defined STAT_STATVFS64            /* AIX */

  struct statvfs64 fsd;

  if (statvfs64 (file, &fsd) < 0)
    return -1;

  /* f_frsize isn't guaranteed to be supported.  */
  fsp->fsu_blocksize = (fsd.f_frsize
                        ? PROPAGATE_ALL_ONES (fsd.f_frsize)
                        : PROPAGATE_ALL_ONES (fsd.f_bsize));

#elif defined STAT_STATFS2_FS_DATA      /* Ultrix */

  struct fs_data fsd;

  if (statfs (file, &fsd) != 1)
    return -1;

  fsp->fsu_blocksize = 1024;
  fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot);
  fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree);
  fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen);
  fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0;
  fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot);
  fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);

#elif defined STAT_READ_FILSYS          /* SVR2 */
# ifndef SUPERBOFF
#  define SUPERBOFF (SUPERB * 512)
# endif

  struct filsys fsd;
  int fd;

  if (! disk)
    {
      errno = 0;
      return -1;
    }

  fd = open (disk, O_RDONLY);
  if (fd < 0)
    return -1;
  lseek (fd, (off_t) SUPERBOFF, 0);
  if (full_read (fd, (char *) &fsd, sizeof fsd) != sizeof fsd)
    {
      close (fd);
      return -1;
    }
  close (fd);

  fsp->fsu_blocksize = (fsd.s_type == Fs2b ? 1024 : 512);
  fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.s_fsize);
  fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.s_tfree);
  fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.s_tfree);
  fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.s_tfree) != 0;
  fsp->fsu_files = (fsd.s_isize == -1
                    ? UINTMAX_MAX
                    : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1));
  fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode);

#elif defined STAT_STATFS3_OSF1         /* OSF/1 */

  struct statfs fsd;

  if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
    return -1;

  fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);

#elif defined STAT_STATFS2_FRSIZE        /* 2.6 < glibc/Linux < 2.6.36 */

  struct statfs fsd;

  if (statfs (file, &fsd) < 0)
    return -1;

  fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize);

#elif defined STAT_STATFS2_BSIZE        /* glibc/Linux < 2.6, 4.3BSD, SunOS 4, \
                                           Mac OS X < 10.4, FreeBSD < 5.0, \
                                           NetBSD < 3.0, OpenBSD < 4.4 */

  struct statfs fsd;

  if (statfs (file, &fsd) < 0)
    return -1;

  fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);

# ifdef STATFS_TRUNCATES_BLOCK_COUNTS

  /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
     struct statfs are truncated to 2GB.  These conditions detect that
     truncation, presumably without botching the 4.1.1 case, in which
     the values are not truncated.  The correct counts are stored in
     undocumented spare fields.  */
  if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0)
    {
      fsd.f_blocks = fsd.f_spare[0];
      fsd.f_bfree = fsd.f_spare[1];
      fsd.f_bavail = fsd.f_spare[2];
    }
# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */

#elif defined STAT_STATFS2_FSIZE        /* 4.4BSD and older NetBSD */

  struct statfs fsd;

  if (statfs (file, &fsd) < 0)
    return -1;

  fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);

#elif defined STAT_STATFS4              /* SVR3, Dynix, old Irix, old AIX, \
                                           Dolphin */

# if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN
#  define f_bavail f_bfree
# endif

  struct statfs fsd;

  if (statfs (file, &fsd, sizeof fsd, 0) < 0)
    return -1;

  /* Empirically, the block counts on most SVR3 and SVR3-derived
     systems seem to always be in terms of 512-byte blocks,
     no matter what value f_bsize has.  */
# if _AIX || defined _CRAY
   fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
# else
   fsp->fsu_blocksize = 512;
# endif

#endif

#if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1                \
     || defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE       \
     || defined STAT_STATFS2_FSIZE || defined STAT_STATFS4)

  fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
  fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);
  fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail);
  fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0;
  fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
  fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);

#endif

  (void) disk;  /* avoid argument-unused warning */
  return 0;
}
Esempio n. 24
0
/*
 * This is the common defrag code for either a full fs
 * defragmentation or a single file.  Check as much as
 * possible with the file, fork a process to setuid to the 
 * target file owner's uid and defragment the file.
 * This is done so the new extents created in a tmp file are 
 * reflected in the owners' quota without having to do any 
 * special code in the kernel.  When the existing extents 
 * are removed, the quotas will be correct.  It's ugly but 
 * it saves us from doing some quota  re-construction in 
 * the extent swap.  The price is that the defragmentation
 * will fail if the owner of the target file is already at
 * their quota limit.
 */
static int
fsrfile_common(
	char		*fname, 
	char		*tname, 
	char		*fsname,
	int		fd,
	xfs_bstat_t	*statp)
{
	int		pid;
	int		error;
	struct statvfs64 vfss;
	struct fsxattr	fsx;
	int		do_rt = 0;
	unsigned long	bsize;
#ifdef HAVE_CAPABILITIES
	cap_t		ocap;
	cap_value_t	cap_setuid = CAP_SETUID;
#endif
		
	if (vflag)
		fsrprintf("%s\n", fname);

	if (fsync(fd) < 0) {
		fsrprintf("sync failed: %s: %s\n", fname, strerror(errno));
		return -1;
	}

	if (statp->bs_size == 0) {
		if (vflag)
			fsrprintf("%s: zero size, ignoring\n", fname);
		return(0);
	}

	/* Check if a mandatory lock is set on the file to try and 
	 * avoid blocking indefinitely on the reads later. Note that
	 * someone could still set a mandatory lock after this check 
	 * but before all reads have completed to block fsr reads.
	 * This change just closes the window a bit.
	 */
	if ( (statp->bs_mode & S_ISGID) && ( ! (statp->bs_mode&S_IXGRP) ) ) {
		struct flock fl;

		fl.l_type = F_RDLCK;
		fl.l_whence = SEEK_SET;
		fl.l_start = (off_t)0;
		fl.l_len = 0;
		if ((fcntl(fd, F_GETLK, &fl)) < 0 ) {
			if (vflag)
				fsrprintf("locking check failed: %s\n", fname);
			return(-1);
		}
		if (fl.l_type != F_UNLCK) {
			/* Mandatory lock is set */
			if (vflag)
				fsrprintf("mandatory lock: %s: ignoring\n",
					  fname);
			return(-1);
		}
	}

	/* Check if there is room to copy the file */
	if ( statvfs64( (fsname == NULL ? fname : fsname), &vfss) < 0) {
		fsrprintf(
		  "unable to get fs stat on %s: %s\n",
		  fname, strerror(errno));
		return (-1);
	}
	bsize = vfss.f_frsize ? vfss.f_frsize : vfss.f_bsize;

	if (statp->bs_size > ((vfss.f_bfree * bsize) - minimumfree)) {
		fsrprintf(
		  "insufficient freespace for: %s: size=%lld: ignoring\n",
		  fname, statp->bs_size);
		return 1;
	}

	/* Check realtime info */
	if ((ioctl(fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
		fsrprintf("failed to get attrs: %s\n", fname);
		return(-1);
	}
	if (fsx.fsx_xflags == XFS_XFLAG_REALTIME) {
		if (xfs_getrt(fd, &vfss) < 0) {
			fsrprintf("could not get rt geom for: %s\n", fname);
			return(-1);
		}
		if (statp->bs_size > ((vfss.f_bfree * bsize) - minimumfree)) {
			fsrprintf("low on rt free space: %s: ignoring file\n",
			          fname);
			return(-1);
		}
		do_rt = 1;
	}

	if ((RealUid != ROOT) && (RealUid != statp->bs_uid)) {
		fsrprintf("cannot open: %s: Permission denied\n", fname);
		return -1;
	}

	pid = fork();
	if (pid < 0) {
		fsrprintf("fork failed: %s\n", strerror(errno));
		close(fd);
		exit(1);
	} else if (pid == 0) {
		/* 
		 * Already checked ownership so we're either
		 * root or our realuid owns the file and can safely 
		 * setuid to the file owner.  This is done so
		 * quotas are maintained for the user.  (No group
		 * quotas so no setgid).
		 */
#ifdef HAVE_CAPABILITIES
		ocap = cap_acquire(1, &cap_setuid);
#endif
		if (setuid(statp->bs_uid) < 0) {
			fsrprintf("setuid failed: uid=%d %s: %s\n", 
				  statp->bs_uid, fname, strerror(errno));
#ifdef HAVE_CAPABILITIES
			cap_surrender(ocap);
#endif
			exit(1);
		}
#ifdef HAVE_CAPABILITIES
		cap_surrender(ocap);
#endif

		error = packfile(fname, tname, fd, statp, do_rt);
		exit(error);
	} else if (pid > 0) {
		wait(&error);
		close(fd);
		if (WIFEXITED(error))
			return(WEXITSTATUS(error));
		return -1;
	}
	/* NOTREACHED */
	return 0;
}