1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Common subroutines used by the programs in these subdirectories. 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <locale.h> 34*0Sstevel@tonic-gate #include <stdio.h> 35*0Sstevel@tonic-gate #include <stdlib.h> 36*0Sstevel@tonic-gate #include <string.h> 37*0Sstevel@tonic-gate #include <assert.h> 38*0Sstevel@tonic-gate #include <unistd.h> 39*0Sstevel@tonic-gate #include <limits.h> 40*0Sstevel@tonic-gate #include <errno.h> 41*0Sstevel@tonic-gate #include <wait.h> 42*0Sstevel@tonic-gate #include <ctype.h> 43*0Sstevel@tonic-gate #include <fcntl.h> 44*0Sstevel@tonic-gate #include <ftw.h> 45*0Sstevel@tonic-gate #include <dirent.h> 46*0Sstevel@tonic-gate #include <sys/types.h> 47*0Sstevel@tonic-gate #include <sys/time.h> 48*0Sstevel@tonic-gate #include <utmpx.h> 49*0Sstevel@tonic-gate #include <sys/uio.h> 50*0Sstevel@tonic-gate #include <sys/param.h> 51*0Sstevel@tonic-gate #include <sys/stat.h> 52*0Sstevel@tonic-gate #include <sys/fcntl.h> 53*0Sstevel@tonic-gate #include <sys/mount.h> 54*0Sstevel@tonic-gate #include <sys/mntent.h> 55*0Sstevel@tonic-gate #include <sys/mnttab.h> 56*0Sstevel@tonic-gate #include <sys/mman.h> 57*0Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h> 58*0Sstevel@tonic-gate #include "subr.h" 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate /* 61*0Sstevel@tonic-gate * 62*0Sstevel@tonic-gate * cachefs_dir_lock 63*0Sstevel@tonic-gate * 64*0Sstevel@tonic-gate * Description: 65*0Sstevel@tonic-gate * Gets a lock on the cache directory. 66*0Sstevel@tonic-gate * To release the lock, call cachefs_dir_unlock 67*0Sstevel@tonic-gate * with the returned value. 68*0Sstevel@tonic-gate * Arguments: 69*0Sstevel@tonic-gate * cachedirp name of the cache directory 70*0Sstevel@tonic-gate * shared 1 if shared, 0 if not 71*0Sstevel@tonic-gate * Returns: 72*0Sstevel@tonic-gate * Returns -1 if the lock cannot be obtained immediatly. 73*0Sstevel@tonic-gate * If the lock is obtained, returns a value >= 0. 74*0Sstevel@tonic-gate * Preconditions: 75*0Sstevel@tonic-gate * precond(cachedirp) 76*0Sstevel@tonic-gate */ 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate int 79*0Sstevel@tonic-gate cachefs_dir_lock(const char *cachedirp, int shared) 80*0Sstevel@tonic-gate { 81*0Sstevel@tonic-gate int fd; 82*0Sstevel@tonic-gate int xx; 83*0Sstevel@tonic-gate int len; 84*0Sstevel@tonic-gate char buf[MAXPATHLEN]; 85*0Sstevel@tonic-gate struct flock fl; 86*0Sstevel@tonic-gate char *strp; 87*0Sstevel@tonic-gate struct stat statb; 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate /* make a path prefix to the cache directory lock file */ 90*0Sstevel@tonic-gate strp = CACHEFS_ROOTRUN; 91*0Sstevel@tonic-gate xx = stat(strp, &statb); 92*0Sstevel@tonic-gate if ((xx < 0) || ((statb.st_mode & S_IFMT) != S_IFDIR)) 93*0Sstevel@tonic-gate strp = "/tmp"; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /* won't overflow */ 96*0Sstevel@tonic-gate len = snprintf(buf, sizeof (buf), "%s/%s", strp, CACHEFS_LOCKDIR_PRE); 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate if (strlcat(buf, cachedirp, sizeof (buf)) >= sizeof (buf)) { 99*0Sstevel@tonic-gate pr_err(gettext("Cache directory name %s is too long"), 100*0Sstevel@tonic-gate cachedirp); 101*0Sstevel@tonic-gate return (-1); 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate strp = &buf[len]; 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate while (strp = strchr(strp, '/')) { /* convert path to a file */ 107*0Sstevel@tonic-gate *strp = '_'; 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* 111*0Sstevel@tonic-gate * Create and open the cache directory lock file. 112*0Sstevel@tonic-gate * This file will be <2G. 113*0Sstevel@tonic-gate */ 114*0Sstevel@tonic-gate fd = open(buf, O_RDWR | O_CREAT, 0700); 115*0Sstevel@tonic-gate if (fd == -1) { 116*0Sstevel@tonic-gate pr_err(gettext("Cannot open lock file %s"), buf); 117*0Sstevel@tonic-gate return (-1); 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* try to set the lock */ 121*0Sstevel@tonic-gate fl.l_type = (shared == 1) ? F_RDLCK : F_WRLCK; 122*0Sstevel@tonic-gate fl.l_whence = 0; 123*0Sstevel@tonic-gate fl.l_start = 1024; 124*0Sstevel@tonic-gate fl.l_len = 1024; 125*0Sstevel@tonic-gate fl.l_sysid = 0; 126*0Sstevel@tonic-gate fl.l_pid = 0; 127*0Sstevel@tonic-gate /* CACHEFS_LOCK_FILE will be <2GB */ 128*0Sstevel@tonic-gate xx = fcntl(fd, F_SETLKW, &fl); 129*0Sstevel@tonic-gate if (xx == -1) { 130*0Sstevel@tonic-gate if (errno == EAGAIN) { 131*0Sstevel@tonic-gate pr_err(gettext("Cannot gain access to the " 132*0Sstevel@tonic-gate "cache directory %s."), cachedirp); 133*0Sstevel@tonic-gate } else { 134*0Sstevel@tonic-gate pr_err(gettext("Unexpected failure on lock file %s %s"), 135*0Sstevel@tonic-gate buf, strerror(errno)); 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate close(fd); 138*0Sstevel@tonic-gate return (-1); 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate /* return the file descriptor which can be used to release the lock */ 142*0Sstevel@tonic-gate return (fd); 143*0Sstevel@tonic-gate } 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate /* 146*0Sstevel@tonic-gate * 147*0Sstevel@tonic-gate * cachefs_dir_unlock 148*0Sstevel@tonic-gate * 149*0Sstevel@tonic-gate * Description: 150*0Sstevel@tonic-gate * Releases an advisory lock on the cache directory. 151*0Sstevel@tonic-gate * Arguments: 152*0Sstevel@tonic-gate * fd cookie returned by cachefs_dir_lock 153*0Sstevel@tonic-gate * Returns: 154*0Sstevel@tonic-gate * Returns -1 if the lock cannot be released or 0 for success. 155*0Sstevel@tonic-gate * Preconditions: 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate int 159*0Sstevel@tonic-gate cachefs_dir_unlock(int fd) 160*0Sstevel@tonic-gate { 161*0Sstevel@tonic-gate struct flock fl; 162*0Sstevel@tonic-gate int error = 0; 163*0Sstevel@tonic-gate int xx; 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate /* release the lock */ 166*0Sstevel@tonic-gate fl.l_type = F_UNLCK; 167*0Sstevel@tonic-gate fl.l_whence = 0; 168*0Sstevel@tonic-gate fl.l_start = 1024; 169*0Sstevel@tonic-gate fl.l_len = 1024; 170*0Sstevel@tonic-gate fl.l_sysid = 0; 171*0Sstevel@tonic-gate fl.l_pid = 0; 172*0Sstevel@tonic-gate /* fd will be <2GB */ 173*0Sstevel@tonic-gate xx = fcntl(fd, F_SETLK, &fl); 174*0Sstevel@tonic-gate if (xx == -1) { 175*0Sstevel@tonic-gate pr_err(gettext("Unexpected failure releasing lock file %s"), 176*0Sstevel@tonic-gate strerror(errno)); 177*0Sstevel@tonic-gate error = -1; 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* close the lock file */ 181*0Sstevel@tonic-gate close(fd); 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate return (error); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * 188*0Sstevel@tonic-gate * cachefs_label_file_get 189*0Sstevel@tonic-gate * 190*0Sstevel@tonic-gate * Description: 191*0Sstevel@tonic-gate * Gets the contents of a cache label file. 192*0Sstevel@tonic-gate * Performs error checking on the file. 193*0Sstevel@tonic-gate * Arguments: 194*0Sstevel@tonic-gate * filep name of the cache label file 195*0Sstevel@tonic-gate * clabelp where to put the file contents 196*0Sstevel@tonic-gate * Returns: 197*0Sstevel@tonic-gate * Returns 0 for success or -1 if an error occurs. 198*0Sstevel@tonic-gate * Preconditions: 199*0Sstevel@tonic-gate * precond(filep) 200*0Sstevel@tonic-gate * precond(clabelp) 201*0Sstevel@tonic-gate */ 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate int 204*0Sstevel@tonic-gate cachefs_label_file_get(const char *filep, struct cache_label *clabelp) 205*0Sstevel@tonic-gate { 206*0Sstevel@tonic-gate int xx; 207*0Sstevel@tonic-gate int fd; 208*0Sstevel@tonic-gate struct stat64 statinfo; 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate /* get info on the file */ 211*0Sstevel@tonic-gate xx = lstat64(filep, &statinfo); 212*0Sstevel@tonic-gate if (xx == -1) { 213*0Sstevel@tonic-gate if (errno != ENOENT) { 214*0Sstevel@tonic-gate pr_err(gettext("Cannot stat file %s: %s"), 215*0Sstevel@tonic-gate filep, strerror(errno)); 216*0Sstevel@tonic-gate } else { 217*0Sstevel@tonic-gate pr_err(gettext("File %s does not exist."), filep); 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate return (-1); 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* if the file is the wrong type */ 224*0Sstevel@tonic-gate if (!S_ISREG(statinfo.st_mode)) { 225*0Sstevel@tonic-gate pr_err(gettext("Cache label file %s corrupted"), filep); 226*0Sstevel@tonic-gate return (-1); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /* if the file is the wrong size; it will be <2GB */ 230*0Sstevel@tonic-gate if (statinfo.st_size != (offset_t)sizeof (struct cache_label)) { 231*0Sstevel@tonic-gate pr_err(gettext("Cache label file %s wrong size"), filep); 232*0Sstevel@tonic-gate return (-1); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* open the cache label file */ 236*0Sstevel@tonic-gate fd = open(filep, O_RDONLY); 237*0Sstevel@tonic-gate if (fd == -1) { 238*0Sstevel@tonic-gate pr_err(gettext("Error opening %s: %s"), filep, 239*0Sstevel@tonic-gate strerror(errno)); 240*0Sstevel@tonic-gate return (-1); 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate /* read the current set of parameters */ 244*0Sstevel@tonic-gate xx = read(fd, clabelp, sizeof (struct cache_label)); 245*0Sstevel@tonic-gate if (xx != sizeof (struct cache_label)) { 246*0Sstevel@tonic-gate pr_err(gettext("Reading %s failed: %s\n"), filep, 247*0Sstevel@tonic-gate strerror(errno)); 248*0Sstevel@tonic-gate close(fd); 249*0Sstevel@tonic-gate return (-1); 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate close(fd); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* return success */ 254*0Sstevel@tonic-gate return (0); 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate /* 258*0Sstevel@tonic-gate * 259*0Sstevel@tonic-gate * cachefs_label_file_put 260*0Sstevel@tonic-gate * 261*0Sstevel@tonic-gate * Description: 262*0Sstevel@tonic-gate * Outputs the contents of a cache label object to a file. 263*0Sstevel@tonic-gate * Arguments: 264*0Sstevel@tonic-gate * filep name of the cache label file 265*0Sstevel@tonic-gate * clabelp where to get the file contents 266*0Sstevel@tonic-gate * Returns: 267*0Sstevel@tonic-gate * Returns 0 for success or -1 if an error occurs. 268*0Sstevel@tonic-gate * Preconditions: 269*0Sstevel@tonic-gate * precond(filep) 270*0Sstevel@tonic-gate * precond(clabelp) 271*0Sstevel@tonic-gate */ 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate int 274*0Sstevel@tonic-gate cachefs_label_file_put(const char *filep, struct cache_label *clabelp) 275*0Sstevel@tonic-gate { 276*0Sstevel@tonic-gate int xx; 277*0Sstevel@tonic-gate int fd; 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* get rid of the file if it already exists */ 280*0Sstevel@tonic-gate xx = unlink(filep); 281*0Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) { 282*0Sstevel@tonic-gate pr_err(gettext("Could not remove %s: %s"), filep, 283*0Sstevel@tonic-gate strerror(errno)); 284*0Sstevel@tonic-gate return (-1); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate /* open the cache label file; this file will be <2GB */ 288*0Sstevel@tonic-gate fd = open(filep, O_CREAT | O_RDWR, 0600); 289*0Sstevel@tonic-gate if (fd == -1) { 290*0Sstevel@tonic-gate pr_err(gettext("Error creating %s: %s"), filep, 291*0Sstevel@tonic-gate strerror(errno)); 292*0Sstevel@tonic-gate return (-1); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate /* write out the cache label object */ 296*0Sstevel@tonic-gate xx = write(fd, clabelp, sizeof (struct cache_label)); 297*0Sstevel@tonic-gate if (xx != sizeof (struct cache_label)) { 298*0Sstevel@tonic-gate pr_err(gettext("Writing %s failed: %s"), filep, 299*0Sstevel@tonic-gate strerror(errno)); 300*0Sstevel@tonic-gate close(fd); 301*0Sstevel@tonic-gate return (-1); 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate /* make sure the contents get to disk */ 305*0Sstevel@tonic-gate if (fsync(fd) != 0) { 306*0Sstevel@tonic-gate pr_err(gettext("Writing %s failed on sync: %s"), filep, 307*0Sstevel@tonic-gate strerror(errno)); 308*0Sstevel@tonic-gate close(fd); 309*0Sstevel@tonic-gate return (-1); 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate close(fd); 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* return success */ 315*0Sstevel@tonic-gate return (0); 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate int 319*0Sstevel@tonic-gate cachefs_label_file_vcheck(char *filep, struct cache_label *clabelp) 320*0Sstevel@tonic-gate { 321*0Sstevel@tonic-gate /* check for an invalid version number */ 322*0Sstevel@tonic-gate if (clabelp->cl_cfsversion != CFSVERSION) { 323*0Sstevel@tonic-gate pr_err(gettext("Cache label file %s corrupted"), filep); 324*0Sstevel@tonic-gate return (-1); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate return (0); 328*0Sstevel@tonic-gate } 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate /* 331*0Sstevel@tonic-gate * 332*0Sstevel@tonic-gate * cachefs_inuse 333*0Sstevel@tonic-gate * 334*0Sstevel@tonic-gate * Description: 335*0Sstevel@tonic-gate * Tests whether or not the cache directory is in use by 336*0Sstevel@tonic-gate * the cache file system. 337*0Sstevel@tonic-gate * Arguments: 338*0Sstevel@tonic-gate * cachedirp name of the file system cache directory 339*0Sstevel@tonic-gate * Returns: 340*0Sstevel@tonic-gate * Returns 1 if the cache is in use or an error, 0 if not. 341*0Sstevel@tonic-gate * Preconditions: 342*0Sstevel@tonic-gate * precond(cachedirp) 343*0Sstevel@tonic-gate */ 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate int 346*0Sstevel@tonic-gate cachefs_inuse(const char *cachedirp) 347*0Sstevel@tonic-gate { 348*0Sstevel@tonic-gate int fd; 349*0Sstevel@tonic-gate int xx; 350*0Sstevel@tonic-gate char buf[MAXPATHLEN]; 351*0Sstevel@tonic-gate char *lockp = CACHEFS_LOCK_FILE; 352*0Sstevel@tonic-gate struct flock fl; 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate /* see if path name is too long */ 355*0Sstevel@tonic-gate xx = strlen(cachedirp) + strlen(lockp) + 3; 356*0Sstevel@tonic-gate if (xx >= MAXPATHLEN) { 357*0Sstevel@tonic-gate pr_err(gettext("Cache directory name %s is too long"), 358*0Sstevel@tonic-gate cachedirp); 359*0Sstevel@tonic-gate return (1); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* make a path to the cache directory lock file */ 363*0Sstevel@tonic-gate snprintf(buf, sizeof (buf), "%s/%s", cachedirp, lockp); 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate /* Open the kernel in use lock file. This file will be <2GB. */ 366*0Sstevel@tonic-gate fd = open(buf, O_RDWR, 0700); 367*0Sstevel@tonic-gate if (fd == -1) { 368*0Sstevel@tonic-gate pr_err(gettext("Cannot open lock file %s"), buf); 369*0Sstevel@tonic-gate return (1); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* test the lock status */ 373*0Sstevel@tonic-gate fl.l_type = F_WRLCK; 374*0Sstevel@tonic-gate fl.l_whence = 0; 375*0Sstevel@tonic-gate fl.l_start = 0; 376*0Sstevel@tonic-gate fl.l_len = 1024; 377*0Sstevel@tonic-gate fl.l_sysid = 0; 378*0Sstevel@tonic-gate fl.l_pid = 0; 379*0Sstevel@tonic-gate xx = fcntl(fd, F_GETLK, &fl); 380*0Sstevel@tonic-gate if (xx == -1) { 381*0Sstevel@tonic-gate pr_err(gettext("Unexpected failure on lock file %s %s"), 382*0Sstevel@tonic-gate buf, strerror(errno)); 383*0Sstevel@tonic-gate close(fd); 384*0Sstevel@tonic-gate return (1); 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate close(fd); 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate if (fl.l_type == F_UNLCK) 389*0Sstevel@tonic-gate xx = 0; 390*0Sstevel@tonic-gate else 391*0Sstevel@tonic-gate xx = 1; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate /* return whether or not the cache is in use */ 394*0Sstevel@tonic-gate return (xx); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate /* 398*0Sstevel@tonic-gate * 399*0Sstevel@tonic-gate * cachefs_resouce_size 400*0Sstevel@tonic-gate * 401*0Sstevel@tonic-gate * Description: 402*0Sstevel@tonic-gate * Returns information about a resource file. 403*0Sstevel@tonic-gate * Arguments: 404*0Sstevel@tonic-gate * maxinodes number of inodes to be managed by the resource file 405*0Sstevel@tonic-gate * rinfop set to info about the resource file 406*0Sstevel@tonic-gate * Returns: 407*0Sstevel@tonic-gate * Preconditions: 408*0Sstevel@tonic-gate * precond(rinfop) 409*0Sstevel@tonic-gate */ 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate void 412*0Sstevel@tonic-gate cachefs_resource_size(int maxinodes, struct cachefs_rinfo *rinfop) 413*0Sstevel@tonic-gate { 414*0Sstevel@tonic-gate int fsize; 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate fsize = MAXBSIZE; 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate rinfop->r_ptroffset = fsize; 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate fsize += MAXBSIZE * (maxinodes / CACHEFS_RLPMBS); 421*0Sstevel@tonic-gate if ((maxinodes % CACHEFS_RLPMBS) != 0) 422*0Sstevel@tonic-gate fsize += MAXBSIZE; 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate rinfop->r_fsize = fsize; 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate 427*0Sstevel@tonic-gate /* 428*0Sstevel@tonic-gate * 429*0Sstevel@tonic-gate * cachefs_create_cache 430*0Sstevel@tonic-gate * 431*0Sstevel@tonic-gate * Description: 432*0Sstevel@tonic-gate * Creates the specified cache directory and populates it as 433*0Sstevel@tonic-gate * needed by CFS. 434*0Sstevel@tonic-gate * Arguments: 435*0Sstevel@tonic-gate * dirp the name of the cache directory 436*0Sstevel@tonic-gate * uv user values (may be NULL) 437*0Sstevel@tonic-gate * clabel label file contents, or placeholder for this 438*0Sstevel@tonic-gate * Returns: 439*0Sstevel@tonic-gate * Returns 0 for success or: 440*0Sstevel@tonic-gate * -1 for an error 441*0Sstevel@tonic-gate * -2 for an error and cache directory partially created 442*0Sstevel@tonic-gate * Preconditions: 443*0Sstevel@tonic-gate * precond(dirp) 444*0Sstevel@tonic-gate */ 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate int 447*0Sstevel@tonic-gate cachefs_create_cache(char *dirp, struct cachefs_user_values *uv, 448*0Sstevel@tonic-gate struct cache_label *clabel) 449*0Sstevel@tonic-gate { 450*0Sstevel@tonic-gate int xx; 451*0Sstevel@tonic-gate char path[CACHEFS_XMAXPATH]; 452*0Sstevel@tonic-gate int fd; 453*0Sstevel@tonic-gate void *bufp; 454*0Sstevel@tonic-gate int cnt; 455*0Sstevel@tonic-gate struct cache_usage cu; 456*0Sstevel@tonic-gate FILE *fp; 457*0Sstevel@tonic-gate char *parent; 458*0Sstevel@tonic-gate struct statvfs64 svfs; 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate cu.cu_blksused = 0; 461*0Sstevel@tonic-gate cu.cu_filesused = 0; 462*0Sstevel@tonic-gate cu.cu_flags = 0; 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate /* make sure cache dir name is not too long */ 465*0Sstevel@tonic-gate if (strlen(dirp) > (size_t)PATH_MAX) { 466*0Sstevel@tonic-gate pr_err(gettext("path name %s is too long."), dirp); 467*0Sstevel@tonic-gate return (-1); 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate /* ensure the path isn't in cachefs */ 471*0Sstevel@tonic-gate parent = cachefs_file_to_dir(dirp); 472*0Sstevel@tonic-gate if (parent == NULL) { 473*0Sstevel@tonic-gate pr_err(gettext("Out of memory")); 474*0Sstevel@tonic-gate return (-1); 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate if (statvfs64(parent, &svfs) != 0) { 477*0Sstevel@tonic-gate pr_err(gettext("%s: %s"), parent, strerror(errno)); 478*0Sstevel@tonic-gate free(parent); 479*0Sstevel@tonic-gate return (-1); 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate if (strcmp(svfs.f_basetype, CACHEFS_BASETYPE) == 0) { 482*0Sstevel@tonic-gate pr_err(gettext("Cannot create cache in cachefs filesystem")); 483*0Sstevel@tonic-gate free(parent); 484*0Sstevel@tonic-gate return (-1); 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate free(parent); 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate /* make the directory */ 489*0Sstevel@tonic-gate if (mkdir(dirp, 0) == -1) { 490*0Sstevel@tonic-gate switch (errno) { 491*0Sstevel@tonic-gate case EEXIST: 492*0Sstevel@tonic-gate pr_err(gettext("%s already exists."), dirp); 493*0Sstevel@tonic-gate break; 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate default: 496*0Sstevel@tonic-gate pr_err(gettext("mkdir %s failed: %s"), 497*0Sstevel@tonic-gate dirp, strerror(errno)); 498*0Sstevel@tonic-gate } 499*0Sstevel@tonic-gate return (-1); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate cu.cu_filesused += 1; 502*0Sstevel@tonic-gate cu.cu_blksused += 1; 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate /* convert user values to a cache_label */ 505*0Sstevel@tonic-gate if (uv != NULL) { 506*0Sstevel@tonic-gate xx = cachefs_convert_uv2cl(uv, clabel, dirp); 507*0Sstevel@tonic-gate if (xx) 508*0Sstevel@tonic-gate return (-2); 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate /* 512*0Sstevel@tonic-gate * Create the cache directory lock file. 513*0Sstevel@tonic-gate * Used by the kernel module to indicate the cache is in use. 514*0Sstevel@tonic-gate * This file will be <2G. 515*0Sstevel@tonic-gate */ 516*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_LOCK_FILE); 517*0Sstevel@tonic-gate fd = open(path, O_RDWR | O_CREAT, 0700); 518*0Sstevel@tonic-gate if (fd == -1) { 519*0Sstevel@tonic-gate pr_err(gettext("Cannot create lock file %s"), path); 520*0Sstevel@tonic-gate return (-1); 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate close(fd); 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate /* make the directory for the back file system mount points */ 525*0Sstevel@tonic-gate /* note: we do not count this directory in the resources */ 526*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, BACKMNT_NAME); 527*0Sstevel@tonic-gate if (mkdir(path, 0700) == -1) { 528*0Sstevel@tonic-gate pr_err(gettext("mkdir %s failed: %s"), path, 529*0Sstevel@tonic-gate strerror(errno)); 530*0Sstevel@tonic-gate return (-2); 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate /* make the directory for lost+found */ 534*0Sstevel@tonic-gate /* note: we do not count this directory in the resources */ 535*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_LOSTFOUND_NAME); 536*0Sstevel@tonic-gate if (mkdir(path, 0700) == -1) { 537*0Sstevel@tonic-gate pr_err(gettext("mkdir %s failed: %s"), path, 538*0Sstevel@tonic-gate strerror(errno)); 539*0Sstevel@tonic-gate return (-2); 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate /* make the networker "don't back up" file; this file is <2GB */ 543*0Sstevel@tonic-gate xx = 0; 544*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, NOBACKUP_NAME); 545*0Sstevel@tonic-gate if ((fp = fopen(path, "w")) != NULL) { 546*0Sstevel@tonic-gate if (realpath(dirp, path) != NULL) { 547*0Sstevel@tonic-gate fprintf(fp, "<< ./ >>\n", path); 548*0Sstevel@tonic-gate fprintf(fp, "+skip: .?* *\n"); 549*0Sstevel@tonic-gate if (fclose(fp) == 0) 550*0Sstevel@tonic-gate xx = 1; 551*0Sstevel@tonic-gate } 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate if (xx == 0) { 554*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, NOBACKUP_NAME); 555*0Sstevel@tonic-gate pr_err(gettext("can't create %s"), path); 556*0Sstevel@tonic-gate (void) unlink(path); 557*0Sstevel@tonic-gate } else { 558*0Sstevel@tonic-gate cu.cu_filesused += 1; 559*0Sstevel@tonic-gate cu.cu_blksused += 1; 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate /* create the unmount file */ 563*0Sstevel@tonic-gate xx = 0; 564*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_UNMNT_FILE); 565*0Sstevel@tonic-gate if ((fp = fopen(path, "w")) != NULL) { 566*0Sstevel@tonic-gate time32_t btime; 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate btime = get_boottime(); 569*0Sstevel@tonic-gate fwrite((void *)&btime, sizeof (btime), 1, fp); 570*0Sstevel@tonic-gate if (fclose(fp) == 0) 571*0Sstevel@tonic-gate xx = 1; 572*0Sstevel@tonic-gate } 573*0Sstevel@tonic-gate if (xx == 0) 574*0Sstevel@tonic-gate pr_err(gettext("can't create .cfs_unmnt file")); 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate /* create the cache label file */ 577*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHELABEL_NAME); 578*0Sstevel@tonic-gate xx = cachefs_label_file_put(path, clabel); 579*0Sstevel@tonic-gate if (xx == -1) { 580*0Sstevel@tonic-gate pr_err(gettext("creating %s failed."), path); 581*0Sstevel@tonic-gate return (-2); 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate cu.cu_filesused += 1; 584*0Sstevel@tonic-gate cu.cu_blksused += 1; 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate /* create the cache label duplicate file */ 587*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s.dup", dirp, CACHELABEL_NAME); 588*0Sstevel@tonic-gate xx = cachefs_label_file_put(path, clabel); 589*0Sstevel@tonic-gate if (xx == -1) { 590*0Sstevel@tonic-gate pr_err(gettext("creating %s failed."), path); 591*0Sstevel@tonic-gate return (-2); 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate cu.cu_filesused += 1; 594*0Sstevel@tonic-gate cu.cu_blksused += 1; 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate /* create the resouce file; this file will be <2GB */ 597*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, RESOURCE_NAME); 598*0Sstevel@tonic-gate fd = open(path, O_CREAT | O_RDWR, 0600); 599*0Sstevel@tonic-gate if (fd == -1) { 600*0Sstevel@tonic-gate pr_err(gettext("create %s failed: %s"), path, 601*0Sstevel@tonic-gate strerror(errno)); 602*0Sstevel@tonic-gate return (-2); 603*0Sstevel@tonic-gate } 604*0Sstevel@tonic-gate cu.cu_filesused += 1; 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate /* allocate a zeroed buffer for filling the resouce file */ 607*0Sstevel@tonic-gate bufp = calloc(1, MAXBSIZE); 608*0Sstevel@tonic-gate if (bufp == NULL) { 609*0Sstevel@tonic-gate pr_err(gettext("out of space %d."), MAXBSIZE); 610*0Sstevel@tonic-gate close(fd); 611*0Sstevel@tonic-gate return (-2); 612*0Sstevel@tonic-gate } 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate /* determine number of MAXBSIZE chunks to make the file */ 615*0Sstevel@tonic-gate cnt = 1; /* for the header */ 616*0Sstevel@tonic-gate cnt += clabel->cl_maxinodes / CACHEFS_RLPMBS; 617*0Sstevel@tonic-gate if ((clabel->cl_maxinodes % CACHEFS_RLPMBS) != 0) 618*0Sstevel@tonic-gate ++cnt; 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate /* fill up the file with zeros */ 621*0Sstevel@tonic-gate for (xx = 0; xx < cnt; xx++) { 622*0Sstevel@tonic-gate if (write(fd, bufp, MAXBSIZE) != MAXBSIZE) { 623*0Sstevel@tonic-gate pr_err(gettext("write %s failed: %s"), path, 624*0Sstevel@tonic-gate strerror(errno)); 625*0Sstevel@tonic-gate close(fd); 626*0Sstevel@tonic-gate free(bufp); 627*0Sstevel@tonic-gate return (-2); 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate } 630*0Sstevel@tonic-gate free(bufp); 631*0Sstevel@tonic-gate cu.cu_blksused += cnt; 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate /* position to the begining of the file */ 634*0Sstevel@tonic-gate if (lseek(fd, 0, SEEK_SET) == -1) { 635*0Sstevel@tonic-gate pr_err(gettext("lseek %s failed: %s"), path, 636*0Sstevel@tonic-gate strerror(errno)); 637*0Sstevel@tonic-gate close(fd); 638*0Sstevel@tonic-gate return (-2); 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate /* write the cache usage structure */ 642*0Sstevel@tonic-gate xx = sizeof (struct cache_usage); 643*0Sstevel@tonic-gate if (write(fd, &cu, xx) != xx) { 644*0Sstevel@tonic-gate pr_err(gettext("cu write %s failed: %s"), path, 645*0Sstevel@tonic-gate strerror(errno)); 646*0Sstevel@tonic-gate close(fd); 647*0Sstevel@tonic-gate return (-2); 648*0Sstevel@tonic-gate } 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate /* make sure the contents get to disk */ 651*0Sstevel@tonic-gate if (fsync(fd) != 0) { 652*0Sstevel@tonic-gate pr_err(gettext("fsync %s failed: %s"), path, 653*0Sstevel@tonic-gate strerror(errno)); 654*0Sstevel@tonic-gate close(fd); 655*0Sstevel@tonic-gate return (-2); 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate close(fd); 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate /* return success */ 660*0Sstevel@tonic-gate return (0); 661*0Sstevel@tonic-gate } 662*0Sstevel@tonic-gate 663*0Sstevel@tonic-gate /* 664*0Sstevel@tonic-gate * 665*0Sstevel@tonic-gate * cachefs_delete_all_cache 666*0Sstevel@tonic-gate * 667*0Sstevel@tonic-gate * Description: 668*0Sstevel@tonic-gate * Delete all caches in cache directory. 669*0Sstevel@tonic-gate * Arguments: 670*0Sstevel@tonic-gate * dirp the pathname of of the cache directory to delete 671*0Sstevel@tonic-gate * Returns: 672*0Sstevel@tonic-gate * Returns 0 for success or -1 for an error. 673*0Sstevel@tonic-gate * Preconditions: 674*0Sstevel@tonic-gate * precond(dirp) 675*0Sstevel@tonic-gate */ 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate int 678*0Sstevel@tonic-gate cachefs_delete_all_cache(char *dirp) 679*0Sstevel@tonic-gate { 680*0Sstevel@tonic-gate DIR *dp; 681*0Sstevel@tonic-gate struct dirent64 *dep; 682*0Sstevel@tonic-gate int xx; 683*0Sstevel@tonic-gate char path[CACHEFS_XMAXPATH]; 684*0Sstevel@tonic-gate struct stat64 statinfo; 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate /* make sure cache dir name is not too long */ 687*0Sstevel@tonic-gate if (strlen(dirp) > (size_t)PATH_MAX) { 688*0Sstevel@tonic-gate pr_err(gettext("path name %s is too long."), 689*0Sstevel@tonic-gate dirp); 690*0Sstevel@tonic-gate return (-1); 691*0Sstevel@tonic-gate } 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate /* check that dirp is probably a cachefs directory */ 694*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, BACKMNT_NAME); 695*0Sstevel@tonic-gate xx = access(path, R_OK | W_OK | X_OK); 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHELABEL_NAME); 698*0Sstevel@tonic-gate xx |= access(path, R_OK | W_OK); 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate if (xx) { 701*0Sstevel@tonic-gate pr_err(gettext("%s does not appear to be a " 702*0Sstevel@tonic-gate "cachefs cache directory."), dirp); 703*0Sstevel@tonic-gate return (-1); 704*0Sstevel@tonic-gate } 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate /* remove the lost+found directory if it exists and is empty */ 707*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_LOSTFOUND_NAME); 708*0Sstevel@tonic-gate xx = rmdir(path); 709*0Sstevel@tonic-gate if (xx == -1) { 710*0Sstevel@tonic-gate if (errno == EEXIST) { 711*0Sstevel@tonic-gate pr_err(gettext("Cannot delete cache '%s'. " 712*0Sstevel@tonic-gate "First move files in '%s' to a safe location."), 713*0Sstevel@tonic-gate dirp, path); 714*0Sstevel@tonic-gate return (-1); 715*0Sstevel@tonic-gate } else if (errno != ENOENT) { 716*0Sstevel@tonic-gate pr_err(gettext("rmdir %s failed: %s"), path, 717*0Sstevel@tonic-gate strerror(errno)); 718*0Sstevel@tonic-gate return (-1); 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate /* delete the back FS mount point directory if it exists */ 723*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, BACKMNT_NAME); 724*0Sstevel@tonic-gate xx = lstat64(path, &statinfo); 725*0Sstevel@tonic-gate if (xx == -1) { 726*0Sstevel@tonic-gate if (errno != ENOENT) { 727*0Sstevel@tonic-gate pr_err(gettext("lstat %s failed: %s"), path, 728*0Sstevel@tonic-gate strerror(errno)); 729*0Sstevel@tonic-gate return (-1); 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate } else { 732*0Sstevel@tonic-gate xx = nftw64(path, cachefs_delete_file, 16, 733*0Sstevel@tonic-gate FTW_PHYS | FTW_DEPTH | FTW_MOUNT); 734*0Sstevel@tonic-gate if (xx == -1) { 735*0Sstevel@tonic-gate pr_err(gettext("unable to delete %s"), path); 736*0Sstevel@tonic-gate return (-1); 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate } 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate /* open the cache directory specified */ 741*0Sstevel@tonic-gate if ((dp = opendir(dirp)) == NULL) { 742*0Sstevel@tonic-gate pr_err(gettext("cannot open cache directory %s: %s"), 743*0Sstevel@tonic-gate dirp, strerror(errno)); 744*0Sstevel@tonic-gate return (-1); 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate /* read the file names in the cache directory */ 748*0Sstevel@tonic-gate while ((dep = readdir64(dp)) != NULL) { 749*0Sstevel@tonic-gate /* ignore . and .. */ 750*0Sstevel@tonic-gate if (strcmp(dep->d_name, ".") == 0 || 751*0Sstevel@tonic-gate strcmp(dep->d_name, "..") == 0) 752*0Sstevel@tonic-gate continue; 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate /* stat the file */ 755*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, dep->d_name); 756*0Sstevel@tonic-gate xx = lstat64(path, &statinfo); 757*0Sstevel@tonic-gate if (xx == -1) { 758*0Sstevel@tonic-gate if (errno == ENOENT) { 759*0Sstevel@tonic-gate /* delete_cache may have nuked a directory */ 760*0Sstevel@tonic-gate continue; 761*0Sstevel@tonic-gate } 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate pr_err(gettext("lstat %s failed: %s"), 764*0Sstevel@tonic-gate path, strerror(errno)); 765*0Sstevel@tonic-gate closedir(dp); 766*0Sstevel@tonic-gate return (-1); 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate /* ignore anything that is not a link */ 770*0Sstevel@tonic-gate if (!S_ISLNK(statinfo.st_mode)) 771*0Sstevel@tonic-gate continue; 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate /* delete the file system cache directory */ 774*0Sstevel@tonic-gate xx = cachefs_delete_cache(dirp, dep->d_name); 775*0Sstevel@tonic-gate if (xx) { 776*0Sstevel@tonic-gate closedir(dp); 777*0Sstevel@tonic-gate return (-1); 778*0Sstevel@tonic-gate } 779*0Sstevel@tonic-gate } 780*0Sstevel@tonic-gate closedir(dp); 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate /* remove the cache dir unmount file */ 783*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_UNMNT_FILE); 784*0Sstevel@tonic-gate xx = unlink(path); 785*0Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) { 786*0Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path, 787*0Sstevel@tonic-gate strerror(errno)); 788*0Sstevel@tonic-gate return (-1); 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate /* remove the cache label file */ 792*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHELABEL_NAME); 793*0Sstevel@tonic-gate xx = unlink(path); 794*0Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) { 795*0Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path, 796*0Sstevel@tonic-gate strerror(errno)); 797*0Sstevel@tonic-gate return (-1); 798*0Sstevel@tonic-gate } 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate /* remove the cache label duplicate file */ 801*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s.dup", dirp, CACHELABEL_NAME); 802*0Sstevel@tonic-gate xx = unlink(path); 803*0Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) { 804*0Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path, 805*0Sstevel@tonic-gate strerror(errno)); 806*0Sstevel@tonic-gate return (-1); 807*0Sstevel@tonic-gate } 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate /* remove the resource file */ 810*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, RESOURCE_NAME); 811*0Sstevel@tonic-gate xx = unlink(path); 812*0Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) { 813*0Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path, 814*0Sstevel@tonic-gate strerror(errno)); 815*0Sstevel@tonic-gate return (-1); 816*0Sstevel@tonic-gate } 817*0Sstevel@tonic-gate 818*0Sstevel@tonic-gate /* remove the cachefslog file if it exists */ 819*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, LOG_STATUS_NAME); 820*0Sstevel@tonic-gate (void) unlink(path); 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate /* remove the networker "don't back up" file if it exists */ 823*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, NOBACKUP_NAME); 824*0Sstevel@tonic-gate (void) unlink(path); 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate /* remove the lock file */ 827*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, CACHEFS_LOCK_FILE); 828*0Sstevel@tonic-gate xx = unlink(path); 829*0Sstevel@tonic-gate if ((xx == -1) && (errno != ENOENT)) { 830*0Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path, 831*0Sstevel@tonic-gate strerror(errno)); 832*0Sstevel@tonic-gate return (-1); 833*0Sstevel@tonic-gate } 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate /* remove the directory */ 836*0Sstevel@tonic-gate xx = rmdir(dirp); 837*0Sstevel@tonic-gate if (xx == -1) { 838*0Sstevel@tonic-gate pr_err(gettext("rmdir %s failed: %s"), dirp, 839*0Sstevel@tonic-gate strerror(errno)); 840*0Sstevel@tonic-gate return (-1); 841*0Sstevel@tonic-gate } 842*0Sstevel@tonic-gate 843*0Sstevel@tonic-gate /* return success */ 844*0Sstevel@tonic-gate return (0); 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate /* 848*0Sstevel@tonic-gate * 849*0Sstevel@tonic-gate * cachefs_delete_cache 850*0Sstevel@tonic-gate * 851*0Sstevel@tonic-gate * Description: 852*0Sstevel@tonic-gate * Deletes the specified file system cache. 853*0Sstevel@tonic-gate * Arguments: 854*0Sstevel@tonic-gate * dirp cache directory name 855*0Sstevel@tonic-gate * namep file system cache directory to delete 856*0Sstevel@tonic-gate * Returns: 857*0Sstevel@tonic-gate * Returns 0 for success, -1 for failure. 858*0Sstevel@tonic-gate * Preconditions: 859*0Sstevel@tonic-gate * precond(dirp) 860*0Sstevel@tonic-gate * precond(namep) 861*0Sstevel@tonic-gate */ 862*0Sstevel@tonic-gate 863*0Sstevel@tonic-gate int 864*0Sstevel@tonic-gate cachefs_delete_cache(char *dirp, char *namep) 865*0Sstevel@tonic-gate { 866*0Sstevel@tonic-gate char path[CACHEFS_XMAXPATH]; 867*0Sstevel@tonic-gate char buf[CACHEFS_XMAXPATH]; 868*0Sstevel@tonic-gate int xx; 869*0Sstevel@tonic-gate struct stat64 statinfo; 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate /* make sure cache dir name is not too long */ 872*0Sstevel@tonic-gate if (strlen(dirp) > (size_t)PATH_MAX) { 873*0Sstevel@tonic-gate pr_err(gettext("path name %s is too long."), 874*0Sstevel@tonic-gate dirp); 875*0Sstevel@tonic-gate return (-1); 876*0Sstevel@tonic-gate } 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate /* construct the path name of the file system cache directory */ 879*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, namep); 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate /* stat the specified file */ 882*0Sstevel@tonic-gate xx = lstat64(path, &statinfo); 883*0Sstevel@tonic-gate if (xx == -1) { 884*0Sstevel@tonic-gate pr_err(gettext("lstat %s failed: %s"), path, 885*0Sstevel@tonic-gate strerror(errno)); 886*0Sstevel@tonic-gate return (-1); 887*0Sstevel@tonic-gate } 888*0Sstevel@tonic-gate 889*0Sstevel@tonic-gate /* make sure name is a symbolic link */ 890*0Sstevel@tonic-gate if (!S_ISLNK(statinfo.st_mode)) { 891*0Sstevel@tonic-gate pr_err(gettext("\"%s\" is not a valid cache id."), namep); 892*0Sstevel@tonic-gate return (-1); 893*0Sstevel@tonic-gate } 894*0Sstevel@tonic-gate 895*0Sstevel@tonic-gate /* read the contents of the symbolic link */ 896*0Sstevel@tonic-gate xx = readlink(path, buf, sizeof (buf)); 897*0Sstevel@tonic-gate if (xx == -1) { 898*0Sstevel@tonic-gate pr_err(gettext("Readlink of %s failed: %s"), path, 899*0Sstevel@tonic-gate strerror(errno)); 900*0Sstevel@tonic-gate return (-1); 901*0Sstevel@tonic-gate } 902*0Sstevel@tonic-gate buf[xx] = '\0'; 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate /* remove the directory */ 905*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, buf); 906*0Sstevel@tonic-gate xx = nftw64(path, cachefs_delete_file, 16, 907*0Sstevel@tonic-gate FTW_PHYS | FTW_DEPTH | FTW_MOUNT); 908*0Sstevel@tonic-gate if (xx == -1) { 909*0Sstevel@tonic-gate pr_err(gettext("directory walk of %s failed."), dirp); 910*0Sstevel@tonic-gate return (-1); 911*0Sstevel@tonic-gate } 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate /* delete the link */ 914*0Sstevel@tonic-gate snprintf(path, sizeof (path), "%s/%s", dirp, namep); 915*0Sstevel@tonic-gate if (unlink(path) == -1) { 916*0Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), path, 917*0Sstevel@tonic-gate strerror(errno)); 918*0Sstevel@tonic-gate return (-1); 919*0Sstevel@tonic-gate } 920*0Sstevel@tonic-gate 921*0Sstevel@tonic-gate /* return success */ 922*0Sstevel@tonic-gate return (0); 923*0Sstevel@tonic-gate } 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate /* 926*0Sstevel@tonic-gate * 927*0Sstevel@tonic-gate * cachefs_delete_file 928*0Sstevel@tonic-gate * 929*0Sstevel@tonic-gate * Description: 930*0Sstevel@tonic-gate * Remove a file or directory; called by nftw64(). 931*0Sstevel@tonic-gate * Arguments: 932*0Sstevel@tonic-gate * namep pathname of the file 933*0Sstevel@tonic-gate * statp stat info about the file 934*0Sstevel@tonic-gate * flg info about file 935*0Sstevel@tonic-gate * ftwp depth information 936*0Sstevel@tonic-gate * Returns: 937*0Sstevel@tonic-gate * Returns 0 for success, -1 for failure. 938*0Sstevel@tonic-gate * Preconditions: 939*0Sstevel@tonic-gate * precond(namep) 940*0Sstevel@tonic-gate */ 941*0Sstevel@tonic-gate 942*0Sstevel@tonic-gate int 943*0Sstevel@tonic-gate cachefs_delete_file(const char *namep, const struct stat64 *statp, int flg, 944*0Sstevel@tonic-gate struct FTW *ftwp) 945*0Sstevel@tonic-gate { 946*0Sstevel@tonic-gate /* ignore . and .. */ 947*0Sstevel@tonic-gate if (strcmp(namep, ".") == 0 || strcmp(namep, "..") == 0) 948*0Sstevel@tonic-gate return (0); 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate switch (flg) { 951*0Sstevel@tonic-gate case FTW_F: /* files */ 952*0Sstevel@tonic-gate case FTW_SL: 953*0Sstevel@tonic-gate if (unlink(namep) == -1) { 954*0Sstevel@tonic-gate pr_err(gettext("unlink %s failed: %s"), 955*0Sstevel@tonic-gate namep, strerror(errno)); 956*0Sstevel@tonic-gate return (-1); 957*0Sstevel@tonic-gate } 958*0Sstevel@tonic-gate break; 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate case FTW_DP: /* directories that have their children processed */ 961*0Sstevel@tonic-gate if (rmdir(namep) == -1) { 962*0Sstevel@tonic-gate pr_err(gettext("rmdir %s failed: %s"), 963*0Sstevel@tonic-gate namep, strerror(errno)); 964*0Sstevel@tonic-gate return (-1); 965*0Sstevel@tonic-gate } 966*0Sstevel@tonic-gate break; 967*0Sstevel@tonic-gate 968*0Sstevel@tonic-gate case FTW_D: /* ignore directories if children not processed */ 969*0Sstevel@tonic-gate break; 970*0Sstevel@tonic-gate 971*0Sstevel@tonic-gate default: 972*0Sstevel@tonic-gate pr_err(gettext("failure on file %s, flg %d."), 973*0Sstevel@tonic-gate namep, flg); 974*0Sstevel@tonic-gate return (-1); 975*0Sstevel@tonic-gate } 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate /* return success */ 978*0Sstevel@tonic-gate return (0); 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate /* 982*0Sstevel@tonic-gate * 983*0Sstevel@tonic-gate * cachefs_convert_uv2cl 984*0Sstevel@tonic-gate * 985*0Sstevel@tonic-gate * Description: 986*0Sstevel@tonic-gate * Copies the contents of a cachefs_user_values object into a 987*0Sstevel@tonic-gate * cache_label object, performing the necessary conversions. 988*0Sstevel@tonic-gate * Arguments: 989*0Sstevel@tonic-gate * uvp cachefs_user_values to copy from 990*0Sstevel@tonic-gate * clp cache_label to copy into 991*0Sstevel@tonic-gate * dirp cache directory 992*0Sstevel@tonic-gate * Returns: 993*0Sstevel@tonic-gate * Returns 0 for success, -1 for an error. 994*0Sstevel@tonic-gate * Preconditions: 995*0Sstevel@tonic-gate * precond(uvp) 996*0Sstevel@tonic-gate * precond(clp) 997*0Sstevel@tonic-gate * precond(dirp) 998*0Sstevel@tonic-gate */ 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate int 1001*0Sstevel@tonic-gate cachefs_convert_uv2cl(const struct cachefs_user_values *uvp, 1002*0Sstevel@tonic-gate struct cache_label *clp, const char *dirp) 1003*0Sstevel@tonic-gate { 1004*0Sstevel@tonic-gate struct statvfs64 fs; 1005*0Sstevel@tonic-gate int xx; 1006*0Sstevel@tonic-gate double ftmp; 1007*0Sstevel@tonic-gate double temp; 1008*0Sstevel@tonic-gate 1009*0Sstevel@tonic-gate /* get file system information */ 1010*0Sstevel@tonic-gate xx = statvfs64(dirp, &fs); 1011*0Sstevel@tonic-gate if (xx == -1) { 1012*0Sstevel@tonic-gate pr_err(gettext("statvfs %s failed: %s"), dirp, 1013*0Sstevel@tonic-gate strerror(errno)); 1014*0Sstevel@tonic-gate return (-1); 1015*0Sstevel@tonic-gate } 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate ftmp = (double)fs.f_frsize / (double)MAXBSIZE; 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate /* front fs is less than 1 terabyte */ 1020*0Sstevel@tonic-gate temp = (double)uvp->uv_maxblocks / 100.0 * 1021*0Sstevel@tonic-gate (double)fs.f_blocks * ftmp + .5; 1022*0Sstevel@tonic-gate clp->cl_maxblks = temp < (double)INT_MAX ? (int)temp : INT_MAX; 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate temp = (double)uvp->uv_minblocks / 100.0 * 1025*0Sstevel@tonic-gate (double)fs.f_blocks * ftmp + .5; 1026*0Sstevel@tonic-gate clp->cl_blockmin = temp < (double)INT_MAX ? (int)temp : INT_MAX; 1027*0Sstevel@tonic-gate 1028*0Sstevel@tonic-gate temp = (double)uvp->uv_threshblocks / 100.0 * 1029*0Sstevel@tonic-gate (double)fs.f_blocks * ftmp + .5; 1030*0Sstevel@tonic-gate clp->cl_blocktresh = temp < (double)INT_MAX ? (int)temp : INT_MAX; 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate temp = (double)uvp->uv_maxfiles / 100.0 * (double)fs.f_files + .5; 1033*0Sstevel@tonic-gate clp->cl_maxinodes = temp < (double)INT_MAX ? (int)temp : INT_MAX; 1034*0Sstevel@tonic-gate 1035*0Sstevel@tonic-gate temp = (double)uvp->uv_minfiles / 100.0 * (double)fs.f_files + .5; 1036*0Sstevel@tonic-gate clp->cl_filemin = temp < (double)INT_MAX ? (int)temp : INT_MAX; 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate temp = (double)uvp->uv_threshfiles / 100.0 * (double)fs.f_files +.5; 1039*0Sstevel@tonic-gate clp->cl_filetresh = temp < (double)INT_MAX ? (int)temp : INT_MAX; 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate ftmp = (double)(1024 * 1024) / (double)MAXBSIZE; 1042*0Sstevel@tonic-gate clp->cl_maxfiles = uvp->uv_maxfilesize * ftmp + .5; 1043*0Sstevel@tonic-gate 1044*0Sstevel@tonic-gate clp->cl_blkhiwat = uvp->uv_hiblocks / 100.0 * clp->cl_maxblks + .5; 1045*0Sstevel@tonic-gate clp->cl_blklowat = uvp->uv_lowblocks / 100.0 * clp->cl_maxblks + .5; 1046*0Sstevel@tonic-gate 1047*0Sstevel@tonic-gate clp->cl_filehiwat = uvp->uv_hifiles / 100.0 * clp->cl_maxinodes + .5; 1048*0Sstevel@tonic-gate clp->cl_filelowat = uvp->uv_lowfiles / 100.0 * clp->cl_maxinodes + .5; 1049*0Sstevel@tonic-gate 1050*0Sstevel@tonic-gate clp->cl_cfsversion = CFSVERSION; 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate /* return success */ 1053*0Sstevel@tonic-gate return (0); 1054*0Sstevel@tonic-gate } 1055*0Sstevel@tonic-gate 1056*0Sstevel@tonic-gate /* 1057*0Sstevel@tonic-gate * 1058*0Sstevel@tonic-gate * cachefs_convert_cl2uv 1059*0Sstevel@tonic-gate * 1060*0Sstevel@tonic-gate * Description: 1061*0Sstevel@tonic-gate * Copies the contents of a cache_label object into a 1062*0Sstevel@tonic-gate * cachefs_user_values object, performing the necessary conversions. 1063*0Sstevel@tonic-gate * Arguments: 1064*0Sstevel@tonic-gate * clp cache_label to copy from 1065*0Sstevel@tonic-gate * uvp cachefs_user_values to copy into 1066*0Sstevel@tonic-gate * dirp cache directory 1067*0Sstevel@tonic-gate * Returns: 1068*0Sstevel@tonic-gate * Returns 0 for success, -1 for an error. 1069*0Sstevel@tonic-gate * Preconditions: 1070*0Sstevel@tonic-gate * precond(clp) 1071*0Sstevel@tonic-gate * precond(uvp) 1072*0Sstevel@tonic-gate * precond(dirp) 1073*0Sstevel@tonic-gate */ 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate int 1076*0Sstevel@tonic-gate cachefs_convert_cl2uv(const struct cache_label *clp, 1077*0Sstevel@tonic-gate struct cachefs_user_values *uvp, const char *dirp) 1078*0Sstevel@tonic-gate { 1079*0Sstevel@tonic-gate struct statvfs64 fs; 1080*0Sstevel@tonic-gate int xx; 1081*0Sstevel@tonic-gate double temp; 1082*0Sstevel@tonic-gate double ftmp; 1083*0Sstevel@tonic-gate long long ltmp; 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate /* get file system information */ 1086*0Sstevel@tonic-gate xx = statvfs64(dirp, &fs); 1087*0Sstevel@tonic-gate if (xx == -1) { 1088*0Sstevel@tonic-gate pr_err(gettext("statvfs %s failed: %s"), dirp, 1089*0Sstevel@tonic-gate strerror(errno)); 1090*0Sstevel@tonic-gate return (-1); 1091*0Sstevel@tonic-gate } 1092*0Sstevel@tonic-gate 1093*0Sstevel@tonic-gate #define BOUND(yy) \ 1094*0Sstevel@tonic-gate yy = (yy < 0) ? 0 : yy; \ 1095*0Sstevel@tonic-gate yy = (yy > 100) ? 100 : yy; 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate ftmp = (double)MAXBSIZE / (double)fs.f_frsize; 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate temp = (double)clp->cl_maxblks * ftmp / 1100*0Sstevel@tonic-gate (double)fs.f_blocks * 100. + .5; 1101*0Sstevel@tonic-gate BOUND(temp); 1102*0Sstevel@tonic-gate uvp->uv_maxblocks = (int)temp; 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate temp = (double)clp->cl_blockmin * ftmp / 1105*0Sstevel@tonic-gate (double)fs.f_blocks * 100. + .5; 1106*0Sstevel@tonic-gate BOUND(temp); 1107*0Sstevel@tonic-gate uvp->uv_minblocks = (int)temp; 1108*0Sstevel@tonic-gate 1109*0Sstevel@tonic-gate temp = (double)clp->cl_blocktresh * ftmp / 1110*0Sstevel@tonic-gate (double)fs.f_blocks * 100. + .5; 1111*0Sstevel@tonic-gate BOUND(temp); 1112*0Sstevel@tonic-gate uvp->uv_threshblocks = (int)temp; 1113*0Sstevel@tonic-gate 1114*0Sstevel@tonic-gate temp = ((double)clp->cl_maxinodes / fs.f_files) * 100. + .5; 1115*0Sstevel@tonic-gate BOUND(temp); 1116*0Sstevel@tonic-gate uvp->uv_maxfiles = (int)temp; 1117*0Sstevel@tonic-gate 1118*0Sstevel@tonic-gate temp = ((double)clp->cl_filemin / fs.f_files) * 100. + .5; 1119*0Sstevel@tonic-gate BOUND(temp); 1120*0Sstevel@tonic-gate uvp->uv_minfiles = (int)temp; 1121*0Sstevel@tonic-gate 1122*0Sstevel@tonic-gate temp = ((double)clp->cl_filetresh / fs.f_files) * 100. + .5; 1123*0Sstevel@tonic-gate BOUND(temp); 1124*0Sstevel@tonic-gate uvp->uv_threshfiles = (int)temp; 1125*0Sstevel@tonic-gate 1126*0Sstevel@tonic-gate ltmp = ((long long)clp->cl_maxfiles * MAXBSIZE); 1127*0Sstevel@tonic-gate uvp->uv_maxfilesize = (ltmp + (MAXBSIZE / 2)) / (1024 * 1024); 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate xx = ((double)clp->cl_blkhiwat / clp->cl_maxblks) * 100. + .5; 1130*0Sstevel@tonic-gate BOUND(xx); 1131*0Sstevel@tonic-gate uvp->uv_hiblocks = xx; 1132*0Sstevel@tonic-gate 1133*0Sstevel@tonic-gate xx = ((double)clp->cl_blklowat / clp->cl_maxblks) * 100. + .5; 1134*0Sstevel@tonic-gate BOUND(xx); 1135*0Sstevel@tonic-gate uvp->uv_lowblocks = xx; 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate xx = ((double)clp->cl_filehiwat / clp->cl_maxinodes) * 100. + .5; 1138*0Sstevel@tonic-gate BOUND(xx); 1139*0Sstevel@tonic-gate uvp->uv_hifiles = xx; 1140*0Sstevel@tonic-gate 1141*0Sstevel@tonic-gate xx = ((double)clp->cl_filelowat / clp->cl_maxinodes) * 100. + .5; 1142*0Sstevel@tonic-gate BOUND(xx); 1143*0Sstevel@tonic-gate uvp->uv_lowfiles = xx; 1144*0Sstevel@tonic-gate 1145*0Sstevel@tonic-gate /* return success */ 1146*0Sstevel@tonic-gate return (0); 1147*0Sstevel@tonic-gate } 1148*0Sstevel@tonic-gate 1149*0Sstevel@tonic-gate /* 1150*0Sstevel@tonic-gate * cachefs_file_to_dir 1151*0Sstevel@tonic-gate * 1152*0Sstevel@tonic-gate * takes in a path, and returns the parent directory of that path. 1153*0Sstevel@tonic-gate * 1154*0Sstevel@tonic-gate * it's the caller's responsibility to free the pointer returned by 1155*0Sstevel@tonic-gate * this function. 1156*0Sstevel@tonic-gate */ 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate char * 1159*0Sstevel@tonic-gate cachefs_file_to_dir(const char *path) 1160*0Sstevel@tonic-gate { 1161*0Sstevel@tonic-gate char *rc, *cp; 1162*0Sstevel@tonic-gate 1163*0Sstevel@tonic-gate if (path == NULL) 1164*0Sstevel@tonic-gate return (NULL); 1165*0Sstevel@tonic-gate 1166*0Sstevel@tonic-gate rc = strdup(path); 1167*0Sstevel@tonic-gate if (rc == NULL) 1168*0Sstevel@tonic-gate return (NULL); 1169*0Sstevel@tonic-gate 1170*0Sstevel@tonic-gate if ((cp = strrchr(rc, '/')) == NULL) { 1171*0Sstevel@tonic-gate 1172*0Sstevel@tonic-gate /* 1173*0Sstevel@tonic-gate * if no slashes at all, return "." (current directory). 1174*0Sstevel@tonic-gate */ 1175*0Sstevel@tonic-gate 1176*0Sstevel@tonic-gate (void) free(rc); 1177*0Sstevel@tonic-gate rc = strdup("."); 1178*0Sstevel@tonic-gate 1179*0Sstevel@tonic-gate } else if (cp == rc) { 1180*0Sstevel@tonic-gate 1181*0Sstevel@tonic-gate /* 1182*0Sstevel@tonic-gate * else, if the last '/' is the first character, chop 1183*0Sstevel@tonic-gate * off from there (i.e. return "/"). 1184*0Sstevel@tonic-gate */ 1185*0Sstevel@tonic-gate 1186*0Sstevel@tonic-gate rc[1] = '\0'; 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate } else { 1189*0Sstevel@tonic-gate 1190*0Sstevel@tonic-gate /* 1191*0Sstevel@tonic-gate * else, we have a path like /foo/bar or foo/bar. 1192*0Sstevel@tonic-gate * chop off from the last '/'. 1193*0Sstevel@tonic-gate */ 1194*0Sstevel@tonic-gate 1195*0Sstevel@tonic-gate *cp = '\0'; 1196*0Sstevel@tonic-gate 1197*0Sstevel@tonic-gate } 1198*0Sstevel@tonic-gate 1199*0Sstevel@tonic-gate return (rc); 1200*0Sstevel@tonic-gate } 1201*0Sstevel@tonic-gate 1202*0Sstevel@tonic-gate /* 1203*0Sstevel@tonic-gate * cachefs_clean_flag_test 1204*0Sstevel@tonic-gate * 1205*0Sstevel@tonic-gate * Description: 1206*0Sstevel@tonic-gate * Tests whether or not the clean flag on the file system 1207*0Sstevel@tonic-gate * is set. 1208*0Sstevel@tonic-gate * Arguments: 1209*0Sstevel@tonic-gate * cachedirp name of the the file system cache directory 1210*0Sstevel@tonic-gate * Returns: 1211*0Sstevel@tonic-gate * Returns 1 if the cache was shut down cleanly, 0 if not. 1212*0Sstevel@tonic-gate * Preconditions: 1213*0Sstevel@tonic-gate * precond(cachedirp) 1214*0Sstevel@tonic-gate */ 1215*0Sstevel@tonic-gate 1216*0Sstevel@tonic-gate int 1217*0Sstevel@tonic-gate cachefs_clean_flag_test(const char *cachedirp) 1218*0Sstevel@tonic-gate { 1219*0Sstevel@tonic-gate char *namep; 1220*0Sstevel@tonic-gate int xx; 1221*0Sstevel@tonic-gate char buf[MAXPATHLEN]; 1222*0Sstevel@tonic-gate int fd; 1223*0Sstevel@tonic-gate struct cache_usage cu; 1224*0Sstevel@tonic-gate 1225*0Sstevel@tonic-gate /* construct the path name of the resource file */ 1226*0Sstevel@tonic-gate namep = RESOURCE_NAME; 1227*0Sstevel@tonic-gate xx = strlen(cachedirp) + strlen(namep) + 3; 1228*0Sstevel@tonic-gate if (xx >= MAXPATHLEN) { 1229*0Sstevel@tonic-gate pr_err(gettext("Path name too long %s/%s"), 1230*0Sstevel@tonic-gate cachedirp, namep); 1231*0Sstevel@tonic-gate return (39); 1232*0Sstevel@tonic-gate } 1233*0Sstevel@tonic-gate snprintf(buf, sizeof (buf), "%s/%s", cachedirp, namep); 1234*0Sstevel@tonic-gate 1235*0Sstevel@tonic-gate /* open the file; it will be <2GB */ 1236*0Sstevel@tonic-gate fd = open(buf, O_RDONLY); 1237*0Sstevel@tonic-gate if (fd == -1) { 1238*0Sstevel@tonic-gate pr_err(gettext("Cannot open %s: %s"), buf, strerror(errno)); 1239*0Sstevel@tonic-gate return (0); 1240*0Sstevel@tonic-gate } 1241*0Sstevel@tonic-gate 1242*0Sstevel@tonic-gate /* read the cache_usage structure */ 1243*0Sstevel@tonic-gate xx = read(fd, &cu, sizeof (cu)); 1244*0Sstevel@tonic-gate if (xx != sizeof (cu)) { 1245*0Sstevel@tonic-gate pr_err(gettext("Error reading %s: %d %s"), buf, 1246*0Sstevel@tonic-gate xx, strerror(errno)); 1247*0Sstevel@tonic-gate close(fd); 1248*0Sstevel@tonic-gate return (0); 1249*0Sstevel@tonic-gate } 1250*0Sstevel@tonic-gate close(fd); 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate /* return state of the cache */ 1253*0Sstevel@tonic-gate return ((cu.cu_flags & CUSAGE_ACTIVE) == 0); 1254*0Sstevel@tonic-gate } 1255*0Sstevel@tonic-gate 1256*0Sstevel@tonic-gate time32_t 1257*0Sstevel@tonic-gate get_boottime() 1258*0Sstevel@tonic-gate { 1259*0Sstevel@tonic-gate struct utmpx id, *putmp; 1260*0Sstevel@tonic-gate 1261*0Sstevel@tonic-gate id.ut_type = BOOT_TIME; 1262*0Sstevel@tonic-gate setutxent(); 1263*0Sstevel@tonic-gate if ((putmp = getutxid(&id)) != NULL) 1264*0Sstevel@tonic-gate return ((time32_t)putmp->ut_tv.tv_sec); 1265*0Sstevel@tonic-gate return (-1); 1266*0Sstevel@tonic-gate } 1267