10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*633Sgt29601 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * Common subroutines used by the programs in these subdirectories.
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include <locale.h>
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <assert.h>
380Sstevel@tonic-gate #include <unistd.h>
390Sstevel@tonic-gate #include <limits.h>
400Sstevel@tonic-gate #include <errno.h>
410Sstevel@tonic-gate #include <wait.h>
420Sstevel@tonic-gate #include <ctype.h>
430Sstevel@tonic-gate #include <fcntl.h>
440Sstevel@tonic-gate #include <ftw.h>
450Sstevel@tonic-gate #include <dirent.h>
460Sstevel@tonic-gate #include <sys/types.h>
470Sstevel@tonic-gate #include <sys/time.h>
480Sstevel@tonic-gate #include <utmpx.h>
490Sstevel@tonic-gate #include <sys/uio.h>
500Sstevel@tonic-gate #include <sys/param.h>
510Sstevel@tonic-gate #include <sys/stat.h>
520Sstevel@tonic-gate #include <sys/fcntl.h>
530Sstevel@tonic-gate #include <sys/mount.h>
540Sstevel@tonic-gate #include <sys/mntent.h>
550Sstevel@tonic-gate #include <sys/mnttab.h>
560Sstevel@tonic-gate #include <sys/mman.h>
570Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
580Sstevel@tonic-gate #include "subr.h"
590Sstevel@tonic-gate
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate *
620Sstevel@tonic-gate * cachefs_dir_lock
630Sstevel@tonic-gate *
640Sstevel@tonic-gate * Description:
650Sstevel@tonic-gate * Gets a lock on the cache directory.
660Sstevel@tonic-gate * To release the lock, call cachefs_dir_unlock
670Sstevel@tonic-gate * with the returned value.
680Sstevel@tonic-gate * Arguments:
690Sstevel@tonic-gate * cachedirp name of the cache directory
700Sstevel@tonic-gate * shared 1 if shared, 0 if not
710Sstevel@tonic-gate * Returns:
720Sstevel@tonic-gate * Returns -1 if the lock cannot be obtained immediatly.
730Sstevel@tonic-gate * If the lock is obtained, returns a value >= 0.
740Sstevel@tonic-gate * Preconditions:
750Sstevel@tonic-gate * precond(cachedirp)
760Sstevel@tonic-gate */
770Sstevel@tonic-gate
780Sstevel@tonic-gate int
cachefs_dir_lock(const char * cachedirp,int shared)790Sstevel@tonic-gate cachefs_dir_lock(const char *cachedirp, int shared)
800Sstevel@tonic-gate {
810Sstevel@tonic-gate int fd;
820Sstevel@tonic-gate int xx;
830Sstevel@tonic-gate int len;
840Sstevel@tonic-gate char buf[MAXPATHLEN];
850Sstevel@tonic-gate struct flock fl;
860Sstevel@tonic-gate char *strp;
870Sstevel@tonic-gate struct stat statb;
880Sstevel@tonic-gate
890Sstevel@tonic-gate /* make a path prefix to the cache directory lock file */
900Sstevel@tonic-gate strp = CACHEFS_ROOTRUN;
910Sstevel@tonic-gate xx = stat(strp, &statb);
920Sstevel@tonic-gate if ((xx < 0) || ((statb.st_mode & S_IFMT) != S_IFDIR))
930Sstevel@tonic-gate strp = "/tmp";
940Sstevel@tonic-gate
950Sstevel@tonic-gate /* won't overflow */
960Sstevel@tonic-gate len = snprintf(buf, sizeof (buf), "%s/%s", strp, CACHEFS_LOCKDIR_PRE);
970Sstevel@tonic-gate
980Sstevel@tonic-gate if (strlcat(buf, cachedirp, sizeof (buf)) >= sizeof (buf)) {
990Sstevel@tonic-gate pr_err(gettext("Cache directory name %s is too long"),
1000Sstevel@tonic-gate cachedirp);
1010Sstevel@tonic-gate return (-1);
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate strp = &buf[len];
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate while (strp = strchr(strp, '/')) { /* convert path to a file */
1070Sstevel@tonic-gate *strp = '_';
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate * Create and open the cache directory lock file.
1120Sstevel@tonic-gate * This file will be <2G.
1130Sstevel@tonic-gate */
1140Sstevel@tonic-gate fd = open(buf, O_RDWR | O_CREAT, 0700);
1150Sstevel@tonic-gate if (fd == -1) {
1160Sstevel@tonic-gate pr_err(gettext("Cannot open lock file %s"), buf);
1170Sstevel@tonic-gate return (-1);
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate /* try to set the lock */
1210Sstevel@tonic-gate fl.l_type = (shared == 1) ? F_RDLCK : F_WRLCK;
1220Sstevel@tonic-gate fl.l_whence = 0;
1230Sstevel@tonic-gate fl.l_start = 1024;
1240Sstevel@tonic-gate fl.l_len = 1024;
1250Sstevel@tonic-gate fl.l_sysid = 0;
1260Sstevel@tonic-gate fl.l_pid = 0;
1270Sstevel@tonic-gate /* CACHEFS_LOCK_FILE will be <2GB */
1280Sstevel@tonic-gate xx = fcntl(fd, F_SETLKW, &fl);
1290Sstevel@tonic-gate if (xx == -1) {
1300Sstevel@tonic-gate if (errno == EAGAIN) {
1310Sstevel@tonic-gate pr_err(gettext("Cannot gain access to the "
1320Sstevel@tonic-gate "cache directory %s."), cachedirp);
1330Sstevel@tonic-gate } else {
1340Sstevel@tonic-gate pr_err(gettext("Unexpected failure on lock file %s %s"),
1350Sstevel@tonic-gate buf, strerror(errno));
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate close(fd);
1380Sstevel@tonic-gate return (-1);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate /* return the file descriptor which can be used to release the lock */
1420Sstevel@tonic-gate return (fd);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate /*
1460Sstevel@tonic-gate *
1470Sstevel@tonic-gate * cachefs_dir_unlock
1480Sstevel@tonic-gate *
1490Sstevel@tonic-gate * Description:
1500Sstevel@tonic-gate * Releases an advisory lock on the cache directory.
1510Sstevel@tonic-gate * Arguments:
1520Sstevel@tonic-gate * fd cookie returned by cachefs_dir_lock
1530Sstevel@tonic-gate * Returns:
1540Sstevel@tonic-gate * Returns -1 if the lock cannot be released or 0 for success.
1550Sstevel@tonic-gate * Preconditions:
1560Sstevel@tonic-gate */
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate int
cachefs_dir_unlock(int fd)1590Sstevel@tonic-gate cachefs_dir_unlock(int fd)
1600Sstevel@tonic-gate {
1610Sstevel@tonic-gate struct flock fl;
1620Sstevel@tonic-gate int error = 0;
1630Sstevel@tonic-gate int xx;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate /* release the lock */
1660Sstevel@tonic-gate fl.l_type = F_UNLCK;
1670Sstevel@tonic-gate fl.l_whence = 0;
1680Sstevel@tonic-gate fl.l_start = 1024;
1690Sstevel@tonic-gate fl.l_len = 1024;
1700Sstevel@tonic-gate fl.l_sysid = 0;
1710Sstevel@tonic-gate fl.l_pid = 0;
1720Sstevel@tonic-gate /* fd will be <2GB */
1730Sstevel@tonic-gate xx = fcntl(fd, F_SETLK, &fl);
1740Sstevel@tonic-gate if (xx == -1) {
1750Sstevel@tonic-gate pr_err(gettext("Unexpected failure releasing lock file %s"),
1760Sstevel@tonic-gate strerror(errno));
1770Sstevel@tonic-gate error = -1;
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /* close the lock file */
1810Sstevel@tonic-gate close(fd);
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate return (error);
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate /*
1870Sstevel@tonic-gate *
1880Sstevel@tonic-gate * cachefs_label_file_get
1890Sstevel@tonic-gate *
1900Sstevel@tonic-gate * Description:
1910Sstevel@tonic-gate * Gets the contents of a cache label file.
1920Sstevel@tonic-gate * Performs error checking on the file.
1930Sstevel@tonic-gate * Arguments:
1940Sstevel@tonic-gate * filep name of the cache label file
1950Sstevel@tonic-gate * clabelp where to put the file contents
1960Sstevel@tonic-gate * Returns:
1970Sstevel@tonic-gate * Returns 0 for success or -1 if an error occurs.
1980Sstevel@tonic-gate * Preconditions:
1990Sstevel@tonic-gate * precond(filep)
2000Sstevel@tonic-gate * precond(clabelp)
2010Sstevel@tonic-gate */
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate int
cachefs_label_file_get(const char * filep,struct cache_label * clabelp)2040Sstevel@tonic-gate cachefs_label_file_get(const char *filep, struct cache_label *clabelp)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate int xx;
2070Sstevel@tonic-gate int fd;
2080Sstevel@tonic-gate struct stat64 statinfo;
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate /* get info on the file */
2110Sstevel@tonic-gate xx = lstat64(filep, &statinfo);
2120Sstevel@tonic-gate if (xx == -1) {
2130Sstevel@tonic-gate if (errno != ENOENT) {
2140Sstevel@tonic-gate pr_err(gettext("Cannot stat file %s: %s"),
2150Sstevel@tonic-gate filep, strerror(errno));
2160Sstevel@tonic-gate } else {
2170Sstevel@tonic-gate pr_err(gettext("File %s does not exist."), filep);
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate return (-1);
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate /* if the file is the wrong type */
2240Sstevel@tonic-gate if (!S_ISREG(statinfo.st_mode)) {
2250Sstevel@tonic-gate pr_err(gettext("Cache label file %s corrupted"), filep);
2260Sstevel@tonic-gate return (-1);
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate /* if the file is the wrong size; it will be <2GB */
2300Sstevel@tonic-gate if (statinfo.st_size != (offset_t)sizeof (struct cache_label)) {
2310Sstevel@tonic-gate pr_err(gettext("Cache label file %s wrong size"), filep);
2320Sstevel@tonic-gate return (-1);
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate /* open the cache label file */
2360Sstevel@tonic-gate fd = open(filep, O_RDONLY);
2370Sstevel@tonic-gate if (fd == -1) {
2380Sstevel@tonic-gate pr_err(gettext("Error opening %s: %s"), filep,
2390Sstevel@tonic-gate strerror(errno));
2400Sstevel@tonic-gate return (-1);
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate /* read the current set of parameters */
2440Sstevel@tonic-gate xx = read(fd, clabelp, sizeof (struct cache_label));
2450Sstevel@tonic-gate if (xx != sizeof (struct cache_label)) {
2460Sstevel@tonic-gate pr_err(gettext("Reading %s failed: %s\n"), filep,
2470Sstevel@tonic-gate strerror(errno));
2480Sstevel@tonic-gate close(fd);
2490Sstevel@tonic-gate return (-1);
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate close(fd);
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate /* return success */
2540Sstevel@tonic-gate return (0);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate /*
2580Sstevel@tonic-gate *
2590Sstevel@tonic-gate * cachefs_label_file_put
2600Sstevel@tonic-gate *
2610Sstevel@tonic-gate * Description:
2620Sstevel@tonic-gate * Outputs the contents of a cache label object to a file.
2630Sstevel@tonic-gate * Arguments:
2640Sstevel@tonic-gate * filep name of the cache label file
2650Sstevel@tonic-gate * clabelp where to get the file contents
2660Sstevel@tonic-gate * Returns:
2670Sstevel@tonic-gate * Returns 0 for success or -1 if an error occurs.
2680Sstevel@tonic-gate * Preconditions:
2690Sstevel@tonic-gate * precond(filep)
2700Sstevel@tonic-gate * precond(clabelp)
2710Sstevel@tonic-gate */
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate int
cachefs_label_file_put(const char * filep,struct cache_label * clabelp)2740Sstevel@tonic-gate cachefs_label_file_put(const char *filep, struct cache_label *clabelp)
2750Sstevel@tonic-gate {
2760Sstevel@tonic-gate int xx;
2770Sstevel@tonic-gate int fd;
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate /* get rid of the file if it already exists */
2800Sstevel@tonic-gate xx = unlink(filep);
2810Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) {
2820Sstevel@tonic-gate pr_err(gettext("Could not remove %s: %s"), filep,
2830Sstevel@tonic-gate strerror(errno));
2840Sstevel@tonic-gate return (-1);
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate /* open the cache label file; this file will be <2GB */
2880Sstevel@tonic-gate fd = open(filep, O_CREAT | O_RDWR, 0600);
2890Sstevel@tonic-gate if (fd == -1) {
2900Sstevel@tonic-gate pr_err(gettext("Error creating %s: %s"), filep,
2910Sstevel@tonic-gate strerror(errno));
2920Sstevel@tonic-gate return (-1);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /* write out the cache label object */
2960Sstevel@tonic-gate xx = write(fd, clabelp, sizeof (struct cache_label));
2970Sstevel@tonic-gate if (xx != sizeof (struct cache_label)) {
2980Sstevel@tonic-gate pr_err(gettext("Writing %s failed: %s"), filep,
2990Sstevel@tonic-gate strerror(errno));
3000Sstevel@tonic-gate close(fd);
3010Sstevel@tonic-gate return (-1);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate /* make sure the contents get to disk */
3050Sstevel@tonic-gate if (fsync(fd) != 0) {
3060Sstevel@tonic-gate pr_err(gettext("Writing %s failed on sync: %s"), filep,
3070Sstevel@tonic-gate strerror(errno));
3080Sstevel@tonic-gate close(fd);
3090Sstevel@tonic-gate return (-1);
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate close(fd);
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate /* return success */
3150Sstevel@tonic-gate return (0);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate int
cachefs_label_file_vcheck(char * filep,struct cache_label * clabelp)3190Sstevel@tonic-gate cachefs_label_file_vcheck(char *filep, struct cache_label *clabelp)
3200Sstevel@tonic-gate {
3210Sstevel@tonic-gate /* check for an invalid version number */
3220Sstevel@tonic-gate if (clabelp->cl_cfsversion != CFSVERSION) {
3230Sstevel@tonic-gate pr_err(gettext("Cache label file %s corrupted"), filep);
3240Sstevel@tonic-gate return (-1);
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate return (0);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate /*
3310Sstevel@tonic-gate *
3320Sstevel@tonic-gate * cachefs_inuse
3330Sstevel@tonic-gate *
3340Sstevel@tonic-gate * Description:
3350Sstevel@tonic-gate * Tests whether or not the cache directory is in use by
3360Sstevel@tonic-gate * the cache file system.
3370Sstevel@tonic-gate * Arguments:
3380Sstevel@tonic-gate * cachedirp name of the file system cache directory
3390Sstevel@tonic-gate * Returns:
3400Sstevel@tonic-gate * Returns 1 if the cache is in use or an error, 0 if not.
3410Sstevel@tonic-gate * Preconditions:
3420Sstevel@tonic-gate * precond(cachedirp)
3430Sstevel@tonic-gate */
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate int
cachefs_inuse(const char * cachedirp)3460Sstevel@tonic-gate cachefs_inuse(const char *cachedirp)
3470Sstevel@tonic-gate {
3480Sstevel@tonic-gate int fd;
3490Sstevel@tonic-gate int xx;
3500Sstevel@tonic-gate char buf[MAXPATHLEN];
3510Sstevel@tonic-gate char *lockp = CACHEFS_LOCK_FILE;
3520Sstevel@tonic-gate struct flock fl;
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate /* see if path name is too long */
3550Sstevel@tonic-gate xx = strlen(cachedirp) + strlen(lockp) + 3;
3560Sstevel@tonic-gate if (xx >= MAXPATHLEN) {
3570Sstevel@tonic-gate pr_err(gettext("Cache directory name %s is too long"),
3580Sstevel@tonic-gate cachedirp);
3590Sstevel@tonic-gate return (1);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate /* make a path to the cache directory lock file */
3630Sstevel@tonic-gate snprintf(buf, sizeof (buf), "%s/%s", cachedirp, lockp);
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate /* Open the kernel in use lock file. This file will be <2GB. */
3660Sstevel@tonic-gate fd = open(buf, O_RDWR, 0700);
3670Sstevel@tonic-gate if (fd == -1) {
3680Sstevel@tonic-gate pr_err(gettext("Cannot open lock file %s"), buf);
3690Sstevel@tonic-gate return (1);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate /* test the lock status */
3730Sstevel@tonic-gate fl.l_type = F_WRLCK;
3740Sstevel@tonic-gate fl.l_whence = 0;
3750Sstevel@tonic-gate fl.l_start = 0;
3760Sstevel@tonic-gate fl.l_len = 1024;
3770Sstevel@tonic-gate fl.l_sysid = 0;
3780Sstevel@tonic-gate fl.l_pid = 0;
3790Sstevel@tonic-gate xx = fcntl(fd, F_GETLK, &fl);
3800Sstevel@tonic-gate if (xx == -1) {
3810Sstevel@tonic-gate pr_err(gettext("Unexpected failure on lock file %s %s"),
3820Sstevel@tonic-gate buf, strerror(errno));
3830Sstevel@tonic-gate close(fd);
3840Sstevel@tonic-gate return (1);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate close(fd);
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate if (fl.l_type == F_UNLCK)
3890Sstevel@tonic-gate xx = 0;
3900Sstevel@tonic-gate else
3910Sstevel@tonic-gate xx = 1;
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate /* return whether or not the cache is in use */
3940Sstevel@tonic-gate return (xx);
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate /*
3980Sstevel@tonic-gate *
3990Sstevel@tonic-gate * cachefs_resouce_size
4000Sstevel@tonic-gate *
4010Sstevel@tonic-gate * Description:
4020Sstevel@tonic-gate * Returns information about a resource file.
4030Sstevel@tonic-gate * Arguments:
4040Sstevel@tonic-gate * maxinodes number of inodes to be managed by the resource file
4050Sstevel@tonic-gate * rinfop set to info about the resource file
4060Sstevel@tonic-gate * Returns:
4070Sstevel@tonic-gate * Preconditions:
4080Sstevel@tonic-gate * precond(rinfop)
4090Sstevel@tonic-gate */
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate void
cachefs_resource_size(int maxinodes,struct cachefs_rinfo * rinfop)4120Sstevel@tonic-gate cachefs_resource_size(int maxinodes, struct cachefs_rinfo *rinfop)
4130Sstevel@tonic-gate {
4140Sstevel@tonic-gate int fsize;
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate fsize = MAXBSIZE;
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate rinfop->r_ptroffset = fsize;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate fsize += MAXBSIZE * (maxinodes / CACHEFS_RLPMBS);
4210Sstevel@tonic-gate if ((maxinodes % CACHEFS_RLPMBS) != 0)
4220Sstevel@tonic-gate fsize += MAXBSIZE;
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate rinfop->r_fsize = fsize;
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate /*
4280Sstevel@tonic-gate *
4290Sstevel@tonic-gate * cachefs_create_cache
4300Sstevel@tonic-gate *
4310Sstevel@tonic-gate * Description:
4320Sstevel@tonic-gate * Creates the specified cache directory and populates it as
4330Sstevel@tonic-gate * needed by CFS.
4340Sstevel@tonic-gate * Arguments:
4350Sstevel@tonic-gate * dirp the name of the cache directory
4360Sstevel@tonic-gate * uv user values (may be NULL)
4370Sstevel@tonic-gate * clabel label file contents, or placeholder for this
4380Sstevel@tonic-gate * Returns:
4390Sstevel@tonic-gate * Returns 0 for success or:
4400Sstevel@tonic-gate * -1 for an error
4410Sstevel@tonic-gate * -2 for an error and cache directory partially created
4420Sstevel@tonic-gate * Preconditions:
4430Sstevel@tonic-gate * precond(dirp)
4440Sstevel@tonic-gate */
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate int
cachefs_create_cache(char * dirp,struct cachefs_user_values * uv,struct cache_label * clabel)4470Sstevel@tonic-gate cachefs_create_cache(char *dirp, struct cachefs_user_values *uv,
4480Sstevel@tonic-gate struct cache_label *clabel)
4490Sstevel@tonic-gate {
4500Sstevel@tonic-gate int xx;
4510Sstevel@tonic-gate char path[CACHEFS_XMAXPATH];
4520Sstevel@tonic-gate int fd;
4530Sstevel@tonic-gate void *bufp;
4540Sstevel@tonic-gate int cnt;
4550Sstevel@tonic-gate struct cache_usage cu;
4560Sstevel@tonic-gate FILE *fp;
4570Sstevel@tonic-gate char *parent;
4580Sstevel@tonic-gate struct statvfs64 svfs;
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate cu.cu_blksused = 0;
4610Sstevel@tonic-gate cu.cu_filesused = 0;
4620Sstevel@tonic-gate cu.cu_flags = 0;
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate /* make sure cache dir name is not too long */
4650Sstevel@tonic-gate if (strlen(dirp) > (size_t)PATH_MAX) {
4660Sstevel@tonic-gate pr_err(gettext("path name %s is too long."), dirp);
4670Sstevel@tonic-gate return (-1);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate /* ensure the path isn't in cachefs */
4710Sstevel@tonic-gate parent = cachefs_file_to_dir(dirp);
4720Sstevel@tonic-gate if (parent == NULL) {
4730Sstevel@tonic-gate pr_err(gettext("Out of memory"));
4740Sstevel@tonic-gate return (-1);
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate if (statvfs64(parent, &svfs) != 0) {
4770Sstevel@tonic-gate pr_err(gettext("%s: %s"), parent, strerror(errno));
4780Sstevel@tonic-gate free(parent);
4790Sstevel@tonic-gate return (-1);
4800Sstevel@tonic-gate }
4810Sstevel@tonic-gate if (strcmp(svfs.f_basetype, CACHEFS_BASETYPE) == 0) {
4820Sstevel@tonic-gate pr_err(gettext("Cannot create cache in cachefs filesystem"));
4830Sstevel@tonic-gate free(parent);
4840Sstevel@tonic-gate return (-1);
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate free(parent);
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate /* make the directory */
4890Sstevel@tonic-gate if (mkdir(dirp, 0) == -1) {
4900Sstevel@tonic-gate switch (errno) {
4910Sstevel@tonic-gate case EEXIST:
4920Sstevel@tonic-gate pr_err(gettext("%s already exists."), dirp);
4930Sstevel@tonic-gate break;
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate default:
4960Sstevel@tonic-gate pr_err(gettext("mkdir %s failed: %s"),
4970Sstevel@tonic-gate dirp, strerror(errno));
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate return (-1);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate cu.cu_filesused += 1;
5020Sstevel@tonic-gate cu.cu_blksused += 1;
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate /* convert user values to a cache_label */
5050Sstevel@tonic-gate if (uv != NULL) {
5060Sstevel@tonic-gate xx = cachefs_convert_uv2cl(uv, clabel, dirp);
5070Sstevel@tonic-gate if (xx)
5080Sstevel@tonic-gate return (-2);
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate /*
5120Sstevel@tonic-gate * Create the cache directory lock file.
5130Sstevel@tonic-gate * Used by the kernel module to indicate the cache is in use.
5140Sstevel@tonic-gate * This file will be <2G.
5150Sstevel@tonic-gate */
5160Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_LOCK_FILE);
5170Sstevel@tonic-gate fd = open(path, O_RDWR | O_CREAT, 0700);
5180Sstevel@tonic-gate if (fd == -1) {
5190Sstevel@tonic-gate pr_err(gettext("Cannot create lock file %s"), path);
5200Sstevel@tonic-gate return (-1);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate close(fd);
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate /* make the directory for the back file system mount points */
5250Sstevel@tonic-gate /* note: we do not count this directory in the resources */
5260Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, BACKMNT_NAME);
5270Sstevel@tonic-gate if (mkdir(path, 0700) == -1) {
5280Sstevel@tonic-gate pr_err(gettext("mkdir %s failed: %s"), path,
5290Sstevel@tonic-gate strerror(errno));
5300Sstevel@tonic-gate return (-2);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate /* make the directory for lost+found */
5340Sstevel@tonic-gate /* note: we do not count this directory in the resources */
5350Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_LOSTFOUND_NAME);
5360Sstevel@tonic-gate if (mkdir(path, 0700) == -1) {
5370Sstevel@tonic-gate pr_err(gettext("mkdir %s failed: %s"), path,
5380Sstevel@tonic-gate strerror(errno));
5390Sstevel@tonic-gate return (-2);
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate /* make the networker "don't back up" file; this file is <2GB */
5430Sstevel@tonic-gate xx = 0;
5440Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, NOBACKUP_NAME);
5450Sstevel@tonic-gate if ((fp = fopen(path, "w")) != NULL) {
5460Sstevel@tonic-gate if (realpath(dirp, path) != NULL) {
547*633Sgt29601 fprintf(fp, "<< ./ >>\n");
5480Sstevel@tonic-gate fprintf(fp, "+skip: .?* *\n");
5490Sstevel@tonic-gate if (fclose(fp) == 0)
5500Sstevel@tonic-gate xx = 1;
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate if (xx == 0) {
5540Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, NOBACKUP_NAME);
5550Sstevel@tonic-gate pr_err(gettext("can't create %s"), path);
5560Sstevel@tonic-gate (void) unlink(path);
5570Sstevel@tonic-gate } else {
5580Sstevel@tonic-gate cu.cu_filesused += 1;
5590Sstevel@tonic-gate cu.cu_blksused += 1;
5600Sstevel@tonic-gate }
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate /* create the unmount file */
5630Sstevel@tonic-gate xx = 0;
5640Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_UNMNT_FILE);
5650Sstevel@tonic-gate if ((fp = fopen(path, "w")) != NULL) {
5660Sstevel@tonic-gate time32_t btime;
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate btime = get_boottime();
5690Sstevel@tonic-gate fwrite((void *)&btime, sizeof (btime), 1, fp);
5700Sstevel@tonic-gate if (fclose(fp) == 0)
5710Sstevel@tonic-gate xx = 1;
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate if (xx == 0)
5740Sstevel@tonic-gate pr_err(gettext("can't create .cfs_unmnt file"));
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate /* create the cache label file */
5770Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHELABEL_NAME);
5780Sstevel@tonic-gate xx = cachefs_label_file_put(path, clabel);
5790Sstevel@tonic-gate if (xx == -1) {
5800Sstevel@tonic-gate pr_err(gettext("creating %s failed."), path);
5810Sstevel@tonic-gate return (-2);
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate cu.cu_filesused += 1;
5840Sstevel@tonic-gate cu.cu_blksused += 1;
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate /* create the cache label duplicate file */
5870Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s.dup", dirp, CACHELABEL_NAME);
5880Sstevel@tonic-gate xx = cachefs_label_file_put(path, clabel);
5890Sstevel@tonic-gate if (xx == -1) {
5900Sstevel@tonic-gate pr_err(gettext("creating %s failed."), path);
5910Sstevel@tonic-gate return (-2);
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate cu.cu_filesused += 1;
5940Sstevel@tonic-gate cu.cu_blksused += 1;
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate /* create the resouce file; this file will be <2GB */
5970Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, RESOURCE_NAME);
5980Sstevel@tonic-gate fd = open(path, O_CREAT | O_RDWR, 0600);
5990Sstevel@tonic-gate if (fd == -1) {
6000Sstevel@tonic-gate pr_err(gettext("create %s failed: %s"), path,
6010Sstevel@tonic-gate strerror(errno));
6020Sstevel@tonic-gate return (-2);
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate cu.cu_filesused += 1;
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate /* allocate a zeroed buffer for filling the resouce file */
6070Sstevel@tonic-gate bufp = calloc(1, MAXBSIZE);
6080Sstevel@tonic-gate if (bufp == NULL) {
6090Sstevel@tonic-gate pr_err(gettext("out of space %d."), MAXBSIZE);
6100Sstevel@tonic-gate close(fd);
6110Sstevel@tonic-gate return (-2);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate /* determine number of MAXBSIZE chunks to make the file */
6150Sstevel@tonic-gate cnt = 1; /* for the header */
6160Sstevel@tonic-gate cnt += clabel->cl_maxinodes / CACHEFS_RLPMBS;
6170Sstevel@tonic-gate if ((clabel->cl_maxinodes % CACHEFS_RLPMBS) != 0)
6180Sstevel@tonic-gate ++cnt;
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate /* fill up the file with zeros */
6210Sstevel@tonic-gate for (xx = 0; xx < cnt; xx++) {
6220Sstevel@tonic-gate if (write(fd, bufp, MAXBSIZE) != MAXBSIZE) {
6230Sstevel@tonic-gate pr_err(gettext("write %s failed: %s"), path,
6240Sstevel@tonic-gate strerror(errno));
6250Sstevel@tonic-gate close(fd);
6260Sstevel@tonic-gate free(bufp);
6270Sstevel@tonic-gate return (-2);
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate free(bufp);
6310Sstevel@tonic-gate cu.cu_blksused += cnt;
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate /* position to the begining of the file */
6340Sstevel@tonic-gate if (lseek(fd, 0, SEEK_SET) == -1) {
6350Sstevel@tonic-gate pr_err(gettext("lseek %s failed: %s"), path,
6360Sstevel@tonic-gate strerror(errno));
6370Sstevel@tonic-gate close(fd);
6380Sstevel@tonic-gate return (-2);
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate /* write the cache usage structure */
6420Sstevel@tonic-gate xx = sizeof (struct cache_usage);
6430Sstevel@tonic-gate if (write(fd, &cu, xx) != xx) {
6440Sstevel@tonic-gate pr_err(gettext("cu write %s failed: %s"), path,
6450Sstevel@tonic-gate strerror(errno));
6460Sstevel@tonic-gate close(fd);
6470Sstevel@tonic-gate return (-2);
6480Sstevel@tonic-gate }
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate /* make sure the contents get to disk */
6510Sstevel@tonic-gate if (fsync(fd) != 0) {
6520Sstevel@tonic-gate pr_err(gettext("fsync %s failed: %s"), path,
6530Sstevel@tonic-gate strerror(errno));
6540Sstevel@tonic-gate close(fd);
6550Sstevel@tonic-gate return (-2);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate close(fd);
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /* return success */
6600Sstevel@tonic-gate return (0);
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate /*
6640Sstevel@tonic-gate *
6650Sstevel@tonic-gate * cachefs_delete_all_cache
6660Sstevel@tonic-gate *
6670Sstevel@tonic-gate * Description:
6680Sstevel@tonic-gate * Delete all caches in cache directory.
6690Sstevel@tonic-gate * Arguments:
6700Sstevel@tonic-gate * dirp the pathname of of the cache directory to delete
6710Sstevel@tonic-gate * Returns:
6720Sstevel@tonic-gate * Returns 0 for success or -1 for an error.
6730Sstevel@tonic-gate * Preconditions:
6740Sstevel@tonic-gate * precond(dirp)
6750Sstevel@tonic-gate */
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate int
cachefs_delete_all_cache(char * dirp)6780Sstevel@tonic-gate cachefs_delete_all_cache(char *dirp)
6790Sstevel@tonic-gate {
6800Sstevel@tonic-gate DIR *dp;
6810Sstevel@tonic-gate struct dirent64 *dep;
6820Sstevel@tonic-gate int xx;
6830Sstevel@tonic-gate char path[CACHEFS_XMAXPATH];
6840Sstevel@tonic-gate struct stat64 statinfo;
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate /* make sure cache dir name is not too long */
6870Sstevel@tonic-gate if (strlen(dirp) > (size_t)PATH_MAX) {
6880Sstevel@tonic-gate pr_err(gettext("path name %s is too long."),
6890Sstevel@tonic-gate dirp);
6900Sstevel@tonic-gate return (-1);
6910Sstevel@tonic-gate }
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate /* check that dirp is probably a cachefs directory */
6940Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, BACKMNT_NAME);
6950Sstevel@tonic-gate xx = access(path, R_OK | W_OK | X_OK);
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHELABEL_NAME);
6980Sstevel@tonic-gate xx |= access(path, R_OK | W_OK);
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate if (xx) {
7010Sstevel@tonic-gate pr_err(gettext("%s does not appear to be a "
7020Sstevel@tonic-gate "cachefs cache directory."), dirp);
7030Sstevel@tonic-gate return (-1);
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate /* remove the lost+found directory if it exists and is empty */
7070Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_LOSTFOUND_NAME);
7080Sstevel@tonic-gate xx = rmdir(path);
7090Sstevel@tonic-gate if (xx == -1) {
7100Sstevel@tonic-gate if (errno == EEXIST) {
7110Sstevel@tonic-gate pr_err(gettext("Cannot delete cache '%s'. "
7120Sstevel@tonic-gate "First move files in '%s' to a safe location."),
7130Sstevel@tonic-gate dirp, path);
7140Sstevel@tonic-gate return (-1);
7150Sstevel@tonic-gate } else if (errno != ENOENT) {
7160Sstevel@tonic-gate pr_err(gettext("rmdir %s failed: %s"), path,
7170Sstevel@tonic-gate strerror(errno));
7180Sstevel@tonic-gate return (-1);
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate }
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate /* delete the back FS mount point directory if it exists */
7230Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, BACKMNT_NAME);
7240Sstevel@tonic-gate xx = lstat64(path, &statinfo);
7250Sstevel@tonic-gate if (xx == -1) {
7260Sstevel@tonic-gate if (errno != ENOENT) {
7270Sstevel@tonic-gate pr_err(gettext("lstat %s failed: %s"), path,
7280Sstevel@tonic-gate strerror(errno));
7290Sstevel@tonic-gate return (-1);
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate } else {
7320Sstevel@tonic-gate xx = nftw64(path, cachefs_delete_file, 16,
7330Sstevel@tonic-gate FTW_PHYS | FTW_DEPTH | FTW_MOUNT);
7340Sstevel@tonic-gate if (xx == -1) {
7350Sstevel@tonic-gate pr_err(gettext("unable to delete %s"), path);
7360Sstevel@tonic-gate return (-1);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate /* open the cache directory specified */
7410Sstevel@tonic-gate if ((dp = opendir(dirp)) == NULL) {
7420Sstevel@tonic-gate pr_err(gettext("cannot open cache directory %s: %s"),
7430Sstevel@tonic-gate dirp, strerror(errno));
7440Sstevel@tonic-gate return (-1);
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate /* read the file names in the cache directory */
7480Sstevel@tonic-gate while ((dep = readdir64(dp)) != NULL) {
7490Sstevel@tonic-gate /* ignore . and .. */
7500Sstevel@tonic-gate if (strcmp(dep->d_name, ".") == 0 ||
7510Sstevel@tonic-gate strcmp(dep->d_name, "..") == 0)
7520Sstevel@tonic-gate continue;
7530Sstevel@tonic-gate
7540Sstevel@tonic-gate /* stat the file */
7550Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, dep->d_name);
7560Sstevel@tonic-gate xx = lstat64(path, &statinfo);
7570Sstevel@tonic-gate if (xx == -1) {
7580Sstevel@tonic-gate if (errno == ENOENT) {
7590Sstevel@tonic-gate /* delete_cache may have nuked a directory */
7600Sstevel@tonic-gate continue;
7610Sstevel@tonic-gate }
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate pr_err(gettext("lstat %s failed: %s"),
7640Sstevel@tonic-gate path, strerror(errno));
7650Sstevel@tonic-gate closedir(dp);
7660Sstevel@tonic-gate return (-1);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate /* ignore anything that is not a link */
7700Sstevel@tonic-gate if (!S_ISLNK(statinfo.st_mode))
7710Sstevel@tonic-gate continue;
7720Sstevel@tonic-gate
7730Sstevel@tonic-gate /* delete the file system cache directory */
7740Sstevel@tonic-gate xx = cachefs_delete_cache(dirp, dep->d_name);
7750Sstevel@tonic-gate if (xx) {
7760Sstevel@tonic-gate closedir(dp);
7770Sstevel@tonic-gate return (-1);
7780Sstevel@tonic-gate }
7790Sstevel@tonic-gate }
7800Sstevel@tonic-gate closedir(dp);
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate /* remove the cache dir unmount file */
7830Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_UNMNT_FILE);
7840Sstevel@tonic-gate xx = unlink(path);
7850Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) {
7860Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path,
7870Sstevel@tonic-gate strerror(errno));
7880Sstevel@tonic-gate return (-1);
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate /* remove the cache label file */
7920Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHELABEL_NAME);
7930Sstevel@tonic-gate xx = unlink(path);
7940Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) {
7950Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path,
7960Sstevel@tonic-gate strerror(errno));
7970Sstevel@tonic-gate return (-1);
7980Sstevel@tonic-gate }
7990Sstevel@tonic-gate
8000Sstevel@tonic-gate /* remove the cache label duplicate file */
8010Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s.dup", dirp, CACHELABEL_NAME);
8020Sstevel@tonic-gate xx = unlink(path);
8030Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) {
8040Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path,
8050Sstevel@tonic-gate strerror(errno));
8060Sstevel@tonic-gate return (-1);
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate /* remove the resource file */
8100Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, RESOURCE_NAME);
8110Sstevel@tonic-gate xx = unlink(path);
8120Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) {
8130Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path,
8140Sstevel@tonic-gate strerror(errno));
8150Sstevel@tonic-gate return (-1);
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate /* remove the cachefslog file if it exists */
8190Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, LOG_STATUS_NAME);
8200Sstevel@tonic-gate (void) unlink(path);
8210Sstevel@tonic-gate
8220Sstevel@tonic-gate /* remove the networker "don't back up" file if it exists */
8230Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, NOBACKUP_NAME);
8240Sstevel@tonic-gate (void) unlink(path);
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate /* remove the lock file */
8270Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_LOCK_FILE);
8280Sstevel@tonic-gate xx = unlink(path);
8290Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) {
8300Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path,
8310Sstevel@tonic-gate strerror(errno));
8320Sstevel@tonic-gate return (-1);
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate /* remove the directory */
8360Sstevel@tonic-gate xx = rmdir(dirp);
8370Sstevel@tonic-gate if (xx == -1) {
8380Sstevel@tonic-gate pr_err(gettext("rmdir %s failed: %s"), dirp,
8390Sstevel@tonic-gate strerror(errno));
8400Sstevel@tonic-gate return (-1);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate /* return success */
8440Sstevel@tonic-gate return (0);
8450Sstevel@tonic-gate }
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate /*
8480Sstevel@tonic-gate *
8490Sstevel@tonic-gate * cachefs_delete_cache
8500Sstevel@tonic-gate *
8510Sstevel@tonic-gate * Description:
8520Sstevel@tonic-gate * Deletes the specified file system cache.
8530Sstevel@tonic-gate * Arguments:
8540Sstevel@tonic-gate * dirp cache directory name
8550Sstevel@tonic-gate * namep file system cache directory to delete
8560Sstevel@tonic-gate * Returns:
8570Sstevel@tonic-gate * Returns 0 for success, -1 for failure.
8580Sstevel@tonic-gate * Preconditions:
8590Sstevel@tonic-gate * precond(dirp)
8600Sstevel@tonic-gate * precond(namep)
8610Sstevel@tonic-gate */
8620Sstevel@tonic-gate
8630Sstevel@tonic-gate int
cachefs_delete_cache(char * dirp,char * namep)8640Sstevel@tonic-gate cachefs_delete_cache(char *dirp, char *namep)
8650Sstevel@tonic-gate {
8660Sstevel@tonic-gate char path[CACHEFS_XMAXPATH];
8670Sstevel@tonic-gate char buf[CACHEFS_XMAXPATH];
8680Sstevel@tonic-gate int xx;
8690Sstevel@tonic-gate struct stat64 statinfo;
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate /* make sure cache dir name is not too long */
8720Sstevel@tonic-gate if (strlen(dirp) > (size_t)PATH_MAX) {
8730Sstevel@tonic-gate pr_err(gettext("path name %s is too long."),
8740Sstevel@tonic-gate dirp);
8750Sstevel@tonic-gate return (-1);
8760Sstevel@tonic-gate }
8770Sstevel@tonic-gate
8780Sstevel@tonic-gate /* construct the path name of the file system cache directory */
8790Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, namep);
8800Sstevel@tonic-gate
8810Sstevel@tonic-gate /* stat the specified file */
8820Sstevel@tonic-gate xx = lstat64(path, &statinfo);
8830Sstevel@tonic-gate if (xx == -1) {
8840Sstevel@tonic-gate pr_err(gettext("lstat %s failed: %s"), path,
8850Sstevel@tonic-gate strerror(errno));
8860Sstevel@tonic-gate return (-1);
8870Sstevel@tonic-gate }
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate /* make sure name is a symbolic link */
8900Sstevel@tonic-gate if (!S_ISLNK(statinfo.st_mode)) {
8910Sstevel@tonic-gate pr_err(gettext("\"%s\" is not a valid cache id."), namep);
8920Sstevel@tonic-gate return (-1);
8930Sstevel@tonic-gate }
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate /* read the contents of the symbolic link */
8960Sstevel@tonic-gate xx = readlink(path, buf, sizeof (buf));
8970Sstevel@tonic-gate if (xx == -1) {
8980Sstevel@tonic-gate pr_err(gettext("Readlink of %s failed: %s"), path,
8990Sstevel@tonic-gate strerror(errno));
9000Sstevel@tonic-gate return (-1);
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate buf[xx] = '\0';
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate /* remove the directory */
9050Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, buf);
9060Sstevel@tonic-gate xx = nftw64(path, cachefs_delete_file, 16,
9070Sstevel@tonic-gate FTW_PHYS | FTW_DEPTH | FTW_MOUNT);
9080Sstevel@tonic-gate if (xx == -1) {
9090Sstevel@tonic-gate pr_err(gettext("directory walk of %s failed."), dirp);
9100Sstevel@tonic-gate return (-1);
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate /* delete the link */
9140Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, namep);
9150Sstevel@tonic-gate if (unlink(path) == -1) {
9160Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path,
9170Sstevel@tonic-gate strerror(errno));
9180Sstevel@tonic-gate return (-1);
9190Sstevel@tonic-gate }
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate /* return success */
9220Sstevel@tonic-gate return (0);
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate
9250Sstevel@tonic-gate /*
9260Sstevel@tonic-gate *
9270Sstevel@tonic-gate * cachefs_delete_file
9280Sstevel@tonic-gate *
9290Sstevel@tonic-gate * Description:
9300Sstevel@tonic-gate * Remove a file or directory; called by nftw64().
9310Sstevel@tonic-gate * Arguments:
9320Sstevel@tonic-gate * namep pathname of the file
9330Sstevel@tonic-gate * statp stat info about the file
9340Sstevel@tonic-gate * flg info about file
9350Sstevel@tonic-gate * ftwp depth information
9360Sstevel@tonic-gate * Returns:
9370Sstevel@tonic-gate * Returns 0 for success, -1 for failure.
9380Sstevel@tonic-gate * Preconditions:
9390Sstevel@tonic-gate * precond(namep)
9400Sstevel@tonic-gate */
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate int
cachefs_delete_file(const char * namep,const struct stat64 * statp,int flg,struct FTW * ftwp)9430Sstevel@tonic-gate cachefs_delete_file(const char *namep, const struct stat64 *statp, int flg,
9440Sstevel@tonic-gate struct FTW *ftwp)
9450Sstevel@tonic-gate {
9460Sstevel@tonic-gate /* ignore . and .. */
9470Sstevel@tonic-gate if (strcmp(namep, ".") == 0 || strcmp(namep, "..") == 0)
9480Sstevel@tonic-gate return (0);
9490Sstevel@tonic-gate
9500Sstevel@tonic-gate switch (flg) {
9510Sstevel@tonic-gate case FTW_F: /* files */
9520Sstevel@tonic-gate case FTW_SL:
9530Sstevel@tonic-gate if (unlink(namep) == -1) {
9540Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"),
9550Sstevel@tonic-gate namep, strerror(errno));
9560Sstevel@tonic-gate return (-1);
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate break;
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate case FTW_DP: /* directories that have their children processed */
9610Sstevel@tonic-gate if (rmdir(namep) == -1) {
9620Sstevel@tonic-gate pr_err(gettext("rmdir %s failed: %s"),
9630Sstevel@tonic-gate namep, strerror(errno));
9640Sstevel@tonic-gate return (-1);
9650Sstevel@tonic-gate }
9660Sstevel@tonic-gate break;
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate case FTW_D: /* ignore directories if children not processed */
9690Sstevel@tonic-gate break;
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate default:
9720Sstevel@tonic-gate pr_err(gettext("failure on file %s, flg %d."),
9730Sstevel@tonic-gate namep, flg);
9740Sstevel@tonic-gate return (-1);
9750Sstevel@tonic-gate }
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate /* return success */
9780Sstevel@tonic-gate return (0);
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate /*
9820Sstevel@tonic-gate *
9830Sstevel@tonic-gate * cachefs_convert_uv2cl
9840Sstevel@tonic-gate *
9850Sstevel@tonic-gate * Description:
9860Sstevel@tonic-gate * Copies the contents of a cachefs_user_values object into a
9870Sstevel@tonic-gate * cache_label object, performing the necessary conversions.
9880Sstevel@tonic-gate * Arguments:
9890Sstevel@tonic-gate * uvp cachefs_user_values to copy from
9900Sstevel@tonic-gate * clp cache_label to copy into
9910Sstevel@tonic-gate * dirp cache directory
9920Sstevel@tonic-gate * Returns:
9930Sstevel@tonic-gate * Returns 0 for success, -1 for an error.
9940Sstevel@tonic-gate * Preconditions:
9950Sstevel@tonic-gate * precond(uvp)
9960Sstevel@tonic-gate * precond(clp)
9970Sstevel@tonic-gate * precond(dirp)
9980Sstevel@tonic-gate */
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate int
cachefs_convert_uv2cl(const struct cachefs_user_values * uvp,struct cache_label * clp,const char * dirp)10010Sstevel@tonic-gate cachefs_convert_uv2cl(const struct cachefs_user_values *uvp,
10020Sstevel@tonic-gate struct cache_label *clp, const char *dirp)
10030Sstevel@tonic-gate {
10040Sstevel@tonic-gate struct statvfs64 fs;
10050Sstevel@tonic-gate int xx;
10060Sstevel@tonic-gate double ftmp;
10070Sstevel@tonic-gate double temp;
10080Sstevel@tonic-gate
10090Sstevel@tonic-gate /* get file system information */
10100Sstevel@tonic-gate xx = statvfs64(dirp, &fs);
10110Sstevel@tonic-gate if (xx == -1) {
10120Sstevel@tonic-gate pr_err(gettext("statvfs %s failed: %s"), dirp,
10130Sstevel@tonic-gate strerror(errno));
10140Sstevel@tonic-gate return (-1);
10150Sstevel@tonic-gate }
10160Sstevel@tonic-gate
10170Sstevel@tonic-gate ftmp = (double)fs.f_frsize / (double)MAXBSIZE;
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate /* front fs is less than 1 terabyte */
10200Sstevel@tonic-gate temp = (double)uvp->uv_maxblocks / 100.0 *
10210Sstevel@tonic-gate (double)fs.f_blocks * ftmp + .5;
10220Sstevel@tonic-gate clp->cl_maxblks = temp < (double)INT_MAX ? (int)temp : INT_MAX;
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate temp = (double)uvp->uv_minblocks / 100.0 *
10250Sstevel@tonic-gate (double)fs.f_blocks * ftmp + .5;
10260Sstevel@tonic-gate clp->cl_blockmin = temp < (double)INT_MAX ? (int)temp : INT_MAX;
10270Sstevel@tonic-gate
10280Sstevel@tonic-gate temp = (double)uvp->uv_threshblocks / 100.0 *
10290Sstevel@tonic-gate (double)fs.f_blocks * ftmp + .5;
10300Sstevel@tonic-gate clp->cl_blocktresh = temp < (double)INT_MAX ? (int)temp : INT_MAX;
10310Sstevel@tonic-gate
10320Sstevel@tonic-gate temp = (double)uvp->uv_maxfiles / 100.0 * (double)fs.f_files + .5;
10330Sstevel@tonic-gate clp->cl_maxinodes = temp < (double)INT_MAX ? (int)temp : INT_MAX;
10340Sstevel@tonic-gate
10350Sstevel@tonic-gate temp = (double)uvp->uv_minfiles / 100.0 * (double)fs.f_files + .5;
10360Sstevel@tonic-gate clp->cl_filemin = temp < (double)INT_MAX ? (int)temp : INT_MAX;
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate temp = (double)uvp->uv_threshfiles / 100.0 * (double)fs.f_files +.5;
10390Sstevel@tonic-gate clp->cl_filetresh = temp < (double)INT_MAX ? (int)temp : INT_MAX;
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate ftmp = (double)(1024 * 1024) / (double)MAXBSIZE;
10420Sstevel@tonic-gate clp->cl_maxfiles = uvp->uv_maxfilesize * ftmp + .5;
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate clp->cl_blkhiwat = uvp->uv_hiblocks / 100.0 * clp->cl_maxblks + .5;
10450Sstevel@tonic-gate clp->cl_blklowat = uvp->uv_lowblocks / 100.0 * clp->cl_maxblks + .5;
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate clp->cl_filehiwat = uvp->uv_hifiles / 100.0 * clp->cl_maxinodes + .5;
10480Sstevel@tonic-gate clp->cl_filelowat = uvp->uv_lowfiles / 100.0 * clp->cl_maxinodes + .5;
10490Sstevel@tonic-gate
10500Sstevel@tonic-gate clp->cl_cfsversion = CFSVERSION;
10510Sstevel@tonic-gate
10520Sstevel@tonic-gate /* return success */
10530Sstevel@tonic-gate return (0);
10540Sstevel@tonic-gate }
10550Sstevel@tonic-gate
10560Sstevel@tonic-gate /*
10570Sstevel@tonic-gate *
10580Sstevel@tonic-gate * cachefs_convert_cl2uv
10590Sstevel@tonic-gate *
10600Sstevel@tonic-gate * Description:
10610Sstevel@tonic-gate * Copies the contents of a cache_label object into a
10620Sstevel@tonic-gate * cachefs_user_values object, performing the necessary conversions.
10630Sstevel@tonic-gate * Arguments:
10640Sstevel@tonic-gate * clp cache_label to copy from
10650Sstevel@tonic-gate * uvp cachefs_user_values to copy into
10660Sstevel@tonic-gate * dirp cache directory
10670Sstevel@tonic-gate * Returns:
10680Sstevel@tonic-gate * Returns 0 for success, -1 for an error.
10690Sstevel@tonic-gate * Preconditions:
10700Sstevel@tonic-gate * precond(clp)
10710Sstevel@tonic-gate * precond(uvp)
10720Sstevel@tonic-gate * precond(dirp)
10730Sstevel@tonic-gate */
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate int
cachefs_convert_cl2uv(const struct cache_label * clp,struct cachefs_user_values * uvp,const char * dirp)10760Sstevel@tonic-gate cachefs_convert_cl2uv(const struct cache_label *clp,
10770Sstevel@tonic-gate struct cachefs_user_values *uvp, const char *dirp)
10780Sstevel@tonic-gate {
10790Sstevel@tonic-gate struct statvfs64 fs;
10800Sstevel@tonic-gate int xx;
10810Sstevel@tonic-gate double temp;
10820Sstevel@tonic-gate double ftmp;
10830Sstevel@tonic-gate long long ltmp;
10840Sstevel@tonic-gate
10850Sstevel@tonic-gate /* get file system information */
10860Sstevel@tonic-gate xx = statvfs64(dirp, &fs);
10870Sstevel@tonic-gate if (xx == -1) {
10880Sstevel@tonic-gate pr_err(gettext("statvfs %s failed: %s"), dirp,
10890Sstevel@tonic-gate strerror(errno));
10900Sstevel@tonic-gate return (-1);
10910Sstevel@tonic-gate }
10920Sstevel@tonic-gate
10930Sstevel@tonic-gate #define BOUND(yy) \
10940Sstevel@tonic-gate yy = (yy < 0) ? 0 : yy; \
10950Sstevel@tonic-gate yy = (yy > 100) ? 100 : yy;
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate ftmp = (double)MAXBSIZE / (double)fs.f_frsize;
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate temp = (double)clp->cl_maxblks * ftmp /
11000Sstevel@tonic-gate (double)fs.f_blocks * 100. + .5;
11010Sstevel@tonic-gate BOUND(temp);
11020Sstevel@tonic-gate uvp->uv_maxblocks = (int)temp;
11030Sstevel@tonic-gate
11040Sstevel@tonic-gate temp = (double)clp->cl_blockmin * ftmp /
11050Sstevel@tonic-gate (double)fs.f_blocks * 100. + .5;
11060Sstevel@tonic-gate BOUND(temp);
11070Sstevel@tonic-gate uvp->uv_minblocks = (int)temp;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate temp = (double)clp->cl_blocktresh * ftmp /
11100Sstevel@tonic-gate (double)fs.f_blocks * 100. + .5;
11110Sstevel@tonic-gate BOUND(temp);
11120Sstevel@tonic-gate uvp->uv_threshblocks = (int)temp;
11130Sstevel@tonic-gate
11140Sstevel@tonic-gate temp = ((double)clp->cl_maxinodes / fs.f_files) * 100. + .5;
11150Sstevel@tonic-gate BOUND(temp);
11160Sstevel@tonic-gate uvp->uv_maxfiles = (int)temp;
11170Sstevel@tonic-gate
11180Sstevel@tonic-gate temp = ((double)clp->cl_filemin / fs.f_files) * 100. + .5;
11190Sstevel@tonic-gate BOUND(temp);
11200Sstevel@tonic-gate uvp->uv_minfiles = (int)temp;
11210Sstevel@tonic-gate
11220Sstevel@tonic-gate temp = ((double)clp->cl_filetresh / fs.f_files) * 100. + .5;
11230Sstevel@tonic-gate BOUND(temp);
11240Sstevel@tonic-gate uvp->uv_threshfiles = (int)temp;
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate ltmp = ((long long)clp->cl_maxfiles * MAXBSIZE);
11270Sstevel@tonic-gate uvp->uv_maxfilesize = (ltmp + (MAXBSIZE / 2)) / (1024 * 1024);
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate xx = ((double)clp->cl_blkhiwat / clp->cl_maxblks) * 100. + .5;
11300Sstevel@tonic-gate BOUND(xx);
11310Sstevel@tonic-gate uvp->uv_hiblocks = xx;
11320Sstevel@tonic-gate
11330Sstevel@tonic-gate xx = ((double)clp->cl_blklowat / clp->cl_maxblks) * 100. + .5;
11340Sstevel@tonic-gate BOUND(xx);
11350Sstevel@tonic-gate uvp->uv_lowblocks = xx;
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate xx = ((double)clp->cl_filehiwat / clp->cl_maxinodes) * 100. + .5;
11380Sstevel@tonic-gate BOUND(xx);
11390Sstevel@tonic-gate uvp->uv_hifiles = xx;
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate xx = ((double)clp->cl_filelowat / clp->cl_maxinodes) * 100. + .5;
11420Sstevel@tonic-gate BOUND(xx);
11430Sstevel@tonic-gate uvp->uv_lowfiles = xx;
11440Sstevel@tonic-gate
11450Sstevel@tonic-gate /* return success */
11460Sstevel@tonic-gate return (0);
11470Sstevel@tonic-gate }
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate /*
11500Sstevel@tonic-gate * cachefs_file_to_dir
11510Sstevel@tonic-gate *
11520Sstevel@tonic-gate * takes in a path, and returns the parent directory of that path.
11530Sstevel@tonic-gate *
11540Sstevel@tonic-gate * it's the caller's responsibility to free the pointer returned by
11550Sstevel@tonic-gate * this function.
11560Sstevel@tonic-gate */
11570Sstevel@tonic-gate
11580Sstevel@tonic-gate char *
cachefs_file_to_dir(const char * path)11590Sstevel@tonic-gate cachefs_file_to_dir(const char *path)
11600Sstevel@tonic-gate {
11610Sstevel@tonic-gate char *rc, *cp;
11620Sstevel@tonic-gate
11630Sstevel@tonic-gate if (path == NULL)
11640Sstevel@tonic-gate return (NULL);
11650Sstevel@tonic-gate
11660Sstevel@tonic-gate rc = strdup(path);
11670Sstevel@tonic-gate if (rc == NULL)
11680Sstevel@tonic-gate return (NULL);
11690Sstevel@tonic-gate
11700Sstevel@tonic-gate if ((cp = strrchr(rc, '/')) == NULL) {
11710Sstevel@tonic-gate
11720Sstevel@tonic-gate /*
11730Sstevel@tonic-gate * if no slashes at all, return "." (current directory).
11740Sstevel@tonic-gate */
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate (void) free(rc);
11770Sstevel@tonic-gate rc = strdup(".");
11780Sstevel@tonic-gate
11790Sstevel@tonic-gate } else if (cp == rc) {
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate /*
11820Sstevel@tonic-gate * else, if the last '/' is the first character, chop
11830Sstevel@tonic-gate * off from there (i.e. return "/").
11840Sstevel@tonic-gate */
11850Sstevel@tonic-gate
11860Sstevel@tonic-gate rc[1] = '\0';
11870Sstevel@tonic-gate
11880Sstevel@tonic-gate } else {
11890Sstevel@tonic-gate
11900Sstevel@tonic-gate /*
11910Sstevel@tonic-gate * else, we have a path like /foo/bar or foo/bar.
11920Sstevel@tonic-gate * chop off from the last '/'.
11930Sstevel@tonic-gate */
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate *cp = '\0';
11960Sstevel@tonic-gate
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate return (rc);
12000Sstevel@tonic-gate }
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate /*
12030Sstevel@tonic-gate * cachefs_clean_flag_test
12040Sstevel@tonic-gate *
12050Sstevel@tonic-gate * Description:
12060Sstevel@tonic-gate * Tests whether or not the clean flag on the file system
12070Sstevel@tonic-gate * is set.
12080Sstevel@tonic-gate * Arguments:
12090Sstevel@tonic-gate * cachedirp name of the the file system cache directory
12100Sstevel@tonic-gate * Returns:
12110Sstevel@tonic-gate * Returns 1 if the cache was shut down cleanly, 0 if not.
12120Sstevel@tonic-gate * Preconditions:
12130Sstevel@tonic-gate * precond(cachedirp)
12140Sstevel@tonic-gate */
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate int
cachefs_clean_flag_test(const char * cachedirp)12170Sstevel@tonic-gate cachefs_clean_flag_test(const char *cachedirp)
12180Sstevel@tonic-gate {
12190Sstevel@tonic-gate char *namep;
12200Sstevel@tonic-gate int xx;
12210Sstevel@tonic-gate char buf[MAXPATHLEN];
12220Sstevel@tonic-gate int fd;
12230Sstevel@tonic-gate struct cache_usage cu;
12240Sstevel@tonic-gate
12250Sstevel@tonic-gate /* construct the path name of the resource file */
12260Sstevel@tonic-gate namep = RESOURCE_NAME;
12270Sstevel@tonic-gate xx = strlen(cachedirp) + strlen(namep) + 3;
12280Sstevel@tonic-gate if (xx >= MAXPATHLEN) {
12290Sstevel@tonic-gate pr_err(gettext("Path name too long %s/%s"),
12300Sstevel@tonic-gate cachedirp, namep);
12310Sstevel@tonic-gate return (39);
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate snprintf(buf, sizeof (buf), "%s/%s", cachedirp, namep);
12340Sstevel@tonic-gate
12350Sstevel@tonic-gate /* open the file; it will be <2GB */
12360Sstevel@tonic-gate fd = open(buf, O_RDONLY);
12370Sstevel@tonic-gate if (fd == -1) {
12380Sstevel@tonic-gate pr_err(gettext("Cannot open %s: %s"), buf, strerror(errno));
12390Sstevel@tonic-gate return (0);
12400Sstevel@tonic-gate }
12410Sstevel@tonic-gate
12420Sstevel@tonic-gate /* read the cache_usage structure */
12430Sstevel@tonic-gate xx = read(fd, &cu, sizeof (cu));
12440Sstevel@tonic-gate if (xx != sizeof (cu)) {
12450Sstevel@tonic-gate pr_err(gettext("Error reading %s: %d %s"), buf,
12460Sstevel@tonic-gate xx, strerror(errno));
12470Sstevel@tonic-gate close(fd);
12480Sstevel@tonic-gate return (0);
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate close(fd);
12510Sstevel@tonic-gate
12520Sstevel@tonic-gate /* return state of the cache */
12530Sstevel@tonic-gate return ((cu.cu_flags & CUSAGE_ACTIVE) == 0);
12540Sstevel@tonic-gate }
12550Sstevel@tonic-gate
12560Sstevel@tonic-gate time32_t
get_boottime()12570Sstevel@tonic-gate get_boottime()
12580Sstevel@tonic-gate {
12590Sstevel@tonic-gate struct utmpx id, *putmp;
12600Sstevel@tonic-gate
12610Sstevel@tonic-gate id.ut_type = BOOT_TIME;
12620Sstevel@tonic-gate setutxent();
12630Sstevel@tonic-gate if ((putmp = getutxid(&id)) != NULL)
12640Sstevel@tonic-gate return ((time32_t)putmp->ut_tv.tv_sec);
12650Sstevel@tonic-gate return (-1);
12660Sstevel@tonic-gate }
1267