1*45916cd2Sjpk /* 2*45916cd2Sjpk * CDDL HEADER START 3*45916cd2Sjpk * 4*45916cd2Sjpk * The contents of this file are subject to the terms of the 5*45916cd2Sjpk * Common Development and Distribution License (the "License"). 6*45916cd2Sjpk * You may not use this file except in compliance with the License. 7*45916cd2Sjpk * 8*45916cd2Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*45916cd2Sjpk * or http://www.opensolaris.org/os/licensing. 10*45916cd2Sjpk * See the License for the specific language governing permissions 11*45916cd2Sjpk * and limitations under the License. 12*45916cd2Sjpk * 13*45916cd2Sjpk * When distributing Covered Code, include this CDDL HEADER in each 14*45916cd2Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*45916cd2Sjpk * If applicable, add the following below this CDDL HEADER, with the 16*45916cd2Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 17*45916cd2Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 18*45916cd2Sjpk * 19*45916cd2Sjpk * CDDL HEADER END 20*45916cd2Sjpk */ 21*45916cd2Sjpk 22*45916cd2Sjpk /* 23*45916cd2Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*45916cd2Sjpk * Use is subject to license terms. 25*45916cd2Sjpk */ 26*45916cd2Sjpk 27*45916cd2Sjpk #pragma ident "%Z%%M% %I% %E% SMI" 28*45916cd2Sjpk 29*45916cd2Sjpk #include <stdlib.h> 30*45916cd2Sjpk #include <ctype.h> 31*45916cd2Sjpk #include <unistd.h> 32*45916cd2Sjpk #include <limits.h> 33*45916cd2Sjpk #include <fcntl.h> 34*45916cd2Sjpk #include <sys/types.h> 35*45916cd2Sjpk #include <sys/stat.h> 36*45916cd2Sjpk #include <utime.h> 37*45916cd2Sjpk #include <synch.h> 38*45916cd2Sjpk #include <strings.h> 39*45916cd2Sjpk #include <string.h> 40*45916cd2Sjpk #include <libintl.h> 41*45916cd2Sjpk #include <errno.h> 42*45916cd2Sjpk #include <auth_list.h> 43*45916cd2Sjpk #include <bsm/devices.h> 44*45916cd2Sjpk #include <bsm/devalloc.h> 45*45916cd2Sjpk 46*45916cd2Sjpk #define DA_DEFS "/etc/security/tsol/devalloc_defaults" 47*45916cd2Sjpk 48*45916cd2Sjpk extern int _readbufline(char *, int, char *, int, int *); 49*45916cd2Sjpk extern char *strtok_r(char *, const char *, char **); 50*45916cd2Sjpk extern char *_strtok_escape(char *, char *, char **); 51*45916cd2Sjpk extern int getdaon(void); 52*45916cd2Sjpk extern int da_matchname(devalloc_t *, char *); 53*45916cd2Sjpk extern int da_match(devalloc_t *, da_args *); 54*45916cd2Sjpk extern int dmap_matchname(devmap_t *, char *); 55*45916cd2Sjpk extern int dm_match(devmap_t *, da_args *); 56*45916cd2Sjpk 57*45916cd2Sjpk /* 58*45916cd2Sjpk * The following structure is for recording old entries to be retained. 59*45916cd2Sjpk * We read the entries from the database into a linked list in memory, 60*45916cd2Sjpk * then turn around and write them out again. 61*45916cd2Sjpk */ 62*45916cd2Sjpk typedef struct strentry { 63*45916cd2Sjpk struct strentry *se_next; 64*45916cd2Sjpk char se_str[4096 + 1]; 65*45916cd2Sjpk } strentry_t; 66*45916cd2Sjpk 67*45916cd2Sjpk /* 68*45916cd2Sjpk * da_check_longindevperm - 69*45916cd2Sjpk * reads /etc/logindevperm and checks if specified device is in the file. 70*45916cd2Sjpk * returns 1 if specified device found in /etc/logindevperm, else returns 0 71*45916cd2Sjpk */ 72*45916cd2Sjpk int 73*45916cd2Sjpk da_check_logindevperm(char *devname) 74*45916cd2Sjpk { 75*45916cd2Sjpk int ret = 0; 76*45916cd2Sjpk int fd = -1; 77*45916cd2Sjpk int nlen, plen, slen, lineno, fsize; 78*45916cd2Sjpk char line[MAX_CANON]; 79*45916cd2Sjpk char *field_delims = " \t\n"; 80*45916cd2Sjpk char *fbuf = NULL; 81*45916cd2Sjpk char *ptr, *device; 82*45916cd2Sjpk char *lasts = NULL; 83*45916cd2Sjpk FILE *fp; 84*45916cd2Sjpk struct stat f_stat; 85*45916cd2Sjpk 86*45916cd2Sjpk /* 87*45916cd2Sjpk * check if /etc/logindevperm exists and get its size 88*45916cd2Sjpk */ 89*45916cd2Sjpk if ((fd = open(LOGINDEVPERM, O_RDONLY)) == -1) 90*45916cd2Sjpk return (0); 91*45916cd2Sjpk if (fstat(fd, &f_stat) != 0) { 92*45916cd2Sjpk (void) close(fd); 93*45916cd2Sjpk return (0); 94*45916cd2Sjpk } 95*45916cd2Sjpk fsize = f_stat.st_size; 96*45916cd2Sjpk if ((fbuf = (char *)malloc(fsize)) == NULL) { 97*45916cd2Sjpk (void) close(fd); 98*45916cd2Sjpk return (0); 99*45916cd2Sjpk } 100*45916cd2Sjpk if ((fp = fdopen(fd, "r")) == NULL) { 101*45916cd2Sjpk free(fbuf); 102*45916cd2Sjpk (void) close(fd); 103*45916cd2Sjpk return (0); 104*45916cd2Sjpk } 105*45916cd2Sjpk 106*45916cd2Sjpk /* 107*45916cd2Sjpk * read and parse /etc/logindevperm 108*45916cd2Sjpk */ 109*45916cd2Sjpk plen = nlen = lineno = 0; 110*45916cd2Sjpk while (fgets(line, MAX_CANON, fp) != NULL) { 111*45916cd2Sjpk lineno++; 112*45916cd2Sjpk if ((ptr = strchr(line, '#')) != NULL) 113*45916cd2Sjpk *ptr = '\0'; /* handle comments */ 114*45916cd2Sjpk if (strtok_r(line, field_delims, &lasts) == NULL) 115*45916cd2Sjpk continue; /* ignore blank lines */ 116*45916cd2Sjpk if (strtok_r(NULL, field_delims, &lasts) == NULL) 117*45916cd2Sjpk /* invalid entry */ 118*45916cd2Sjpk continue; 119*45916cd2Sjpk if ((ptr = strtok_r(NULL, field_delims, &lasts)) == NULL) 120*45916cd2Sjpk /* empty device list */ 121*45916cd2Sjpk continue; 122*45916cd2Sjpk nlen = strlen(ptr) + 1; /* +1 terminator */ 123*45916cd2Sjpk nlen += (plen + 1); 124*45916cd2Sjpk if (plen == 0) 125*45916cd2Sjpk slen = snprintf(fbuf, nlen, "%s", ptr); 126*45916cd2Sjpk else 127*45916cd2Sjpk slen = snprintf(fbuf + plen, nlen - plen, ":%s", ptr); 128*45916cd2Sjpk if (slen >= fsize) { 129*45916cd2Sjpk fbuf[0] = '\0'; 130*45916cd2Sjpk (void) fclose(fp); 131*45916cd2Sjpk return (slen); 132*45916cd2Sjpk } 133*45916cd2Sjpk plen += slen; 134*45916cd2Sjpk } 135*45916cd2Sjpk (void) fclose(fp); 136*45916cd2Sjpk 137*45916cd2Sjpk /* 138*45916cd2Sjpk * check if devname exists in /etc/logindevperm 139*45916cd2Sjpk */ 140*45916cd2Sjpk device = strtok_r(fbuf, ":", &lasts); 141*45916cd2Sjpk while (device != NULL) { 142*45916cd2Sjpk /* 143*45916cd2Sjpk * device and devname may be one of these types - 144*45916cd2Sjpk * /dev/xx 145*45916cd2Sjpk * /dev/xx* 146*45916cd2Sjpk * /dev/dir/xx 147*45916cd2Sjpk * /dev/dir/xx* 148*45916cd2Sjpk * /dev/dir/"*" 149*45916cd2Sjpk */ 150*45916cd2Sjpk if (strcmp(device, devname) == 0) { 151*45916cd2Sjpk /* /dev/xx, /dev/dir/xx */ 152*45916cd2Sjpk free(fbuf); 153*45916cd2Sjpk return (1); 154*45916cd2Sjpk } 155*45916cd2Sjpk if ((ptr = strrchr(device, KV_WILDCHAR)) != NULL) { 156*45916cd2Sjpk /* all wildcard types */ 157*45916cd2Sjpk *ptr = '\0'; 158*45916cd2Sjpk if (strncmp(device, devname, strlen(device)) == 0) { 159*45916cd2Sjpk free(fbuf); 160*45916cd2Sjpk return (1); 161*45916cd2Sjpk } 162*45916cd2Sjpk } 163*45916cd2Sjpk device = strtok_r(NULL, ":", &lasts); 164*45916cd2Sjpk } 165*45916cd2Sjpk 166*45916cd2Sjpk return (ret); 167*45916cd2Sjpk } 168*45916cd2Sjpk 169*45916cd2Sjpk /* 170*45916cd2Sjpk * _da_read_file - 171*45916cd2Sjpk * establishes readers/writer lock on fname; reads in the file if its 172*45916cd2Sjpk * contents changed since the last time we read it. 173*45916cd2Sjpk * returns size of buffer read, or -1 on failure. 174*45916cd2Sjpk */ 175*45916cd2Sjpk int 176*45916cd2Sjpk _da_read_file(char *fname, char **fbuf, time_t *ftime, rwlock_t *flock, 177*45916cd2Sjpk int flag) 178*45916cd2Sjpk { 179*45916cd2Sjpk int fd = -1; 180*45916cd2Sjpk int fsize = 0; 181*45916cd2Sjpk time_t newtime; 182*45916cd2Sjpk FILE *fp = NULL; 183*45916cd2Sjpk struct stat f_stat; 184*45916cd2Sjpk 185*45916cd2Sjpk if (flag & DA_FORCE) 186*45916cd2Sjpk *ftime = 0; 187*45916cd2Sjpk 188*45916cd2Sjpk /* check the size and the time stamp on the file */ 189*45916cd2Sjpk if (rw_rdlock(flock) != 0) 190*45916cd2Sjpk return (-1); 191*45916cd2Sjpk if (stat(fname, &f_stat) != 0) { 192*45916cd2Sjpk (void) rw_unlock(flock); 193*45916cd2Sjpk return (-1); 194*45916cd2Sjpk } 195*45916cd2Sjpk fsize = f_stat.st_size; 196*45916cd2Sjpk newtime = f_stat.st_mtime; 197*45916cd2Sjpk (void) rw_unlock(flock); 198*45916cd2Sjpk 199*45916cd2Sjpk while (newtime > *ftime) { 200*45916cd2Sjpk /* 201*45916cd2Sjpk * file has been modified since we last read it; or this 202*45916cd2Sjpk * is a forced read. 203*45916cd2Sjpk * read file into the buffer with rw lock. 204*45916cd2Sjpk */ 205*45916cd2Sjpk if (rw_wrlock(flock) != 0) 206*45916cd2Sjpk return (-1); 207*45916cd2Sjpk if ((fp = fopen(fname, "r")) == NULL) { 208*45916cd2Sjpk (void) rw_unlock(flock); 209*45916cd2Sjpk return (-1); 210*45916cd2Sjpk } 211*45916cd2Sjpk fd = fileno(fp); 212*45916cd2Sjpk if (*fbuf != NULL) { 213*45916cd2Sjpk free(*fbuf); 214*45916cd2Sjpk *fbuf = NULL; 215*45916cd2Sjpk } 216*45916cd2Sjpk if ((*fbuf = malloc(fsize)) == NULL) { 217*45916cd2Sjpk (void) rw_unlock(flock); 218*45916cd2Sjpk (void) close(fd); 219*45916cd2Sjpk return (-1); 220*45916cd2Sjpk } 221*45916cd2Sjpk if (read(fd, *fbuf, fsize) < fsize) { 222*45916cd2Sjpk free(*fbuf); 223*45916cd2Sjpk (void) rw_unlock(flock); 224*45916cd2Sjpk (void) close(fd); 225*45916cd2Sjpk return (-1); 226*45916cd2Sjpk } 227*45916cd2Sjpk (void) rw_unlock(flock); 228*45916cd2Sjpk /* 229*45916cd2Sjpk * verify that the file did not change just after we read it. 230*45916cd2Sjpk */ 231*45916cd2Sjpk if (rw_rdlock(flock) != 0) { 232*45916cd2Sjpk free(*fbuf); 233*45916cd2Sjpk (void) close(fd); 234*45916cd2Sjpk return (-1); 235*45916cd2Sjpk } 236*45916cd2Sjpk if (stat(fname, &f_stat) != 0) { 237*45916cd2Sjpk free(*fbuf); 238*45916cd2Sjpk (void) rw_unlock(flock); 239*45916cd2Sjpk (void) close(fd); 240*45916cd2Sjpk return (-1); 241*45916cd2Sjpk } 242*45916cd2Sjpk fsize = f_stat.st_size; 243*45916cd2Sjpk newtime = f_stat.st_mtime; 244*45916cd2Sjpk (void) rw_unlock(flock); 245*45916cd2Sjpk (void) close(fd); 246*45916cd2Sjpk *ftime = newtime; 247*45916cd2Sjpk } 248*45916cd2Sjpk 249*45916cd2Sjpk return (fsize); 250*45916cd2Sjpk } 251*45916cd2Sjpk 252*45916cd2Sjpk /* 253*45916cd2Sjpk * _update_zonename - 254*45916cd2Sjpk * add/remove current zone's name to the given devalloc_t. 255*45916cd2Sjpk */ 256*45916cd2Sjpk void 257*45916cd2Sjpk _update_zonename(da_args *dargs, devalloc_t *dap) 258*45916cd2Sjpk { 259*45916cd2Sjpk int i, j; 260*45916cd2Sjpk int oldsize, newsize; 261*45916cd2Sjpk int has_zonename = 0; 262*45916cd2Sjpk char *zonename; 263*45916cd2Sjpk kva_t *newkva, *oldkva; 264*45916cd2Sjpk kv_t *newdata, *olddata; 265*45916cd2Sjpk devinfo_t *devinfo; 266*45916cd2Sjpk 267*45916cd2Sjpk devinfo = dargs->devinfo; 268*45916cd2Sjpk oldkva = dap->da_devopts; 269*45916cd2Sjpk if (oldkva == NULL) { 270*45916cd2Sjpk if (dargs->optflag & DA_REMOVE_ZONE) 271*45916cd2Sjpk return; 272*45916cd2Sjpk if (dargs->optflag & DA_ADD_ZONE) { 273*45916cd2Sjpk newkva = _str2kva(devinfo->devopts, KV_ASSIGN, 274*45916cd2Sjpk KV_TOKEN_DELIMIT); 275*45916cd2Sjpk if (newkva != NULL) 276*45916cd2Sjpk dap->da_devopts = newkva; 277*45916cd2Sjpk return; 278*45916cd2Sjpk } 279*45916cd2Sjpk } 280*45916cd2Sjpk newsize = oldsize = oldkva->length; 281*45916cd2Sjpk if (kva_match(oldkva, DAOPT_ZONE)) 282*45916cd2Sjpk has_zonename = 1; 283*45916cd2Sjpk if (dargs->optflag & DA_ADD_ZONE) { 284*45916cd2Sjpk if ((zonename = index(devinfo->devopts, '=')) == NULL) 285*45916cd2Sjpk return; 286*45916cd2Sjpk zonename++; 287*45916cd2Sjpk if (has_zonename) { 288*45916cd2Sjpk (void) _insert2kva(oldkva, DAOPT_ZONE, zonename); 289*45916cd2Sjpk return; 290*45916cd2Sjpk } 291*45916cd2Sjpk newsize += 1; 292*45916cd2Sjpk } else if (dargs->optflag & DA_REMOVE_ZONE) { 293*45916cd2Sjpk if (has_zonename) { 294*45916cd2Sjpk newsize -= 1; 295*45916cd2Sjpk if (newsize == 0) { 296*45916cd2Sjpk /* 297*45916cd2Sjpk * If zone name was the only key/value pair, 298*45916cd2Sjpk * put 'reserved' in the empty slot. 299*45916cd2Sjpk */ 300*45916cd2Sjpk _kva_free(oldkva); 301*45916cd2Sjpk dap->da_devopts = NULL; 302*45916cd2Sjpk return; 303*45916cd2Sjpk } 304*45916cd2Sjpk } else { 305*45916cd2Sjpk return; 306*45916cd2Sjpk } 307*45916cd2Sjpk } 308*45916cd2Sjpk newkva = _new_kva(newsize); 309*45916cd2Sjpk newkva->length = 0; 310*45916cd2Sjpk newdata = newkva->data; 311*45916cd2Sjpk olddata = oldkva->data; 312*45916cd2Sjpk for (i = 0, j = 0; i < oldsize; i++) { 313*45916cd2Sjpk if ((dargs->optflag & DA_REMOVE_ZONE) && 314*45916cd2Sjpk (strcmp(olddata[i].key, DAOPT_ZONE) == 0)) 315*45916cd2Sjpk continue; 316*45916cd2Sjpk newdata[j].key = strdup(olddata[i].key); 317*45916cd2Sjpk newdata[j].value = strdup(olddata[i].value); 318*45916cd2Sjpk newkva->length++; 319*45916cd2Sjpk j++; 320*45916cd2Sjpk } 321*45916cd2Sjpk if (dargs->optflag & DA_ADD_ZONE) { 322*45916cd2Sjpk newdata[j].key = strdup(DAOPT_ZONE); 323*45916cd2Sjpk newdata[j].value = strdup(zonename); 324*45916cd2Sjpk newkva->length++; 325*45916cd2Sjpk } 326*45916cd2Sjpk _kva_free(oldkva); 327*45916cd2Sjpk dap->da_devopts = newkva; 328*45916cd2Sjpk } 329*45916cd2Sjpk 330*45916cd2Sjpk /* 331*45916cd2Sjpk * _dmap2str - 332*45916cd2Sjpk * converts a device_map entry into a printable string 333*45916cd2Sjpk * returns 0 on success, -1 on error. 334*45916cd2Sjpk */ 335*45916cd2Sjpk /*ARGSUSED*/ 336*45916cd2Sjpk static int 337*45916cd2Sjpk _dmap2str(da_args *dargs, devmap_t *dmp, char *buf, int size, const char *sep) 338*45916cd2Sjpk { 339*45916cd2Sjpk int length; 340*45916cd2Sjpk 341*45916cd2Sjpk length = snprintf(buf, size, "%s%s", dmp->dmap_devname, sep); 342*45916cd2Sjpk if (length >= size) 343*45916cd2Sjpk return (-1); 344*45916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 345*45916cd2Sjpk dmp->dmap_devtype, sep); 346*45916cd2Sjpk if (length >= size) 347*45916cd2Sjpk return (-1); 348*45916cd2Sjpk length += snprintf(buf + length, size - length, "%s\n", 349*45916cd2Sjpk dmp->dmap_devlist); 350*45916cd2Sjpk if (length >= size) 351*45916cd2Sjpk return (-1); 352*45916cd2Sjpk return (0); 353*45916cd2Sjpk } 354*45916cd2Sjpk 355*45916cd2Sjpk /* 356*45916cd2Sjpk * _dmap2strentry - 357*45916cd2Sjpk * calls dmap2str to break given devmap_t into printable entry. 358*45916cd2Sjpk * returns pointer to decoded entry, NULL on error. 359*45916cd2Sjpk */ 360*45916cd2Sjpk static strentry_t * 361*45916cd2Sjpk _dmap2strentry(da_args *dargs, devmap_t *devmapp) 362*45916cd2Sjpk { 363*45916cd2Sjpk strentry_t *sep; 364*45916cd2Sjpk 365*45916cd2Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 366*45916cd2Sjpk return (NULL); 367*45916cd2Sjpk if (_dmap2str(dargs, devmapp, sep->se_str, sizeof (sep->se_str), 368*45916cd2Sjpk KV_TOKEN_DELIMIT"\\\n\t") != 0) { 369*45916cd2Sjpk free(sep); 370*45916cd2Sjpk return (NULL); 371*45916cd2Sjpk } 372*45916cd2Sjpk return (sep); 373*45916cd2Sjpk } 374*45916cd2Sjpk 375*45916cd2Sjpk /* 376*45916cd2Sjpk * fix_optstr - 377*45916cd2Sjpk * removes trailing ':' from buf. 378*45916cd2Sjpk */ 379*45916cd2Sjpk void 380*45916cd2Sjpk fix_optstr(char *buf) 381*45916cd2Sjpk { 382*45916cd2Sjpk char *p = NULL; 383*45916cd2Sjpk 384*45916cd2Sjpk if (p = rindex(buf, ':')) 385*45916cd2Sjpk *p = ';'; 386*45916cd2Sjpk } 387*45916cd2Sjpk 388*45916cd2Sjpk /* 389*45916cd2Sjpk * _da2str - 390*45916cd2Sjpk * converts a device_allocate entry into a printable string 391*45916cd2Sjpk * returns 0 on success, -1 on error. 392*45916cd2Sjpk */ 393*45916cd2Sjpk static int 394*45916cd2Sjpk _da2str(da_args *dargs, devalloc_t *dap, char *buf, int size, const char *sep, 395*45916cd2Sjpk const char *osep) 396*45916cd2Sjpk { 397*45916cd2Sjpk int length; 398*45916cd2Sjpk int matching_entry = 0; 399*45916cd2Sjpk char **dnames; 400*45916cd2Sjpk 401*45916cd2Sjpk if (dargs->optflag & DA_UPDATE && 402*45916cd2Sjpk (dargs->optflag & DA_ADD_ZONE || 403*45916cd2Sjpk dargs->optflag & DA_REMOVE_ZONE) && 404*45916cd2Sjpk dargs->devnames) { 405*45916cd2Sjpk for (dnames = dargs->devnames; *dnames != NULL; dnames++) { 406*45916cd2Sjpk if (da_matchname(dap, *dnames)) { 407*45916cd2Sjpk matching_entry = 1; 408*45916cd2Sjpk break; 409*45916cd2Sjpk } 410*45916cd2Sjpk } 411*45916cd2Sjpk } 412*45916cd2Sjpk length = snprintf(buf, size, "%s%s", dap->da_devname, sep); 413*45916cd2Sjpk if (length >= size) 414*45916cd2Sjpk return (-1); 415*45916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 416*45916cd2Sjpk dap->da_devtype, sep); 417*45916cd2Sjpk if (length >= size) 418*45916cd2Sjpk return (-1); 419*45916cd2Sjpk if (matching_entry) 420*45916cd2Sjpk _update_zonename(dargs, dap); 421*45916cd2Sjpk if ((dap->da_devopts == NULL) || ((dap->da_devopts->length == 1) && 422*45916cd2Sjpk (strcmp(dap->da_devopts->data->key, DA_RESERVED) == 0))) { 423*45916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 424*45916cd2Sjpk DA_RESERVED, sep); 425*45916cd2Sjpk } else { 426*45916cd2Sjpk if (_kva2str(dap->da_devopts, buf + length, size - length, 427*45916cd2Sjpk KV_ASSIGN, (char *)osep) != 0) 428*45916cd2Sjpk return (-1); 429*45916cd2Sjpk length = strlen(buf); 430*45916cd2Sjpk } 431*45916cd2Sjpk if (dap->da_devopts) 432*45916cd2Sjpk fix_optstr(buf); 433*45916cd2Sjpk if (length >= size) 434*45916cd2Sjpk return (-1); 435*45916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 436*45916cd2Sjpk DA_RESERVED, sep); 437*45916cd2Sjpk if (length >= size) 438*45916cd2Sjpk return (-1); 439*45916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 440*45916cd2Sjpk dap->da_devauth ? dap->da_devauth : DA_ANYUSER, sep); 441*45916cd2Sjpk if (length >= size) 442*45916cd2Sjpk return (-1); 443*45916cd2Sjpk length += snprintf(buf + length, size - length, "%s\n", 444*45916cd2Sjpk dap->da_devexec ? dap->da_devexec : ""); 445*45916cd2Sjpk if (length >= size) 446*45916cd2Sjpk return (-1); 447*45916cd2Sjpk 448*45916cd2Sjpk return (0); 449*45916cd2Sjpk } 450*45916cd2Sjpk 451*45916cd2Sjpk /* 452*45916cd2Sjpk * _da2strentry - 453*45916cd2Sjpk * calls da2str to break given devalloc_t into printable entry. 454*45916cd2Sjpk * returns pointer to decoded entry, NULL on error. 455*45916cd2Sjpk */ 456*45916cd2Sjpk static strentry_t * 457*45916cd2Sjpk _da2strentry(da_args *dargs, devalloc_t *dap) 458*45916cd2Sjpk { 459*45916cd2Sjpk strentry_t *sep; 460*45916cd2Sjpk 461*45916cd2Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 462*45916cd2Sjpk return (NULL); 463*45916cd2Sjpk if (_da2str(dargs, dap, sep->se_str, sizeof (sep->se_str), 464*45916cd2Sjpk KV_DELIMITER "\\\n\t", KV_TOKEN_DELIMIT "\\\n\t") != 0) { 465*45916cd2Sjpk free(sep); 466*45916cd2Sjpk return (NULL); 467*45916cd2Sjpk } 468*45916cd2Sjpk return (sep); 469*45916cd2Sjpk } 470*45916cd2Sjpk 471*45916cd2Sjpk /* 472*45916cd2Sjpk * _def2str 473*45916cd2Sjpk * converts da_defs_t into a printable string. 474*45916cd2Sjpk * returns 0 on success, -1 on error. 475*45916cd2Sjpk */ 476*45916cd2Sjpk static int 477*45916cd2Sjpk _def2str(da_defs_t *da_defs, char *buf, int size, const char *sep) 478*45916cd2Sjpk { 479*45916cd2Sjpk int length; 480*45916cd2Sjpk 481*45916cd2Sjpk length = snprintf(buf, size, "%s%s", da_defs->devtype, sep); 482*45916cd2Sjpk if (length >= size) 483*45916cd2Sjpk return (-1); 484*45916cd2Sjpk if (da_defs->devopts) { 485*45916cd2Sjpk if (_kva2str(da_defs->devopts, buf + length, size - length, 486*45916cd2Sjpk KV_ASSIGN, KV_DELIMITER) != 0) 487*45916cd2Sjpk return (-1); 488*45916cd2Sjpk length = strlen(buf); 489*45916cd2Sjpk } 490*45916cd2Sjpk if (length >= size) 491*45916cd2Sjpk return (-1); 492*45916cd2Sjpk 493*45916cd2Sjpk return (0); 494*45916cd2Sjpk } 495*45916cd2Sjpk 496*45916cd2Sjpk /* 497*45916cd2Sjpk * _def2strentry 498*45916cd2Sjpk * calls _def2str to break given da_defs_t into printable entry. 499*45916cd2Sjpk * returns pointer decoded entry, NULL on error. 500*45916cd2Sjpk */ 501*45916cd2Sjpk static strentry_t * 502*45916cd2Sjpk _def2strentry(da_defs_t *da_defs) 503*45916cd2Sjpk { 504*45916cd2Sjpk strentry_t *sep; 505*45916cd2Sjpk 506*45916cd2Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 507*45916cd2Sjpk return (NULL); 508*45916cd2Sjpk if (_def2str(da_defs, sep->se_str, sizeof (sep->se_str), 509*45916cd2Sjpk KV_TOKEN_DELIMIT) != 0) { 510*45916cd2Sjpk free(sep); 511*45916cd2Sjpk return (NULL); 512*45916cd2Sjpk } 513*45916cd2Sjpk 514*45916cd2Sjpk return (sep); 515*45916cd2Sjpk } 516*45916cd2Sjpk 517*45916cd2Sjpk /* 518*45916cd2Sjpk * _build_defattrs 519*45916cd2Sjpk * cycles through all defattr entries, stores them in memory. removes 520*45916cd2Sjpk * entries with the given search_key (device type). 521*45916cd2Sjpk * returns 0 if given entry not found, 1 if given entry removed, 2 on 522*45916cd2Sjpk * error. 523*45916cd2Sjpk */ 524*45916cd2Sjpk static int 525*45916cd2Sjpk _build_defattrs(da_args *dargs, strentry_t **head_defent) 526*45916cd2Sjpk { 527*45916cd2Sjpk int rc = 0; 528*45916cd2Sjpk da_defs_t *da_defs; 529*45916cd2Sjpk strentry_t *tail_str, *tmp_str; 530*45916cd2Sjpk 531*45916cd2Sjpk setdadefent(); 532*45916cd2Sjpk while ((da_defs = getdadefent()) != NULL) { 533*45916cd2Sjpk rc = !(strcmp(da_defs->devtype, dargs->devinfo->devtype)); 534*45916cd2Sjpk if (rc && dargs->optflag & DA_ADD && 535*45916cd2Sjpk !(dargs->optflag & DA_FORCE)) { 536*45916cd2Sjpk /* 537*45916cd2Sjpk * During DA_ADD, we keep an existing entry unless 538*45916cd2Sjpk * we have DA_FORCE set to override that entry. 539*45916cd2Sjpk */ 540*45916cd2Sjpk dargs->optflag |= DA_NO_OVERRIDE; 541*45916cd2Sjpk rc = 0; 542*45916cd2Sjpk } 543*45916cd2Sjpk if (rc == 0) { 544*45916cd2Sjpk tmp_str = _def2strentry(da_defs); 545*45916cd2Sjpk if (tmp_str == NULL) { 546*45916cd2Sjpk freedadefent(da_defs); 547*45916cd2Sjpk enddadefent(); 548*45916cd2Sjpk return (2); 549*45916cd2Sjpk } 550*45916cd2Sjpk /* retaining defattr entry: tmp_str->se_str */ 551*45916cd2Sjpk tmp_str->se_next = NULL; 552*45916cd2Sjpk if (*head_defent == NULL) { 553*45916cd2Sjpk *head_defent = tail_str = tmp_str; 554*45916cd2Sjpk } else { 555*45916cd2Sjpk tail_str->se_next = tmp_str; 556*45916cd2Sjpk tail_str = tmp_str; 557*45916cd2Sjpk } 558*45916cd2Sjpk } 559*45916cd2Sjpk freedadefent(da_defs); 560*45916cd2Sjpk } 561*45916cd2Sjpk enddadefent(); 562*45916cd2Sjpk 563*45916cd2Sjpk return (rc); 564*45916cd2Sjpk } 565*45916cd2Sjpk 566*45916cd2Sjpk /* 567*45916cd2Sjpk * _build_lists - 568*45916cd2Sjpk * cycles through all the entries, stores them in memory. removes entries 569*45916cd2Sjpk * with the given search_key (device name or type). 570*45916cd2Sjpk * returns 0 if given entry not found, 1 if given entry removed, 2 on 571*45916cd2Sjpk * error. 572*45916cd2Sjpk */ 573*45916cd2Sjpk static int 574*45916cd2Sjpk _build_lists(da_args *dargs, strentry_t **head_devallocp, 575*45916cd2Sjpk strentry_t **head_devmapp) 576*45916cd2Sjpk { 577*45916cd2Sjpk int rc = 0; 578*45916cd2Sjpk devalloc_t *devallocp; 579*45916cd2Sjpk devmap_t *devmapp; 580*45916cd2Sjpk strentry_t *tail_str; 581*45916cd2Sjpk strentry_t *tmp_str; 582*45916cd2Sjpk 583*45916cd2Sjpk if (dargs->optflag & DA_MAPS_ONLY) 584*45916cd2Sjpk goto dmap_only; 585*45916cd2Sjpk 586*45916cd2Sjpk /* build device_allocate */ 587*45916cd2Sjpk setdaent(); 588*45916cd2Sjpk while ((devallocp = getdaent()) != NULL) { 589*45916cd2Sjpk rc = da_match(devallocp, dargs); 590*45916cd2Sjpk if (rc && dargs->optflag & DA_ADD && 591*45916cd2Sjpk !(dargs->optflag & DA_FORCE)) { 592*45916cd2Sjpk /* 593*45916cd2Sjpk * During DA_ADD, we keep an existing entry unless 594*45916cd2Sjpk * we have DA_FORCE set to override that entry. 595*45916cd2Sjpk */ 596*45916cd2Sjpk dargs->optflag |= DA_NO_OVERRIDE; 597*45916cd2Sjpk rc = 0; 598*45916cd2Sjpk } 599*45916cd2Sjpk if (rc == 0) { 600*45916cd2Sjpk tmp_str = _da2strentry(dargs, devallocp); 601*45916cd2Sjpk if (tmp_str == NULL) { 602*45916cd2Sjpk freedaent(devallocp); 603*45916cd2Sjpk enddaent(); 604*45916cd2Sjpk return (2); 605*45916cd2Sjpk } 606*45916cd2Sjpk /* retaining devalloc entry: tmp_str->se_str */ 607*45916cd2Sjpk tmp_str->se_next = NULL; 608*45916cd2Sjpk if (*head_devallocp == NULL) { 609*45916cd2Sjpk *head_devallocp = tail_str = tmp_str; 610*45916cd2Sjpk } else { 611*45916cd2Sjpk tail_str->se_next = tmp_str; 612*45916cd2Sjpk tail_str = tmp_str; 613*45916cd2Sjpk } 614*45916cd2Sjpk } 615*45916cd2Sjpk freedaent(devallocp); 616*45916cd2Sjpk } 617*45916cd2Sjpk enddaent(); 618*45916cd2Sjpk 619*45916cd2Sjpk dmap_only: 620*45916cd2Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 621*45916cd2Sjpk return (rc); 622*45916cd2Sjpk 623*45916cd2Sjpk /* build device_maps */ 624*45916cd2Sjpk rc = 0; 625*45916cd2Sjpk setdmapent(); 626*45916cd2Sjpk while ((devmapp = getdmapent()) != NULL) { 627*45916cd2Sjpk rc = dm_match(devmapp, dargs); 628*45916cd2Sjpk if (rc && dargs->optflag & DA_ADD && 629*45916cd2Sjpk !(dargs->optflag & DA_FORCE)) { 630*45916cd2Sjpk /* 631*45916cd2Sjpk * During DA_ADD, we keep an existing entry unless 632*45916cd2Sjpk * we have DA_FORCE set to override that entry. 633*45916cd2Sjpk */ 634*45916cd2Sjpk dargs->optflag |= DA_NO_OVERRIDE; 635*45916cd2Sjpk rc = 0; 636*45916cd2Sjpk } 637*45916cd2Sjpk if (rc == 0) { 638*45916cd2Sjpk tmp_str = _dmap2strentry(dargs, devmapp); 639*45916cd2Sjpk if (tmp_str == NULL) { 640*45916cd2Sjpk freedmapent(devmapp); 641*45916cd2Sjpk enddmapent(); 642*45916cd2Sjpk return (2); 643*45916cd2Sjpk } 644*45916cd2Sjpk /* retaining devmap entry: tmp_str->se_str */ 645*45916cd2Sjpk tmp_str->se_next = NULL; 646*45916cd2Sjpk if (*head_devmapp == NULL) { 647*45916cd2Sjpk *head_devmapp = tail_str = tmp_str; 648*45916cd2Sjpk } else { 649*45916cd2Sjpk tail_str->se_next = tmp_str; 650*45916cd2Sjpk tail_str = tmp_str; 651*45916cd2Sjpk } 652*45916cd2Sjpk } 653*45916cd2Sjpk freedmapent(devmapp); 654*45916cd2Sjpk } 655*45916cd2Sjpk enddmapent(); 656*45916cd2Sjpk 657*45916cd2Sjpk return (rc); 658*45916cd2Sjpk } 659*45916cd2Sjpk 660*45916cd2Sjpk /* 661*45916cd2Sjpk * _write_defattrs 662*45916cd2Sjpk * writes current entries to devalloc_defaults. 663*45916cd2Sjpk */ 664*45916cd2Sjpk static void 665*45916cd2Sjpk _write_defattrs(FILE *fp, strentry_t *head_defent) 666*45916cd2Sjpk { 667*45916cd2Sjpk strentry_t *tmp_str; 668*45916cd2Sjpk 669*45916cd2Sjpk for (tmp_str = head_defent; tmp_str != NULL; 670*45916cd2Sjpk tmp_str = tmp_str->se_next) { 671*45916cd2Sjpk (void) fputs(tmp_str->se_str, fp); 672*45916cd2Sjpk (void) fputs("\n", fp); 673*45916cd2Sjpk } 674*45916cd2Sjpk 675*45916cd2Sjpk } 676*45916cd2Sjpk 677*45916cd2Sjpk /* 678*45916cd2Sjpk * _write_device_allocate - 679*45916cd2Sjpk * writes current entries in the list to device_allocate. 680*45916cd2Sjpk */ 681*45916cd2Sjpk static void 682*45916cd2Sjpk _write_device_allocate(char *odevalloc, FILE *dafp, strentry_t *head_devallocp) 683*45916cd2Sjpk { 684*45916cd2Sjpk int is_on = -1; 685*45916cd2Sjpk strentry_t *tmp_str; 686*45916cd2Sjpk struct stat dastat; 687*45916cd2Sjpk 688*45916cd2Sjpk (void) fseek(dafp, (off_t)0, SEEK_SET); 689*45916cd2Sjpk 690*45916cd2Sjpk /* 691*45916cd2Sjpk * if the devalloc on/off string existed before, 692*45916cd2Sjpk * put it back before anything else. 693*45916cd2Sjpk * we need to check for the string only if the file 694*45916cd2Sjpk * exists. 695*45916cd2Sjpk */ 696*45916cd2Sjpk if (stat(odevalloc, &dastat) == 0) { 697*45916cd2Sjpk is_on = da_is_on(); 698*45916cd2Sjpk if (is_on == 0) 699*45916cd2Sjpk (void) fputs(DA_OFF_STR, dafp); 700*45916cd2Sjpk else if (is_on == 1) 701*45916cd2Sjpk (void) fputs(DA_ON_STR, dafp); 702*45916cd2Sjpk } 703*45916cd2Sjpk tmp_str = head_devallocp; 704*45916cd2Sjpk while (tmp_str) { 705*45916cd2Sjpk (void) fputs(tmp_str->se_str, dafp); 706*45916cd2Sjpk (void) fputs("\n", dafp); 707*45916cd2Sjpk tmp_str = tmp_str->se_next; 708*45916cd2Sjpk } 709*45916cd2Sjpk } 710*45916cd2Sjpk 711*45916cd2Sjpk /* 712*45916cd2Sjpk * _write_device_maps - 713*45916cd2Sjpk * writes current entries in the list to device_maps. 714*45916cd2Sjpk */ 715*45916cd2Sjpk static void 716*45916cd2Sjpk _write_device_maps(FILE *dmfp, strentry_t *head_devmapp) 717*45916cd2Sjpk { 718*45916cd2Sjpk strentry_t *tmp_str; 719*45916cd2Sjpk 720*45916cd2Sjpk (void) fseek(dmfp, (off_t)0, SEEK_SET); 721*45916cd2Sjpk 722*45916cd2Sjpk tmp_str = head_devmapp; 723*45916cd2Sjpk while (tmp_str) { 724*45916cd2Sjpk (void) fputs(tmp_str->se_str, dmfp); 725*45916cd2Sjpk (void) fputs("\n", dmfp); 726*45916cd2Sjpk tmp_str = tmp_str->se_next; 727*45916cd2Sjpk } 728*45916cd2Sjpk } 729*45916cd2Sjpk 730*45916cd2Sjpk /* 731*45916cd2Sjpk * _write_new_defattrs 732*45916cd2Sjpk * writes the new entry to devalloc_defaults. 733*45916cd2Sjpk * returns 0 on success, -1 on error. 734*45916cd2Sjpk */ 735*45916cd2Sjpk static int 736*45916cd2Sjpk _write_new_defattrs(FILE *fp, da_args *dargs) 737*45916cd2Sjpk { 738*45916cd2Sjpk int count; 739*45916cd2Sjpk char *tok = NULL, *tokp = NULL; 740*45916cd2Sjpk char *lasts; 741*45916cd2Sjpk devinfo_t *devinfo = dargs->devinfo; 742*45916cd2Sjpk 743*45916cd2Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 744*45916cd2Sjpk return (-1); 745*45916cd2Sjpk if (!devinfo->devopts) 746*45916cd2Sjpk return (0); 747*45916cd2Sjpk (void) fprintf(fp, "%s%s", (devinfo->devtype ? devinfo->devtype : ""), 748*45916cd2Sjpk KV_TOKEN_DELIMIT); 749*45916cd2Sjpk if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) { 750*45916cd2Sjpk (void) strcpy(tokp, devinfo->devopts); 751*45916cd2Sjpk if ((tok = strtok_r(tokp, KV_DELIMITER, &lasts)) != NULL) { 752*45916cd2Sjpk (void) fprintf(fp, "%s", tok); 753*45916cd2Sjpk count = 1; 754*45916cd2Sjpk } 755*45916cd2Sjpk while ((tok = strtok_r(NULL, KV_DELIMITER, &lasts)) != NULL) { 756*45916cd2Sjpk if (count) 757*45916cd2Sjpk (void) fprintf(fp, "%s", KV_DELIMITER); 758*45916cd2Sjpk (void) fprintf(fp, "%s", tok); 759*45916cd2Sjpk count++; 760*45916cd2Sjpk } 761*45916cd2Sjpk } else { 762*45916cd2Sjpk (void) fprintf(fp, "%s", devinfo->devopts); 763*45916cd2Sjpk } 764*45916cd2Sjpk 765*45916cd2Sjpk return (0); 766*45916cd2Sjpk } 767*45916cd2Sjpk 768*45916cd2Sjpk /* 769*45916cd2Sjpk * _write_new_entry - 770*45916cd2Sjpk * writes the new devalloc_t to device_allocate or the new devmap_t to 771*45916cd2Sjpk * device_maps. 772*45916cd2Sjpk * returns 0 on success, -1 on error. 773*45916cd2Sjpk */ 774*45916cd2Sjpk static int 775*45916cd2Sjpk _write_new_entry(FILE *fp, da_args *dargs, int flag) 776*45916cd2Sjpk { 777*45916cd2Sjpk int count; 778*45916cd2Sjpk char *tok = NULL, *tokp = NULL; 779*45916cd2Sjpk char *lasts; 780*45916cd2Sjpk devinfo_t *devinfo = dargs->devinfo; 781*45916cd2Sjpk 782*45916cd2Sjpk if (flag & DA_MAPS_ONLY) 783*45916cd2Sjpk goto dmap_only; 784*45916cd2Sjpk 785*45916cd2Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 786*45916cd2Sjpk return (-1); 787*45916cd2Sjpk 788*45916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", 789*45916cd2Sjpk (devinfo->devname ? devinfo->devname : ""), KV_DELIMITER); 790*45916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", 791*45916cd2Sjpk (devinfo->devtype ? devinfo->devtype : ""), KV_DELIMITER); 792*45916cd2Sjpk if (devinfo->devopts == NULL) { 793*45916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, 794*45916cd2Sjpk KV_DELIMITER); 795*45916cd2Sjpk } else { 796*45916cd2Sjpk if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) { 797*45916cd2Sjpk (void) strcpy(tokp, devinfo->devopts); 798*45916cd2Sjpk if ((tok = strtok_r(tokp, KV_TOKEN_DELIMIT, &lasts)) != 799*45916cd2Sjpk NULL) { 800*45916cd2Sjpk (void) fprintf(fp, "%s", tok); 801*45916cd2Sjpk count = 1; 802*45916cd2Sjpk } 803*45916cd2Sjpk while ((tok = strtok_r(NULL, KV_TOKEN_DELIMIT, 804*45916cd2Sjpk &lasts)) != NULL) { 805*45916cd2Sjpk if (count) 806*45916cd2Sjpk (void) fprintf(fp, "%s", 807*45916cd2Sjpk KV_TOKEN_DELIMIT "\\\n\t"); 808*45916cd2Sjpk (void) fprintf(fp, "%s", tok); 809*45916cd2Sjpk count++; 810*45916cd2Sjpk } 811*45916cd2Sjpk if (count) 812*45916cd2Sjpk (void) fprintf(fp, "%s", 813*45916cd2Sjpk KV_DELIMITER "\\\n\t"); 814*45916cd2Sjpk } else { 815*45916cd2Sjpk (void) fprintf(fp, "%s%s", devinfo->devopts, 816*45916cd2Sjpk KV_DELIMITER "\\\n\t"); 817*45916cd2Sjpk } 818*45916cd2Sjpk } 819*45916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, KV_DELIMITER); 820*45916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", 821*45916cd2Sjpk (devinfo->devauths ? devinfo->devauths : DA_ANYUSER), 822*45916cd2Sjpk KV_DELIMITER); 823*45916cd2Sjpk (void) fprintf(fp, "%s\n", 824*45916cd2Sjpk (devinfo->devexec ? devinfo->devexec : KV_DELIMITER)); 825*45916cd2Sjpk 826*45916cd2Sjpk dmap_only: 827*45916cd2Sjpk if (flag & DA_ALLOC_ONLY) 828*45916cd2Sjpk return (0); 829*45916cd2Sjpk 830*45916cd2Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 831*45916cd2Sjpk return (-1); 832*45916cd2Sjpk 833*45916cd2Sjpk (void) fprintf(fp, "%s%s\\\n", 834*45916cd2Sjpk (devinfo->devname ? devinfo->devname : ""), KV_TOKEN_DELIMIT); 835*45916cd2Sjpk (void) fprintf(fp, "\t%s%s\\\n", 836*45916cd2Sjpk (devinfo->devtype ? devinfo->devtype : ""), KV_TOKEN_DELIMIT); 837*45916cd2Sjpk (void) fprintf(fp, "\t%s\n", 838*45916cd2Sjpk (devinfo->devlist ? devinfo->devlist : KV_TOKEN_DELIMIT)); 839*45916cd2Sjpk 840*45916cd2Sjpk return (0); 841*45916cd2Sjpk } 842*45916cd2Sjpk 843*45916cd2Sjpk /* 844*45916cd2Sjpk * _da_lock_devdb - 845*45916cd2Sjpk * locks the database files; lock can be either broken explicitly by 846*45916cd2Sjpk * closing the fd of the lock file, or it expires automatically at process 847*45916cd2Sjpk * termination. 848*45916cd2Sjpk * returns fd of the lock file or -1 on error. 849*45916cd2Sjpk */ 850*45916cd2Sjpk int 851*45916cd2Sjpk _da_lock_devdb(char *rootdir) 852*45916cd2Sjpk { 853*45916cd2Sjpk int lockfd = -1; 854*45916cd2Sjpk char *lockfile; 855*45916cd2Sjpk char path[MAXPATHLEN]; 856*45916cd2Sjpk int size = sizeof (path); 857*45916cd2Sjpk 858*45916cd2Sjpk if (rootdir == NULL) { 859*45916cd2Sjpk lockfile = DA_DB_LOCK; 860*45916cd2Sjpk } else { 861*45916cd2Sjpk path[0] = '\0'; 862*45916cd2Sjpk if (snprintf(path, size, "%s%s", rootdir, DA_DB_LOCK) >= size) 863*45916cd2Sjpk return (-1); 864*45916cd2Sjpk lockfile = path; 865*45916cd2Sjpk } 866*45916cd2Sjpk 867*45916cd2Sjpk if ((lockfd = open(lockfile, O_RDWR | O_CREAT, 0600)) == -1) 868*45916cd2Sjpk /* cannot open lock file */ 869*45916cd2Sjpk return (-1); 870*45916cd2Sjpk 871*45916cd2Sjpk (void) fchown(lockfd, DA_UID, DA_GID); 872*45916cd2Sjpk 873*45916cd2Sjpk if (lseek(lockfd, (off_t)0, SEEK_SET) == -1) { 874*45916cd2Sjpk /* cannot position lock file */ 875*45916cd2Sjpk (void) close(lockfd); 876*45916cd2Sjpk return (-1); 877*45916cd2Sjpk } 878*45916cd2Sjpk if (lockf(lockfd, F_TLOCK, 0) == -1) { 879*45916cd2Sjpk /* cannot set lock */ 880*45916cd2Sjpk (void) close(lockfd); 881*45916cd2Sjpk return (-1); 882*45916cd2Sjpk } 883*45916cd2Sjpk (void) utime(lockfile, NULL); 884*45916cd2Sjpk 885*45916cd2Sjpk return (lockfd); 886*45916cd2Sjpk } 887*45916cd2Sjpk 888*45916cd2Sjpk /* 889*45916cd2Sjpk * da_open_devdb - 890*45916cd2Sjpk * opens one or both database files - device_allocate, device_maps - in 891*45916cd2Sjpk * the specified mode. 892*45916cd2Sjpk * locks the database files; lock is either broken explicitly by the 893*45916cd2Sjpk * caller by closing the lock file fd, or it expires automatically at 894*45916cd2Sjpk * process termination. 895*45916cd2Sjpk * writes the file pointer of opened file in the input args - dafp, dmfp. 896*45916cd2Sjpk * returns fd of the lock file on success, -2 if database file does not 897*45916cd2Sjpk * exist, -1 on other errors. 898*45916cd2Sjpk */ 899*45916cd2Sjpk int 900*45916cd2Sjpk da_open_devdb(char *rootdir, FILE **dafp, FILE **dmfp, int flag) 901*45916cd2Sjpk { 902*45916cd2Sjpk int oflag = 0; 903*45916cd2Sjpk int fda = -1; 904*45916cd2Sjpk int fdm = -1; 905*45916cd2Sjpk int lockfd = -1; 906*45916cd2Sjpk char *fname; 907*45916cd2Sjpk char *fmode; 908*45916cd2Sjpk char path[MAXPATHLEN]; 909*45916cd2Sjpk FILE *devfile; 910*45916cd2Sjpk 911*45916cd2Sjpk if ((dafp == NULL) && (dmfp == NULL)) 912*45916cd2Sjpk return (-1); 913*45916cd2Sjpk 914*45916cd2Sjpk if (flag & DA_RDWR) { 915*45916cd2Sjpk oflag = DA_RDWR; 916*45916cd2Sjpk fmode = "r+"; 917*45916cd2Sjpk } else if (flag & DA_RDONLY) { 918*45916cd2Sjpk oflag = DA_RDONLY; 919*45916cd2Sjpk fmode = "r"; 920*45916cd2Sjpk } 921*45916cd2Sjpk 922*45916cd2Sjpk if ((lockfd = _da_lock_devdb(rootdir)) == -1) 923*45916cd2Sjpk return (-1); 924*45916cd2Sjpk 925*45916cd2Sjpk if ((dafp == NULL) || (flag & DA_MAPS_ONLY)) 926*45916cd2Sjpk goto dmap_only; 927*45916cd2Sjpk 928*45916cd2Sjpk path[0] = '\0'; 929*45916cd2Sjpk 930*45916cd2Sjpk /* 931*45916cd2Sjpk * open the device allocation file 932*45916cd2Sjpk */ 933*45916cd2Sjpk if (rootdir == NULL) { 934*45916cd2Sjpk fname = DEVALLOC; 935*45916cd2Sjpk } else { 936*45916cd2Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 937*45916cd2Sjpk DEVALLOC) >= sizeof (path)) { 938*45916cd2Sjpk if (lockfd != -1) 939*45916cd2Sjpk (void) close(lockfd); 940*45916cd2Sjpk return (-1); 941*45916cd2Sjpk } 942*45916cd2Sjpk fname = path; 943*45916cd2Sjpk } 944*45916cd2Sjpk if ((fda = open(fname, oflag, DA_DBMODE)) == -1) { 945*45916cd2Sjpk if (lockfd != -1) 946*45916cd2Sjpk (void) close(lockfd); 947*45916cd2Sjpk return ((errno == ENOENT) ? -2 : -1); 948*45916cd2Sjpk } 949*45916cd2Sjpk if ((devfile = fdopen(fda, fmode)) == NULL) { 950*45916cd2Sjpk (void) close(fda); 951*45916cd2Sjpk if (lockfd != -1) 952*45916cd2Sjpk (void) close(lockfd); 953*45916cd2Sjpk return (-1); 954*45916cd2Sjpk } 955*45916cd2Sjpk *dafp = devfile; 956*45916cd2Sjpk (void) fchmod(fda, DA_DBMODE); 957*45916cd2Sjpk 958*45916cd2Sjpk if ((flag & DA_ALLOC_ONLY)) 959*45916cd2Sjpk goto out; 960*45916cd2Sjpk 961*45916cd2Sjpk dmap_only: 962*45916cd2Sjpk path[0] = '\0'; 963*45916cd2Sjpk /* 964*45916cd2Sjpk * open the device map file 965*45916cd2Sjpk */ 966*45916cd2Sjpk if (rootdir == NULL) { 967*45916cd2Sjpk fname = DEVMAP; 968*45916cd2Sjpk } else { 969*45916cd2Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 970*45916cd2Sjpk DEVMAP) >= sizeof (path)) { 971*45916cd2Sjpk (void) close(fda); 972*45916cd2Sjpk if (lockfd != -1) 973*45916cd2Sjpk (void) close(lockfd); 974*45916cd2Sjpk return (-1); 975*45916cd2Sjpk } 976*45916cd2Sjpk fname = path; 977*45916cd2Sjpk } 978*45916cd2Sjpk 979*45916cd2Sjpk if ((fdm = open(fname, oflag, DA_DBMODE)) == -1) { 980*45916cd2Sjpk if (lockfd != -1) 981*45916cd2Sjpk (void) close(lockfd); 982*45916cd2Sjpk return ((errno == ENOENT) ? -2 : -1); 983*45916cd2Sjpk } 984*45916cd2Sjpk 985*45916cd2Sjpk if ((devfile = fdopen(fdm, fmode)) == NULL) { 986*45916cd2Sjpk (void) close(fdm); 987*45916cd2Sjpk (void) close(fda); 988*45916cd2Sjpk if (lockfd != -1) 989*45916cd2Sjpk (void) close(lockfd); 990*45916cd2Sjpk return (-1); 991*45916cd2Sjpk } 992*45916cd2Sjpk *dmfp = devfile; 993*45916cd2Sjpk (void) fchmod(fdm, DA_DBMODE); 994*45916cd2Sjpk 995*45916cd2Sjpk out: 996*45916cd2Sjpk return (lockfd); 997*45916cd2Sjpk } 998*45916cd2Sjpk 999*45916cd2Sjpk /* 1000*45916cd2Sjpk * _record_on_off - 1001*45916cd2Sjpk * adds either DA_ON_STR or DA_OFF_STR to device_allocate 1002*45916cd2Sjpk * returns 0 on success, -1 on error. 1003*45916cd2Sjpk */ 1004*45916cd2Sjpk static int 1005*45916cd2Sjpk _record_on_off(da_args *dargs, FILE *tafp, FILE *dafp) 1006*45916cd2Sjpk { 1007*45916cd2Sjpk int dafd; 1008*45916cd2Sjpk int nsize; 1009*45916cd2Sjpk int nitems = 1; 1010*45916cd2Sjpk int actionlen; 1011*45916cd2Sjpk int str_found = 0; 1012*45916cd2Sjpk int len = 0, nlen = 0, plen = 0; 1013*45916cd2Sjpk char *ptr = NULL; 1014*45916cd2Sjpk char *actionstr; 1015*45916cd2Sjpk char *nbuf = NULL; 1016*45916cd2Sjpk char line[MAX_CANON]; 1017*45916cd2Sjpk struct stat dastat; 1018*45916cd2Sjpk 1019*45916cd2Sjpk if (dargs->optflag & DA_ON) 1020*45916cd2Sjpk actionstr = DA_ON_STR; 1021*45916cd2Sjpk else 1022*45916cd2Sjpk actionstr = DA_OFF_STR; 1023*45916cd2Sjpk actionlen = strlen(actionstr); 1024*45916cd2Sjpk dafd = fileno(dafp); 1025*45916cd2Sjpk if (fstat(dafd, &dastat) == -1) 1026*45916cd2Sjpk return (-1); 1027*45916cd2Sjpk 1028*45916cd2Sjpk /* check the old device_allocate for on/off string */ 1029*45916cd2Sjpk ptr = fgets(line, MAX_CANON, dafp); 1030*45916cd2Sjpk if (ptr != NULL) { 1031*45916cd2Sjpk if ((strcmp(line, DA_ON_STR) == 0) || 1032*45916cd2Sjpk (strcmp(line, DA_OFF_STR) == 0)) { 1033*45916cd2Sjpk str_found = 1; 1034*45916cd2Sjpk nsize = dastat.st_size; 1035*45916cd2Sjpk } 1036*45916cd2Sjpk } 1037*45916cd2Sjpk if (!ptr || !str_found) { 1038*45916cd2Sjpk /* 1039*45916cd2Sjpk * the file never had either the on or the off string; 1040*45916cd2Sjpk * make room for it. 1041*45916cd2Sjpk */ 1042*45916cd2Sjpk str_found = 0; 1043*45916cd2Sjpk nsize = dastat.st_size + actionlen + 1; 1044*45916cd2Sjpk } 1045*45916cd2Sjpk if ((nbuf = (char *)malloc(nsize)) == NULL) 1046*45916cd2Sjpk return (-1); 1047*45916cd2Sjpk nbuf[0] = '\0'; 1048*45916cd2Sjpk /* put the on/off string */ 1049*45916cd2Sjpk (void) strcpy(nbuf, actionstr); 1050*45916cd2Sjpk nlen = strlen(nbuf); 1051*45916cd2Sjpk plen = nlen; 1052*45916cd2Sjpk if (ptr && !str_found) { 1053*45916cd2Sjpk /* now put the first line that we read in fgets */ 1054*45916cd2Sjpk nlen = plen + strlen(line) + 1; 1055*45916cd2Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 1056*45916cd2Sjpk if (len >= nsize) { 1057*45916cd2Sjpk free(nbuf); 1058*45916cd2Sjpk return (-1); 1059*45916cd2Sjpk } 1060*45916cd2Sjpk plen += len; 1061*45916cd2Sjpk } 1062*45916cd2Sjpk 1063*45916cd2Sjpk /* now get the rest of the old file */ 1064*45916cd2Sjpk while (fgets(line, MAX_CANON, dafp) != NULL) { 1065*45916cd2Sjpk nlen = plen + strlen(line) + 1; 1066*45916cd2Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 1067*45916cd2Sjpk if (len >= nsize) { 1068*45916cd2Sjpk free(nbuf); 1069*45916cd2Sjpk return (-1); 1070*45916cd2Sjpk } 1071*45916cd2Sjpk plen += len; 1072*45916cd2Sjpk } 1073*45916cd2Sjpk len = strlen(nbuf) + 1; 1074*45916cd2Sjpk if (len < nsize) 1075*45916cd2Sjpk nbuf[len] = '\n'; 1076*45916cd2Sjpk 1077*45916cd2Sjpk /* write the on/off str + the old device_allocate to the temp file */ 1078*45916cd2Sjpk if (fwrite(nbuf, nsize, nitems, tafp) < nitems) { 1079*45916cd2Sjpk free(nbuf); 1080*45916cd2Sjpk return (-1); 1081*45916cd2Sjpk } 1082*45916cd2Sjpk 1083*45916cd2Sjpk free(nbuf); 1084*45916cd2Sjpk 1085*45916cd2Sjpk return (0); 1086*45916cd2Sjpk } 1087*45916cd2Sjpk 1088*45916cd2Sjpk /* 1089*45916cd2Sjpk * da_update_defattrs - 1090*45916cd2Sjpk * writes default attributes to devalloc_defaults 1091*45916cd2Sjpk * returns 0 on success, -1 on error. 1092*45916cd2Sjpk */ 1093*45916cd2Sjpk int 1094*45916cd2Sjpk da_update_defattrs(da_args *dargs) 1095*45916cd2Sjpk { 1096*45916cd2Sjpk int rc = 0, lockfd = 0, tmpfd = 0; 1097*45916cd2Sjpk char *defpath = DEFATTRS; 1098*45916cd2Sjpk char *tmpdefpath = TMPATTRS; 1099*45916cd2Sjpk FILE *tmpfp = NULL; 1100*45916cd2Sjpk struct stat dstat; 1101*45916cd2Sjpk strentry_t *head_defent = NULL; 1102*45916cd2Sjpk 1103*45916cd2Sjpk if (dargs == NULL) 1104*45916cd2Sjpk return (0); 1105*45916cd2Sjpk if ((lockfd = _da_lock_devdb(NULL)) == -1) 1106*45916cd2Sjpk return (-1); 1107*45916cd2Sjpk if ((tmpfd = open(tmpdefpath, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 1108*45916cd2Sjpk (void) close(lockfd); 1109*45916cd2Sjpk return (-1); 1110*45916cd2Sjpk } 1111*45916cd2Sjpk (void) fchown(tmpfd, DA_UID, DA_GID); 1112*45916cd2Sjpk if ((tmpfp = fdopen(tmpfd, "r+")) == NULL) { 1113*45916cd2Sjpk (void) close(tmpfd); 1114*45916cd2Sjpk (void) unlink(tmpdefpath); 1115*45916cd2Sjpk (void) close(lockfd); 1116*45916cd2Sjpk return (-1); 1117*45916cd2Sjpk } 1118*45916cd2Sjpk /* 1119*45916cd2Sjpk * examine all entries, remove an old one if required, check 1120*45916cd2Sjpk * if a new one needs to be added. 1121*45916cd2Sjpk */ 1122*45916cd2Sjpk if (stat(defpath, &dstat) == 0) { 1123*45916cd2Sjpk if ((rc = _build_defattrs(dargs, &head_defent)) != 0) { 1124*45916cd2Sjpk if (rc == 1) { 1125*45916cd2Sjpk (void) close(tmpfd); 1126*45916cd2Sjpk (void) unlink(tmpdefpath); 1127*45916cd2Sjpk (void) close(lockfd); 1128*45916cd2Sjpk return (rc); 1129*45916cd2Sjpk } 1130*45916cd2Sjpk } 1131*45916cd2Sjpk } 1132*45916cd2Sjpk /* 1133*45916cd2Sjpk * write back any existing entries. 1134*45916cd2Sjpk */ 1135*45916cd2Sjpk _write_defattrs(tmpfp, head_defent); 1136*45916cd2Sjpk 1137*45916cd2Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 1138*45916cd2Sjpk /* add new entries */ 1139*45916cd2Sjpk rc = _write_new_defattrs(tmpfp, dargs); 1140*45916cd2Sjpk (void) fclose(tmpfp); 1141*45916cd2Sjpk } else { 1142*45916cd2Sjpk (void) fclose(tmpfp); 1143*45916cd2Sjpk } 1144*45916cd2Sjpk if (rename(tmpdefpath, defpath) != 0) { 1145*45916cd2Sjpk rc = -1; 1146*45916cd2Sjpk (void) unlink(tmpdefpath); 1147*45916cd2Sjpk } 1148*45916cd2Sjpk (void) close(lockfd); 1149*45916cd2Sjpk 1150*45916cd2Sjpk return (rc); 1151*45916cd2Sjpk } 1152*45916cd2Sjpk 1153*45916cd2Sjpk /* 1154*45916cd2Sjpk * da_update_device - 1155*45916cd2Sjpk * writes devices entries to device_allocate and device_maps. 1156*45916cd2Sjpk * returns 0 on success, -1 on error. 1157*45916cd2Sjpk */ 1158*45916cd2Sjpk int 1159*45916cd2Sjpk da_update_device(da_args *dargs) 1160*45916cd2Sjpk { 1161*45916cd2Sjpk int rc; 1162*45916cd2Sjpk int tafd = -1, tmfd = -1; 1163*45916cd2Sjpk int lockfd = -1; 1164*45916cd2Sjpk char *rootdir = NULL; 1165*45916cd2Sjpk char *apathp = NULL, *mpathp = NULL, *dapathp = NULL, 1166*45916cd2Sjpk *dmpathp = NULL; 1167*45916cd2Sjpk char apath[MAXPATHLEN], mpath[MAXPATHLEN], 1168*45916cd2Sjpk dapath[MAXPATHLEN], dmpath[MAXPATHLEN]; 1169*45916cd2Sjpk FILE *tafp = NULL, *tmfp = NULL, *dafp = NULL; 1170*45916cd2Sjpk struct stat dastat; 1171*45916cd2Sjpk devinfo_t *devinfo; 1172*45916cd2Sjpk strentry_t *head_devmapp = NULL; 1173*45916cd2Sjpk strentry_t *head_devallocp = NULL; 1174*45916cd2Sjpk 1175*45916cd2Sjpk if (dargs == NULL) 1176*45916cd2Sjpk return (0); 1177*45916cd2Sjpk 1178*45916cd2Sjpk rootdir = dargs->rootdir; 1179*45916cd2Sjpk devinfo = dargs->devinfo; 1180*45916cd2Sjpk 1181*45916cd2Sjpk /* 1182*45916cd2Sjpk * adding/removing entries should be done in both 1183*45916cd2Sjpk * device_allocate and device_maps. updates can be 1184*45916cd2Sjpk * done in both or either of the files. 1185*45916cd2Sjpk */ 1186*45916cd2Sjpk if (dargs->optflag & DA_ADD || dargs->optflag & DA_REMOVE) { 1187*45916cd2Sjpk if (dargs->optflag & DA_ALLOC_ONLY || 1188*45916cd2Sjpk dargs->optflag & DA_MAPS_ONLY) 1189*45916cd2Sjpk return (0); 1190*45916cd2Sjpk } 1191*45916cd2Sjpk 1192*45916cd2Sjpk /* 1193*45916cd2Sjpk * name, type and list are required fields for adding a new 1194*45916cd2Sjpk * device. 1195*45916cd2Sjpk */ 1196*45916cd2Sjpk if ((dargs->optflag & DA_ADD) && 1197*45916cd2Sjpk ((devinfo->devname == NULL) || 1198*45916cd2Sjpk (devinfo->devtype == NULL) || 1199*45916cd2Sjpk (devinfo->devlist == NULL))) { 1200*45916cd2Sjpk return (-1); 1201*45916cd2Sjpk } 1202*45916cd2Sjpk 1203*45916cd2Sjpk if (rootdir != NULL) { 1204*45916cd2Sjpk if (snprintf(apath, sizeof (apath), "%s%s", rootdir, 1205*45916cd2Sjpk TMPALLOC) >= sizeof (apath)) 1206*45916cd2Sjpk return (-1); 1207*45916cd2Sjpk apathp = apath; 1208*45916cd2Sjpk if (snprintf(dapath, sizeof (dapath), "%s%s", rootdir, 1209*45916cd2Sjpk DEVALLOC) >= sizeof (dapath)) 1210*45916cd2Sjpk return (-1); 1211*45916cd2Sjpk dapathp = dapath; 1212*45916cd2Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 1213*45916cd2Sjpk if (snprintf(mpath, sizeof (mpath), "%s%s", rootdir, 1214*45916cd2Sjpk TMPMAP) >= sizeof (mpath)) 1215*45916cd2Sjpk return (-1); 1216*45916cd2Sjpk mpathp = mpath; 1217*45916cd2Sjpk if (snprintf(dmpath, sizeof (dmpath), "%s%s", rootdir, 1218*45916cd2Sjpk DEVMAP) >= sizeof (dmpath)) 1219*45916cd2Sjpk return (-1); 1220*45916cd2Sjpk dmpathp = dmpath; 1221*45916cd2Sjpk } 1222*45916cd2Sjpk } else { 1223*45916cd2Sjpk apathp = TMPALLOC; 1224*45916cd2Sjpk dapathp = DEVALLOC; 1225*45916cd2Sjpk mpathp = TMPMAP; 1226*45916cd2Sjpk dmpathp = DEVMAP; 1227*45916cd2Sjpk } 1228*45916cd2Sjpk 1229*45916cd2Sjpk if (dargs->optflag & DA_MAPS_ONLY) 1230*45916cd2Sjpk goto dmap_only; 1231*45916cd2Sjpk 1232*45916cd2Sjpk /* 1233*45916cd2Sjpk * Check if we are here just to record on/off status of 1234*45916cd2Sjpk * device_allocation. 1235*45916cd2Sjpk */ 1236*45916cd2Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) 1237*45916cd2Sjpk lockfd = da_open_devdb(dargs->rootdir, &dafp, NULL, 1238*45916cd2Sjpk DA_RDONLY|DA_ALLOC_ONLY); 1239*45916cd2Sjpk else 1240*45916cd2Sjpk lockfd = _da_lock_devdb(rootdir); 1241*45916cd2Sjpk if (lockfd == -1) 1242*45916cd2Sjpk return (-1); 1243*45916cd2Sjpk 1244*45916cd2Sjpk if ((tafd = open(apathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 1245*45916cd2Sjpk (void) close(lockfd); 1246*45916cd2Sjpk (void) fclose(dafp); 1247*45916cd2Sjpk return (-1); 1248*45916cd2Sjpk } 1249*45916cd2Sjpk (void) fchown(tafd, DA_UID, DA_GID); 1250*45916cd2Sjpk if ((tafp = fdopen(tafd, "r+")) == NULL) { 1251*45916cd2Sjpk (void) close(tafd); 1252*45916cd2Sjpk (void) unlink(apathp); 1253*45916cd2Sjpk (void) fclose(dafp); 1254*45916cd2Sjpk (void) close(lockfd); 1255*45916cd2Sjpk return (-1); 1256*45916cd2Sjpk } 1257*45916cd2Sjpk 1258*45916cd2Sjpk /* 1259*45916cd2Sjpk * We don't need to parse the file if we are here just to record 1260*45916cd2Sjpk * on/off status of device_allocation. 1261*45916cd2Sjpk */ 1262*45916cd2Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) { 1263*45916cd2Sjpk if (_record_on_off(dargs, tafp, dafp) == -1) { 1264*45916cd2Sjpk (void) close(tafd); 1265*45916cd2Sjpk (void) unlink(apathp); 1266*45916cd2Sjpk (void) fclose(dafp); 1267*45916cd2Sjpk (void) close(lockfd); 1268*45916cd2Sjpk return (-1); 1269*45916cd2Sjpk } 1270*45916cd2Sjpk (void) fclose(dafp); 1271*45916cd2Sjpk goto out; 1272*45916cd2Sjpk } 1273*45916cd2Sjpk 1274*45916cd2Sjpk /* 1275*45916cd2Sjpk * examine all the entries, remove an old one if forced to, 1276*45916cd2Sjpk * and check that they are suitable for updating. 1277*45916cd2Sjpk * we need to do this only if the file exists already. 1278*45916cd2Sjpk */ 1279*45916cd2Sjpk if (stat(dapathp, &dastat) == 0) { 1280*45916cd2Sjpk if ((rc = _build_lists(dargs, &head_devallocp, 1281*45916cd2Sjpk &head_devmapp)) != 0) { 1282*45916cd2Sjpk if (rc != 1) { 1283*45916cd2Sjpk (void) close(tafd); 1284*45916cd2Sjpk (void) unlink(apathp); 1285*45916cd2Sjpk (void) close(lockfd); 1286*45916cd2Sjpk return (rc); 1287*45916cd2Sjpk } 1288*45916cd2Sjpk } 1289*45916cd2Sjpk } 1290*45916cd2Sjpk 1291*45916cd2Sjpk /* 1292*45916cd2Sjpk * write back any existing devalloc entries, along with 1293*45916cd2Sjpk * the devalloc on/off string. 1294*45916cd2Sjpk */ 1295*45916cd2Sjpk _write_device_allocate(dapathp, tafp, head_devallocp); 1296*45916cd2Sjpk 1297*45916cd2Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 1298*45916cd2Sjpk goto out; 1299*45916cd2Sjpk 1300*45916cd2Sjpk dmap_only: 1301*45916cd2Sjpk if ((tmfd = open(mpathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 1302*45916cd2Sjpk (void) close(tafd); 1303*45916cd2Sjpk (void) unlink(apathp); 1304*45916cd2Sjpk (void) close(lockfd); 1305*45916cd2Sjpk return (-1); 1306*45916cd2Sjpk } 1307*45916cd2Sjpk (void) fchown(tmfd, DA_UID, DA_GID); 1308*45916cd2Sjpk if ((tmfp = fdopen(tmfd, "r+")) == NULL) { 1309*45916cd2Sjpk (void) close(tafd); 1310*45916cd2Sjpk (void) unlink(apathp); 1311*45916cd2Sjpk (void) close(tmfd); 1312*45916cd2Sjpk (void) unlink(mpathp); 1313*45916cd2Sjpk (void) close(lockfd); 1314*45916cd2Sjpk return (-1); 1315*45916cd2Sjpk } 1316*45916cd2Sjpk 1317*45916cd2Sjpk /* write back any existing devmap entries */ 1318*45916cd2Sjpk if (head_devmapp != NULL) 1319*45916cd2Sjpk _write_device_maps(tmfp, head_devmapp); 1320*45916cd2Sjpk 1321*45916cd2Sjpk out: 1322*45916cd2Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 1323*45916cd2Sjpk /* add any new entries */ 1324*45916cd2Sjpk rc = _write_new_entry(tafp, dargs, DA_ALLOC_ONLY); 1325*45916cd2Sjpk (void) fclose(tafp); 1326*45916cd2Sjpk 1327*45916cd2Sjpk if (rc == 0) 1328*45916cd2Sjpk rc = _write_new_entry(tmfp, dargs, DA_MAPS_ONLY); 1329*45916cd2Sjpk (void) fclose(tmfp); 1330*45916cd2Sjpk } else { 1331*45916cd2Sjpk if (tafp) 1332*45916cd2Sjpk (void) fclose(tafp); 1333*45916cd2Sjpk if (tmfp) 1334*45916cd2Sjpk (void) fclose(tmfp); 1335*45916cd2Sjpk } 1336*45916cd2Sjpk 1337*45916cd2Sjpk rc = 0; 1338*45916cd2Sjpk if (!(dargs->optflag & DA_MAPS_ONLY)) { 1339*45916cd2Sjpk if (rename(apathp, dapathp) != 0) { 1340*45916cd2Sjpk rc = -1; 1341*45916cd2Sjpk (void) unlink(apathp); 1342*45916cd2Sjpk } 1343*45916cd2Sjpk } 1344*45916cd2Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 1345*45916cd2Sjpk if (rename(mpathp, dmpathp) != 0) { 1346*45916cd2Sjpk rc = -1; 1347*45916cd2Sjpk (void) unlink(mpathp); 1348*45916cd2Sjpk } 1349*45916cd2Sjpk } 1350*45916cd2Sjpk 1351*45916cd2Sjpk (void) close(lockfd); 1352*45916cd2Sjpk 1353*45916cd2Sjpk return (rc); 1354*45916cd2Sjpk } 1355*45916cd2Sjpk 1356*45916cd2Sjpk /* 1357*45916cd2Sjpk * da_add_list - 1358*45916cd2Sjpk * adds new /dev link name to the linked list of devices. 1359*45916cd2Sjpk * returns 0 if link added successfully, -1 on error. 1360*45916cd2Sjpk */ 1361*45916cd2Sjpk int 1362*45916cd2Sjpk da_add_list(devlist_t *dlist, char *link, int new_instance, int flag) 1363*45916cd2Sjpk { 1364*45916cd2Sjpk int instance; 1365*45916cd2Sjpk int nlen, plen; 1366*45916cd2Sjpk int new_entry = 0; 1367*45916cd2Sjpk char *dtype, *dexec, *tname, *kval; 1368*45916cd2Sjpk char *minstr = NULL, *maxstr = NULL; 1369*45916cd2Sjpk char dname[DA_MAXNAME]; 1370*45916cd2Sjpk kva_t *kva; 1371*45916cd2Sjpk deventry_t *dentry = NULL, *nentry = NULL, *pentry = NULL; 1372*45916cd2Sjpk da_defs_t *da_defs; 1373*45916cd2Sjpk 1374*45916cd2Sjpk if (dlist == NULL || link == NULL) 1375*45916cd2Sjpk return (-1); 1376*45916cd2Sjpk 1377*45916cd2Sjpk dname[0] = '\0'; 1378*45916cd2Sjpk if (flag & DA_AUDIO) { 1379*45916cd2Sjpk dentry = dlist->audio; 1380*45916cd2Sjpk tname = DA_AUDIO_NAME; 1381*45916cd2Sjpk dtype = DA_AUDIO_TYPE; 1382*45916cd2Sjpk dexec = DA_DEFAULT_AUDIO_CLEAN; 1383*45916cd2Sjpk } else if (flag & DA_CD) { 1384*45916cd2Sjpk dentry = dlist->cd; 1385*45916cd2Sjpk tname = DA_CD_NAME; 1386*45916cd2Sjpk dtype = DA_CD_TYPE; 1387*45916cd2Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 1388*45916cd2Sjpk } else if (flag & DA_FLOPPY) { 1389*45916cd2Sjpk dentry = dlist->floppy; 1390*45916cd2Sjpk tname = DA_FLOPPY_NAME; 1391*45916cd2Sjpk dtype = DA_FLOPPY_TYPE; 1392*45916cd2Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 1393*45916cd2Sjpk } else if (flag & DA_TAPE) { 1394*45916cd2Sjpk dentry = dlist->tape; 1395*45916cd2Sjpk tname = DA_TAPE_NAME; 1396*45916cd2Sjpk dtype = DA_TAPE_TYPE; 1397*45916cd2Sjpk dexec = DA_DEFAULT_TAPE_CLEAN; 1398*45916cd2Sjpk } else if (flag & DA_RMDISK) { 1399*45916cd2Sjpk dentry = dlist->rmdisk; 1400*45916cd2Sjpk tname = DA_RMDISK_NAME; 1401*45916cd2Sjpk dtype = DA_RMDISK_TYPE; 1402*45916cd2Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 1403*45916cd2Sjpk } else { 1404*45916cd2Sjpk return (-1); 1405*45916cd2Sjpk } 1406*45916cd2Sjpk 1407*45916cd2Sjpk for (nentry = dentry; nentry != NULL; nentry = nentry->next) { 1408*45916cd2Sjpk pentry = nentry; 1409*45916cd2Sjpk (void) sscanf(nentry->devinfo.devname, "%*[a-z]%d", &instance); 1410*45916cd2Sjpk if (nentry->devinfo.instance == new_instance) 1411*45916cd2Sjpk /* 1412*45916cd2Sjpk * Add the new link name to the list of links 1413*45916cd2Sjpk * that the device 'dname' has. 1414*45916cd2Sjpk */ 1415*45916cd2Sjpk break; 1416*45916cd2Sjpk } 1417*45916cd2Sjpk 1418*45916cd2Sjpk if (nentry == NULL) { 1419*45916cd2Sjpk /* 1420*45916cd2Sjpk * Either this is the first entry ever, or no matching entry 1421*45916cd2Sjpk * was found. Create a new one and add to the list. 1422*45916cd2Sjpk */ 1423*45916cd2Sjpk if (dentry == NULL) /* first entry ever */ 1424*45916cd2Sjpk instance = 0; 1425*45916cd2Sjpk else /* no matching entry */ 1426*45916cd2Sjpk instance++; 1427*45916cd2Sjpk (void) snprintf(dname, sizeof (dname), "%s%d", tname, instance); 1428*45916cd2Sjpk if ((nentry = (deventry_t *)malloc(sizeof (deventry_t))) == 1429*45916cd2Sjpk NULL) 1430*45916cd2Sjpk return (-1); 1431*45916cd2Sjpk if (pentry != NULL) 1432*45916cd2Sjpk pentry->next = nentry; 1433*45916cd2Sjpk new_entry = 1; 1434*45916cd2Sjpk nentry->devinfo.devname = strdup(dname); 1435*45916cd2Sjpk nentry->devinfo.devtype = dtype; 1436*45916cd2Sjpk nentry->devinfo.devauths = DEFAULT_DEV_ALLOC_AUTH; 1437*45916cd2Sjpk nentry->devinfo.devexec = dexec; 1438*45916cd2Sjpk nentry->devinfo.instance = new_instance; 1439*45916cd2Sjpk /* 1440*45916cd2Sjpk * Look for default label range, authorizations and cleaning 1441*45916cd2Sjpk * program in devalloc_defaults. If label range is not 1442*45916cd2Sjpk * specified in devalloc_defaults, assume it to be admin_low 1443*45916cd2Sjpk * to admin_high. 1444*45916cd2Sjpk */ 1445*45916cd2Sjpk minstr = DA_DEFAULT_MIN; 1446*45916cd2Sjpk maxstr = DA_DEFAULT_MAX; 1447*45916cd2Sjpk setdadefent(); 1448*45916cd2Sjpk if (da_defs = getdadeftype(nentry->devinfo.devtype)) { 1449*45916cd2Sjpk kva = da_defs->devopts; 1450*45916cd2Sjpk if ((kval = kva_match(kva, DAOPT_MINLABEL)) != NULL) 1451*45916cd2Sjpk minstr = strdup(kval); 1452*45916cd2Sjpk if ((kval = kva_match(kva, DAOPT_MAXLABEL)) != NULL) 1453*45916cd2Sjpk maxstr = strdup(kval); 1454*45916cd2Sjpk if ((kval = kva_match(kva, DAOPT_AUTHS)) != NULL) 1455*45916cd2Sjpk nentry->devinfo.devauths = strdup(kval); 1456*45916cd2Sjpk if ((kval = kva_match(kva, DAOPT_CSCRIPT)) != NULL) 1457*45916cd2Sjpk nentry->devinfo.devexec = strdup(kval); 1458*45916cd2Sjpk freedadefent(da_defs); 1459*45916cd2Sjpk } 1460*45916cd2Sjpk enddadefent(); 1461*45916cd2Sjpk kval = NULL; 1462*45916cd2Sjpk nlen = strlen(DAOPT_MINLABEL) + strlen(KV_ASSIGN) + 1463*45916cd2Sjpk strlen(minstr) + strlen(KV_TOKEN_DELIMIT) + 1464*45916cd2Sjpk strlen(DAOPT_MAXLABEL) + strlen(KV_ASSIGN) + strlen(maxstr) 1465*45916cd2Sjpk + 1; /* +1 for terminator */ 1466*45916cd2Sjpk if (kval = (char *)malloc(nlen)) 1467*45916cd2Sjpk (void) snprintf(kval, nlen, "%s%s%s%s%s%s%s", 1468*45916cd2Sjpk DAOPT_MINLABEL, KV_ASSIGN, minstr, KV_TOKEN_DELIMIT, 1469*45916cd2Sjpk DAOPT_MAXLABEL, KV_ASSIGN, maxstr); 1470*45916cd2Sjpk nentry->devinfo.devopts = kval; 1471*45916cd2Sjpk 1472*45916cd2Sjpk nentry->devinfo.devlist = NULL; 1473*45916cd2Sjpk nentry->next = NULL; 1474*45916cd2Sjpk } 1475*45916cd2Sjpk 1476*45916cd2Sjpk nlen = strlen(link) + 1; /* +1 terminator */ 1477*45916cd2Sjpk if (nentry->devinfo.devlist) { 1478*45916cd2Sjpk plen = strlen(nentry->devinfo.devlist); 1479*45916cd2Sjpk nlen = nlen + plen + 1; /* +1 for blank to separate entries */ 1480*45916cd2Sjpk } else { 1481*45916cd2Sjpk plen = 0; 1482*45916cd2Sjpk } 1483*45916cd2Sjpk 1484*45916cd2Sjpk if ((nentry->devinfo.devlist = 1485*45916cd2Sjpk (char *)realloc(nentry->devinfo.devlist, nlen)) == NULL) { 1486*45916cd2Sjpk if (new_entry) { 1487*45916cd2Sjpk nentry->devinfo.devname = NULL; 1488*45916cd2Sjpk free(nentry->devinfo.devname); 1489*45916cd2Sjpk nentry = NULL; 1490*45916cd2Sjpk free(nentry); 1491*45916cd2Sjpk if (pentry != NULL) 1492*45916cd2Sjpk pentry->next = NULL; 1493*45916cd2Sjpk } 1494*45916cd2Sjpk return (-1); 1495*45916cd2Sjpk } 1496*45916cd2Sjpk 1497*45916cd2Sjpk if (plen == 0) 1498*45916cd2Sjpk (void) snprintf(nentry->devinfo.devlist, nlen, "%s", link); 1499*45916cd2Sjpk else 1500*45916cd2Sjpk (void) snprintf(nentry->devinfo.devlist + plen, nlen - plen, 1501*45916cd2Sjpk " %s", link); 1502*45916cd2Sjpk 1503*45916cd2Sjpk if (pentry == NULL) { 1504*45916cd2Sjpk /* 1505*45916cd2Sjpk * This is the first entry of this device type. 1506*45916cd2Sjpk */ 1507*45916cd2Sjpk if (flag & DA_AUDIO) 1508*45916cd2Sjpk dlist->audio = nentry; 1509*45916cd2Sjpk else if (flag & DA_CD) 1510*45916cd2Sjpk dlist->cd = nentry; 1511*45916cd2Sjpk else if (flag & DA_FLOPPY) 1512*45916cd2Sjpk dlist->floppy = nentry; 1513*45916cd2Sjpk else if (flag & DA_TAPE) 1514*45916cd2Sjpk dlist->tape = nentry; 1515*45916cd2Sjpk else if (flag & DA_RMDISK) 1516*45916cd2Sjpk dlist->rmdisk = nentry; 1517*45916cd2Sjpk } 1518*45916cd2Sjpk 1519*45916cd2Sjpk return (0); 1520*45916cd2Sjpk } 1521*45916cd2Sjpk 1522*45916cd2Sjpk /* 1523*45916cd2Sjpk * da_remove_list - 1524*45916cd2Sjpk * removes a /dev link name from the linked list of devices. 1525*45916cd2Sjpk * returns type of device if link for that device removed 1526*45916cd2Sjpk * successfully, else returns -1 on error. 1527*45916cd2Sjpk * if all links for a device are removed, stores that device 1528*45916cd2Sjpk * name in devname. 1529*45916cd2Sjpk */ 1530*45916cd2Sjpk int 1531*45916cd2Sjpk da_remove_list(devlist_t *dlist, char *link, int type, char *devname, int size) 1532*45916cd2Sjpk { 1533*45916cd2Sjpk int flag; 1534*45916cd2Sjpk int remove_dev = 0; 1535*45916cd2Sjpk int nlen, plen, slen; 1536*45916cd2Sjpk char *lasts, *lname, *oldlist; 1537*45916cd2Sjpk struct stat rmstat; 1538*45916cd2Sjpk deventry_t *dentry, *current, *prev; 1539*45916cd2Sjpk 1540*45916cd2Sjpk if (type != NULL) 1541*45916cd2Sjpk flag = type; 1542*45916cd2Sjpk else if (link == NULL) 1543*45916cd2Sjpk return (-1); 1544*45916cd2Sjpk else if (strstr(link, DA_AUDIO_NAME) || strstr(link, DA_SOUND_NAME)) 1545*45916cd2Sjpk flag = DA_AUDIO; 1546*45916cd2Sjpk else if (strstr(link, "dsk") || strstr(link, "rdsk") || 1547*45916cd2Sjpk strstr(link, "sr") || strstr(link, "rsr")) 1548*45916cd2Sjpk flag = DA_CD; 1549*45916cd2Sjpk else if (strstr(link, "fd") || strstr(link, "rfd") || 1550*45916cd2Sjpk strstr(link, "diskette") || strstr(link, "rdiskette")) 1551*45916cd2Sjpk flag = DA_FLOPPY; 1552*45916cd2Sjpk else if (strstr(link, DA_TAPE_NAME)) 1553*45916cd2Sjpk flag = DA_TAPE; 1554*45916cd2Sjpk else 1555*45916cd2Sjpk flag = DA_RMDISK; 1556*45916cd2Sjpk 1557*45916cd2Sjpk switch (type) { 1558*45916cd2Sjpk case DA_AUDIO: 1559*45916cd2Sjpk dentry = dlist->audio; 1560*45916cd2Sjpk break; 1561*45916cd2Sjpk case DA_CD: 1562*45916cd2Sjpk dentry = dlist->cd; 1563*45916cd2Sjpk break; 1564*45916cd2Sjpk case DA_FLOPPY: 1565*45916cd2Sjpk dentry = dlist->floppy; 1566*45916cd2Sjpk break; 1567*45916cd2Sjpk case DA_TAPE: 1568*45916cd2Sjpk dentry = dlist->tape; 1569*45916cd2Sjpk break; 1570*45916cd2Sjpk case DA_RMDISK: 1571*45916cd2Sjpk dentry = dlist->rmdisk; 1572*45916cd2Sjpk break; 1573*45916cd2Sjpk default: 1574*45916cd2Sjpk return (-1); 1575*45916cd2Sjpk } 1576*45916cd2Sjpk 1577*45916cd2Sjpk if ((type != NULL) && (link == NULL)) { 1578*45916cd2Sjpk for (current = dentry, prev = dentry; current != NULL; 1579*45916cd2Sjpk current = current->next) { 1580*45916cd2Sjpk oldlist = strdup(current->devinfo.devlist); 1581*45916cd2Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 1582*45916cd2Sjpk lname != NULL; 1583*45916cd2Sjpk lname = strtok_r(NULL, " ", &lasts)) { 1584*45916cd2Sjpk if (stat(lname, &rmstat) != 0) { 1585*45916cd2Sjpk remove_dev = 1; 1586*45916cd2Sjpk goto remove_dev; 1587*45916cd2Sjpk } 1588*45916cd2Sjpk } 1589*45916cd2Sjpk prev = current; 1590*45916cd2Sjpk } 1591*45916cd2Sjpk return (-1); 1592*45916cd2Sjpk } 1593*45916cd2Sjpk 1594*45916cd2Sjpk for (current = dentry, prev = dentry; current != NULL; 1595*45916cd2Sjpk current = current->next) { 1596*45916cd2Sjpk plen = strlen(current->devinfo.devlist); 1597*45916cd2Sjpk nlen = strlen(link); 1598*45916cd2Sjpk if (plen == nlen) { 1599*45916cd2Sjpk if (strcmp(current->devinfo.devlist, link) == 0) { 1600*45916cd2Sjpk /* last name in the list */ 1601*45916cd2Sjpk remove_dev = 1; 1602*45916cd2Sjpk break; 1603*45916cd2Sjpk } 1604*45916cd2Sjpk } 1605*45916cd2Sjpk if (strstr(current->devinfo.devlist, link)) { 1606*45916cd2Sjpk nlen = plen - nlen + 1; 1607*45916cd2Sjpk oldlist = strdup(current->devinfo.devlist); 1608*45916cd2Sjpk if ((current->devinfo.devlist = 1609*45916cd2Sjpk (char *)realloc(current->devinfo.devlist, 1610*45916cd2Sjpk nlen)) == NULL) { 1611*45916cd2Sjpk free(oldlist); 1612*45916cd2Sjpk return (-1); 1613*45916cd2Sjpk } 1614*45916cd2Sjpk current->devinfo.devlist[0] = '\0'; 1615*45916cd2Sjpk nlen = plen = slen = 0; 1616*45916cd2Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 1617*45916cd2Sjpk lname != NULL; 1618*45916cd2Sjpk lname = strtok_r(NULL, " ", &lasts)) { 1619*45916cd2Sjpk if (strcmp(lname, link) == 0) 1620*45916cd2Sjpk continue; 1621*45916cd2Sjpk nlen = strlen(lname) + plen + 1; 1622*45916cd2Sjpk if (plen == 0) { 1623*45916cd2Sjpk slen = 1624*45916cd2Sjpk snprintf(current->devinfo.devlist, 1625*45916cd2Sjpk nlen, "%s", lname); 1626*45916cd2Sjpk } else { 1627*45916cd2Sjpk slen = 1628*45916cd2Sjpk snprintf(current->devinfo.devlist + 1629*45916cd2Sjpk plen, nlen - plen, " %s", 1630*45916cd2Sjpk lname); 1631*45916cd2Sjpk } 1632*45916cd2Sjpk plen = plen + slen + 1; 1633*45916cd2Sjpk } 1634*45916cd2Sjpk free(oldlist); 1635*45916cd2Sjpk break; 1636*45916cd2Sjpk } 1637*45916cd2Sjpk prev = current; 1638*45916cd2Sjpk } 1639*45916cd2Sjpk 1640*45916cd2Sjpk remove_dev: 1641*45916cd2Sjpk if (remove_dev == 1) { 1642*45916cd2Sjpk (void) strlcpy(devname, current->devinfo.devname, size); 1643*45916cd2Sjpk free(current->devinfo.devname); 1644*45916cd2Sjpk free(current->devinfo.devlist); 1645*45916cd2Sjpk current->devinfo.devname = current->devinfo.devlist = NULL; 1646*45916cd2Sjpk prev->next = current->next; 1647*45916cd2Sjpk free(current); 1648*45916cd2Sjpk current = NULL; 1649*45916cd2Sjpk } 1650*45916cd2Sjpk if ((remove_dev == 1) && (prev->devinfo.devname == NULL)) { 1651*45916cd2Sjpk if (prev->next) { 1652*45916cd2Sjpk /* 1653*45916cd2Sjpk * what we removed above was the first entry 1654*45916cd2Sjpk * in the list. make the next entry to be the 1655*45916cd2Sjpk * first. 1656*45916cd2Sjpk */ 1657*45916cd2Sjpk current = prev->next; 1658*45916cd2Sjpk } else { 1659*45916cd2Sjpk /* 1660*45916cd2Sjpk * the matching entry was the only entry in the list 1661*45916cd2Sjpk * for this type. 1662*45916cd2Sjpk */ 1663*45916cd2Sjpk current = NULL; 1664*45916cd2Sjpk } 1665*45916cd2Sjpk if (flag & DA_AUDIO) 1666*45916cd2Sjpk dlist->audio = current; 1667*45916cd2Sjpk else if (flag & DA_CD) 1668*45916cd2Sjpk dlist->cd = current; 1669*45916cd2Sjpk else if (flag & DA_FLOPPY) 1670*45916cd2Sjpk dlist->floppy = current; 1671*45916cd2Sjpk else if (flag & DA_TAPE) 1672*45916cd2Sjpk dlist->tape = current; 1673*45916cd2Sjpk else if (flag & DA_RMDISK) 1674*45916cd2Sjpk dlist->rmdisk = current; 1675*45916cd2Sjpk } 1676*45916cd2Sjpk 1677*45916cd2Sjpk return (flag); 1678*45916cd2Sjpk } 1679*45916cd2Sjpk 1680*45916cd2Sjpk /* 1681*45916cd2Sjpk * da_is_on - 1682*45916cd2Sjpk * checks if device allocation feature is turned on. 1683*45916cd2Sjpk * returns 1 if on, 0 if off, -1 if status string not 1684*45916cd2Sjpk * found in device_allocate. 1685*45916cd2Sjpk */ 1686*45916cd2Sjpk int 1687*45916cd2Sjpk da_is_on() 1688*45916cd2Sjpk { 1689*45916cd2Sjpk return (getdaon()); 1690*45916cd2Sjpk } 1691*45916cd2Sjpk 1692*45916cd2Sjpk /* 1693*45916cd2Sjpk * da_print_device - 1694*45916cd2Sjpk * debug routine to print device entries. 1695*45916cd2Sjpk */ 1696*45916cd2Sjpk void 1697*45916cd2Sjpk da_print_device(int flag, devlist_t *devlist) 1698*45916cd2Sjpk { 1699*45916cd2Sjpk deventry_t *entry, *dentry; 1700*45916cd2Sjpk devinfo_t *devinfo; 1701*45916cd2Sjpk 1702*45916cd2Sjpk if (flag & DA_AUDIO) 1703*45916cd2Sjpk dentry = devlist->audio; 1704*45916cd2Sjpk else if (flag & DA_CD) 1705*45916cd2Sjpk dentry = devlist->cd; 1706*45916cd2Sjpk else if (flag & DA_FLOPPY) 1707*45916cd2Sjpk dentry = devlist->floppy; 1708*45916cd2Sjpk else if (flag & DA_TAPE) 1709*45916cd2Sjpk dentry = devlist->tape; 1710*45916cd2Sjpk else if (flag & DA_RMDISK) 1711*45916cd2Sjpk dentry = devlist->rmdisk; 1712*45916cd2Sjpk else 1713*45916cd2Sjpk return; 1714*45916cd2Sjpk 1715*45916cd2Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 1716*45916cd2Sjpk devinfo = &(entry->devinfo); 1717*45916cd2Sjpk (void) fprintf(stdout, "name: %s\n", devinfo->devname); 1718*45916cd2Sjpk (void) fprintf(stdout, "type: %s\n", devinfo->devtype); 1719*45916cd2Sjpk (void) fprintf(stdout, "auth: %s\n", devinfo->devauths); 1720*45916cd2Sjpk (void) fprintf(stdout, "exec: %s\n", devinfo->devexec); 1721*45916cd2Sjpk (void) fprintf(stdout, "list: %s\n\n", devinfo->devlist); 1722*45916cd2Sjpk } 1723*45916cd2Sjpk } 1724