4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1996-1997, by Sun Microsystems, Inc.
24 * All Rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
39 * _adddevtabrec() Add a record to the device table
40 * _putdevtabrec() Write a record to the device table
41 * _moddevtabrec() Modify a device-table record
42 * _rmdevtabrec() Remove a device-table record
43 * _rmdevtabattrs() Remove attributes from a device-table record
44 * oam_devtab File descriptor of the open device table
48 * G L O B A L R E F E R E N C E S
51 * Externals Referenced
56 * <sys/types.h> UNIX(r) Data Types
58 * <stdio.h> Standard I/O definitions
59 * <fcntl.h> Definitions for file control
60 * <errno.h> Error handling definitions
61 * <string.h> String Handling Definitions
62 * <devmgmt.h> Device Management Definitions
63 * <unistd.h> Get UNIX(r) Standard Definitions
64 * "devtab.h" Local Device Management Definitions
67 #include <sys/types.h>
79 * L O C A L D E F I N I T I O N S
81 * TDTABNM Name of the temporary device table (in the
82 * directory of the existing table)
85 #define TDTABNM "%sdevtab.%6.6d"
90 * strcatesc Copies a character-string from one place to another
91 * escaping the appropriate characters
92 * lkdevtab Locks the device table
93 * unlkdevtab Unlocks the device table
94 * mkdevtabent Builds a device-table entry from the alias and the
95 * list of attr=val pairs given
96 * opennewdevtab Opens a new device table (as a temp file)
97 * mknewdevtab Makes the temp device table the new devtab
98 * rmnewdevtab Remove the temporary device table and free space
99 * allocated to the filename of that file.
102 static char *strcatesc(char *, char *);
103 static int lkdevtab(char *, short);
104 static int unlkdevtab(void);
105 static struct devtabent
*mkdevtabent(char *, char **);
106 static FILE *opennewdevtab(char **);
107 static int mknewdevtab(char *);
108 static int rmnewdevtab(char *);
111 * char *strcatesc(p, q)
115 * Write the character-string pointed to by "q" to the place
116 * pointed to by "p", escaping those characters in "q" found in the
117 * string "DTAB_ESCS" by preceding them with '\\'. Return a pointer to
118 * the byte beyond the last character written to "p".
121 * p The place to begin writing to
122 * q The string to write
125 * The address of the byte beyond the last character written into "p"
130 char *p
, /* Place to write to */
131 char *q
) /* Thing to write */
134 if (strchr(DTAB_ESCS
, *q
)) *p
++ = '\\';
141 * FILE *opennewdevtab(pname)
144 * Generates a temporary device-table name from the existing
145 * device table name (in the same directory) and opens that
146 * file for writing. It puts a pointer to the malloc()ed space
147 * containing the temp device table's name at the place referenced
151 * pname Pointer to the char * to contain the address of the name
152 * of the temporary file
155 * A pointer to the opened stream or (FILE *) NULL if an error occurred.
156 * If an error occurred, "errno" will be set to reflect the problem.
160 opennewdevtab(char **pname
) /* A(ptr to temp filename's path) */
162 char *oldname
; /* Ptr to the device-table's name */
163 char *buf
; /* Ptr to the temp file's name */
164 char *dirname
; /* Directory containing devtab */
165 char *p
; /* Ptr to last '/' in devtab name */
166 int fd
; /* Opened file descriptor */
167 FILE *fp
; /* Opened file pointer */
168 struct stat64 sbuf
; /* stat buf for old devtab file */
171 if (oldname
= _devtabpath()) {
173 * It is possible for us to have sufficient permissions to create
174 * the new file without having sufficient permissions to write the
175 * original devtab file. For consistency with the operations which
176 * modify the original file by writing it directly we require write
177 * permissions for the original file in order to make a new one.
179 if ((fd
= open(oldname
, O_WRONLY
)) == -1)
182 if (fstat64(fd
, &sbuf
) == -1) {
188 if (p
= strrchr(oldname
, '/')) {
191 } else dirname
= "./";
192 if (asprintf(&buf
, TDTABNM
, dirname
, getpid()) >= 0) {
195 * Build the name of the temp device table and
196 * open the file. We must reset the owner, group
197 * and perms to those of the original devtab file.
199 if (fp
= fopen(buf
, "w")) {
201 (void) fchmod(fileno(fp
), sbuf
.st_mode
& 0777);
202 (void) fchown(fileno(fp
), sbuf
.st_uid
, sbuf
.st_gid
);
210 * Free the space containing the device table's name.
215 /* Finished. Return what we've got */
220 * int rmnewdevtab(tempname)
223 * Unlink the temp device table and free the memory allocated to
224 * contain the name of that file
227 * tempname Name of the temporary file
230 * TRUE if successful, FALSE otherwise
234 rmnewdevtab(char *tempname
) /* Filename of new device table */
236 int noerr
; /* Flag, TRUE if no error, FALSE otherwise */
238 /* Unlink the file */
239 noerr
= (unlink(tempname
) == 0);
241 /* Free the space allocated to the filename */
244 /* Return success indicator */
249 * int mknewdevtab(tempname)
252 * Make the temporary device-table the new system device table
255 * tempname Name of the temporary file
258 * TRUE if successful, FALSE otherwise
261 * - Need to use rename() someday instead of link()/unlink()
262 * - This code is somewhat ineffecient in that asks for the name
263 * of the device-table more than once. Done so that we don't
264 * have to manage that space, but this may be somewhat lazy.
268 mknewdevtab(char *tempname
) /* Ptr to name of temp dev tab */
270 char *devtabname
; /* Ptr to the device table's name */
271 int noerr
; /* FLAG, TRUE if all's well */
273 /* Get the device table's pathname */
274 if (devtabname
= _devtabpath()) {
276 /* Unlink the existing file */
277 if (unlink(devtabname
) == 0) {
279 /* Make the temp file the real device table */
280 noerr
= (link(tempname
, devtabname
) == 0) ? TRUE
: FALSE
;
282 /* Remove the temp file (and resources) */
283 if (noerr
) (void) rmnewdevtab(tempname
);
285 } else noerr
= FALSE
; /* unlink() failed */
287 /* Free the device table's name */
290 } else noerr
= FALSE
; /* devtabpath() failed */
292 /* Finished. Return success indicator */
297 * static int lkdevtab(o_mode, lktype)
301 * Lock the device table for writing. If it isn't available, it waits
305 * o_mode The open() mode to use when opening the device table
306 * lktype The type of lock to apply
309 * TRUE if successful, FALSE with errno set otherwise
314 char *o_mode
, /* Open mode */
315 short lktype
) /* Lock type */
318 struct flock lockinfo
; /* File locking structure */
319 int noerr
; /* FLAG, TRUE if no error */
320 int olderrno
; /* Old value of "errno" */
323 /* Close the device table (if it's open) */
326 /* Open the device table for read/append */
328 if (_opendevtab(o_mode
)) {
331 * Lock the device table (for writing). If it's not
332 * available, wait until it is, then close and open the
333 * table (modify and delete change the table!) and try
337 /* Build the locking structure */
338 lockinfo
.l_type
= lktype
;
339 lockinfo
.l_whence
= 0;
340 lockinfo
.l_start
= 0L;
344 /* Keep on going until we lock the file or an error happens */
345 while ((fcntl(fileno(oam_devtab
), F_SETLK
, &lockinfo
) == -1) &&
347 if (errno
== EACCES
) {
348 if (fcntl(fileno(oam_devtab
), F_SETLKW
, &lockinfo
) == -1)
351 /* Reopen the file (maybe it's moved?) */
353 if (!_opendevtab(o_mode
)) noerr
= FALSE
;
354 else errno
= olderrno
;
356 } else noerr
= FALSE
;
359 if (!noerr
) _enddevtab(); /* Don't keep open if in error */
361 } else noerr
= FALSE
;
370 * Unlock the locked device table.
375 * Whatever fcntl() returns...
382 struct flock lockinfo
; /* Locking structure */
383 int noerr
; /* FLAG, TRUE if all's well */
385 /* Build the locking structure */
386 lockinfo
.l_type
= F_UNLCK
; /* Lock type */
387 lockinfo
.l_whence
= 0; /* Count from top of file */
388 lockinfo
.l_start
= 0L; /* From beginning */
389 lockinfo
.l_len
= 0L; /* Length of locked data */
392 noerr
= (fcntl(fileno(oam_devtab
), F_SETLK
, &lockinfo
) != -1);
400 * struct devtabent *mkdevtabent(alias, attrlist)
404 * This function builds a struct devtabent structure describing the
405 * alias <alias> using the information in the attribute list <attrlist>.
406 * The <attrlist> contains data of the form attr=value where attr is
407 * the name of an attribute and value is the value of that attribute.
410 * alias The alias being added to the device table
411 * attrlist The attributes and values for that alias
413 * Returns: struct devtabent *
414 * A completed struct devtabent structure containing the description
415 * of the alias. The structure, and all of the data in the structure
416 * are each in space allocated using the malloc() function and should
417 * be freed using the free() function (or the _freedevtabent() function).
420 * EINVAL If "alias" is used as an attribute in an attr=val pair
421 * EAGAIN If an attribute is specified more than once
424 static struct devtabent
*
426 char *alias
, /* Alias of entry */
427 char **attrlist
) /* Attributes of new entry */
430 struct devtabent
*devtabent
; /* * to struct we're making */
431 struct attrval
*prevattrval
; /* * to prev attr/val struct */
432 struct attrval
*attrval
; /* * to current struct */
433 char **pp
; /* Ptr into list of ptrs */
434 char *peq
; /* Ptr to '=' in string */
435 char *val
; /* Ptr to space for value */
436 char *name
; /* Ptr to space for name */
437 ssize_t len
; /* Length of name */
438 int noerr
; /* TRUE if all's well */
439 int found
; /* TRUE the attr is found */
442 /* No problems (yet) */
445 /* Get space for the structure */
446 if (devtabent
= malloc(sizeof (struct devtabent
))) {
448 /* Fill in default values */
449 if (devtabent
->alias
= malloc(strlen(alias
)+1)) {
451 (void) strcpy(devtabent
->alias
, alias
); /* alias */
452 devtabent
->comment
= FALSE
; /* data rec */
453 devtabent
->cdevice
= NULL
; /* cdevice */
454 devtabent
->bdevice
= NULL
; /* bdevice */
455 devtabent
->pathname
= NULL
; /* pathname */
456 devtabent
->attrstr
= NULL
; /* string */
457 devtabent
->attrlist
= NULL
; /* attr list */
459 /* Add attributes to the structure */
461 if ((pp
= attrlist
) != NULL
)
462 while (*pp
&& noerr
) {
464 /* Valid attr=value pair? */
465 if (((peq
= strchr(*pp
, '=')) != NULL
) &&
466 ((len
= peq
- *pp
) > 0)) {
468 /* Get space for the value */
469 if (val
= malloc(strlen(peq
))) {
470 (void) strcpy(val
, peq
+1); /* Copy it */
472 /* Get space for attribute name */
473 if (name
= malloc((size_t)(len
+ 1))) {
474 (void) strncpy(name
, *pp
, (size_t)len
);
477 /* Specifying the alias? If so, ERROR */
478 if (strcmp(name
, DTAB_ALIAS
) == 0) {
485 /* Specifying the char device path? */
486 else if (strcmp(name
, DTAB_CDEVICE
) == 0) {
487 if (!devtabent
->cdevice
) {
494 devtabent
->cdevice
= val
;
505 /* Specifying the block device path? */
506 else if (strcmp(name
, DTAB_BDEVICE
) == 0) {
507 if (!devtabent
->bdevice
) {
514 devtabent
->bdevice
= val
;
525 /* Specifying the pathname (generic)? */
526 else if (strcmp(name
, DTAB_PATHNAME
) == 0) {
527 if (!devtabent
->pathname
) {
534 devtabent
->pathname
= val
;
545 /* Some other attribute */
548 if ((attrval
= devtabent
->attrlist
) != NULL
)
550 if (strcmp(attrval
->attr
,
558 } while (!found
&& noerr
&&
559 (attrval
= attrval
->next
));
561 if (!found
&& noerr
) {
563 /* Get space for attr/val structure */
565 malloc(sizeof (struct attrval
))) {
567 /* Fill attr/val structure */
568 attrval
->attr
= name
;
570 attrval
->next
= NULL
;
573 * Link into the list of attributes
576 prevattrval
->next
= attrval
;
577 else devtabent
->attrlist
= attrval
;
578 prevattrval
= attrval
;
581 /* malloc() for attrval failed */
587 } /* End else (some other attribute) */
589 } else { /* malloc() for attribute name failed */
594 } else noerr
= FALSE
; /* Malloc() for "val" failed */
596 /* If we saw an error, free structure, returning NULL */
598 _freedevtabent(devtabent
);
602 } /* Ignore invalid attr=val pair */
606 } /* End attribute processing loop */
608 } else { /* malloc() failed */
619 * int _putdevtabrec(stream, rec)
621 * struct devtabent *rec
623 * Write a device table record containing the information in the struct
624 * devtab structure <rec> to the current position of the standard I/O
628 * stream The stream to write to
629 * rec The structure containing the information to write
632 * The number of characters written or EOF if there was some error.
637 FILE *stream
, /* Stream to which to write */
638 struct devtabent
*rec
) /* Record to write */
641 struct attrval
*attrval
; /* Ptr to attr/val pair */
642 char *buf
; /* Allocated buffer */
643 char *p
; /* Temp char pointer */
644 int count
; /* Number of chars written */
645 size_t size
= 0; /* Size of needed buffer */
648 /* Comment or data record? */
652 * Record is a comment
655 /* Copy (escaping chars) record into temp buffer */
656 size
= (strlen(rec
->attrstr
)*2)+1; /* Max rec size */
657 if (buf
= malloc(size
+1)) {
659 p
= strcatesc(buf
, rec
->attrstr
); /* Copy "escaped" */
660 *(p
-2) = '\n'; /* Unescape last \n */
661 *(p
-1) = '\0'; /* Terminate string */
663 /* Write the record */
664 count
= fputs(buf
, stream
);
667 } else count
= EOF
; /* malloc() failed */
673 * Record is a data record
677 * Figure out maximum amount of space you're going to need.
678 * (Assume every escapable character is escaped to determine the
679 * maximum size needed)
683 size
+= (strlen(rec
->cdevice
)*2) + 1; /* cdevice: */
685 size
+= (strlen(rec
->bdevice
)*2) + 1; /* bdevice: */
687 size
+= (strlen(rec
->pathname
)*2) + 1; /* pathname: */
688 if ((attrval
= rec
->attrlist
) != NULL
) do { /* Attributes */
690 size
+= (strlen(attrval
->attr
)*2); /* attr */
692 /* val & '="" ' or val & '=""\n' */
693 size
+= (strlen(attrval
->val
)*2) +4;
695 } while ((attrval
= attrval
->next
) != NULL
); /* Next attr/val */
696 else size
++; /* Else make room for trailing '\n' */
698 /* Alloc space for "escaped" record */
699 if (buf
= malloc(size
+1)) {
701 /* Initializations */
704 /* Write the alias ("alias" attribute) */
705 p
= strcatesc(p
, rec
->alias
);
708 /* Write the character device ("cdevice" attribute) */
709 if (rec
->cdevice
) p
= strcatesc(p
, rec
->cdevice
);
712 /* Write the block device ("bdevice" attribute) */
713 if (rec
->bdevice
) p
= strcatesc(p
, rec
->bdevice
);
716 /* Write the pathname ("pathname" attribute) */
717 if (rec
->pathname
) p
= strcatesc(p
, rec
->pathname
);
720 /* Write the rest of the attributes */
721 if ((attrval
= rec
->attrlist
) != NULL
)
723 p
= strcatesc(p
, attrval
->attr
);
726 p
= strcatesc(p
, attrval
->val
);
728 if ((attrval
= attrval
->next
) != NULL
)
732 /* Terminate the record */
736 /* Write the record */
737 count
= fputs(buf
, stream
);
739 } else count
= EOF
; /* malloc() failed */
747 * int _adddevtabrec(alias, attrval)
751 * This function adds a record to the device table. That record will
752 * have the alias <alias> and will have the attributes described in
753 * the list referenced by <attrval>.
755 * It always adds the record to the end of the table.
758 * alias The alias of the device whose description is being
759 * added to the device table.
760 * attrval The pointer to the first item of a list of attributes
761 * defining the device whose description is being added.
762 * (This value may be (char **) NULL).
765 * TRUE if successful, FALSE with errno set otherwise.
770 char *alias
, /* Alias to add to the device table */
771 char **attrval
) /* Attributes for that device */
774 struct devtabent
*devtabent
; /* Ptr to dev tab entry */
775 int olderrno
; /* Errno on entry */
776 int noerr
; /* FLAG, TRUE if all's well */
778 /* Validate the device alias. Error (EINVAL) if it's not valid */
779 if (!_validalias(alias
)) {
785 * Lock the device table. This only returns if the table is locked or
786 * some error occurred. It waits until the table is available.
788 if (!lkdevtab("a+", F_WRLCK
))
791 /* Make sure that the alias isn't already in the table */
794 if (devtabent
= _getdevrec(alias
)) {
796 /* The alias is already in the table */
797 _freedevtabent(devtabent
); /* Free device table info */
798 errno
= EEXIST
; /* Set errno, entry exists */
799 noerr
= FALSE
; /* All's not well */
800 } else if ((errno
== ENOENT
) || (errno
== ENODEV
)) {
802 /* The alias wasn't in the table or there wasn't a table. */
804 errno
= olderrno
; /* Reset errno */
806 /* Build a struct devtabent that describes the new alias */
807 if (devtabent
= mkdevtabent(alias
, attrval
)) {
809 /* Position to the end of the existing table */
810 if (fseek(oam_devtab
, 0, SEEK_END
) == 0)
812 /* Write the new entry */
813 noerr
= (_putdevtabrec(oam_devtab
, devtabent
) != EOF
);
815 /* Free the info we just wrote */
816 _freedevtabent(devtabent
);
818 } else noerr
= FALSE
; /* mkdevtabent() failed */
819 } else noerr
= FALSE
; /* Some odd error, _devtab */
821 /* Unlock and close the device table */
829 * int _moddevtabrec(device, attrval)
833 * This function modifies the description for the specified device
834 * so that it has the attributes and values as specified in the
838 * device The name of the device whose description
840 * attrval The first attr/val value in the list (attr=val) of
841 * the attributes that are to change
844 * TRUE if all went well, FALSE with errno set otherwise
849 char *device
, /* Device to modify */
850 char **attrval
) /* Attributes to add or change */
853 FILE *fd
; /* File ptr, new device table */
854 struct devtabent
*ent
; /* Device's current description */
855 struct devtabent
*chg
; /* Changes to make to description */
856 struct attrval
*new; /* New attribute/value desc */
857 struct attrval
*old
; /* Old attribute/value desc */
858 struct attrval
*newnew
; /* Next "new" value to look at */
859 struct attrval
*prevnew
; /* Previous item in the 'new' list */
860 char *tname
; /* name of temp devtab file */
861 int noerr
; /* FLAG, TRUE if all's well */
862 int found
; /* FLAG, TRUE if attr found for dev */
864 /* Lock the device table */
865 if (!lkdevtab("r", F_WRLCK
))
868 /* No problems (so far) */
871 /* Get the entry to modify */
872 if (ent
= _getdevrec(device
)) {
874 /* Build a structure describing the changes */
875 if (chg
= mkdevtabent(device
, attrval
)) {
877 /* If the "cdevice" field is specified, change it */
880 ent
->cdevice
= chg
->cdevice
;
884 /* If the "bdevice" field is specified, change it */
887 ent
->bdevice
= chg
->bdevice
;
891 /* If the "pathname" field is specified, change it */
894 ent
->pathname
= chg
->pathname
;
895 chg
->pathname
= NULL
;
898 /* Change the other attributes (if any) */
901 if ((new = chg
->attrlist
) != NULL
) do {
904 for (old
= ent
->attrlist
; !found
&& old
;
906 if (strcmp(old
->attr
, new->attr
) == 0) {
912 } /* Loop through the existing attribute list */
915 * If the attribute wasn't found, add it to the list
916 * of attributes for the device. If it was found, just
917 * bump to the next one and look for it
923 * Not found. Move attr/val description to the
924 * device's list of attributes
927 if (prevnew
) prevnew
->next
= new->next
;
928 else chg
->attrlist
= new->next
;
930 new->next
= ent
->attrlist
;
935 /* Attribute changed, bump to the next one */
939 } while (new); /* Loop for each attr to add or modify */
943 /* Device had no attributes -- add entire list */
944 ent
->attrlist
= chg
->attrlist
;
945 chg
->attrlist
= NULL
;
948 /* Free the structure containing the changes */
951 } else noerr
= FALSE
; /* Couldn't build changes struct */
953 /* If there hasn't been an error (so far), write the new record */
956 /* Open the new device table */
957 if (fd
= opennewdevtab(&tname
)) {
960 * For each entry in the existing table, write that entry
961 * to the new table. If the entry is the one being
962 * modified, write the modified entry instead of the
966 _setdevtab(); /* Rewind existing table */
967 chg
= ent
; /* Remember new record */
968 while (((ent
= _getdevtabent()) != NULL
) && noerr
) {
969 if (ent
->entryno
!= chg
->entryno
)
970 noerr
= _putdevtabrec(fd
, ent
) != EOF
;
971 else noerr
= _putdevtabrec(fd
, chg
) != EOF
;
976 * If we successfully generated the new table, make it the
977 * new system device table. Otherwise, just remove the
978 * temporary file we've created.
983 noerr
= mknewdevtab(tname
);
986 (void) rmnewdevtab(tname
);
989 /* Free the changed device structure */
992 } /* if (_opennewdevtab()) */
995 } else _freedevtabent(ent
); /* if (noerr) */
997 } else noerr
= FALSE
; /* Device not found? */
999 /* Finished. Unlock the device table and quit */
1000 (void) unlkdevtab();
1005 * int _rmdevtabrec(device)
1008 * This function removes the record in the device table for the specified
1012 * device The device (alias, cdevice, bdevice, pathname, or link to one)
1013 * whose entry is to be removed
1016 * Success indicator: TRUE if successful, FALSE with errno set otherwise.
1020 _rmdevtabrec(char *device
) /* Device to remove */
1022 struct devtabent
*rment
;
1023 struct devtabent
*devtabent
;
1028 if (!lkdevtab("r", F_WRLCK
))
1031 if (rment
= _getdevrec(device
)) {
1032 if (fd
= opennewdevtab(&tempname
)) {
1034 while (((devtabent
= _getdevtabent()) != NULL
) && noerr
) {
1035 if (devtabent
->entryno
!= rment
->entryno
)
1036 noerr
= _putdevtabrec(fd
, devtabent
) != EOF
;
1037 _freedevtabent(devtabent
);
1041 noerr
= mknewdevtab(tempname
);
1044 (void) rmnewdevtab(tempname
);
1046 } else noerr
= FALSE
;
1047 _freedevtabent(rment
);
1048 } else noerr
= FALSE
;
1049 (void) unlkdevtab();
1054 * int _rmdevtabattrs(device, attributes, notfounds)
1059 * Remove the specified attributes from the specified device. The
1060 * device is specified by <device>, <attributes> is the address of
1061 * the first char * in the list of char * pointing to the attributes
1062 * to remove from the device, and <notfounds> is the address of a
1063 * char ** to put the address of the first element in the malloc()ed
1064 * list of (char *) pointing to requested attributes that were not
1065 * defined for the device <device>.
1068 * device The device from which attributes are to be removed
1069 * attributes The address of the first element in the list of
1070 * attributes to remove. This list is terminated by
1072 * notfounds The place to put the address of the list of addresses
1073 * referencing the requested attributes that are not
1074 * defined for the specified device.
1077 * TRUE if successful, FALSE with errno set otherwise.
1080 * - "alias" may not be undefined
1081 * - "cdevice", "bdevice", and "pathname" are made "null", not really
1087 char *device
, /* Device to modify */
1088 char **attributes
, /* Attributes to remove */
1089 char ***notfounds
) /* Attributes req'd but not found */
1092 char **pnxt
; /* Ptr to next attribute */
1093 char **pp
; /* Ptr to current attr name */
1094 struct devtabent
*modent
; /* Entry being modified */
1095 struct devtabent
*devtabent
; /* Entry being copied */
1096 struct attrval
*attrval
; /* Ptr to attr/val desc */
1097 struct attrval
*prevattrval
; /* Ptr to prev attr/val */
1098 FILE *fd
; /* File desc, temp file */
1099 char *tempname
; /* Name of temp file */
1100 int nattrs
; /* Number of attrs to remove */
1101 int nobaderr
; /* TRUE if no fatal error */
1102 int noerr
; /* TRUE if no non-fatal error */
1103 int found
; /* TRUE if attribute found */
1104 int nonotfounds
; /* TRUE if no attrs not fount */
1107 /* Initializations */
1111 /* Count attributes to remove -- make sure "alias" isn't specified */
1112 for (pp
= attributes
, nattrs
= 0; *pp
; pp
++, nattrs
++)
1113 if (strcmp(*pp
, DTAB_ALIAS
) == 0) {
1119 /* Lock the device table */
1120 if (!lkdevtab("r", F_WRLCK
))
1123 /* Is there a record for the requested device? */
1124 if (modent
= _getdevrec(device
)) {
1126 /* Record found. Try to modify it */
1129 /* For each of the attributes in the attribute list ... */
1130 for (pp
= attributes
; nobaderr
&& *pp
; pp
++) {
1133 * Modify the device description, removing the requested
1134 * attributes from the structure
1137 found
= FALSE
; /* Not found yet */
1139 /* If it's the "cdevice" attribute, make it a null-string */
1140 if (strcmp(*pp
, DTAB_CDEVICE
) == 0) {
1141 if (modent
->cdevice
) {
1142 free(modent
->cdevice
);
1143 modent
->cdevice
= NULL
;
1148 /* If it's the "bdevice" attribute, make it a null-string */
1149 else if (strcmp(*pp
, DTAB_BDEVICE
) == 0) {
1150 if (modent
->bdevice
) {
1151 free(modent
->bdevice
);
1152 modent
->bdevice
= NULL
;
1157 /* If it's the "pathname" attribute, make it a null-string */
1158 else if (strcmp(*pp
, DTAB_PATHNAME
) == 0) {
1159 if (modent
->pathname
) {
1160 free(modent
->pathname
);
1161 modent
->pathname
= NULL
;
1166 /* Must be one of the other "auxilliary" attributes */
1169 /* Search the attribute list for the attribute */
1171 if ((attrval
= modent
->attrlist
) != NULL
) do {
1172 if (strcmp(*pp
, attrval
->attr
) == 0) {
1174 /* Found. Remove from attribute list */
1176 free(attrval
->attr
);
1179 prevattrval
->next
= attrval
->next
;
1181 attrval
= prevattrval
->next
;
1183 modent
->attrlist
= attrval
->next
;
1185 attrval
= modent
->attrlist
;
1188 prevattrval
= attrval
; /* Advance to next */
1189 attrval
= attrval
->next
;
1191 } while (!found
&& attrval
);
1193 } /* End attribute search loop */
1196 * If the requested attribute wasn't defined for the device,
1197 * put it in the list of attributes not found
1203 * If there's no list (yet), alloc enough space for
1208 if (*notfounds
= malloc(sizeof (char **)*(nattrs
+1))) {
1210 /* List allocated -- put in the first entry */
1211 nonotfounds
= FALSE
;
1213 if (*pnxt
= malloc(strlen(*pp
)+1)) {
1216 (void) strcpy(*pnxt
++, *pp
);
1218 /* malloc() failed, free list */
1225 } else nobaderr
= FALSE
; /* malloc() failed */
1228 /* Already a list, add this attribute to it */
1229 if (*pnxt
= malloc(strlen(*pp
)+1))
1230 (void) strcpy(*pnxt
++, *pp
);
1232 /* Out of memory, clean up */
1233 for (pnxt
= *notfounds
; *pnxt
; pnxt
++)
1242 } /* end if (!found) */
1244 /* Terminate the not-found list */
1245 if (!nonotfounds
) *pnxt
= NULL
;
1247 } /* end (for each attribute in attribute list) loop */
1251 * If we haven't seen any problems so far,
1252 * write the new device table
1257 /* Open the new device table */
1258 if (fd
= opennewdevtab(&tempname
)) {
1261 * For each entry in the existing table, write that entry
1262 * to the new table. If the entry is the one being
1263 * modified, write the modified entry instead of the
1267 _setdevtab(); /* Rewind existing table */
1268 while (((devtabent
= _getdevtabent()) != NULL
) &&
1271 if (devtabent
->entryno
!= modent
->entryno
)
1272 nobaderr
= _putdevtabrec(fd
, devtabent
) != EOF
;
1273 else nobaderr
= _putdevtabrec(fd
, modent
) != EOF
;
1274 _freedevtabent(devtabent
);
1278 * If we successfully generated the new table, make it the
1279 * new system device table. Otherwise, just remove the
1280 * temporary file we've created.
1285 nobaderr
= mknewdevtab(tempname
);
1288 (void) rmnewdevtab(tempname
);
1291 } /* if (_opennewdevtab()) */
1292 else nobaderr
= FALSE
;
1295 * If there was some error, we need to clean up
1296 * allocated resources
1298 if (!nobaderr
&& !nonotfounds
) {
1299 for (pnxt
= *notfounds
; *pnxt
; pnxt
++)
1306 } /* if (nobaderr) */
1308 /* Free the resources alloc'ed for <device>'s entry */
1309 _freedevtabent(modent
);
1312 /* _getdevrec(device) failed */
1317 /* Unlock the device table */
1318 (void) unlkdevtab();
1320 /* We're finished */
1321 return (noerr
&& nobaderr
);