4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include "cfga_scsi.h"
36 scfga_recur_t (*devlink_to_dyncomp_p
)(dyn_t
*dyntp
);
37 scfga_recur_t (*dyncomp_to_devlink_p
)(dyn_t
*dyntp
);
42 dynrules_t
*rule_array
;
56 /* Function prototypes */
58 static int drv_to_hba_logid(di_node_t node
, di_minor_t minor
, void *arg
);
59 static scfga_ret_t
drv_dyn_to_devpath(const char *hba_phys
,
60 const char *dyncomp
, char **pathpp
, int *l_errnop
);
61 static int do_drv_dyn_to_devpath(di_node_t node
, void *arg
);
62 static scfga_ret_t
devlink_dyn_to_devpath(const char *hba_phys
,
63 const char *dyncomp
, char **pathpp
, int *l_errnop
);
65 static scfga_recur_t
disk_dyncomp_to_devlink(dyn_t
*dyntp
);
66 static scfga_recur_t
tape_dyncomp_to_devlink(dyn_t
*dyntp
);
67 static scfga_recur_t
def_dyncomp_to_devlink(dyn_t
*dyntp
);
69 static scfga_ret_t
devlink_to_dyncomp(char *devlink
,
70 char **dyncompp
, int *l_errnop
);
71 static scfga_recur_t
disk_devlink_to_dyncomp(dyn_t
*dyntp
);
72 static scfga_recur_t
tape_devlink_to_dyncomp(dyn_t
*dyntp
);
73 static scfga_recur_t
def_devlink_to_dyncomp(dyn_t
*dyntp
);
74 static scfga_ret_t
drv_to_dyncomp(di_node_t node
, const char *phys
,
75 char **dyncompp
, int *l_errnop
);
76 static scfga_ret_t
get_hba_devlink(const char *hba_phys
,
77 char **hba_logpp
, int *l_errnop
);
78 static scfga_ret_t
path_apid_dyn_to_path(const char *hba_phys
, const char *dyn
,
79 char **pathpp
, int *l_errnop
);
85 * Rules for converting between a devlink and logical ap_id and vice-versa
86 * The default rules must be the last entry.
88 static dynrules_t dyncvt_rules
[] = {
89 {disk_devlink_to_dyncomp
, disk_dyncomp_to_devlink
},
90 {tape_devlink_to_dyncomp
, tape_dyncomp_to_devlink
},
91 {def_devlink_to_dyncomp
, def_dyncomp_to_devlink
}
94 #define N_DYNRULES (sizeof (dyncvt_rules)/sizeof (dyncvt_rules[0]))
97 * Numbering of disk slices is assumed to be 0 through n - 1
104 static slice_t disk_slices
[] = {
109 #define N_SLICE_TYPES (sizeof (disk_slices) / sizeof (disk_slices[0]))
111 static const char *tape_modes
[] = {
114 "c", "cb", "cbn", "cn",
115 "h", "hb", "hbn", "hn",
116 "l", "lb", "lbn", "ln",
117 "m", "mb", "mbn", "mn",
119 "u", "ub", "ubn", "un"
122 #define N_TAPE_MODES (sizeof (tape_modes) / sizeof (tape_modes[0]))
125 /* Various conversions routines */
128 * Generates the HBA logical ap_id from physical ap_id.
131 make_hba_logid(const char *hba_phys
, char **hba_logpp
, int *l_errnop
)
134 pathm_t pmt
= {NULL
};
138 if (*hba_logpp
!= NULL
) {
142 /* A devlink for the HBA may or may not exist */
143 if (get_hba_devlink(hba_phys
, hba_logpp
, l_errnop
) == SCFGA_OK
) {
144 assert(*hba_logpp
!= NULL
);
149 * No devlink based logical ap_id.
150 * Try driver name and instance number.
152 u
.minor_args
.nodetype
= DDI_NT_SCSI_ATTACHMENT_POINT
;
153 u
.minor_args
.fcn
= drv_to_hba_logid
;
155 pmt
.phys
= (char *)hba_phys
;
156 pmt
.ret
= SCFGA_APID_NOEXIST
;
159 ret
= walk_tree(pmt
.phys
, &pmt
, DINFOMINOR
| DINFOPROP
, &u
,
160 SCFGA_WALK_MINOR
, &pmt
.l_errno
);
161 if (ret
== SCFGA_OK
&& (ret
= pmt
.ret
) == SCFGA_OK
) {
162 assert(pmt
.log
!= NULL
);
163 *hba_logpp
= pmt
.log
;
167 /* failed to create logical ap_id */
168 if (pmt
.log
!= NULL
) {
173 *l_errnop
= pmt
.l_errno
;
178 get_hba_devlink(const char *hba_phys
, char **hba_logpp
, int *l_errnop
)
184 ret
= physpath_to_devlink((char *)hba_phys
, hba_logpp
,
185 l_errnop
, match_minor
);
186 if (ret
!= SCFGA_OK
) {
190 assert(*hba_logpp
!= NULL
);
192 /* Remove the "/dev/cfg/" prefix */
193 len
= strlen(CFGA_DEV_DIR SLASH
);
195 (void) memmove(*hba_logpp
, *hba_logpp
+ len
,
196 strlen(*hba_logpp
+ len
) + 1);
201 /* Make logical name for HBA based on driver and instance */
203 drv_to_hba_logid(di_node_t node
, di_minor_t minor
, void *arg
)
206 char *drv
, *mn
, *log
;
208 const size_t loglen
= MAXPATHLEN
;
210 ptp
= (pathm_t
*)arg
;
214 mn
= di_minor_name(minor
);
215 drv
= di_driver_name(node
);
216 inst
= di_instance(node
);
217 log
= calloc(1, loglen
);
219 if (mn
!= NULL
&& drv
!= NULL
&& inst
!= -1 && log
!= NULL
) {
220 /* Count does not include terminating NULL */
221 if (snprintf(log
, loglen
, "%s%d:%s", drv
, inst
, mn
) < loglen
) {
224 return (DI_WALK_TERMINATE
);
229 return (DI_WALK_CONTINUE
);
233 * Given a bus or device ap_id <hba_phys, dyncomp>, returns the physical
235 * Returns: SCFGA_APID_NOEXIST if the path does not exist.
240 const char *hba_phys
,
247 if (*pathpp
!= NULL
) {
248 return (SCFGA_LIB_ERR
);
251 /* If a bus, the physical ap_id is the physical path */
252 if (dyncomp
== NULL
) {
253 if ((*pathpp
= strdup(hba_phys
)) == NULL
) {
255 return (SCFGA_LIB_ERR
);
260 /* Dynamic component exists, we have a device */
263 * If the dynamic component has a '/', it was derived from a devlink
264 * Else it was derived from driver name and instance number.
265 * If it is pathinfo instance number based ap id, it will have a format
268 if (strchr(dyncomp
, '/') != NULL
) {
269 ret
= devlink_dyn_to_devpath(hba_phys
, dyncomp
, pathpp
,
271 } else if (strstr(dyncomp
, PATH_APID_DYN_SEP
) != NULL
) {
272 ret
= path_apid_dyn_to_path(hba_phys
, dyncomp
, pathpp
,
275 ret
= drv_dyn_to_devpath(hba_phys
, dyncomp
, pathpp
, l_errnop
);
277 assert(ret
!= SCFGA_OK
|| *pathpp
!= NULL
);
284 * Get the devfs path of pathinfo node that is associated with
285 * the given dynamic component.
288 * hba_phys: physical path of HBA
289 * dyn : bus address of pathinfo node
291 * pathpp: devfs path of the pathinfo node.
294 path_apid_dyn_to_path(
295 const char *hba_phys
,
301 di_node_t root
, walk_root
;
302 di_path_t pi_node
= DI_PATH_NIL
;
303 char *root_path
, *devpath
, *cp
;
308 /* *pathpp should be NULL if pathpp is not NULL. */
309 if ((hba_phys
== NULL
) || (pathpp
!= NULL
) && (*pathpp
!= NULL
)) {
310 return (SCFGA_LIB_ERR
);
313 if ((root_path
= strdup(hba_phys
)) == NULL
) {
315 return (SCFGA_LIB_ERR
);
318 /* Fix up path for di_init() */
319 len
= strlen(DEVICES_DIR
);
320 if (strncmp(root_path
, DEVICES_DIR SLASH
,
321 len
+ strlen(SLASH
)) == 0) {
322 cp
= root_path
+ len
;
323 (void) memmove(root_path
, cp
, strlen(cp
) + 1);
324 } else if (*root_path
!= '/') {
330 /* Remove dynamic component if any */
331 if ((cp
= GET_DYN(root_path
)) != NULL
) {
335 /* Remove minor name if any */
336 if ((cp
= strrchr(root_path
, ':')) != NULL
) {
341 * Cached snapshots are always rooted at "/"
345 if ((root
= di_init("/", DINFOCACHE
)) == DI_NODE_NIL
) {
352 * Lookup the subtree of interest
354 walk_root
= di_lookup_node(root
, root_path
);
356 if (walk_root
== DI_NODE_NIL
) {
360 return (SCFGA_LIB_ERR
);
365 if ((pi_node
= di_path_next_client(walk_root
, pi_node
)) ==
368 return (SCFGA_APID_NOEXIST
);
372 * now parse the path info node.
375 /* check the length first. */
376 if (strlen(di_path_bus_addr(pi_node
)) != strlen(dyn
)) {
380 if (strcmp(di_path_bus_addr(pi_node
), dyn
) == 0) {
381 /* get the devfspath of pathinfo node. */
382 devpath
= di_path_devfs_path(pi_node
);
383 if (devpath
== NULL
) {
389 len
= strlen(DEVICES_DIR
) + strlen(devpath
) + 1;
390 *pathpp
= calloc(1, len
);
391 if (*pathpp
== NULL
) {
393 di_devfs_path_free(devpath
);
397 (void) snprintf(*pathpp
, len
, "%s%s",
398 DEVICES_DIR
, devpath
);
399 di_devfs_path_free(devpath
);
404 pi_node
= di_path_next_client(walk_root
, pi_node
);
405 } while (pi_node
!= DI_PATH_NIL
);
408 return (SCFGA_APID_NOEXIST
);
413 const char *hba_phys
,
419 devpath_t dpt
= {NULL
};
422 /* A device MUST have a dynamic component */
423 if (dyncomp
== NULL
|| *pathpp
!= NULL
) {
424 return (SCFGA_LIB_ERR
);
427 u
.node_args
.flags
= DI_WALK_CLDFIRST
;
428 u
.node_args
.fcn
= do_drv_dyn_to_devpath
;
430 dpt
.hba_phys
= hba_phys
;
431 dpt
.dyncomp
= dyncomp
;
432 dpt
.ret
= SCFGA_APID_NOEXIST
;
434 ret
= walk_tree(hba_phys
, &dpt
, DINFOCPYALL
, &u
,
435 SCFGA_WALK_NODE
, &dpt
.l_errno
);
437 if (ret
== SCFGA_OK
&& (ret
= dpt
.ret
) == SCFGA_OK
) {
438 assert(dpt
.path
!= NULL
);
443 if (dpt
.path
!= NULL
) {
448 *l_errnop
= dpt
.l_errno
;
452 /* Converts a driver and instance number based logid into a physical path */
454 do_drv_dyn_to_devpath(di_node_t node
, void *arg
)
456 int inst
, rv
, match_minor
;
458 char *physpath
, *drv
;
459 char *drvinst
, *devpath
;
460 const size_t drvlen
= MAXPATHLEN
;
463 dptp
= (devpath_t
*)arg
;
465 assert(dptp
->hba_phys
!= NULL
&& dptp
->dyncomp
!= NULL
);
466 assert(dptp
->path
== NULL
);
471 if (IS_STUB_NODE(node
)) {
472 return (DI_WALK_CONTINUE
);
477 drv
= di_driver_name(node
);
478 inst
= di_instance(node
);
479 physpath
= di_devfs_path(node
);
480 if (drv
== NULL
|| inst
== -1 || physpath
== NULL
) {
481 rv
= DI_WALK_CONTINUE
;
485 devlen
= strlen(DEVICES_DIR
) + strlen(physpath
) + 1;
487 devpath
= calloc(1, devlen
);
488 drvinst
= calloc(1, drvlen
);
489 if (devpath
== NULL
|| drvinst
== NULL
) {
490 dptp
->l_errno
= errno
;
491 dptp
->ret
= SCFGA_LIB_ERR
;
492 rv
= DI_WALK_TERMINATE
;
496 (void) snprintf(drvinst
, drvlen
, "%s%d", drv
, inst
);
498 /* Create the physical path */
499 (void) snprintf(devpath
, devlen
, "%s%s", DEVICES_DIR
, physpath
);
501 /* Skip node if it is the HBA */
503 if (!dev_cmp(dptp
->hba_phys
, devpath
, match_minor
)) {
504 rv
= DI_WALK_CONTINUE
;
508 /* Compare the base and dynamic components */
509 if (!hba_dev_cmp(dptp
->hba_phys
, devpath
) &&
510 strcmp(dptp
->dyncomp
, drvinst
) == 0) {
511 dptp
->ret
= SCFGA_OK
;
512 dptp
->path
= devpath
;
513 rv
= DI_WALK_TERMINATE
;
515 rv
= DI_WALK_CONTINUE
;
521 if (physpath
!= NULL
) di_devfs_path_free(physpath
);
522 if (dptp
->ret
!= SCFGA_OK
) S_FREE(devpath
);
526 /* readlink wrapper to ensure proper null termination of the results */
528 s_readlink(char *link
, char *buf
, int len
)
532 count
= readlink(link
, buf
, len
- 1);
538 /* Converts a devlink based dynamic component to a path */
540 devlink_dyn_to_devpath(
541 const char *hba_phys
,
549 char buf
[PATH_MAX
], *path
;
551 if (*pathpp
!= NULL
) {
552 return (SCFGA_LIB_ERR
);
555 /* Convert the dynamic component to the corresponding devlink */
556 dynt
.dyncomp
= (char *)dyncomp
;
557 dynt
.ret
= SCFGA_APID_NOEXIST
;
559 for (i
= 0; i
< N_DYNRULES
; i
++) {
560 if (dyncvt_rules
[i
].dyncomp_to_devlink_p(&dynt
)
566 if (i
>= N_DYNRULES
) {
567 dynt
.ret
= SCFGA_APID_NOEXIST
;
570 if (dynt
.ret
!= SCFGA_OK
) {
571 /* No symlink or error */
575 assert(dynt
.devlink
!= NULL
);
578 * Follow devlink to get the physical path
579 * Note: Do not use realpath(). It will stat() device
580 * and stat() fails under devfs if device is offline.
583 if ((s_readlink(dynt
.devlink
, buf
, PATH_MAX
) == -1) ||
584 ((path
= strstr(buf
, "/devices/")) == NULL
) ||
585 ((*pathpp
= strdup(path
)) == NULL
)) {
591 /* Compare base components as well */
592 if (!hba_dev_cmp(hba_phys
, path
)) {
595 /* Mismatched base and dynamic component */
597 ret
= SCFGA_APID_NOEXIST
;
602 S_FREE(dynt
.devlink
);
603 if (ret
!= SCFGA_OK
) S_FREE(*pathpp
);
610 const char *physpath
,
614 char *devlink
= NULL
;
618 char pathbuf
[MAXPATHLEN
];
621 if (*dyncompp
!= NULL
) {
622 return (SCFGA_LIB_ERR
);
625 /* tag on minor name */
626 minor
= di_minor_next(node
, DI_MINOR_NIL
);
627 if (minor
== DI_MINOR_NIL
) {
629 path
= (char *)physpath
;
632 (void) snprintf(pathbuf
, MAXPATHLEN
, "%s:%s", physpath
,
633 di_minor_name(minor
));
637 /* Get the corresponding devlink from the physical path */
638 ret
= physpath_to_devlink(path
, &devlink
, l_errnop
, match_minor
);
639 if (ret
== SCFGA_OK
) {
640 assert(devlink
!= NULL
);
642 /* Create dynamic component. */
643 ret
= devlink_to_dyncomp(devlink
, dyncompp
, l_errnop
);
645 if (ret
== SCFGA_OK
) {
646 assert(*dyncompp
!= NULL
);
651 * Failed to get devlink based dynamic component.
652 * Try driver and instance
656 ret
= drv_to_dyncomp(node
, physpath
, dyncompp
, l_errnop
);
657 assert(ret
!= SCFGA_OK
|| *dyncompp
!= NULL
);
663 * Create a dynamic component of path ap_id for the given path info node.
664 * The caller should free the buffer for the dynamic component.
674 if ((path
== DI_PATH_NIL
) || (*dyncompp
!= NULL
)) {
675 return (SCFGA_LIB_ERR
);
678 if ((pi_addr
= di_path_bus_addr(path
)) != NULL
) {
679 *dyncompp
= calloc(1, strlen(pi_addr
) + 1);
680 if (*dyncompp
== NULL
) {
682 return (SCFGA_LIB_ERR
);
684 (void) strncpy(*dyncompp
, pi_addr
, strlen(pi_addr
));
686 return (SCFGA_LIB_ERR
);
694 drv_to_dyncomp(di_node_t node
, const char *phys
, char **dyncompp
, int *l_errnop
)
698 const int dynlen
= MAXPATHLEN
;
703 if ((*dyncompp
= calloc(1, dynlen
)) == NULL
) {
705 return (SCFGA_LIB_ERR
);
708 drv
= di_driver_name(node
);
709 inst
= di_instance(node
);
710 if (drv
!= NULL
&& inst
!= -1) {
711 if (snprintf(*dyncompp
, dynlen
, "%s%d", drv
, inst
) < dynlen
) {
717 ret
= SCFGA_APID_NOEXIST
;
724 /* Get a dynamic component from a physical path if possible */
726 devlink_to_dyncomp(char *devlink
, char **dyncompp
, int *l_errnop
)
733 if (*dyncompp
!= NULL
) {
734 return (SCFGA_LIB_ERR
);
737 /* Convert devlink to dynamic component */
738 dynt
.devlink
= devlink
;
739 dynt
.ret
= SCFGA_APID_NOEXIST
;
741 for (i
= 0; i
< N_DYNRULES
; i
++) {
742 if (dyncvt_rules
[i
].devlink_to_dyncomp_p(&dynt
)
748 if (i
>= N_DYNRULES
) {
749 dynt
.ret
= SCFGA_APID_NOEXIST
;
752 if (dynt
.ret
== SCFGA_OK
) {
753 assert(dynt
.dyncomp
!= NULL
);
754 *dyncompp
= dynt
.dyncomp
;
760 /* For disks remove partition information, (s or p) */
762 disk_devlink_to_dyncomp(dyn_t
*dyntp
)
764 char *cp
= NULL
, *cp1
= NULL
;
766 assert(dyntp
->devlink
!= NULL
);
770 if (dyntp
->dyncomp
!= NULL
) {
774 /* Check if a disk devlink */
775 if (strncmp(dyntp
->devlink
, DEV_DSK SLASH
, strlen(DEV_DSK SLASH
)) &&
776 strncmp(dyntp
->devlink
, DEV_RDSK SLASH
, strlen(DEV_RDSK SLASH
))) {
777 return (SCFGA_CONTINUE
);
780 cp
= dyntp
->devlink
+ strlen(DEV_DIR SLASH
);
782 if ((dyntp
->dyncomp
= strdup(cp
)) == NULL
) {
783 dyntp
->l_errno
= errno
;
787 /* Get the leaf component from dsk/cXtYdZsN */
788 cp1
= strrchr(dyntp
->dyncomp
, '/');
790 /* Blank out partition information */
791 dyntp
->ret
= SCFGA_OK
;
792 if ((cp
= strchr(cp1
+ 1, 's')) != NULL
) {
794 } else if ((cp
= strchr(cp1
+ 1, 'p')) != NULL
) {
797 S_FREE(dyntp
->dyncomp
);
798 dyntp
->ret
= SCFGA_ERR
;
801 return (SCFGA_TERMINATE
);
804 dyntp
->ret
= SCFGA_LIB_ERR
;
805 return (SCFGA_TERMINATE
);
810 disk_dyncomp_to_devlink(dyn_t
*dyntp
)
812 char buf
[MAXPATHLEN
], *cp
= NULL
;
817 assert(dyntp
->dyncomp
!= NULL
);
821 if (dyntp
->devlink
!= NULL
) {
822 dyntp
->ret
= SCFGA_LIB_ERR
;
823 return (SCFGA_TERMINATE
);
826 /* A disk link can only be from DEV_DSK (ignore /dev/rdsk) */
827 if (strncmp(dyntp
->dyncomp
, DSK_DIR SLASH
, strlen(DSK_DIR SLASH
)) != 0)
828 return (SCFGA_CONTINUE
); /* not a disk link */
830 (void) snprintf(buf
, sizeof (buf
), "%s%s", DEV_DIR SLASH
,
835 len
= sizeof (buf
) - len
;
837 for (i
= 0; i
< N_SLICE_TYPES
; i
++) {
838 for (j
= 0; j
< disk_slices
[i
].nslices
; j
++) {
839 if (snprintf(cp
, len
, "%s%d", disk_slices
[i
].prefix
, j
)
844 if (lstat(buf
, &sbuf
) != -1 && S_ISLNK(sbuf
.st_mode
)) {
845 if ((dyntp
->devlink
= strdup(buf
)) == NULL
) {
846 dyntp
->l_errno
= errno
;
847 dyntp
->ret
= SCFGA_LIB_ERR
;
848 return (SCFGA_TERMINATE
);
850 dyntp
->ret
= SCFGA_OK
;
851 return (SCFGA_TERMINATE
);
856 dyntp
->ret
= SCFGA_APID_NOEXIST
;
857 return (SCFGA_TERMINATE
);
860 /* For tapes, remove mode(minor) information from link */
862 tape_devlink_to_dyncomp(dyn_t
*dyntp
)
866 assert(dyntp
->devlink
!= NULL
);
870 if (dyntp
->dyncomp
!= NULL
) {
874 if (strncmp(dyntp
->devlink
, DEV_RMT SLASH
, strlen(DEV_RMT SLASH
))) {
875 return (SCFGA_CONTINUE
); /* not a tape */
878 cp
= dyntp
->devlink
+ strlen(DEV_DIR SLASH
);
879 if ((dyntp
->dyncomp
= strdup(cp
)) == NULL
) {
880 dyntp
->l_errno
= errno
;
884 /* Get the leaf component from rmt/xyz */
885 cp
= strrchr(dyntp
->dyncomp
, '/');
887 /* Remove the mode part */
888 while (isdigit(*(++cp
))) {
893 dyntp
->ret
= SCFGA_OK
;
894 return (SCFGA_TERMINATE
);
897 dyntp
->ret
= SCFGA_LIB_ERR
;
898 return (SCFGA_TERMINATE
);
902 tape_dyncomp_to_devlink(dyn_t
*dyntp
)
904 char buf
[MAXPATHLEN
], *cp
= NULL
;
909 assert(dyntp
->dyncomp
!= NULL
);
913 if (dyntp
->devlink
!= NULL
) {
917 if (strncmp(dyntp
->dyncomp
, RMT_DIR SLASH
, strlen(RMT_DIR SLASH
))) {
918 return (SCFGA_CONTINUE
); /* not a tape */
922 (void) snprintf(buf
, sizeof (buf
), "%s%s", DEV_DIR SLASH
,
927 len
= sizeof (buf
) - len
;
929 for (i
= 0; i
< N_TAPE_MODES
; i
++) {
930 (void) snprintf(cp
, len
, "%s", tape_modes
[i
]);
932 if (lstat(buf
, &sbuf
) != -1 && S_ISLNK(sbuf
.st_mode
)) {
933 if ((dyntp
->devlink
= strdup(buf
)) == NULL
) {
934 dyntp
->l_errno
= errno
;
937 dyntp
->ret
= SCFGA_OK
;
938 return (SCFGA_TERMINATE
);
942 dyntp
->ret
= SCFGA_APID_NOEXIST
;
943 return (SCFGA_TERMINATE
);
946 dyntp
->ret
= SCFGA_LIB_ERR
;
947 return (SCFGA_TERMINATE
);
955 def_devlink_to_dyncomp(dyn_t
*dyntp
)
960 assert(dyntp
->devlink
!= NULL
);
964 if (dyntp
->dyncomp
!= NULL
) {
965 dyntp
->ret
= SCFGA_LIB_ERR
;
966 return (SCFGA_TERMINATE
);
969 /* Is it a link in DEV_DIR directory ? */
970 len
= strlen(DEV_DIR SLASH
);
971 if (strncmp(dyntp
->devlink
, DEV_DIR SLASH
, len
)) {
972 return (SCFGA_CONTINUE
);
975 /* Check if this is a top level devlink */
976 if (strchr(dyntp
->devlink
+ len
, '/') != NULL
) {
977 /* not top level - Remove DEV_DIR SLASH prefix */
978 cp
= dyntp
->devlink
+ len
;
980 /* top level, leave DEV_DIR SLASH part in */
984 if ((dyntp
->dyncomp
= strdup(cp
)) == NULL
) {
985 dyntp
->l_errno
= errno
;
986 dyntp
->ret
= SCFGA_LIB_ERR
;
988 dyntp
->ret
= SCFGA_OK
;
991 return (SCFGA_TERMINATE
);
996 def_dyncomp_to_devlink(dyn_t
*dyntp
)
1000 size_t prelen
, linklen
;
1002 assert(dyntp
->dyncomp
!= NULL
);
1006 if (dyntp
->devlink
!= NULL
) {
1010 prelen
= strlen(DEV_DIR SLASH
);
1011 linklen
= strlen(dyntp
->dyncomp
) + 1;
1014 * Check if the dynamic component was derived from a top level entry
1017 if (strncmp(dyntp
->dyncomp
, DEV_DIR SLASH
, prelen
) == 0) {
1019 } else if (*dyntp
->dyncomp
!= '/' && linklen
> 1 &&
1020 strchr(dyntp
->dyncomp
+ 1, '/') != NULL
) {
1022 linklen
+= prelen
; /* The "/dev/" needs to be prepended */
1024 /* Not a dynamic component we handle */
1025 return (SCFGA_CONTINUE
);
1028 if ((dyntp
->devlink
= calloc(1, linklen
)) == NULL
) {
1029 dyntp
->l_errno
= errno
;
1033 *dyntp
->devlink
= '\0';
1035 (void) strcpy(dyntp
->devlink
, DEV_DIR SLASH
);
1037 (void) strcat(dyntp
->devlink
, dyntp
->dyncomp
);
1039 if (lstat(dyntp
->devlink
, &sbuf
) != -1 && S_ISLNK(sbuf
.st_mode
)) {
1040 dyntp
->ret
= SCFGA_OK
;
1041 return (SCFGA_TERMINATE
);
1045 S_FREE(dyntp
->devlink
);
1046 return (SCFGA_CONTINUE
);
1049 dyntp
->ret
= SCFGA_LIB_ERR
;
1050 return (SCFGA_TERMINATE
);