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.
27 #include <sys/types.h>
38 #define MAXNBKTS 10007
40 static const int hashsize
[] = {
41 3, 7, 13, 31, 53, 67, 83, 97,
42 101, 151, 211, 251, 307, 353, 401, 457, 503,
43 557, 601, 653, 701, 751, 809, 859, 907, 953,
44 1009, 1103, 1201, 1301, 1409, 1511, 1601, 1709, 1801,
45 1901, 2003, 2111, 2203, 2309, 2411, 2503, 2609, 2707,
46 2801, 2903, 3001, 3109, 3203, 3301, 3407, 3511, 3607,
47 3701, 3803, 3907, 4001, 5003, 6101, 7001, 8101, 9001,
52 * Generate a configuration file from the internal configuration information.
53 * (very link-editor like).
56 genconfig(Crle_desc
*crle
)
59 size_t size
, hashoff
= 0, stroff
= 0, objoff
= 0;
60 size_t diroff
= 0, fileoff
= 0, envoff
= 0;
61 size_t fltroff
= 0, flteoff
= 0;
65 Word
*hashtbl
, *hashbkt
, *hashchn
, hashbkts
= 0;
66 char *strtbl
, *_strtbl
;
72 Rtc_flte
*fltetbl
, * _fltetbl
;
73 Hash_tbl
*stbl
= crle
->c_strtbl
;
77 * Establish the size of the configuration file.
79 size
= S_ROUND(sizeof (Rtc_head
), sizeof (Word
));
81 if (crle
->c_hashstrnum
) {
85 * Increment the hash string number to account for an initial
86 * null entry. Indexes start at 1 to simplify hash lookup.
91 * Determine the hash table size. Establish the number of
92 * buckets from the number of strings, the number of chains is
93 * equivalent to the number of objects, and two entries for the
94 * nbucket and nchain entries.
96 for (ndx
= 0; ndx
< (sizeof (hashsize
) / sizeof (int)); ndx
++) {
97 if (crle
->c_hashstrnum
> hashsize
[ndx
])
99 hashbkts
= hashsize
[ndx
];
104 size
+= ((2 + hashbkts
+ crle
->c_hashstrnum
) * sizeof (Word
));
105 size
= S_ROUND(size
, sizeof (Lword
));
109 * Add the object table size (account for an 8-byte alignment
110 * requirement for each object).
112 size
+= (crle
->c_hashstrnum
*
113 S_ROUND(sizeof (Rtc_obj
), sizeof (Lword
)));
116 * Add the file descriptor arrays.
119 size
+= S_ROUND((crle
->c_filenum
* sizeof (Rtc_file
)),
123 * Add the directory descriptor array.
126 size
+= S_ROUND((crle
->c_dirnum
* sizeof (Rtc_dir
)),
131 * Add any environment string array (insure zero last entry).
133 if (crle
->c_envnum
) {
135 size
+= S_ROUND(((crle
->c_envnum
+ 1) * sizeof (Rtc_env
)),
140 * Add any filter/filtee association arrays (insure zero last entry for
141 * the filter array, the filtee arrays are already accounted for).
143 if (crle
->c_fltrnum
) {
145 size
+= S_ROUND(((crle
->c_fltrnum
+ 1) * sizeof (Rtc_fltr
)),
148 size
+= S_ROUND((crle
->c_fltenum
* sizeof (Rtc_flte
)),
153 * Add the string table size (this may contain library and/or secure
154 * path strings, in addition to any directory/file strings).
156 if (crle
->c_strsize
) {
158 size
+= S_ROUND(crle
->c_strsize
, sizeof (Word
));
161 /* Account for addition of Rtc_id block at the start */
162 if (crle
->c_flags
& CRLE_ADDID
)
163 size
+= sizeof (Rtc_id
);
166 * Truncate our temporary file now that we know its size and map it.
168 if (ftruncate(crle
->c_tempfd
, size
) == -1) {
170 (void) fprintf(stderr
, MSG_INTL(MSG_SYS_TRUNC
),
171 crle
->c_name
, crle
->c_tempname
, strerror(err
));
172 (void) close(crle
->c_tempfd
);
175 if ((addr
= (Addr
)mmap(NULL
, size
, (PROT_READ
| PROT_WRITE
), MAP_SHARED
,
176 crle
->c_tempfd
, 0)) == (Addr
)-1) {
178 (void) fprintf(stderr
, MSG_INTL(MSG_SYS_MMAP
),
179 crle
->c_name
, crle
->c_tempname
, strerror(err
));
180 (void) close(crle
->c_tempfd
);
185 * Save the mapped files info for possible dldump(3dl) updates.
187 crle
->c_tempaddr
= addr
;
188 crle
->c_tempsize
= size
;
191 * Rtc_id goes at the top, followed by the Rtc_head. We base
192 * all offset calculations relative to Rtc_head, not from
193 * the top of the file. This eases backwards compatability to
194 * older versons that lacked the Rtc_id at the top.
196 if (crle
->c_flags
& CRLE_ADDID
) {
197 /* The contents of the Rtc_id are all known at compile time */
198 static const Rtc_id id_template
= {
199 RTC_ID_MAG0
, RTC_ID_MAG1
, RTC_ID_MAG2
, RTC_ID_MAG3
,
200 M_CLASS
, M_DATA
, M_MACH
,
201 { 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
203 id
= (Rtc_id
*) addr
;
204 *id
= id_template
; /* Fill in the Rtc_id data */
205 addr
+= sizeof (Rtc_id
);
209 crle
->c_tempheadaddr
= addr
;
210 head
= (Rtc_head
*)addr
;
213 * Establish the real address of each of the structures within the file.
215 head
->ch_hash
= hashoff
;
217 hashtbl
= (Word
*)(CAST_PTRINT(char *, head
->ch_hash
) + addr
);
219 head
->ch_obj
= objoff
;
221 objtbl
= (Rtc_obj
*)(CAST_PTRINT(char *, head
->ch_obj
) + addr
);
222 objtbl
= (Rtc_obj
*)S_ROUND((uintptr_t)(objtbl
+ 1), sizeof (Lword
));
224 head
->ch_file
= fileoff
;
226 filetbl
= (Rtc_file
*)(CAST_PTRINT(char *, head
->ch_file
) + addr
);
228 head
->ch_dir
= diroff
;
230 dirtbl
= (Rtc_dir
*)(CAST_PTRINT(char *, head
->ch_dir
) + addr
);
232 head
->ch_env
= envoff
;
234 envtbl
= (Rtc_env
*)(CAST_PTRINT(char *, head
->ch_env
) + addr
);
236 head
->ch_fltr
= fltroff
;
238 fltrtbl
= (Rtc_fltr
*)(CAST_PTRINT(char *, head
->ch_fltr
) + addr
);
239 head
->ch_flte
= flteoff
;
241 fltetbl
= _fltetbl
= (Rtc_flte
*)(CAST_PTRINT(char *, head
->ch_flte
) +
244 head
->ch_str
= stroff
;
245 strtbl
= _strtbl
= (char *)(CAST_PTRINT(char *, head
->ch_str
) + addr
);
248 * Fill in additional basic header information.
250 head
->ch_version
= RTC_VER_CURRENT
;
252 if (crle
->c_flags
& CRLE_ALTER
)
253 head
->ch_cnflags
|= RTC_HDR_ALTER
;
254 if (crle
->c_flags
& CRLE_DUMP
) {
255 head
->ch_cnflags
|= RTC_HDR_IGNORE
;
256 head
->ch_dlflags
= crle
->c_dlflags
;
259 head
->ch_cnflags
|= RTC_HDR_64
;
262 #ifndef SGS_PRE_UNIFIED_PROCESS
263 head
->ch_cnflags
|= RTC_HDR_UPM
;
266 * If we have a hash table then there are directory and file entries
269 if (crle
->c_hashstrnum
) {
270 hashtbl
[0] = hashbkts
;
271 hashtbl
[1] = crle
->c_hashstrnum
;
272 hashbkt
= &hashtbl
[2];
273 hashchn
= &hashtbl
[2 + hashbkts
];
276 * Insure all hash chain and directory/filename table entries
279 (void) memset(hashchn
, 0, (crle
->c_hashstrnum
* sizeof (Word
)));
280 (void) memset(dirtbl
, 0, (strtbl
- (char *)dirtbl
));
283 * Loop through the current string table list inspecting only
286 for (ndx
= 1, bkt
= 0; bkt
< stbl
->t_size
; bkt
++) {
287 for (ent
= stbl
->t_entry
[bkt
]; ent
; ent
= ent
->e_next
) {
289 Hash_obj
*obj
= ent
->e_obj
;
290 char *dir
= (char *)ent
->e_key
;
294 * Skip any empty and non-directory entries.
297 ((obj
->o_flags
& RTC_OBJ_DIRENT
) == 0))
301 * Assign basic object attributes.
303 objtbl
->co_hash
= ent
->e_hash
;
304 objtbl
->co_id
= ent
->e_id
;
305 objtbl
->co_flags
= obj
->o_flags
| ent
->e_flags
;
306 objtbl
->co_info
= obj
->o_info
;
308 ent
->e_cobj
= objtbl
;
311 * Assign the directory name (from its key),
312 * and copy its name to the string table.
314 objtbl
->co_name
= (Addr
)(_strtbl
- strtbl
);
315 (void) strcpy(_strtbl
, dir
);
316 _strtbl
+= strlen(dir
) + 1;
319 * Establish an entry in the directory table and
320 * reserve space for its associated filename
321 * entries (note, we add a trailing null file
322 * entry to simplify later inspection of the
323 * final configuration file.
325 _dirtbl
= &dirtbl
[ent
->e_id
- 1];
327 CAST_PTRINT(Word
, ((char *)filetbl
- addr
));
329 CAST_PTRINT(Word
, ((char *)objtbl
- addr
));
332 filetbl
= (Rtc_file
*)((char *)filetbl
+
333 ((ent
->e_cnt
+ 1) * sizeof (Rtc_file
)));
336 * Add this object to the hash table.
338 hashval
= ent
->e_hash
% hashbkts
;
339 hashchn
[ndx
] = hashbkt
[hashval
];
340 hashbkt
[hashval
] = ndx
++;
343 * Increment Rt_obj pointer (make sure pointer
344 * falls on an 8-byte boundary).
347 (Rtc_obj
*)S_ROUND((uintptr_t)(objtbl
+ 1),
353 * Now collect all pathnames. These are typically full
354 * pathnames, but may also be relative. Simple filenames are
355 * recorded as offsets into these pathnames, thus we need to
356 * establish the new pathname first.
358 for (bkt
= 0; bkt
< stbl
->t_size
; bkt
++) {
359 for (ent
= stbl
->t_entry
[bkt
]; ent
; ent
= ent
->e_next
) {
361 Hash_obj
*obj
= ent
->e_obj
;
362 char *file
= (char *)ent
->e_key
;
369 * Skip empty and directory entries, and any
370 * simple filename entries.
373 (obj
->o_flags
& RTC_OBJ_DIRENT
) ||
378 * Assign basic object attributes.
380 objtbl
->co_hash
= ent
->e_hash
;
381 objtbl
->co_id
= ent
->e_id
;
382 objtbl
->co_flags
= obj
->o_flags
| ent
->e_flags
;
383 objtbl
->co_info
= obj
->o_info
;
385 ent
->e_cobj
= objtbl
;
388 * Assign the file name (from its key),
389 * and copy its name to the string table.
391 objtbl
->co_name
= (Addr
)(_strtbl
- strtbl
);
392 (void) strcpy(_strtbl
, file
);
393 _strtbl
+= strlen(file
) + 1;
396 * Add this file to its associated directory.
398 _dirtbl
= &dirtbl
[ent
->e_id
- 1];
400 _filetbl
= (Rtc_file
*)(CAST_PTRINT(char *,
401 _dirtbl
->cd_file
) + addr
);
403 _id
= --ent
->e_dir
->e_cnt
;
404 _filetbl
[_id
].cf_obj
=
405 CAST_PTRINT(Word
, ((char *)objtbl
- addr
));
408 * If object has an alternative, record it in
409 * the string table and assign the alternate
410 * pointer. The new alternative offset is
411 * retained for reuse in other filename entries.
413 if ((objtbl
->co_flags
& RTC_OBJ_ALTER
) &&
414 (obj
->o_calter
== 0)) {
416 objtbl
->co_alter
= obj
->o_calter
=
417 (Addr
)(_strtbl
- strtbl
);
418 (void) strcpy(_strtbl
, _str
);
419 _strtbl
+= strlen(_str
) + 1;
421 objtbl
->co_alter
= obj
->o_calter
;
424 * If object identifies the specific application
425 * for which this cache is relevant, record it
428 if ((objtbl
->co_flags
&
429 (RTC_OBJ_APP
| RTC_OBJ_REALPTH
)) ==
430 (RTC_OBJ_APP
| RTC_OBJ_REALPTH
))
431 head
->ch_app
= _filetbl
[_id
].cf_obj
;
434 * Add this object to the hash table.
436 hashval
= ent
->e_hash
% hashbkts
;
437 hashchn
[ndx
] = hashbkt
[hashval
];
438 hashbkt
[hashval
] = ndx
++;
441 * Increment Rt_obj pointer (make sure pointer
442 * falls on an 8-byte boundary).
445 S_ROUND((uintptr_t)(objtbl
+ 1),
451 * Finally pick off any simple filenames.
453 for (bkt
= 0; bkt
< stbl
->t_size
; bkt
++) {
454 for (ent
= stbl
->t_entry
[bkt
]; ent
; ent
= ent
->e_next
) {
456 Hash_obj
* obj
= ent
->e_obj
;
462 * Skip everything except simple filenames.
468 * Assign basic object attributes.
470 objtbl
->co_hash
= ent
->e_hash
;
471 objtbl
->co_id
= ent
->e_id
;
472 objtbl
->co_flags
= obj
->o_flags
| ent
->e_flags
;
473 objtbl
->co_info
= obj
->o_info
;
474 objtbl
->co_alter
= obj
->o_calter
;
476 ent
->e_cobj
= objtbl
;
479 * Assign the file name from its full name.
481 objtbl
->co_name
= (Addr
)(CAST_PTRINT(char *,
482 ent
->e_path
->e_cobj
->co_name
) + ent
->e_off
);
485 * Add this file to its associated directory.
487 _dirtbl
= &dirtbl
[ent
->e_id
- 1];
489 _filetbl
= (Rtc_file
*)
490 (CAST_PTRINT(char *, _dirtbl
->cd_file
) +
493 _id
= --ent
->e_dir
->e_cnt
;
494 _filetbl
[_id
].cf_obj
=
495 CAST_PTRINT(Word
, ((char *)objtbl
- addr
));
498 * Add this object to the hash table.
500 hashval
= ent
->e_hash
% hashbkts
;
501 hashchn
[ndx
] = hashbkt
[hashval
];
502 hashbkt
[hashval
] = ndx
++;
505 * Increment Rt_obj pointer (make sure pointer
506 * falls on an 8-byte boundary).
509 S_ROUND((uintptr_t)(objtbl
+ 1),
516 * Add any library, or secure path definitions.
518 if (crle
->c_edlibpath
) {
519 head
->ch_edlibpath
= head
->ch_str
+ (_strtbl
- strtbl
);
521 (void) strcpy(_strtbl
, crle
->c_edlibpath
);
522 _strtbl
+= strlen((char *)crle
->c_edlibpath
) + 1;
524 head
->ch_edlibpath
= 0;
526 if (crle
->c_adlibpath
) {
527 head
->ch_adlibpath
= head
->ch_str
+ (_strtbl
- strtbl
);
529 (void) strcpy(_strtbl
, crle
->c_adlibpath
);
530 _strtbl
+= strlen((char *)crle
->c_adlibpath
) + 1;
532 head
->ch_adlibpath
= 0;
534 if (crle
->c_eslibpath
) {
535 head
->ch_eslibpath
= head
->ch_str
+ (_strtbl
- strtbl
);
537 (void) strcpy(_strtbl
, crle
->c_eslibpath
);
538 _strtbl
+= strlen((char *)crle
->c_eslibpath
) + 1;
540 head
->ch_eslibpath
= 0;
542 if (crle
->c_aslibpath
) {
543 head
->ch_aslibpath
= head
->ch_str
+ (_strtbl
- strtbl
);
545 (void) strcpy(_strtbl
, crle
->c_aslibpath
);
546 _strtbl
+= strlen((char *)crle
->c_aslibpath
) + 1;
548 head
->ch_aslibpath
= 0;
551 * Add any environment variable entries.
553 if (crle
->c_envnum
) {
557 for (APLIST_TRAVERSE(crle
->c_env
, idx
, env
)) {
558 envtbl
->env_str
= head
->ch_str
+ (_strtbl
- strtbl
);
559 envtbl
->env_flags
= env
->e_flags
;
561 (void) strcpy(_strtbl
, env
->e_str
);
562 _strtbl
+= env
->e_totsz
;
567 envtbl
->env_flags
= 0;
571 * Add any filter/filtee association entries.
573 if (crle
->c_fltrnum
) {
577 for (APLIST_TRAVERSE(crle
->c_flt
, idx1
, flt
)) {
582 * Establish the filter name, and filtee string, as
583 * offsets into the configuration files string table.
584 * Establish the filtee as the offset into the filtee
587 fltrtbl
->fr_filter
= flt
->f_fent
->e_cobj
->co_name
;
588 fltrtbl
->fr_string
= _strtbl
- strtbl
;
589 (void) strcpy(_strtbl
, flt
->f_str
);
590 _strtbl
+= flt
->f_strsz
;
591 fltrtbl
->fr_filtee
= (Word
)
592 ((uintptr_t)_fltetbl
- (uintptr_t)fltetbl
);
594 for (APLIST_TRAVERSE(flt
->f_filtee
, idx2
, flte
)) {
596 * Establish the filtee name as the offset into
597 * the configuration files string table.
599 _fltetbl
->fe_filtee
= flte
->e_cobj
->co_name
;
602 _fltetbl
->fe_filtee
= 0;
603 _fltetbl
++, fltrtbl
++;
605 fltrtbl
->fr_filter
= 0;
606 fltrtbl
->fr_filtee
= 0;
610 * Flush everything out.
612 (void) close(crle
->c_tempfd
);
613 if (msync((void *)crle
->c_tempaddr
, crle
->c_tempsize
, MS_ASYNC
) == -1) {
615 (void) fprintf(stderr
, MSG_INTL(MSG_SYS_TRUNC
),
616 crle
->c_name
, crle
->c_tempname
, strerror(err
));
624 * Update a configuration file. If dldump()'ed images have been created then
625 * the memory reservation of those images is added to the configuration file.
626 * The temporary file is then moved into its final resting place.
629 updateconfig(Crle_desc
* crle
)
631 Rtc_head
*head
= (Rtc_head
*)crle
->c_tempheadaddr
;
633 if (crle
->c_flags
& CRLE_DUMP
) {
634 head
->ch_cnflags
&= ~RTC_HDR_IGNORE
;
636 if (msync((void *)crle
->c_tempaddr
, crle
->c_tempsize
,
639 (void) fprintf(stderr
, MSG_INTL(MSG_SYS_TRUNC
),
640 crle
->c_name
, crle
->c_tempname
, strerror(err
));
646 * If an original configuration file exists, remove it.
648 if (crle
->c_flags
& CRLE_EXISTS
)
649 (void) unlink(crle
->c_confil
);
652 * Move the config file to its final resting place. If the two files
653 * exist on the same filesystem a rename is sufficient.
655 if (crle
->c_flags
& CRLE_DIFFDEV
) {
658 if ((fd
= open(crle
->c_confil
, (O_RDWR
| O_CREAT
| O_TRUNC
),
661 (void) fprintf(stderr
, MSG_INTL(MSG_SYS_OPEN
),
662 crle
->c_name
, crle
->c_confil
, strerror(err
));
665 if (write(fd
, (void *)crle
->c_tempaddr
, crle
->c_tempsize
) !=
668 (void) fprintf(stderr
, MSG_INTL(MSG_SYS_WRITE
),
669 crle
->c_name
, crle
->c_confil
, strerror(err
));
673 (void) unlink(crle
->c_tempname
);
675 (void) rename(crle
->c_tempname
, crle
->c_confil
);