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