2 * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <si_module.h>
32 #include <arpa/inet.h>
33 #include <sys/param.h>
34 #include <sys/mount.h>
38 /* These really should be in netdb.h & etc. */
39 #define _PATH_RPCS "/etc/rpc"
40 #define _PATH_ALIASES "/etc/aliases"
41 #define _PATH_ETHERS "/etc/ethers"
43 static si_item_t
*rootfs
= NULL
;
46 _fsi_copy_string(char *s
)
51 if (s
== NULL
) return NULL
;
60 _fsi_append_string(char *s
, char **l
)
64 if (s
== NULL
) return l
;
67 l
= (char **)malloc(2 * sizeof(char *));
73 for (i
= 0; l
[i
] != NULL
; i
++);
74 len
= i
+ 1; /* count the NULL on the end of the list too! */
76 l
= (char **)reallocf(l
, (len
+ 1) * sizeof(char *));
83 __private_extern__
char **
84 _fsi_tokenize(char *data
, const char *sep
, int trailing_empty
, int *ntokens
)
87 int p
, i
, start
, end
, more
, len
, end_on_sep
;
93 if (data
== NULL
) return NULL
;
95 if (ntokens
!= NULL
) *ntokens
= 0;
98 tokens
= _fsi_append_string(data
, tokens
);
99 if (ntokens
!= NULL
) *ntokens
= *ntokens
+ 1;
106 while (data
[p
] != '\0')
109 /* skip leading white space */
110 while ((data
[p
] == ' ') || (data
[p
] == '\t') || (data
[p
] == '\n')) p
++;
112 /* check for end of line */
113 if (data
[p
] == '\0') break;
115 /* scan for separator */
121 while (scanning
== 1)
123 if (data
[p
] == '\0') break;
125 for (i
= 0; i
< len
; i
++)
127 if (data
[p
] == sep
[i
])
135 /* end is last non-whitespace character */
136 if ((scanning
== 1) && (data
[p
] != ' ') && (data
[p
] != '\t') && (data
[p
] != '\n')) end
= p
;
141 /* see if there's data left after p */
143 if (data
[p
] != '\0') more
= 1;
145 /* set the character following the token to nul */
146 if (start
== p
) data
[p
] = '\0';
147 else data
[end
+ 1] = '\0';
149 tokens
= _fsi_append_string(data
+ start
, tokens
);
150 if (ntokens
!= NULL
) *ntokens
= *ntokens
+ 1;
154 if ((end_on_sep
== 1) && (trailing_empty
!= 0))
156 /* if the scan ended on an empty token, add a null string */
157 tokens
= _fsi_append_string(data
+ p
, tokens
);
158 if (ntokens
!= NULL
) *ntokens
= *ntokens
+ 1;
164 __private_extern__
char *
165 _fsi_get_line(FILE *fp
)
172 fgets(s
, sizeof(s
), fp
);
173 if ((s
== NULL
) || (s
[0] == '\0')) return NULL
;
175 if (s
[0] != '#') s
[strlen(s
) - 1] = '\0';
177 out
= _fsi_copy_string(s
);
184 _fsi_parse_user(si_mod_t
*si
, const char *name
, uid_t uid
, int which
, char *data
, int format
, uint64_t sec
, uint64_t nsec
)
188 time_t change
, exsire
;
192 if (data
== NULL
) return NULL
;
195 tokens
= _fsi_tokenize(data
, ":", 1, &ntokens
);
196 if (((format
== 0) && (ntokens
!= 10)) || ((format
== 1) && (ntokens
!= 7)))
202 xuid
= atoi(tokens
[2]);
205 /* XXX MATCH GECOS? XXX*/
206 if (which
== SEL_ALL
) match
= 1;
207 else if ((which
== SEL_NAME
) && (string_equal(name
, tokens
[0]))) match
= 1;
208 else if ((which
== SEL_NUMBER
) && (uid
== xuid
)) match
= 1;
218 /* master.passwd: name[0] passwd[1] uid[2] gid[3] class[4] change[5] exsire[6] gecos[7] dir[8] shell[9] */
219 /* struct pwd: name[0] passwd[1] uid[2] gid[3] change[5] class[4] gecos[7] dir[8] shell[9] exsire[6] */
220 change
= atoi(tokens
[5]);
221 exsire
= atoi(tokens
[6]);
222 item
= (si_item_t
*)LI_ils_create("L4488ss44LssssL", (unsigned long)si
, CATEGORY_USER
, 1, sec
, nsec
, tokens
[0], tokens
[1], xuid
, atoi(tokens
[3]), change
, tokens
[4], tokens
[7], tokens
[8], tokens
[9], exsire
);
226 /* passwd: name[0] passwd[1] uid[2] gid[3] gecos[4] dir[5] shell[6] */
227 /* struct pwd: name[0] passwd[1] uid[2] gid[3] change[-] class[-] gecos[4] dir[5] shell[6] exsire[-] */
228 item
= (si_item_t
*)LI_ils_create("L4488ss44LssssL", (unsigned long)si
, CATEGORY_USER
, 1, sec
, nsec
, tokens
[0], tokens
[1], xuid
, atoi(tokens
[3]), 0, "", tokens
[4], tokens
[5], tokens
[6], 0);
236 _fsi_get_user(si_mod_t
*si
, const char *name
, uid_t uid
, int which
)
246 if ((which
== SEL_NAME
) && (name
== NULL
)) return NULL
;
256 f
= fopen(_PATH_MASTERPASSWD
, "r");
260 f
= fopen(_PATH_PASSWD
, "r");
264 if (f
== NULL
) return NULL
;
266 memset(&sb
, 0, sizeof(struct stat
));
267 if (fstat(fileno(f
), &sb
) == 0)
269 sec
= sb
.st_mtimespec
.tv_sec
;
270 nsec
= sb
.st_mtimespec
.tv_nsec
;
275 line
= _fsi_get_line(f
);
276 if (line
== NULL
) break;
285 item
= _fsi_parse_user(si
, name
, uid
, which
, line
, fmt
, sec
, nsec
);
289 if (item
== NULL
) continue;
291 if (which
== SEL_ALL
)
293 all
= si_list_add(all
, item
);
294 si_item_release(item
);
308 _fsi_parse_group(si_mod_t
*si
, const char *name
, gid_t gid
, int which
, char *data
, uint64_t sec
, uint64_t nsec
)
310 char **tokens
, **members
;
315 if (data
== NULL
) return NULL
;
318 tokens
= _fsi_tokenize(data
, ":", 1, &ntokens
);
325 xgid
= atoi(tokens
[2]);
328 if (which
== SEL_ALL
) match
= 1;
329 else if ((which
== SEL_NAME
) && (string_equal(name
, tokens
[0]))) match
= 1;
330 else if ((which
== SEL_NUMBER
) && (gid
== xgid
)) match
= 1;
339 members
= _fsi_tokenize(tokens
[3], ",", 1, &ntokens
);
341 item
= (si_item_t
*)LI_ils_create("L4488ss4*", (unsigned long)si
, CATEGORY_GROUP
, 1, sec
, nsec
, tokens
[0], tokens
[1], xgid
, members
);
350 _fsi_get_group(si_mod_t
*si
, const char *name
, gid_t gid
, int which
)
359 if ((which
== SEL_NAME
) && (name
== NULL
)) return NULL
;
366 f
= fopen(_PATH_GROUP
, "r");
367 if (f
== NULL
) return NULL
;
369 memset(&sb
, 0, sizeof(struct stat
));
370 if (fstat(fileno(f
), &sb
) == 0)
372 sec
= sb
.st_mtimespec
.tv_sec
;
373 nsec
= sb
.st_mtimespec
.tv_nsec
;
378 line
= _fsi_get_line(f
);
379 if (line
== NULL
) break;
388 item
= _fsi_parse_group(si
, name
, gid
, which
, line
, sec
, nsec
);
392 if (item
== NULL
) continue;
394 if (which
== SEL_ALL
)
396 all
= si_list_add(all
, item
);
397 si_item_release(item
);
410 _fsi_get_grouplist(si_mod_t
*si
, const char *user
)
412 char **tokens
, **members
;
413 int ntokens
, i
, match
, gidcount
;
419 int32_t gid
, basegid
, *gidp
;
423 if (user
== NULL
) return NULL
;
432 item
= si
->sim_user_byname(si
, user
);
435 pw
= (struct passwd
*)((uintptr_t)item
+ sizeof(si_item_t
));
436 basegid
= pw
->pw_gid
;
440 f
= fopen(_PATH_GROUP
, "r");
441 if (f
== NULL
) return NULL
;
443 memset(&sb
, 0, sizeof(struct stat
));
444 if (fstat(fileno(f
), &sb
) == 0)
446 sec
= sb
.st_mtimespec
.tv_sec
;
447 nsec
= sb
.st_mtimespec
.tv_nsec
;
452 line
= _fsi_get_line(f
);
453 if (line
== NULL
) break;
463 tokens
= _fsi_tokenize(line
, ":", 1, &ntokens
);
471 members
= _fsi_tokenize(tokens
[3], ",", 1, &ntokens
);
476 for (i
= 0; (i
< ntokens
) && (match
== 0); i
++)
478 if (string_equal(user
, members
[i
]))
480 gid
= atoi(tokens
[2]);
492 if (gidcount
== 0) gidlist
= (char **)calloc(1, sizeof(char *));
493 else gidlist
= (char **)reallocf(gidlist
, (gidcount
+ 1) * sizeof(char *));
494 gidp
= (int32_t *)calloc(1, sizeof(int32_t));
504 for (i
= 0; i
< gidcount
; i
++) free(gidlist
[i
]);
511 gidlist
[gidcount
++] = (char *)gidp
;
517 if (gidcount
== 0) return NULL
;
519 gidlist
= (char **)reallocf(gidlist
, (gidcount
+ 1) * sizeof(int32_t *));
520 if (gidlist
== NULL
) return NULL
;
521 gidlist
[gidcount
] = NULL
;
523 item
= (si_item_t
*)LI_ils_create("L4488s44a", (unsigned long)si
, CATEGORY_GROUPLIST
, 1, sec
, nsec
, user
, basegid
, gidcount
, gidlist
);
525 for (i
= 0; i
<= gidcount
; i
++) free(gidlist
[i
]);
534 _fsi_parse_alias(si_mod_t
*si
, const char *name
, int which
, char *data
, uint64_t sec
, uint64_t nsec
)
536 char **tokens
, **members
;
540 if (data
== NULL
) return NULL
;
543 tokens
= _fsi_tokenize(data
, ":", 1, &ntokens
);
552 if (which
== SEL_ALL
) match
= 1;
553 else if (string_equal(name
, tokens
[0])) match
= 1;
562 members
= _fsi_tokenize(tokens
[3], ",", 1, &ntokens
);
564 item
= (si_item_t
*)LI_ils_create("L4488s4*4", (unsigned long)si
, CATEGORY_ALIAS
, 1, sec
, nsec
, tokens
[0], ntokens
, members
, 1);
573 _fsi_get_alias(si_mod_t
*si
, const char *name
, int which
)
582 if ((which
== SEL_NAME
) && (name
== NULL
)) return NULL
;
589 f
= fopen(_PATH_ALIASES
, "r");
590 if (f
== NULL
) return NULL
;
592 memset(&sb
, 0, sizeof(struct stat
));
593 if (fstat(fileno(f
), &sb
) == 0)
595 sec
= sb
.st_mtimespec
.tv_sec
;
596 nsec
= sb
.st_mtimespec
.tv_nsec
;
601 line
= _fsi_get_line(f
);
602 if (line
== NULL
) break;
611 item
= _fsi_parse_alias(si
, name
, which
, line
, sec
, nsec
);
615 if (item
== NULL
) continue;
617 if (which
== SEL_ALL
)
619 all
= si_list_add(all
, item
);
620 si_item_release(item
);
635 _fsi_parse_ether(si_mod_t
*si
, const char *name
, int which
, char *data
, uint64_t sec
, uint64_t nsec
)
642 if (data
== NULL
) return NULL
;
645 tokens
= _fsi_tokenize(data
, " \t", 1, &ntokens
);
652 cmac
= si_canonical_mac_address(tokens
[1]);
660 if (which
== SEL_ALL
) match
= 1;
661 else if ((which
== SEL_NAME
) && (string_equal(name
, tokens
[0]))) match
= 1;
662 else if ((which
== SEL_NUMBER
) && (string_equal(name
, cmac
))) match
= 1;
671 item
= (si_item_t
*)LI_ils_create("L4488ss", (unsigned long)si
, CATEGORY_MAC
, 1, sec
, nsec
, tokens
[0], cmac
);
680 _fsi_get_ether(si_mod_t
*si
, const char *name
, int which
)
689 if ((which
!= SEL_ALL
) && (name
== NULL
)) return NULL
;
692 if (which
== SEL_NUMBER
)
694 cmac
= si_canonical_mac_address(name
);
695 if (cmac
== NULL
) return NULL
;
703 f
= fopen(_PATH_ETHERS
, "r");
704 if (f
== NULL
) return NULL
;
706 memset(&sb
, 0, sizeof(struct stat
));
707 if (fstat(fileno(f
), &sb
) == 0)
709 sec
= sb
.st_mtimespec
.tv_sec
;
710 nsec
= sb
.st_mtimespec
.tv_nsec
;
715 line
= _fsi_get_line(f
);
716 if (line
== NULL
) break;
726 if (which
== SEL_NUMBER
) item
= _fsi_parse_ether(si
, cmac
, which
, line
, sec
, nsec
);
727 else item
= _fsi_parse_ether(si
, name
, which
, line
, sec
, nsec
);
732 if (item
== NULL
) continue;
734 if (which
== SEL_ALL
)
736 all
= si_list_add(all
, item
);
737 si_item_release(item
);
752 _fsi_parse_host(si_mod_t
*si
, const char *name
, const void *addr
, int af
, int which
, char *data
, uint64_t sec
, uint64_t nsec
)
754 char **tokens
, **h_aliases
, *null_alias
;
755 int i
, ntokens
, match
, xaf
, h_length
;
759 char *h_addr_list
[2];
760 char h_addr_4
[4], h_addr_6
[16];
762 if (data
== NULL
) return NULL
;
767 tokens
= _fsi_tokenize(data
, " ", 0, &ntokens
);
774 h_addr_list
[1] = NULL
;
777 if (inet_pton(AF_INET
, tokens
[0], &a4
) == 1)
780 h_length
= sizeof(struct in_addr
);
781 memcpy(h_addr_4
, &a4
, 4);
782 h_addr_list
[0] = h_addr_4
;
784 else if (inet_pton(AF_INET6
, tokens
[0], &a6
) == 1)
787 h_length
= sizeof(struct in6_addr
);
788 memcpy(h_addr_6
, &a6
, 16);
789 h_addr_list
[0] = h_addr_6
;
792 if (xaf
== AF_UNSPEC
)
799 if (ntokens
> 2) h_aliases
= &(tokens
[2]);
803 if (which
== SEL_ALL
) match
= 1;
808 if (which
== SEL_NAME
)
810 if (string_equal(name
, tokens
[1])) match
= 1;
811 else if (h_aliases
!= NULL
)
813 for (i
= 0; (h_aliases
[i
] != NULL
) && (match
== 0); i
++)
814 if (string_equal(name
, h_aliases
[i
])) match
= 1;
817 else if (which
== SEL_NUMBER
)
819 if (memcmp(addr
, h_addr_list
[0], h_length
) == 0) match
= 1;
832 if (h_aliases
== NULL
) h_aliases
= &null_alias
;
836 item
= (si_item_t
*)LI_ils_create("L4488s*44a", (unsigned long)si
, CATEGORY_HOST_IPV4
, 1, sec
, nsec
, tokens
[1], h_aliases
, af
, h_length
, h_addr_list
);
840 item
= (si_item_t
*)LI_ils_create("L4488s*44c", (unsigned long)si
, CATEGORY_HOST_IPV6
, 1, sec
, nsec
, tokens
[1], h_aliases
, af
, h_length
, h_addr_list
);
849 _fsi_get_host(si_mod_t
*si
, const char *name
, const void *addr
, int af
, int which
, uint32_t *err
)
861 if ((which
== SEL_NAME
) && (name
== NULL
))
863 if (err
!= NULL
) *err
= NO_RECOVERY
;
867 if ((which
== SEL_NUMBER
) && (addr
== NULL
))
869 if (err
!= NULL
) *err
= NO_RECOVERY
;
873 f
= fopen(_PATH_HOSTS
, "r");
876 if (err
!= NULL
) *err
= NO_RECOVERY
;
880 memset(&sb
, 0, sizeof(struct stat
));
881 if (fstat(fileno(f
), &sb
) == 0)
883 sec
= sb
.st_mtimespec
.tv_sec
;
884 nsec
= sb
.st_mtimespec
.tv_nsec
;
891 line
= _fsi_get_line(f
);
892 if (line
== NULL
) break;
901 item
= _fsi_parse_host(si
, name
, addr
, af
, which
, line
, sec
, nsec
);
905 if (item
== NULL
) continue;
907 if (which
== SEL_ALL
)
909 all
= si_list_add(all
, item
);
910 si_item_release(item
);
925 _fsi_parse_service(si_mod_t
*si
, const char *name
, const char *proto
, int port
, int which
, char *data
, uint64_t sec
, uint64_t nsec
)
927 char **tokens
, **s_aliases
, *xproto
;
928 int i
, ntokens
, match
;
932 if (data
== NULL
) return NULL
;
937 tokens
= _fsi_tokenize(data
, " ", 0, &ntokens
);
945 if (ntokens
> 2) s_aliases
= &(tokens
[2]);
947 xport
= atoi(tokens
[1]);
949 xproto
= strchr(tokens
[1], '/');
958 if ((proto
!= NULL
) && (string_not_equal(proto
, xproto
)))
965 if (which
== SEL_ALL
) match
= 1;
966 else if (which
== SEL_NAME
)
968 if (string_equal(name
, tokens
[0])) match
= 1;
969 else if (s_aliases
!= NULL
)
971 for (i
= 0; (s_aliases
[i
] != NULL
) && (match
== 0); i
++)
972 if (string_equal(name
, s_aliases
[i
])) match
= 1;
975 else if ((which
== SEL_NUMBER
) && (port
== xport
)) match
= 1;
983 /* strange but correct */
984 xport
= htons(xport
);
986 item
= (si_item_t
*)LI_ils_create("L4488s*4s", (unsigned long)si
, CATEGORY_SERVICE
, 1, sec
, nsec
, tokens
[0], s_aliases
, xport
, xproto
);
994 _fsi_get_service(si_mod_t
*si
, const char *name
, const char *proto
, int port
, int which
)
1006 if ((which
== SEL_NAME
) && (name
== NULL
)) return NULL
;
1007 if ((which
== SEL_NUMBER
) && (port
== 0)) return NULL
;
1009 f
= fopen(_PATH_SERVICES
, "r");
1010 if (f
== NULL
) return NULL
;
1012 memset(&sb
, 0, sizeof(struct stat
));
1013 if (fstat(fileno(f
), &sb
) == 0)
1015 sec
= sb
.st_mtimespec
.tv_sec
;
1016 nsec
= sb
.st_mtimespec
.tv_nsec
;
1023 line
= _fsi_get_line(f
);
1024 if (line
== NULL
) break;
1033 p
= strchr(line
, '#');
1034 if (p
!= NULL
) *p
= '\0';
1036 item
= _fsi_parse_service(si
, name
, proto
, port
, which
, line
, sec
, nsec
);
1040 if (item
== NULL
) continue;
1042 if (which
== SEL_ALL
)
1044 all
= si_list_add(all
, item
);
1045 si_item_release(item
);
1058 * Generic name/number/aliases lookup
1059 * Works for protocols, networks, and rpcs
1063 _fsi_parse_name_num_aliases(si_mod_t
*si
, const char *name
, int num
, int which
, char *data
, uint64_t sec
, uint64_t nsec
, int cat
)
1065 char **tokens
, **aliases
;
1066 int i
, ntokens
, match
, xnum
;
1069 if (data
== NULL
) return NULL
;
1072 tokens
= _fsi_tokenize(data
, " ", 0, &ntokens
);
1079 xnum
= atoi(tokens
[1]);
1082 if (ntokens
> 2) aliases
= &(tokens
[2]);
1086 if (which
== SEL_ALL
) match
= 1;
1087 else if (which
== SEL_NAME
)
1089 if (string_equal(name
, tokens
[0])) match
= 1;
1090 else if (aliases
!= NULL
)
1092 for (i
= 0; (aliases
[i
] != NULL
) && (match
== 0); i
++)
1093 if (string_equal(name
, aliases
[i
])) match
= 1;
1096 else if ((which
== SEL_NUMBER
) && (num
== xnum
)) match
= 1;
1104 item
= (si_item_t
*)LI_ils_create("L4488s*4", (unsigned long)si
, cat
, 1, sec
, nsec
, tokens
[0], aliases
, xnum
);
1112 _fsi_get_name_number_aliases(si_mod_t
*si
, const char *name
, int num
, int which
, int cat
, const char *path
)
1124 f
= fopen(path
, "r");
1125 if (f
== NULL
) return NULL
;
1127 memset(&sb
, 0, sizeof(struct stat
));
1128 if (fstat(fileno(f
), &sb
) == 0)
1130 sec
= sb
.st_mtimespec
.tv_sec
;
1131 nsec
= sb
.st_mtimespec
.tv_nsec
;
1138 line
= _fsi_get_line(f
);
1139 if (line
== NULL
) break;
1148 p
= strchr(line
, '#');
1149 if (p
!= NULL
) *p
= '\0';
1151 item
= _fsi_parse_name_num_aliases(si
, name
, num
, which
, line
, sec
, nsec
, cat
);
1155 if (item
== NULL
) continue;
1157 if (which
== SEL_ALL
)
1159 all
= si_list_add(all
, item
);
1160 si_item_release(item
);
1175 _fsi_parse_fs(si_mod_t
*si
, const char *name
, int which
, char *data
, uint64_t sec
, uint64_t nsec
)
1177 char **tokens
, *tmp
, **opts
, *fstype
;
1178 int ntokens
, match
, i
, freq
, passno
;
1181 if (data
== NULL
) return NULL
;
1188 tokens
= _fsi_tokenize(data
, " ", 0, &ntokens
);
1189 if ((ntokens
< 4) || (ntokens
> 6))
1195 if (ntokens
>= 5) freq
= atoi(tokens
[4]);
1196 if (ntokens
== 6) passno
= atoi(tokens
[5]);
1198 tmp
= strdup(tokens
[3]);
1206 opts
= _fsi_tokenize(tmp
, ",", 0, &ntokens
);
1215 for (i
= 0; i
< ntokens
; i
++)
1217 if ((string_equal(opts
[i
], "rw")) || (string_equal(opts
[i
], "ro")) || (string_equal(opts
[i
], "sw")) || (string_equal(opts
[i
], "xx")))
1226 if (which
== SEL_ALL
) match
= 1;
1227 else if ((which
== SEL_NAME
) && (string_equal(name
, tokens
[0]))) match
= 1;
1228 else if ((which
== SEL_NUMBER
) && (string_equal(name
, tokens
[1]))) match
= 1;
1236 item
= (si_item_t
*)LI_ils_create("L4488sssss44", (unsigned long)si
, CATEGORY_FS
, 1, sec
, nsec
, tokens
[0], tokens
[1], tokens
[2], tokens
[3], (fstype
== NULL
) ? "rw" : fstype
, freq
, passno
);
1246 _fsi_get_device_path(dev_t target_dev
)
1251 char namebuf
[PATH_MAX
];
1255 strlcpy(dev
, _PATH_DEV
, sizeof(dev
));
1257 /* The root device in fstab should always be a block special device */
1258 name
= devname_r(target_dev
, S_IFBLK
, namebuf
, sizeof(namebuf
));
1263 struct dirent
*ent
, entbuf
;
1265 /* No _PATH_DEVDB. We have to search for it the slow way */
1266 dirp
= opendir(_PATH_DEV
);
1267 if (dirp
== NULL
) return NULL
;
1269 while (readdir_r(dirp
, &entbuf
, &ent
) == 0 && ent
!= NULL
)
1271 /* Look for a block special device */
1272 if (ent
->d_type
== DT_BLK
)
1274 strlcat(dev
, ent
->d_name
, sizeof(dev
));
1275 if (stat(dev
, &devst
) == 0)
1277 if (devst
.st_rdev
== target_dev
) {
1278 result
= strdup(dev
);
1284 /* reset dev to _PATH_DEV and try again */
1285 dev
[sizeof(_PATH_DEV
) - 1] = '\0';
1288 if (dirp
) closedir(dirp
);
1292 /* We found the _PATH_DEVDB entry */
1293 strlcat(dev
, name
, sizeof(dev
));
1294 result
= strdup(dev
);
1301 _fsi_fs_root(si_mod_t
*si
)
1303 struct stat rootstat
;
1304 struct statfs rootfsinfo
;
1306 const char *root_path
;
1308 if (rootfs
!= NULL
) return si_item_retain(rootfs
);
1312 if (stat(root_path
, &rootstat
) < 0) return NULL
;
1313 if (statfs(root_path
, &rootfsinfo
) < 0) return NULL
;
1315 /* Check to make sure we're not looking at a synthetic root: */
1316 if (string_equal(rootfsinfo
.f_fstypename
, "synthfs"))
1318 root_path
= "/root";
1319 if (stat(root_path
, &rootstat
) < 0) return NULL
;
1320 if (statfs(root_path
, &rootfsinfo
) < 0) return NULL
;
1323 root_spec
= _fsi_get_device_path(rootstat
.st_dev
);
1325 rootfs
= (si_item_t
*)LI_ils_create("L4488sssss44", (unsigned long)si
, CATEGORY_FS
, 1, 0LL, 0LL, root_spec
, root_path
, rootfsinfo
.f_fstypename
, FSTAB_RW
, FSTAB_RW
, 0, 1);
1331 _fsi_get_fs(si_mod_t
*si
, const char *name
, int which
)
1339 int synthesize_root
;
1342 if ((which
!= SEL_ALL
) && (name
== NULL
)) return NULL
;
1349 synthesize_root
= 1;
1351 synthesize_root
= 0;
1354 f
= fopen(_PATH_FSTAB
, "r");
1355 if ((f
== NULL
) || (synthesize_root
== 1))
1357 item
= _fsi_fs_root(si
);
1360 if (item
!= NULL
) rfs
= (struct fstab
*)((uintptr_t)item
+ sizeof(si_item_t
));
1366 if ((rfs
!= NULL
) && (string_equal(name
, rfs
->fs_spec
)))
1368 if (f
!= NULL
) fclose(f
);
1377 if ((rfs
!= NULL
) && (string_equal(name
, rfs
->fs_file
)))
1379 if (f
!= NULL
) fclose(f
);
1388 all
= si_list_add(all
, item
);
1389 si_item_release(item
);
1395 if (f
== NULL
) return all
;
1397 memset(&sb
, 0, sizeof(struct stat
));
1398 if (fstat(fileno(f
), &sb
) == 0)
1400 sec
= sb
.st_mtimespec
.tv_sec
;
1401 nsec
= sb
.st_mtimespec
.tv_nsec
;
1406 line
= _fsi_get_line(f
);
1407 if (line
== NULL
) break;
1416 item
= _fsi_parse_fs(si
, name
, which
, line
, sec
, nsec
);
1420 if (item
== NULL
) continue;
1422 if (which
== SEL_ALL
)
1424 all
= si_list_add(all
, item
);
1425 si_item_release(item
);
1437 __private_extern__
int
1438 file_is_valid(si_mod_t
*si
, si_item_t
*item
)
1445 if (si
== NULL
) return 0;
1446 if (item
== NULL
) return 0;
1447 if (si
->name
== NULL
) return 0;
1448 if (item
->src
== NULL
) return 0;
1450 src
= (si_mod_t
*)item
->src
;
1452 if (src
->name
== NULL
) return 0;
1453 if (string_not_equal(si
->name
, src
->name
)) return 0;
1455 if (item
== rootfs
) return 1;
1458 memset(&sb
, 0, sizeof(struct stat
));
1459 sec
= item
->validation_a
;
1460 nsec
= item
->validation_b
;
1462 if (item
->type
== CATEGORY_USER
)
1464 if (geteuid() == 0) path
= _PATH_MASTERPASSWD
;
1465 else path
= _PATH_PASSWD
;
1467 else if (item
->type
== CATEGORY_GROUP
) path
= _PATH_GROUP
;
1468 else if (item
->type
== CATEGORY_HOST_IPV4
) path
= _PATH_HOSTS
;
1469 else if (item
->type
== CATEGORY_HOST_IPV6
) path
= _PATH_HOSTS
;
1470 else if (item
->type
== CATEGORY_NETWORK
) path
= _PATH_NETWORKS
;
1471 else if (item
->type
== CATEGORY_SERVICE
) path
= _PATH_SERVICES
;
1472 else if (item
->type
== CATEGORY_PROTOCOL
) path
= _PATH_PROTOCOLS
;
1473 else if (item
->type
== CATEGORY_RPC
) path
= _PATH_RPCS
;
1474 else if (item
->type
== CATEGORY_FS
) path
= _PATH_FSTAB
;
1476 if (path
== NULL
) return 0;
1477 if (stat(path
, &sb
) != 0) return 0;
1478 if (sec
!= sb
.st_mtimespec
.tv_sec
) return 0;
1479 if (nsec
!= sb
.st_mtimespec
.tv_nsec
) return 0;
1484 __private_extern__ si_item_t
*
1485 file_user_byname(si_mod_t
*si
, const char *name
)
1487 return _fsi_get_user(si
, name
, 0, SEL_NAME
);
1490 __private_extern__ si_item_t
*
1491 file_user_byuid(si_mod_t
*si
, uid_t uid
)
1493 return _fsi_get_user(si
, NULL
, uid
, SEL_NUMBER
);
1496 __private_extern__ si_list_t
*
1497 file_user_all(si_mod_t
*si
)
1499 return _fsi_get_user(si
, NULL
, 0, SEL_ALL
);
1502 __private_extern__ si_item_t
*
1503 file_group_byname(si_mod_t
*si
, const char *name
)
1505 return _fsi_get_group(si
, name
, 0, SEL_NAME
);
1508 __private_extern__ si_item_t
*
1509 file_group_bygid(si_mod_t
*si
, gid_t gid
)
1511 return _fsi_get_group(si
, NULL
, gid
, SEL_NUMBER
);
1514 __private_extern__ si_list_t
*
1515 file_group_all(si_mod_t
*si
)
1517 return _fsi_get_group(si
, NULL
, 0, SEL_ALL
);
1520 __private_extern__ si_item_t
*
1521 file_grouplist(si_mod_t
*si
, const char *name
)
1523 return _fsi_get_grouplist(si
, name
);
1526 __private_extern__ si_item_t
*
1527 file_host_byname(si_mod_t
*si
, const char *name
, int af
, const char *ignored
, uint32_t *err
)
1531 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
1533 item
= _fsi_get_host(si
, name
, NULL
, af
, SEL_NAME
, err
);
1534 if ((item
== NULL
) && (err
!= NULL
) && (*err
== 0)) *err
= SI_STATUS_H_ERRNO_HOST_NOT_FOUND
;
1539 __private_extern__ si_item_t
*
1540 file_host_byaddr(si_mod_t
*si
, const void *addr
, int af
, const char *ignored
, uint32_t *err
)
1544 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
1546 item
= _fsi_get_host(si
, NULL
, addr
, af
, SEL_NUMBER
, err
);
1547 if ((item
== NULL
) && (err
!= NULL
) && (*err
== 0)) *err
= SI_STATUS_H_ERRNO_HOST_NOT_FOUND
;
1552 __private_extern__ si_list_t
*
1553 file_host_all(si_mod_t
*si
)
1555 return _fsi_get_host(si
, NULL
, NULL
, 0, SEL_ALL
, NULL
);
1558 __private_extern__ si_item_t
*
1559 file_network_byname(si_mod_t
*si
, const char *name
)
1561 if (name
== NULL
) return NULL
;
1562 return _fsi_get_name_number_aliases(si
, name
, 0, SEL_NAME
, CATEGORY_NETWORK
, _PATH_NETWORKS
);
1565 __private_extern__ si_item_t
*
1566 file_network_byaddr(si_mod_t
*si
, uint32_t addr
)
1568 return _fsi_get_name_number_aliases(si
, NULL
, (int)addr
, SEL_NUMBER
, CATEGORY_NETWORK
, _PATH_NETWORKS
);
1571 __private_extern__ si_list_t
*
1572 file_network_all(si_mod_t
*si
)
1574 return _fsi_get_name_number_aliases(si
, NULL
, 0, SEL_ALL
, CATEGORY_NETWORK
, _PATH_NETWORKS
);
1577 __private_extern__ si_item_t
*
1578 file_service_byname(si_mod_t
*si
, const char *name
, const char *proto
)
1580 return _fsi_get_service(si
, name
, proto
, 0, SEL_NAME
);
1583 __private_extern__ si_item_t
*
1584 file_service_byport(si_mod_t
*si
, int port
, const char *proto
)
1586 return _fsi_get_service(si
, NULL
, proto
, port
, SEL_NUMBER
);
1589 __private_extern__ si_list_t
*
1590 file_service_all(si_mod_t
*si
)
1592 return _fsi_get_service(si
, NULL
, NULL
, 0, SEL_ALL
);
1595 __private_extern__ si_item_t
*
1596 file_protocol_byname(si_mod_t
*si
, const char *name
)
1598 if (name
== NULL
) return NULL
;
1599 return _fsi_get_name_number_aliases(si
, name
, 0, SEL_NAME
, CATEGORY_PROTOCOL
, _PATH_PROTOCOLS
);
1602 __private_extern__ si_item_t
*
1603 file_protocol_bynumber(si_mod_t
*si
, int number
)
1605 return _fsi_get_name_number_aliases(si
, NULL
, number
, SEL_NUMBER
, CATEGORY_PROTOCOL
, _PATH_PROTOCOLS
);
1608 __private_extern__ si_list_t
*
1609 file_protocol_all(si_mod_t
*si
)
1611 return _fsi_get_name_number_aliases(si
, NULL
, 0, SEL_ALL
, CATEGORY_PROTOCOL
, _PATH_PROTOCOLS
);
1614 __private_extern__ si_item_t
*
1615 file_rpc_byname(si_mod_t
*si
, const char *name
)
1617 if (name
== NULL
) return NULL
;
1618 return _fsi_get_name_number_aliases(si
, name
, 0, SEL_NAME
, CATEGORY_RPC
, _PATH_RPCS
);
1621 __private_extern__ si_item_t
*
1622 file_rpc_bynumber(si_mod_t
*si
, int number
)
1624 return _fsi_get_name_number_aliases(si
, NULL
, number
, SEL_NUMBER
, CATEGORY_RPC
, _PATH_RPCS
);
1627 __private_extern__ si_list_t
*
1628 file_rpc_all(si_mod_t
*si
)
1630 return _fsi_get_name_number_aliases(si
, NULL
, 0, SEL_ALL
, CATEGORY_RPC
, _PATH_RPCS
);
1633 __private_extern__ si_item_t
*
1634 file_fs_byspec(si_mod_t
*si
, const char *spec
)
1636 return _fsi_get_fs(si
, spec
, SEL_NAME
);
1639 __private_extern__ si_item_t
*
1640 file_fs_byfile(si_mod_t
*si
, const char *file
)
1642 return _fsi_get_fs(si
, file
, SEL_NUMBER
);
1645 __private_extern__ si_list_t
*
1646 file_fs_all(si_mod_t
*si
)
1648 return _fsi_get_fs(si
, NULL
, SEL_ALL
);
1651 __private_extern__ si_item_t
*
1652 file_alias_byname(si_mod_t
*si
, const char *name
)
1654 return _fsi_get_alias(si
, name
, SEL_NAME
);
1657 __private_extern__ si_list_t
*
1658 file_alias_all(si_mod_t
*si
)
1660 return _fsi_get_alias(si
, NULL
, SEL_ALL
);
1663 __private_extern__ si_item_t
*
1664 file_mac_byname(si_mod_t
*si
, const char *name
)
1666 return _fsi_get_ether(si
, name
, SEL_NAME
);
1669 __private_extern__ si_item_t
*
1670 file_mac_bymac(si_mod_t
*si
, const char *mac
)
1672 return _fsi_get_ether(si
, mac
, SEL_NUMBER
);
1675 __private_extern__ si_list_t
*
1676 file_mac_all(si_mod_t
*si
)
1678 return _fsi_get_ether(si
, NULL
, SEL_ALL
);
1682 file_addrinfo(si_mod_t
*si
, const void *node
, const void *serv
, uint32_t family
, uint32_t socktype
, uint32_t proto
, uint32_t flags
, const char *interface
, uint32_t *err
)
1684 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
1685 return _gai_simple(si
, node
, serv
, family
, socktype
, proto
, flags
, interface
, err
);
1688 __private_extern__ si_mod_t
*
1689 si_module_static_file()
1694 out
= (si_mod_t
*)calloc(1, sizeof(si_mod_t
));
1695 outname
= strdup("file");
1697 if ((out
== NULL
) || (outname
== NULL
))
1699 if (out
!= NULL
) free(out
);
1700 if (outname
!= NULL
) free(outname
);
1706 out
->name
= outname
;
1710 out
->sim_is_valid
= file_is_valid
;
1712 out
->sim_user_byname
= file_user_byname
;
1713 out
->sim_user_byuid
= file_user_byuid
;
1714 out
->sim_user_all
= file_user_all
;
1716 out
->sim_group_byname
= file_group_byname
;
1717 out
->sim_group_bygid
= file_group_bygid
;
1718 out
->sim_group_all
= file_group_all
;
1720 out
->sim_grouplist
= file_grouplist
;
1722 /* NETGROUP SUPPORT NOT IMPLEMENTED */
1723 out
->sim_netgroup_byname
= NULL
;
1724 out
->sim_in_netgroup
= NULL
;
1726 out
->sim_alias_byname
= file_alias_byname
;
1727 out
->sim_alias_all
= file_alias_all
;
1729 out
->sim_host_byname
= file_host_byname
;
1730 out
->sim_host_byaddr
= file_host_byaddr
;
1731 out
->sim_host_all
= file_host_all
;
1733 out
->sim_network_byname
= file_network_byname
;
1734 out
->sim_network_byaddr
= file_network_byaddr
;
1735 out
->sim_network_all
= file_network_all
;
1737 out
->sim_service_byname
= file_service_byname
;
1738 out
->sim_service_byport
= file_service_byport
;
1739 out
->sim_service_all
= file_service_all
;
1741 out
->sim_protocol_byname
= file_protocol_byname
;
1742 out
->sim_protocol_bynumber
= file_protocol_bynumber
;
1743 out
->sim_protocol_all
= file_protocol_all
;
1745 out
->sim_rpc_byname
= file_rpc_byname
;
1746 out
->sim_rpc_bynumber
= file_rpc_bynumber
;
1747 out
->sim_rpc_all
= file_rpc_all
;
1749 out
->sim_fs_byspec
= file_fs_byspec
;
1750 out
->sim_fs_byfile
= file_fs_byfile
;
1751 out
->sim_fs_all
= file_fs_all
;
1753 out
->sim_mac_byname
= file_mac_byname
;
1754 out
->sim_mac_bymac
= file_mac_bymac
;
1755 out
->sim_mac_all
= file_mac_all
;
1757 out
->sim_wants_addrinfo
= NULL
;
1758 out
->sim_addrinfo
= file_addrinfo
;
1760 /* no nameinfo support */
1761 out
->sim_nameinfo
= NULL
;