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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*0Sstevel@tonic-gate /* All Rights Reserved */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gate /* 27*0Sstevel@tonic-gate * Copyright (c) 1997, by Sun Microsystems, Inc. 28*0Sstevel@tonic-gate * All rights reserved. 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*0Sstevel@tonic-gate /*LINTLIBRARY*/ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate /* 35*0Sstevel@tonic-gate * Globals defined: 36*0Sstevel@tonic-gate * 37*0Sstevel@tonic-gate * devreserv() Reserve a set of OA&M devices 38*0Sstevel@tonic-gate * devfree() Free a reserved device 39*0Sstevel@tonic-gate * reservdev() Get a list of reserved devices 40*0Sstevel@tonic-gate * _openlkfile() Opens the lock file 41*0Sstevel@tonic-gate * _rsvtabpath() Get the pathname of the lock table file 42*0Sstevel@tonic-gate * _closelkfile() Closes the lock file 43*0Sstevel@tonic-gate */ 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate /* 46*0Sstevel@tonic-gate * Headers referenced: 47*0Sstevel@tonic-gate * <sys/types.h> System data types 48*0Sstevel@tonic-gate * <errno.h> Error definitions (including "errno") 49*0Sstevel@tonic-gate * <string.h> String handling definitions 50*0Sstevel@tonic-gate * <fcntl.h> File control definitions 51*0Sstevel@tonic-gate * <unistd.h> Unix standard value definitions 52*0Sstevel@tonic-gate * <devmgmt.h> Global Device Management definitions 53*0Sstevel@tonic-gate * "devtab.h" Local Device Management definitions 54*0Sstevel@tonic-gate */ 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate #include <sys/types.h> 57*0Sstevel@tonic-gate #include <errno.h> 58*0Sstevel@tonic-gate #include <string.h> 59*0Sstevel@tonic-gate #include <fcntl.h> 60*0Sstevel@tonic-gate #include <unistd.h> 61*0Sstevel@tonic-gate #include <stdlib.h> 62*0Sstevel@tonic-gate #include <devmgmt.h> 63*0Sstevel@tonic-gate #include "devtab.h" 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate /* 66*0Sstevel@tonic-gate * Local Definitions: 67*0Sstevel@tonic-gate */ 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate /* 71*0Sstevel@tonic-gate * Local data types: 72*0Sstevel@tonic-gate * struct devlks Structure that defines locking information (key 73*0Sstevel@tonic-gate * with alias name (may be '\0' terminated) 74*0Sstevel@tonic-gate */ 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate struct devlks { 77*0Sstevel@tonic-gate int lk_key; 78*0Sstevel@tonic-gate char lk_alias[((DTAB_MXALIASLN+2)/2)*2]; 79*0Sstevel@tonic-gate }; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate * Local Functions: 84*0Sstevel@tonic-gate * isanullstr() Is a character string a null string ("")? 85*0Sstevel@tonic-gate * getlkcnt() Get the number of devices locked 86*0Sstevel@tonic-gate * locklkfile() Lock the OA&M Device locking file 87*0Sstevel@tonic-gate * getlocks() Get the device locks from the device-lock file 88*0Sstevel@tonic-gate * islocked() Determines if a device is locked 89*0Sstevel@tonic-gate * putlocks() Close the device locks w/ update 90*0Sstevel@tonic-gate * freelkfile() Close the device locks w/o updating 91*0Sstevel@tonic-gate * compresslks() Compresses the table containing lock info 92*0Sstevel@tonic-gate */ 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate #define isanullstr(s) (s[0] == '\0') 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate static int locklkfile(short); /* Lock the lock file */ 97*0Sstevel@tonic-gate static int getlkcnt(void); /* Get the number of locked devices */ 98*0Sstevel@tonic-gate static int getlocks(void); /* Get the lock information */ 99*0Sstevel@tonic-gate static int putlocks(char **, int); /* Update lock information */ 100*0Sstevel@tonic-gate static int freelkfile(void); /* Free lock information (no update) */ 101*0Sstevel@tonic-gate static char *islocked(char *); /* Determines if a device is locked */ 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate /* 105*0Sstevel@tonic-gate * Static data 106*0Sstevel@tonic-gate */ 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate static struct flock lkinfo = {0, 0, 0, 0, 0}; 109*0Sstevel@tonic-gate static struct devlks *locklist; 110*0Sstevel@tonic-gate static int lockcount; 111*0Sstevel@tonic-gate static int lkfilefd = -1; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate /* 114*0Sstevel@tonic-gate * char *_rsvtabpath() 115*0Sstevel@tonic-gate * 116*0Sstevel@tonic-gate * Determines the pathname of the device reservation table file 117*0Sstevel@tonic-gate * 118*0Sstevel@tonic-gate * Uses the following sequential steps: 119*0Sstevel@tonic-gate * 1) If OAM_DEVLKFILE is defined and is not null, use that as 120*0Sstevel@tonic-gate * the pathname to the file 121*0Sstevel@tonic-gate * 2) Otherwise, use the devault name found in DVLK_PATH (defined 122*0Sstevel@tonic-gate * in the header file <devtab.h> 123*0Sstevel@tonic-gate * 124*0Sstevel@tonic-gate * Arguments: None 125*0Sstevel@tonic-gate * 126*0Sstevel@tonic-gate * Returns: char * 127*0Sstevel@tonic-gate * A pointer to the filename in malloc()ed memory or (char *) NULL if 128*0Sstevel@tonic-gate * it fails. "errno" will indicate the error if it fails. 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate char * 132*0Sstevel@tonic-gate _rsvtabpath(void) 133*0Sstevel@tonic-gate { 134*0Sstevel@tonic-gate /* Automatics */ 135*0Sstevel@tonic-gate char *lockname; /* Name of the lockfile */ 136*0Sstevel@tonic-gate #ifdef DEBUG 137*0Sstevel@tonic-gate char *p; /* Temporary pointer */ 138*0Sstevel@tonic-gate #endif 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate #ifdef DEBUG 141*0Sstevel@tonic-gate p = getenv(OAM_DEVLKTAB); 142*0Sstevel@tonic-gate if ((p != NULL) && (*p != '\0')) { 143*0Sstevel@tonic-gate if (lockname = malloc(strlen(p)+1)) 144*0Sstevel@tonic-gate (void) strcpy(lockname, p); 145*0Sstevel@tonic-gate } else { 146*0Sstevel@tonic-gate #endif 147*0Sstevel@tonic-gate if (lockname = malloc(strlen(DVLK_PATH)+1)) 148*0Sstevel@tonic-gate (void) strcpy(lockname, DVLK_PATH); 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate #ifdef DEBUG 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate #endif 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* Fini -- return a pointer to the lockfile pathname */ 155*0Sstevel@tonic-gate return (lockname); 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate /* 159*0Sstevel@tonic-gate * int _openlkfile() 160*0Sstevel@tonic-gate * 161*0Sstevel@tonic-gate * The _openlkfile() function opens a device-reservation table file 162*0Sstevel@tonic-gate * for read/write access. 163*0Sstevel@tonic-gate * 164*0Sstevel@tonic-gate * Arguments: None 165*0Sstevel@tonic-gate * 166*0Sstevel@tonic-gate * Returns: int 167*0Sstevel@tonic-gate * TRUE if successful, FALSE otherwise. 168*0Sstevel@tonic-gate * 169*0Sstevel@tonic-gate * Statics Used: 170*0Sstevel@tonic-gate * lkfilefd Lock file file descriptor 171*0Sstevel@tonic-gate */ 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate int 174*0Sstevel@tonic-gate _openlkfile(void) 175*0Sstevel@tonic-gate { 176*0Sstevel@tonic-gate /* 177*0Sstevel@tonic-gate * Automatic data 178*0Sstevel@tonic-gate */ 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate char *lockname; /* Name of the lock file */ 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate /* Close the lockfile -- it might be open */ 184*0Sstevel@tonic-gate (void) _closelkfile(); 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* If we can get the name of the lock file ... */ 187*0Sstevel@tonic-gate if (lockname = _rsvtabpath()) { 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate /* Open it */ 190*0Sstevel@tonic-gate lkfilefd = open(lockname, O_RDWR|O_CREAT, 0600); 191*0Sstevel@tonic-gate free(lockname); 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate /* Finis */ 196*0Sstevel@tonic-gate return ((lkfilefd != -1) ? TRUE : FALSE); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate /* 200*0Sstevel@tonic-gate * int _closelkfile() 201*0Sstevel@tonic-gate * 202*0Sstevel@tonic-gate * Function closes the device-reservation table file and sets the 203*0Sstevel@tonic-gate * necessary external variables to indicate such. 204*0Sstevel@tonic-gate * 205*0Sstevel@tonic-gate * Arguments: None 206*0Sstevel@tonic-gate * 207*0Sstevel@tonic-gate * Returns: int 208*0Sstevel@tonic-gate * Same as close() 209*0Sstevel@tonic-gate * 210*0Sstevel@tonic-gate * Statics referenced: 211*0Sstevel@tonic-gate * lkfilefd The device reservation table file's file descriptor 212*0Sstevel@tonic-gate */ 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate int 215*0Sstevel@tonic-gate _closelkfile(void) 216*0Sstevel@tonic-gate { 217*0Sstevel@tonic-gate /* Automatics */ 218*0Sstevel@tonic-gate int rtnval; /* Value to return */ 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate /* Close the lock file if it's open */ 221*0Sstevel@tonic-gate if (lkfilefd != -1) rtnval = close(lkfilefd); 222*0Sstevel@tonic-gate else rtnval = 0; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate /* Indicate that the lock-file is closed */ 225*0Sstevel@tonic-gate lkfilefd = -1; 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate /* Finis */ 228*0Sstevel@tonic-gate return (rtnval); 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate /* 232*0Sstevel@tonic-gate * int locklkfile(lkflag) 233*0Sstevel@tonic-gate * short lkflag 234*0Sstevel@tonic-gate * 235*0Sstevel@tonic-gate * This function locks the device lock file. If the request cannot 236*0Sstevel@tonic-gate * be serviced, it keeps on trying until it manages to lock the file 237*0Sstevel@tonic-gate * or it encounters an error. 238*0Sstevel@tonic-gate * 239*0Sstevel@tonic-gate * Arguments: 240*0Sstevel@tonic-gate * lkflag Flag (from FCNTL(BA_OS)) indicating which type 241*0Sstevel@tonic-gate * of lock is being requested. Values that make 242*0Sstevel@tonic-gate * sense: 243*0Sstevel@tonic-gate * F_RDLCK: Read lock. 244*0Sstevel@tonic-gate * F_WRLCK: Write lock. 245*0Sstevel@tonic-gate * 246*0Sstevel@tonic-gate * Returns: int 247*0Sstevel@tonic-gate * TRUE (non-zero) if the function managed to lock the file, FALSE 248*0Sstevel@tonic-gate * otherwise ("errno" will indicate the problem). 249*0Sstevel@tonic-gate * 250*0Sstevel@tonic-gate * Statics used: 251*0Sstevel@tonic-gate * int lkfilefd File descriptor of the open lock file 252*0Sstevel@tonic-gate * struct flock lkinfo Structure used by fcntl() to lock a file 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate static int 256*0Sstevel@tonic-gate locklkfile(short lkflag) 257*0Sstevel@tonic-gate { 258*0Sstevel@tonic-gate /* Automatic data */ 259*0Sstevel@tonic-gate int noerror; /* TRUE if no error yet */ 260*0Sstevel@tonic-gate int locked; /* TRUE if the file is locked */ 261*0Sstevel@tonic-gate int olderrno; /* Value of errno on call */ 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate /* Set up the locking structure */ 265*0Sstevel@tonic-gate lkinfo.l_type = lkflag; 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate /* Try to lock the file. If it's locked, wait and try again */ 268*0Sstevel@tonic-gate noerror = TRUE; 269*0Sstevel@tonic-gate locked = FALSE; 270*0Sstevel@tonic-gate olderrno = errno; 271*0Sstevel@tonic-gate while (noerror && !locked) { 272*0Sstevel@tonic-gate if (fcntl(lkfilefd, F_SETLK, &lkinfo) != -1) locked = TRUE; 273*0Sstevel@tonic-gate else { 274*0Sstevel@tonic-gate if ((errno == EACCES) || (errno == EAGAIN)) { 275*0Sstevel@tonic-gate errno = olderrno; 276*0Sstevel@tonic-gate if (sleep(2)) noerror = FALSE; 277*0Sstevel@tonic-gate } else noerror = FALSE; 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate /* Return a success flag */ 282*0Sstevel@tonic-gate return (locked); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate /* 286*0Sstevel@tonic-gate * int getlkcnt() 287*0Sstevel@tonic-gate * 288*0Sstevel@tonic-gate * This function extracts the number of currently-locked devices 289*0Sstevel@tonic-gate * from the lock file. 290*0Sstevel@tonic-gate * 291*0Sstevel@tonic-gate * Arguments: None 292*0Sstevel@tonic-gate * 293*0Sstevel@tonic-gate * Returns: int 294*0Sstevel@tonic-gate * The number of devices locked or -1 if an error occurred. 295*0Sstevel@tonic-gate * 296*0Sstevel@tonic-gate * Statics used: 297*0Sstevel@tonic-gate * lkfilefd File descriptor of the open lockfile 298*0Sstevel@tonic-gate * 299*0Sstevel@tonic-gate * Assumptions: 300*0Sstevel@tonic-gate * - The file is positioned to the beginning-of-file 301*0Sstevel@tonic-gate */ 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate static int 304*0Sstevel@tonic-gate getlkcnt(void) 305*0Sstevel@tonic-gate { 306*0Sstevel@tonic-gate /* Automatics */ 307*0Sstevel@tonic-gate int cntread; /* Number of bytes read */ 308*0Sstevel@tonic-gate int lkcnt; /* Number of current locks */ 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate /* Get the lock count from the file */ 311*0Sstevel@tonic-gate cntread = (int)read(lkfilefd, &lkcnt, sizeof (int)); 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate /* If there wasn't one, set to 0. If error, set to -1 */ 314*0Sstevel@tonic-gate if (cntread != (int)sizeof (int)) 315*0Sstevel@tonic-gate lkcnt = (cntread < 0) ? -1 : 0; 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate /* Return the lock count */ 318*0Sstevel@tonic-gate return (lkcnt); 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* 322*0Sstevel@tonic-gate * int readlocks() 323*0Sstevel@tonic-gate * 324*0Sstevel@tonic-gate * The readlocks() function reads the reserved-device list from 325*0Sstevel@tonic-gate * the reserved-device file (which has already been opened) 326*0Sstevel@tonic-gate * 327*0Sstevel@tonic-gate * Arguments: None 328*0Sstevel@tonic-gate * 329*0Sstevel@tonic-gate * Returns: int 330*0Sstevel@tonic-gate * TRUE if all went well, FALSE otherwise. 331*0Sstevel@tonic-gate * 332*0Sstevel@tonic-gate * Statics Used: 333*0Sstevel@tonic-gate * lockcount Sets this to the number of locks in the lock list 334*0Sstevel@tonic-gate * locklist Sets this to the malloc()ed space containing the 335*0Sstevel@tonic-gate * list of reserved devices. 336*0Sstevel@tonic-gate * lkfilefd Reads data from this file 337*0Sstevel@tonic-gate */ 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate static int 340*0Sstevel@tonic-gate readlocks(void) 341*0Sstevel@tonic-gate { 342*0Sstevel@tonic-gate /* Automatics */ 343*0Sstevel@tonic-gate struct devlks *alloc; /* Ptr to alloc'ed space */ 344*0Sstevel@tonic-gate int noerror; /* TRUE if all is well */ 345*0Sstevel@tonic-gate size_t bufsiz; /* # bytes needed for lock data */ 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate /* Initializations */ 349*0Sstevel@tonic-gate noerror = TRUE; 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate /* Get the number of devices currently locked */ 352*0Sstevel@tonic-gate if ((lockcount = getlkcnt()) > 0) { 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate /* Allocate space for the locks */ 355*0Sstevel@tonic-gate bufsiz = lockcount * sizeof (struct devlks); 356*0Sstevel@tonic-gate if (alloc = malloc(bufsiz)) { 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate /* Read the locks into the malloc()ed buffer */ 359*0Sstevel@tonic-gate if (read(lkfilefd, alloc, bufsiz) != (ssize_t)bufsiz) 360*0Sstevel@tonic-gate noerror = FALSE; 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* If the read failed, free malloc()ed buffer */ 363*0Sstevel@tonic-gate if (!noerror) free(alloc); 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate } else noerror = FALSE; /* malloc() failed */ 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate } else if (lockcount < 0) noerror = FALSE; 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate /* Finished */ 370*0Sstevel@tonic-gate if (noerror) 371*0Sstevel@tonic-gate locklist = (lockcount > 0) ? alloc : NULL; 372*0Sstevel@tonic-gate return (noerror); 373*0Sstevel@tonic-gate } 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate /* 376*0Sstevel@tonic-gate * int getlocks() 377*0Sstevel@tonic-gate * 378*0Sstevel@tonic-gate * getlocks() extracts the list of locked devices from the file 379*0Sstevel@tonic-gate * containing that information. It returns the number of locked 380*0Sstevel@tonic-gate * devices. If there are any locked devices, it allocates a buffer 381*0Sstevel@tonic-gate * for the locked file information, saves that buffer address in 382*0Sstevel@tonic-gate * the allocated buffer. Also, the device lock file is open and 383*0Sstevel@tonic-gate * locked if the function is successful. 384*0Sstevel@tonic-gate * 385*0Sstevel@tonic-gate * Arguments: None 386*0Sstevel@tonic-gate * 387*0Sstevel@tonic-gate * Returns: int 388*0Sstevel@tonic-gate * TRUE if successful, FALSE otherwise. "errno" will reflect the 389*0Sstevel@tonic-gate * error if the function returns FALSE. 390*0Sstevel@tonic-gate * 391*0Sstevel@tonic-gate * Static data referenced: 392*0Sstevel@tonic-gate * int lkfilefd File descriptor of the lock file 393*0Sstevel@tonic-gate */ 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate static int 396*0Sstevel@tonic-gate getlocks(void) 397*0Sstevel@tonic-gate { 398*0Sstevel@tonic-gate /* Automatic data */ 399*0Sstevel@tonic-gate int noerror; /* TRUE if all's well */ 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate /* Initializations */ 403*0Sstevel@tonic-gate noerror = TRUE; 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate /* Open the lock file */ 406*0Sstevel@tonic-gate if (_openlkfile()) { 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate /* Lock the lock file */ 409*0Sstevel@tonic-gate if (locklkfile(F_WRLCK)) { 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate /* Get the number of devices currently locked */ 412*0Sstevel@tonic-gate if (!readlocks()) noerror = FALSE; 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* If something happened, unlock the file */ 415*0Sstevel@tonic-gate if (!noerror) (void) freelkfile(); 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate } else noerror = FALSE; /* Lock failed */ 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate /* If something happened, close the lock file */ 420*0Sstevel@tonic-gate if (!noerror) 421*0Sstevel@tonic-gate (void) _closelkfile(); 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate } else noerror = FALSE; /* Open failed */ 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* Done */ 426*0Sstevel@tonic-gate return (noerror); 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate /* 430*0Sstevel@tonic-gate * int writelks(tblcnt) 431*0Sstevel@tonic-gate * int tblcnt 432*0Sstevel@tonic-gate * 433*0Sstevel@tonic-gate * writelks() writes the lock information to the lock file. Lock 434*0Sstevel@tonic-gate * information includes the number of locks (to be) in the table. 435*0Sstevel@tonic-gate * Note that functions may still be appending new locks after this 436*0Sstevel@tonic-gate * call... 437*0Sstevel@tonic-gate * 438*0Sstevel@tonic-gate * Arguments: 439*0Sstevel@tonic-gate * tblcnt Number of locks in the lock table 440*0Sstevel@tonic-gate * 441*0Sstevel@tonic-gate * Returns: 442*0Sstevel@tonic-gate * TRUE if successful, FALSE otherwise with "errno" containing an 443*0Sstevel@tonic-gate * indication of the error. 444*0Sstevel@tonic-gate * 445*0Sstevel@tonic-gate * Statics Used: 446*0Sstevel@tonic-gate * lockcount Number of locks to exist 447*0Sstevel@tonic-gate * locklist Table of locks (may not include new ones) 448*0Sstevel@tonic-gate * lkfilefd File descriptor of the lock file 449*0Sstevel@tonic-gate * 450*0Sstevel@tonic-gate * Notes: 451*0Sstevel@tonic-gate * - The number of locks that are going to be in the lock file 452*0Sstevel@tonic-gate * is in the static variable "lockcount". <tblcnt> indicates 453*0Sstevel@tonic-gate * the number of entries in the lock table. 454*0Sstevel@tonic-gate */ 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate static int 457*0Sstevel@tonic-gate writelks(int tblcnt) 458*0Sstevel@tonic-gate { 459*0Sstevel@tonic-gate /* Automatic data */ 460*0Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 461*0Sstevel@tonic-gate size_t tblsz; /* Size of the table to write */ 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate /* Initializations */ 464*0Sstevel@tonic-gate noerr = TRUE; 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate /* Rewind the OA&M Device Lock File */ 467*0Sstevel@tonic-gate if (lseek(lkfilefd, 0L, 0) >= 0L) 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate /* Write the number of locks that will (eventually) exist */ 470*0Sstevel@tonic-gate if (write(lkfilefd, &lockcount, sizeof (int)) == sizeof (int)) { 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate /* Write the table as we currently know it */ 473*0Sstevel@tonic-gate tblsz = tblcnt * sizeof (struct devlks); 474*0Sstevel@tonic-gate if (tblsz) 475*0Sstevel@tonic-gate if (!write(lkfilefd, locklist, tblsz) == (ssize_t)tblsz) 476*0Sstevel@tonic-gate noerr = FALSE; /* Write of locks failed */ 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate } else noerr = FALSE; /* write() of count failed */ 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate else noerr = FALSE; /* Rewind failed */ 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate /* Return an indicator of our success */ 483*0Sstevel@tonic-gate return (noerr); 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate /* 487*0Sstevel@tonic-gate * int appendlk(key, alias) 488*0Sstevel@tonic-gate * int key 489*0Sstevel@tonic-gate * char *alias 490*0Sstevel@tonic-gate * 491*0Sstevel@tonic-gate * Write device locking information to the device locking file. 492*0Sstevel@tonic-gate * 493*0Sstevel@tonic-gate * Arguments: 494*0Sstevel@tonic-gate * key Key the device is being locked on 495*0Sstevel@tonic-gate * alias The device alias being locked 496*0Sstevel@tonic-gate * 497*0Sstevel@tonic-gate * Returns: int 498*0Sstevel@tonic-gate * TRUE if we successfully appended a lock to the lock file, 499*0Sstevel@tonic-gate * FALSE with "errno" set otherwise. 500*0Sstevel@tonic-gate * 501*0Sstevel@tonic-gate * Static data used: 502*0Sstevel@tonic-gate * lkfilefd The open file descriptor for the open device 503*0Sstevel@tonic-gate * locking file 504*0Sstevel@tonic-gate */ 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate static int 507*0Sstevel@tonic-gate appendlk( 508*0Sstevel@tonic-gate int key, /* Lock key */ 509*0Sstevel@tonic-gate char *alias) /* Alias to lock */ 510*0Sstevel@tonic-gate { 511*0Sstevel@tonic-gate /* Automatic data */ 512*0Sstevel@tonic-gate struct devlks lk; /* Structure for writing a lock */ 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate /* Set up the data to write */ 515*0Sstevel@tonic-gate lk.lk_key = key; 516*0Sstevel@tonic-gate (void) strcpy(lk.lk_alias, alias); 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate /* Write the data, returning an indicator of our success */ 519*0Sstevel@tonic-gate return (write(lkfilefd, &lk, 520*0Sstevel@tonic-gate sizeof (struct devlks)) == sizeof (struct devlks)); 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate /* 524*0Sstevel@tonic-gate * int compresslks() 525*0Sstevel@tonic-gate * 526*0Sstevel@tonic-gate * This function compresses the lock table, squeezing out the empty 527*0Sstevel@tonic-gate * lock entries. 528*0Sstevel@tonic-gate * 529*0Sstevel@tonic-gate * Arguments: none 530*0Sstevel@tonic-gate * 531*0Sstevel@tonic-gate * Returns: int 532*0Sstevel@tonic-gate * The number of non-empty entries in the table. They will be the 533*0Sstevel@tonic-gate * first 'n' entries in the table after compression. 534*0Sstevel@tonic-gate * 535*0Sstevel@tonic-gate * Statics Used 536*0Sstevel@tonic-gate * lockcount Number of locks in the device lock list 537*0Sstevel@tonic-gate * locklist The device lock list 538*0Sstevel@tonic-gate */ 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate static int 541*0Sstevel@tonic-gate compresslks(void) 542*0Sstevel@tonic-gate { 543*0Sstevel@tonic-gate /* Automatics */ 544*0Sstevel@tonic-gate struct devlks *avail; /* Pointer to empty slot */ 545*0Sstevel@tonic-gate struct devlks *p; /* Running pointer to locks */ 546*0Sstevel@tonic-gate int nlocks; /* Number of locks (up to date) */ 547*0Sstevel@tonic-gate int i; /* Temporary counter */ 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate /* Initializations */ 550*0Sstevel@tonic-gate p = locklist; 551*0Sstevel@tonic-gate nlocks = lockcount; 552*0Sstevel@tonic-gate avail = NULL; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate /* Loop through the lock list squeezing out unused slots */ 555*0Sstevel@tonic-gate for (i = 0; i < lockcount; i++) { 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate /* If we've found an empty slot ... */ 558*0Sstevel@tonic-gate if (isanullstr(p->lk_alias)) { 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate /* 561*0Sstevel@tonic-gate * If we've an empty slot to move to, just decrement 562*0Sstevel@tonic-gate * count of used slots. Otherwise, make it the next 563*0Sstevel@tonic-gate * available slot 564*0Sstevel@tonic-gate */ 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate nlocks--; 567*0Sstevel@tonic-gate if (!avail) avail = p; 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate else if (avail) { 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate /* 573*0Sstevel@tonic-gate * If we found a slot in use and there's an 574*0Sstevel@tonic-gate * available slot, move this one there 575*0Sstevel@tonic-gate */ 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate (void) strcpy(avail->lk_alias, p->lk_alias); 578*0Sstevel@tonic-gate avail->lk_key = p->lk_key; 579*0Sstevel@tonic-gate avail++; 580*0Sstevel@tonic-gate } 581*0Sstevel@tonic-gate 582*0Sstevel@tonic-gate /* Next, please */ 583*0Sstevel@tonic-gate p++; 584*0Sstevel@tonic-gate } 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate return (nlocks); 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate /* 590*0Sstevel@tonic-gate * int freelkfile() 591*0Sstevel@tonic-gate * 592*0Sstevel@tonic-gate * This function unlocks the OA&M device locking file. 593*0Sstevel@tonic-gate * 594*0Sstevel@tonic-gate * Arguments: None 595*0Sstevel@tonic-gate * 596*0Sstevel@tonic-gate * Returns: int 597*0Sstevel@tonic-gate * TRUE if it successfully unlocked the file, FALSE otherwise 598*0Sstevel@tonic-gate * with "errno" set to indicate the problem. 599*0Sstevel@tonic-gate * 600*0Sstevel@tonic-gate * Statics Used: 601*0Sstevel@tonic-gate * lkinfo File-locking structure 602*0Sstevel@tonic-gate * lkfilefd File-descriptor of the open lock file 603*0Sstevel@tonic-gate */ 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate static int 606*0Sstevel@tonic-gate freelkfile(void) 607*0Sstevel@tonic-gate { 608*0Sstevel@tonic-gate /* Automatic data */ 609*0Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate /* Set the action to "unlock" */ 612*0Sstevel@tonic-gate lkinfo.l_type = F_UNLCK; 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate /* Unlock the file */ 615*0Sstevel@tonic-gate noerr = (fcntl(lkfilefd, F_SETLK, &lkinfo) != -1); 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate /* Return an indication of our success */ 618*0Sstevel@tonic-gate return (noerr); 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate /* 622*0Sstevel@tonic-gate * int putlocks(newlist, key) 623*0Sstevel@tonic-gate * char **newlist 624*0Sstevel@tonic-gate * int key 625*0Sstevel@tonic-gate * 626*0Sstevel@tonic-gate * This function updates the file containing OA&M device locks. 627*0Sstevel@tonic-gate * 628*0Sstevel@tonic-gate * Arguments: 629*0Sstevel@tonic-gate * newlist The address of the list of addresses of device 630*0Sstevel@tonic-gate * aliases to add to the list of locked devices 631*0Sstevel@tonic-gate * key The key on which to lock the devices 632*0Sstevel@tonic-gate * 633*0Sstevel@tonic-gate * Returns: int 634*0Sstevel@tonic-gate * TRUE if all went well, FALSE otherwise with "errno" set to an 635*0Sstevel@tonic-gate * error code that indicates the problem. 636*0Sstevel@tonic-gate * 637*0Sstevel@tonic-gate * Statics Used: 638*0Sstevel@tonic-gate * lockcount Number of locks in the locked device structure 639*0Sstevel@tonic-gate * locklist Locked device structure 640*0Sstevel@tonic-gate */ 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate static int 643*0Sstevel@tonic-gate putlocks( 644*0Sstevel@tonic-gate char **newlist, /* New devices to lock */ 645*0Sstevel@tonic-gate int key) /* Key we're locking stuff on */ 646*0Sstevel@tonic-gate { 647*0Sstevel@tonic-gate /* Automatic data */ 648*0Sstevel@tonic-gate struct devlks *plk; /* Ptr into the locks list */ 649*0Sstevel@tonic-gate char **pp; /* Pointer into the device list */ 650*0Sstevel@tonic-gate char **qq; /* Another ptr into the dev list */ 651*0Sstevel@tonic-gate int lkndx; /* Index into locks list */ 652*0Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 653*0Sstevel@tonic-gate int lksintbl; /* Number of locks in the table */ 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * Look through the existing lock list, looking for holes we can 658*0Sstevel@tonic-gate * use for the newly locked devices 659*0Sstevel@tonic-gate */ 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate plk = locklist; 662*0Sstevel@tonic-gate pp = newlist; 663*0Sstevel@tonic-gate lkndx = 0; 664*0Sstevel@tonic-gate while (*pp && (lkndx < lockcount)) { 665*0Sstevel@tonic-gate if (isanullstr(plk->lk_alias)) { 666*0Sstevel@tonic-gate plk->lk_key = key; 667*0Sstevel@tonic-gate (void) strcpy(plk->lk_alias, *pp++); 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate lkndx++; 670*0Sstevel@tonic-gate plk++; 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate /* 674*0Sstevel@tonic-gate * Update the locks file (algorithm depends on whether we're adding 675*0Sstevel@tonic-gate * new locks or not. May be replacing old locks!) 676*0Sstevel@tonic-gate */ 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate if (*pp) { 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate /* 681*0Sstevel@tonic-gate * Need to expand the locks file 682*0Sstevel@tonic-gate * - Remember the old lock count (in existing lock buffer) 683*0Sstevel@tonic-gate * - Count the number of new locks we need to add 684*0Sstevel@tonic-gate * - Write out the old locks structure 685*0Sstevel@tonic-gate * - Append locks for the newly added locks 686*0Sstevel@tonic-gate */ 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate lksintbl = lockcount; 689*0Sstevel@tonic-gate for (qq = pp; *qq; qq++) lockcount++; 690*0Sstevel@tonic-gate noerr = writelks(lksintbl); 691*0Sstevel@tonic-gate while (noerr && *pp) noerr = appendlk(key, *pp++); 692*0Sstevel@tonic-gate } else { 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate /* 695*0Sstevel@tonic-gate * Don't need to expand the locks file. Compress the locks 696*0Sstevel@tonic-gate * then write out the locks information 697*0Sstevel@tonic-gate */ 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate lockcount = compresslks(); 700*0Sstevel@tonic-gate noerr = writelks(lockcount); 701*0Sstevel@tonic-gate } 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate /* Done. Return an indication of our success */ 704*0Sstevel@tonic-gate return (noerr); 705*0Sstevel@tonic-gate } 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate /* 708*0Sstevel@tonic-gate * char *islocked(device) 709*0Sstevel@tonic-gate * char *device 710*0Sstevel@tonic-gate * 711*0Sstevel@tonic-gate * This function checks a device to see if it is locked. If it is 712*0Sstevel@tonic-gate * not locked, it returns the device alias. 713*0Sstevel@tonic-gate * 714*0Sstevel@tonic-gate * A device is not locked if the device's alias does not appear in 715*0Sstevel@tonic-gate * the device locks table, or the key on which the device was locked 716*0Sstevel@tonic-gate * is no longer active. 717*0Sstevel@tonic-gate * 718*0Sstevel@tonic-gate * Argumetns: 719*0Sstevel@tonic-gate * char *device The device to be reserved. This can be 720*0Sstevel@tonic-gate * a pathname to the device or a device 721*0Sstevel@tonic-gate * alias. 722*0Sstevel@tonic-gate * 723*0Sstevel@tonic-gate * Returns: char * 724*0Sstevel@tonic-gate * Returns a pointer to the device alias if it's not locked, or 725*0Sstevel@tonic-gate * (char *) NULL if it's locked or some error occurred. 726*0Sstevel@tonic-gate * 727*0Sstevel@tonic-gate * Static data used: 728*0Sstevel@tonic-gate * struct devlks *locklist Pointer to the list of device locks 729*0Sstevel@tonic-gate * int lockcount The number of devices that are locked 730*0Sstevel@tonic-gate */ 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate static char * 733*0Sstevel@tonic-gate islocked(char *device) 734*0Sstevel@tonic-gate { 735*0Sstevel@tonic-gate /* Automatic data */ 736*0Sstevel@tonic-gate char *alias; /* Alias of "device" */ 737*0Sstevel@tonic-gate struct devlks *plk; /* Ptr to locking info */ 738*0Sstevel@tonic-gate int locked; /* TRUE if device in locked list */ 739*0Sstevel@tonic-gate int i; /* Temp counter */ 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate /* Get the device's alias */ 742*0Sstevel@tonic-gate if (alias = devattr(device, DTAB_ALIAS)) { 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate /* 745*0Sstevel@tonic-gate * Look through the device locks to see if this device alias 746*0Sstevel@tonic-gate * is locked 747*0Sstevel@tonic-gate */ 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate locked = FALSE; 750*0Sstevel@tonic-gate plk = locklist; 751*0Sstevel@tonic-gate for (i = 0; !locked && (i < lockcount); i++) { 752*0Sstevel@tonic-gate if (strncmp(alias, plk->lk_alias, DTAB_MXALIASLN) == 0) 753*0Sstevel@tonic-gate locked = TRUE; 754*0Sstevel@tonic-gate else plk++; 755*0Sstevel@tonic-gate } 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate if (locked) { 758*0Sstevel@tonic-gate free(alias); 759*0Sstevel@tonic-gate alias = NULL; 760*0Sstevel@tonic-gate errno = EAGAIN; 761*0Sstevel@tonic-gate } 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate } /* devattr() failed, no such device? */ 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate /* Return pointer to the device */ 766*0Sstevel@tonic-gate return (alias); 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate /* 770*0Sstevel@tonic-gate * int unreserv(key, device) 771*0Sstevel@tonic-gate * int key 772*0Sstevel@tonic-gate * char *device 773*0Sstevel@tonic-gate * 774*0Sstevel@tonic-gate * This function removes a device reservation. 775*0Sstevel@tonic-gate * 776*0Sstevel@tonic-gate * Arguments: 777*0Sstevel@tonic-gate * int key The key on which the device was allocated 778*0Sstevel@tonic-gate * char *device The device to be freed. 779*0Sstevel@tonic-gate * 780*0Sstevel@tonic-gate * Returns: int 781*0Sstevel@tonic-gate * TRUE if successful, FALSE otherwise with "errno" set. 782*0Sstevel@tonic-gate * 783*0Sstevel@tonic-gate * Explicit "errno" settings: 784*0Sstevel@tonic-gate * (This follows the "signal()" model which gives one the ability 785*0Sstevel@tonic-gate * to determine if a device is allocated without having the 786*0Sstevel@tonic-gate * permission to free it.) 787*0Sstevel@tonic-gate * 788*0Sstevel@tonic-gate * EINVAL The device specified was not locked 789*0Sstevel@tonic-gate * EPERM The device specified was locked but not on the 790*0Sstevel@tonic-gate * specified key 791*0Sstevel@tonic-gate * 792*0Sstevel@tonic-gate * Static data used: 793*0Sstevel@tonic-gate * locklist List of locked devices 794*0Sstevel@tonic-gate * lockcount Number of entries in the locked-device list 795*0Sstevel@tonic-gate */ 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate int 798*0Sstevel@tonic-gate unreserv(int key, char *device) 799*0Sstevel@tonic-gate { 800*0Sstevel@tonic-gate /* Automatics */ 801*0Sstevel@tonic-gate char *srchalias; /* Device alias to search table with */ 802*0Sstevel@tonic-gate char *alias; /* Device's alias (from devattr()) */ 803*0Sstevel@tonic-gate struct devlks *plk; /* Pointer to a device lock */ 804*0Sstevel@tonic-gate int locked; /* TRUE if device currently locked */ 805*0Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 806*0Sstevel@tonic-gate int olderrno; /* Entry value of "errno" */ 807*0Sstevel@tonic-gate int i; /* Counter of locks */ 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate 810*0Sstevel@tonic-gate /* Initializations */ 811*0Sstevel@tonic-gate noerr = TRUE; 812*0Sstevel@tonic-gate 813*0Sstevel@tonic-gate /* 814*0Sstevel@tonic-gate * Get the device alias. If none can be found, try to free 815*0Sstevel@tonic-gate * whatever it is that was given to us (the possibility exists 816*0Sstevel@tonic-gate * that the device has been removed from the device table since 817*0Sstevel@tonic-gate * it was reserved, so the device not being in the table shouldn't 818*0Sstevel@tonic-gate * pose too much of a problem with us...) 819*0Sstevel@tonic-gate */ 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate olderrno = errno; 822*0Sstevel@tonic-gate if (alias = devattr(device, DTAB_ALIAS)) srchalias = alias; 823*0Sstevel@tonic-gate else { 824*0Sstevel@tonic-gate errno = olderrno; 825*0Sstevel@tonic-gate srchalias = device; 826*0Sstevel@tonic-gate } 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate /* Loop through the locked-device list looking for what we've got... */ 829*0Sstevel@tonic-gate locked = FALSE; 830*0Sstevel@tonic-gate plk = locklist; 831*0Sstevel@tonic-gate for (i = 0; !locked && (i < lockcount); i++) { 832*0Sstevel@tonic-gate if (strcmp(srchalias, plk->lk_alias) == 0) 833*0Sstevel@tonic-gate locked = TRUE; 834*0Sstevel@tonic-gate else plk++; 835*0Sstevel@tonic-gate } 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate /* Free the alias string (if any), we don't need it anymore */ 838*0Sstevel@tonic-gate if (alias) free(alias); 839*0Sstevel@tonic-gate 840*0Sstevel@tonic-gate /* If the device is locked ... */ 841*0Sstevel@tonic-gate if (locked) { 842*0Sstevel@tonic-gate 843*0Sstevel@tonic-gate /* 844*0Sstevel@tonic-gate * If it's locked on the key we've been given, free it. 845*0Sstevel@tonic-gate * Otherwise, don't free it and set errno to EPERM 846*0Sstevel@tonic-gate */ 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate if (plk->lk_key == key) { 849*0Sstevel@tonic-gate plk->lk_alias[0] = '\0'; 850*0Sstevel@tonic-gate } else { 851*0Sstevel@tonic-gate noerr = FALSE; 852*0Sstevel@tonic-gate errno = EPERM; 853*0Sstevel@tonic-gate } 854*0Sstevel@tonic-gate } else { 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate /* The device isn't locked. Set errno to EINVAL */ 857*0Sstevel@tonic-gate noerr = FALSE; 858*0Sstevel@tonic-gate errno = EINVAL; 859*0Sstevel@tonic-gate } 860*0Sstevel@tonic-gate 861*0Sstevel@tonic-gate /* Finished. Return an indication of our success */ 862*0Sstevel@tonic-gate return (noerr); 863*0Sstevel@tonic-gate } 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate /* 866*0Sstevel@tonic-gate * char **devreserv(key, rsvlst) 867*0Sstevel@tonic-gate * int key 868*0Sstevel@tonic-gate * char **rsvlist[] 869*0Sstevel@tonic-gate * 870*0Sstevel@tonic-gate * The devreserv() function reserves devices known to the OA&M Device 871*0Sstevel@tonic-gate * Management family of functions. Once a device is reserved, it can't 872*0Sstevel@tonic-gate * be reserved by another until it is freed or the process with the 873*0Sstevel@tonic-gate * "key" is no longer active. It returns a list aliases of the devices 874*0Sstevel@tonic-gate * it allocated. 875*0Sstevel@tonic-gate * 876*0Sstevel@tonic-gate * The function attempts to reserve a single device from each of the 877*0Sstevel@tonic-gate * lists. It scans each list sequentially until it was able to 878*0Sstevel@tonic-gate * reserve a requested device. If it successfully reserved a device 879*0Sstevel@tonic-gate * from each of the lists, it updates the device-locked file and 880*0Sstevel@tonic-gate * returns those aliases to the caller. If it fails, it allocates 881*0Sstevel@tonic-gate * nothing and returns (char **) NULL to the caller. "errno" 882*0Sstevel@tonic-gate * indicates the error. 883*0Sstevel@tonic-gate * 884*0Sstevel@tonic-gate * Arguments: 885*0Sstevel@tonic-gate * int key The key on which this device is being reserved. 886*0Sstevel@tonic-gate * 887*0Sstevel@tonic-gate * char **rsvlist[] The address of the list of addresses of lists 888*0Sstevel@tonic-gate * of pointers to the devices to allocate. 889*0Sstevel@tonic-gate * 890*0Sstevel@tonic-gate * Returns: char ** 891*0Sstevel@tonic-gate * A pointer to malloc()ed space containing pointers to the aliases 892*0Sstevel@tonic-gate * of the reserved devices. The aliases are in malloc()ed space also. 893*0Sstevel@tonic-gate * The list is terminated by the value (char *) NULL. 894*0Sstevel@tonic-gate * 895*0Sstevel@tonic-gate * Static Data Used: 896*0Sstevel@tonic-gate * None directly, but functions called share hidden information 897*0Sstevel@tonic-gate * that really isn't of concern to devreserv(). 898*0Sstevel@tonic-gate */ 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate char ** 901*0Sstevel@tonic-gate devreserv( 902*0Sstevel@tonic-gate int key, /* Key to reserve device on */ 903*0Sstevel@tonic-gate char **rsvlst[]) /* List of lists of devs to reserve */ 904*0Sstevel@tonic-gate { 905*0Sstevel@tonic-gate char ***ppp; /* Ptr to current list in rsvlist */ 906*0Sstevel@tonic-gate char **pp; /* Ptr to current item in list */ 907*0Sstevel@tonic-gate char **qq; /* Ptr to item in rtnlist */ 908*0Sstevel@tonic-gate char **rr; /* Ptr to item in aliases */ 909*0Sstevel@tonic-gate char **aliases; /* List of aliases allocated */ 910*0Sstevel@tonic-gate char **rtnlist; /* Ptr to buf to return */ 911*0Sstevel@tonic-gate char *alias; /* Alias of dev to reserve */ 912*0Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 913*0Sstevel@tonic-gate int olderrno; /* Old value of errno */ 914*0Sstevel@tonic-gate int gotone; /* TRUE if unreserved dev found */ 915*0Sstevel@tonic-gate int foundone; /* Found a valid device in the list */ 916*0Sstevel@tonic-gate int ndevs; /* # of devs to reserve */ 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate noerr = TRUE; 919*0Sstevel@tonic-gate ppp = rsvlst; 920*0Sstevel@tonic-gate olderrno = errno; 921*0Sstevel@tonic-gate for (ndevs = 0; *ppp++; ndevs++) 922*0Sstevel@tonic-gate ; 923*0Sstevel@tonic-gate if (rtnlist = malloc((ndevs+1)*sizeof (char **))) { 924*0Sstevel@tonic-gate if (aliases = malloc((ndevs+1)*sizeof (char **))) { 925*0Sstevel@tonic-gate if (getlocks()) { 926*0Sstevel@tonic-gate qq = rtnlist; 927*0Sstevel@tonic-gate rr = aliases; 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate /* Go through the lists of devices we're to reserve */ 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate for (ppp = rsvlst; noerr && *ppp; ppp++) { 932*0Sstevel@tonic-gate 933*0Sstevel@tonic-gate /* Try to reserve a device from each list */ 934*0Sstevel@tonic-gate gotone = FALSE; 935*0Sstevel@tonic-gate foundone = FALSE; 936*0Sstevel@tonic-gate for (pp = *ppp; noerr && !gotone && *pp; pp++) { 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate /* 939*0Sstevel@tonic-gate * Check the next device in the list. If islocked() 940*0Sstevel@tonic-gate * returns that device's alias, it's ours to have 941*0Sstevel@tonic-gate */ 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate if (alias = islocked(*pp)) { 944*0Sstevel@tonic-gate gotone = TRUE; 945*0Sstevel@tonic-gate foundone = TRUE; 946*0Sstevel@tonic-gate if (*qq = malloc(strlen(*pp)+1)) { 947*0Sstevel@tonic-gate (void) strcpy(*qq++, *pp); 948*0Sstevel@tonic-gate *rr++ = alias; 949*0Sstevel@tonic-gate } else { 950*0Sstevel@tonic-gate *rr = NULL; 951*0Sstevel@tonic-gate noerr = FALSE; 952*0Sstevel@tonic-gate } 953*0Sstevel@tonic-gate } else { 954*0Sstevel@tonic-gate if (errno == EAGAIN) { 955*0Sstevel@tonic-gate foundone = TRUE; 956*0Sstevel@tonic-gate errno = olderrno; 957*0Sstevel@tonic-gate } else if (errno == ENODEV) errno = olderrno; 958*0Sstevel@tonic-gate else { 959*0Sstevel@tonic-gate noerr = FALSE; 960*0Sstevel@tonic-gate *rr = NULL; 961*0Sstevel@tonic-gate } 962*0Sstevel@tonic-gate } 963*0Sstevel@tonic-gate } 964*0Sstevel@tonic-gate 965*0Sstevel@tonic-gate /* 966*0Sstevel@tonic-gate * If no device from the list could be reserved, 967*0Sstevel@tonic-gate * we've failed 968*0Sstevel@tonic-gate */ 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate if (noerr && !gotone) { 971*0Sstevel@tonic-gate noerr = FALSE; 972*0Sstevel@tonic-gate if (!foundone) errno = ENODEV; 973*0Sstevel@tonic-gate else errno = EAGAIN; 974*0Sstevel@tonic-gate *qq = NULL; 975*0Sstevel@tonic-gate *rr = NULL; 976*0Sstevel@tonic-gate } 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate } /* End of loop through lists loop */ 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate /* 981*0Sstevel@tonic-gate * If all went well, update lock file. 982*0Sstevel@tonic-gate * Then, free locks 983*0Sstevel@tonic-gate */ 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate if (noerr) { 986*0Sstevel@tonic-gate *qq = NULL; 987*0Sstevel@tonic-gate *rr = NULL; 988*0Sstevel@tonic-gate if (!putlocks(aliases, key)) noerr = FALSE; 989*0Sstevel@tonic-gate } 990*0Sstevel@tonic-gate 991*0Sstevel@tonic-gate /* Free resources */ 992*0Sstevel@tonic-gate if (!freelkfile()) noerr = FALSE; 993*0Sstevel@tonic-gate if (_closelkfile() != 0) noerr = FALSE; 994*0Sstevel@tonic-gate for (qq = aliases; *qq; qq++) free(*qq); 995*0Sstevel@tonic-gate if (!noerr) 996*0Sstevel@tonic-gate for (pp = rtnlist; *pp; pp++) 997*0Sstevel@tonic-gate free(*pp); 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate } else noerr = FALSE; /* Error getting locks */ 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate free(aliases); 1002*0Sstevel@tonic-gate 1003*0Sstevel@tonic-gate } else noerr = FALSE; /* Malloc() for alias list failed */ 1004*0Sstevel@tonic-gate 1005*0Sstevel@tonic-gate if (!noerr) { 1006*0Sstevel@tonic-gate free(rtnlist); 1007*0Sstevel@tonic-gate rtnlist = NULL; 1008*0Sstevel@tonic-gate } 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate } else noerr = FALSE; /* malloc() failed */ 1011*0Sstevel@tonic-gate 1012*0Sstevel@tonic-gate /* Return list or an indication of an error */ 1013*0Sstevel@tonic-gate return (noerr ? rtnlist : NULL); 1014*0Sstevel@tonic-gate } 1015*0Sstevel@tonic-gate 1016*0Sstevel@tonic-gate /* 1017*0Sstevel@tonic-gate * int devfree(key, device) 1018*0Sstevel@tonic-gate * int key 1019*0Sstevel@tonic-gate * char *device 1020*0Sstevel@tonic-gate * 1021*0Sstevel@tonic-gate * This function unreserves (frees) the given device. It returns 1022*0Sstevel@tonic-gate * an indication of success with "errno" containing information about 1023*0Sstevel@tonic-gate * a failure. 1024*0Sstevel@tonic-gate * 1025*0Sstevel@tonic-gate * Arguments: 1026*0Sstevel@tonic-gate * int key The key that the device is locked on 1027*0Sstevel@tonic-gate * char *device The device (alias, pathname to, etc.) to be freed. 1028*0Sstevel@tonic-gate * 1029*0Sstevel@tonic-gate * Returns: int 1030*0Sstevel@tonic-gate * 0 if successful, -1 with "errno" set if fails. 1031*0Sstevel@tonic-gate */ 1032*0Sstevel@tonic-gate 1033*0Sstevel@tonic-gate int 1034*0Sstevel@tonic-gate devfree( 1035*0Sstevel@tonic-gate int key, /* Key device is locked on */ 1036*0Sstevel@tonic-gate char *device) /* Device to free */ 1037*0Sstevel@tonic-gate { 1038*0Sstevel@tonic-gate /* Automatics */ 1039*0Sstevel@tonic-gate int noerr; 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* Initializations */ 1042*0Sstevel@tonic-gate noerr = TRUE; 1043*0Sstevel@tonic-gate 1044*0Sstevel@tonic-gate /* Get the locks, locking the lock file */ 1045*0Sstevel@tonic-gate if (getlocks()) { 1046*0Sstevel@tonic-gate 1047*0Sstevel@tonic-gate /* Attempt to unreserve the device */ 1048*0Sstevel@tonic-gate if (unreserv(key, device)) { 1049*0Sstevel@tonic-gate 1050*0Sstevel@tonic-gate /* 1051*0Sstevel@tonic-gate * Successful. Compress the lock structure and 1052*0Sstevel@tonic-gate * write the new locks 1053*0Sstevel@tonic-gate */ 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate lockcount = compresslks(); 1056*0Sstevel@tonic-gate if (!writelks(lockcount)) noerr = FALSE; 1057*0Sstevel@tonic-gate 1058*0Sstevel@tonic-gate } else noerr = FALSE; /* Couldn't unreserve the device */ 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate /* Unlock and close the locks file */ 1061*0Sstevel@tonic-gate if (!freelkfile()) noerr = FALSE; 1062*0Sstevel@tonic-gate if (_closelkfile() != 0) noerr = FALSE; 1063*0Sstevel@tonic-gate 1064*0Sstevel@tonic-gate } else noerr = FALSE; 1065*0Sstevel@tonic-gate 1066*0Sstevel@tonic-gate /* Return 0 if successful, something else otherwise */ 1067*0Sstevel@tonic-gate return (noerr? 0 : -1); 1068*0Sstevel@tonic-gate } 1069*0Sstevel@tonic-gate 1070*0Sstevel@tonic-gate /* 1071*0Sstevel@tonic-gate * struct reservdev **reservdev() 1072*0Sstevel@tonic-gate * 1073*0Sstevel@tonic-gate * This function returns the list of reserved devices 1074*0Sstevel@tonic-gate * along with the key on which those devices were locked. 1075*0Sstevel@tonic-gate * 1076*0Sstevel@tonic-gate * Arguments: None. 1077*0Sstevel@tonic-gate * 1078*0Sstevel@tonic-gate * Returns: struct reservdev ** 1079*0Sstevel@tonic-gate * Pointer to the list of pointers to structures describing 1080*0Sstevel@tonic-gate * the reserved devices, or (struct reservdev **) NULL if an 1081*0Sstevel@tonic-gate * error occurred. The list of pointers is terminated by 1082*0Sstevel@tonic-gate * (struct reservdev *) NULL. 1083*0Sstevel@tonic-gate * 1084*0Sstevel@tonic-gate * Statics Used: 1085*0Sstevel@tonic-gate * locklist List of reserved devices 1086*0Sstevel@tonic-gate * lockcount Number of items in the reserved-devices list 1087*0Sstevel@tonic-gate */ 1088*0Sstevel@tonic-gate 1089*0Sstevel@tonic-gate struct reservdev ** 1090*0Sstevel@tonic-gate reservdev(void) 1091*0Sstevel@tonic-gate { 1092*0Sstevel@tonic-gate /* Automatics */ 1093*0Sstevel@tonic-gate struct reservdev **rtnlist; /* Ptr to return list */ 1094*0Sstevel@tonic-gate struct devlks *p; /* Running ptr, locklist */ 1095*0Sstevel@tonic-gate struct reservdev **q; /* Running ptr, rtnlist */ 1096*0Sstevel@tonic-gate char *r; /* Temp ptr to char */ 1097*0Sstevel@tonic-gate size_t bufsiz; /* Size of buffer to alloc */ 1098*0Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 1099*0Sstevel@tonic-gate int i; /* Lock counter */ 1100*0Sstevel@tonic-gate 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate /* Initializations */ 1103*0Sstevel@tonic-gate noerr = TRUE; 1104*0Sstevel@tonic-gate 1105*0Sstevel@tonic-gate /* Open the lock file ... */ 1106*0Sstevel@tonic-gate if (_openlkfile()) { 1107*0Sstevel@tonic-gate 1108*0Sstevel@tonic-gate /* Put a read-lock on the lock-file ... */ 1109*0Sstevel@tonic-gate if (locklkfile(F_RDLCK)) { 1110*0Sstevel@tonic-gate 1111*0Sstevel@tonic-gate /* Read the locks ... */ 1112*0Sstevel@tonic-gate if (readlocks()) { 1113*0Sstevel@tonic-gate 1114*0Sstevel@tonic-gate /* Alloc space for the return list */ 1115*0Sstevel@tonic-gate bufsiz = (lockcount+1) * sizeof (struct reservdev *); 1116*0Sstevel@tonic-gate if (rtnlist = malloc(bufsiz)) { 1117*0Sstevel@tonic-gate 1118*0Sstevel@tonic-gate /* Build the return list from the lock list */ 1119*0Sstevel@tonic-gate p = locklist; 1120*0Sstevel@tonic-gate q = rtnlist; 1121*0Sstevel@tonic-gate for (i = 0; noerr && (i < lockcount); i++) { 1122*0Sstevel@tonic-gate if (*q = malloc(sizeof (struct reservdev))) { 1123*0Sstevel@tonic-gate if (r = malloc(strlen(p->lk_alias)+1)) { 1124*0Sstevel@tonic-gate (*q)->devname = strcpy(r, p->lk_alias); 1125*0Sstevel@tonic-gate (*q)->key = p->lk_key; 1126*0Sstevel@tonic-gate } else noerr = FALSE; /* malloc() error */ 1127*0Sstevel@tonic-gate } else noerr = FALSE; /* malloc() error */ 1128*0Sstevel@tonic-gate p++; 1129*0Sstevel@tonic-gate q++; 1130*0Sstevel@tonic-gate } 1131*0Sstevel@tonic-gate 1132*0Sstevel@tonic-gate /* 1133*0Sstevel@tonic-gate * If no error, terminate the list. Otherwise, free 1134*0Sstevel@tonic-gate * the space we've allocated 1135*0Sstevel@tonic-gate */ 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate if (noerr) *q = NULL; 1138*0Sstevel@tonic-gate else { 1139*0Sstevel@tonic-gate for (q = rtnlist; *q; q++) { 1140*0Sstevel@tonic-gate free((*q)->devname); 1141*0Sstevel@tonic-gate free(*q); 1142*0Sstevel@tonic-gate } 1143*0Sstevel@tonic-gate free(rtnlist); 1144*0Sstevel@tonic-gate } 1145*0Sstevel@tonic-gate 1146*0Sstevel@tonic-gate } else noerr = FALSE; /* Couldn't malloc() list space */ 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate } else noerr = FALSE; /* Problem reading locks */ 1149*0Sstevel@tonic-gate 1150*0Sstevel@tonic-gate /* Free the lock file */ 1151*0Sstevel@tonic-gate (void) freelkfile(); 1152*0Sstevel@tonic-gate 1153*0Sstevel@tonic-gate } else noerr = FALSE; /* Error locking the lock file */ 1154*0Sstevel@tonic-gate 1155*0Sstevel@tonic-gate /* Close the lock file */ 1156*0Sstevel@tonic-gate (void) _closelkfile(); 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate } else noerr = FALSE; /* Error opening the lock file */ 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate /* Return ptr to list of locks or NULL if an error has occurred */ 1161*0Sstevel@tonic-gate return (noerr ? rtnlist : NULL); 1162*0Sstevel@tonic-gate } 1163