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]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
37 #include <sys/types.h>
50 #define ERR_MAJOR "invalid major number <%s> specified for <%s>"
51 #define ERR_MINOR "invalid minor number <%s> specified for <%s>"
52 #define ERR_MODE "invalid mode <%s> specified for <%s>"
53 #define ERR_RELPATH "relative pathname <%s> not permitted"
54 #define ERR_NULLPATH "NULL or garbled pathname"
55 #define ERR_LINK "invalid link specification <%s>"
56 #define ERR_LINKFTYPE "ftype <%c> does not match link specification <%s>"
57 #define ERR_LINKARGS "extra arguments in link specification <%s>"
58 #define ERR_LINKREL "relative pathname in link specification <%s>"
59 #define ERR_FTYPE "invalid ftype <%c> for <%s>"
60 #define ERR_ARGC "invalid number of arguments for <%s>"
61 #define ERR_SPECALL "ftype <%c> requires all fields to be specified"
63 static int validate(struct cfextra
*ext
, int argc
, char *argv
[]);
64 static void checkPaths(char *argv
[]);
67 installf(int argc
, char *argv
[])
74 if (strcmp(argv
[0], "-") != 0) {
76 usage(); /* at least pathname is required */
77 extlist
= calloc(2, sizeof (struct cfextra
*));
78 extlist
[0] = new = calloc(1, sizeof (struct cfextra
));
81 /* There is only one filename on the command line. */
83 if (validate(new, argc
, argv
))
88 /* Read stdin to obtain entries, which need to be sorted. */
91 extlist
= calloc(MALSIZ
, sizeof (struct cfextra
*));
92 while (fgets(line
, LSIZE
, stdin
) != NULL
) {
95 argv
[argc
++] = strtok(line
, " \t\n");
96 while (argv
[argc
] = strtok(NULL
, " \t\n"))
100 usage(); /* at least pathname is required */
102 new = calloc(1, sizeof (struct cfextra
));
104 progerr(strerror(errno
));
110 if (validate(new, argc
, argv
))
113 extlist
[eptnum
] = new;
114 if ((++eptnum
% MALSIZ
) == 0) {
115 extlist
= realloc(extlist
,
116 (sizeof (struct cfextra
*) * (eptnum
+MALSIZ
)));
118 progerr(strerror(errno
));
123 extlist
[eptnum
] = (struct cfextra
*)NULL
;
124 qsort((char *)extlist
, (unsigned)eptnum
, sizeof (struct cfextra
*),
130 validate(struct cfextra
*ext
, int argc
, char *argv
[])
133 int n
, allspec
, is_a_link
;
136 ept
= &(ext
->cf_ent
);
138 /* initialize cfent structure */
140 (void) gpkgmapvfp(ept
, (VFP_T
*)NULL
); /* This just clears stuff. */
144 (void) strncpy(ept
->pkg_class
, classname
, CLSSIZ
);
146 if (argv
[n
] == NULL
|| *(argv
[n
]) == '\000') {
147 progerr(gettext(ERR_NULLPATH
));
152 * It would be a good idea to figure out how to get much of
153 * this done using facilities in procmap.c - JST
155 if (pt
= strchr(argv
[n
], '=')) {
156 *pt
= '\0'; /* cut off pathname at the = sign */
161 if (RELATIVE(argv
[n
])) {
162 progerr(gettext(ERR_RELPATH
),
163 (argv
[n
] == NULL
) ? "unknown" : argv
[n
]);
167 /* get the pathnames */
168 if (eval_path(&(ext
->server_path
), &(ext
->client_path
),
169 &(ext
->map_path
), argv
[n
++]) == 0)
172 ept
->path
= ext
->client_path
;
174 /* This isn't likely to happen; but, better safe than sorry. */
175 if (RELATIVE(ept
->path
)) {
176 progerr(gettext(ERR_RELPATH
), ept
->path
);
181 /* links specifications should be handled right here */
182 ept
->ftype
= ((n
>= argc
) ? 'l' : argv
[n
++][0]);
184 /* If nothing follows the '=', it's invalid */
186 progerr(gettext(ERR_LINK
), ept
->path
);
190 /* Test for an argument after the link. */
192 progerr(gettext(ERR_LINKARGS
), ept
->path
);
197 * If it's a link but it's neither hard nor symbolic then
200 if (!strchr("sl", ept
->ftype
)) {
201 progerr(gettext(ERR_LINKFTYPE
), ept
->ftype
, ept
->path
);
205 ext
->server_local
= pathdup(pt
+1);
206 ext
->client_local
= ext
->server_local
;
208 ept
->ainfo
.local
= ext
->client_local
;
211 } else if (n
>= argc
) {
212 /* we are expecting to change object's contents */
216 ept
->ftype
= argv
[n
++][0];
217 if (strchr("sl", ept
->ftype
)) {
218 progerr(gettext(ERR_LINK
), ept
->path
);
220 } else if (!strchr("?fvedxcbp", ept
->ftype
)) {
221 progerr(gettext(ERR_FTYPE
), ept
->ftype
, ept
->path
);
225 if (ept
->ftype
== 'b' || ept
->ftype
== 'c') {
227 ept
->ainfo
.major
= strtol(argv
[n
++], &ret
, 0);
229 progerr(gettext(ERR_MAJOR
), argv
[n
-1],
235 ept
->ainfo
.minor
= strtol(argv
[n
++], &ret
, 0);
237 progerr(gettext(ERR_MINOR
), argv
[n
-1],
247 ept
->ainfo
.mode
= strtol(argv
[n
++], &ret
, 8);
249 progerr(gettext(ERR_MODE
), argv
[n
-1], ept
->path
);
254 (void) strncpy(ept
->ainfo
.owner
, argv
[n
++], ATRSIZ
);
256 (void) strncpy(ept
->ainfo
.group
, argv
[n
++], ATRSIZ
);
259 if (strchr("dxbcp", ept
->ftype
) && !allspec
) {
260 progerr(gettext(ERR_ARGC
), ept
->path
);
261 progerr(gettext(ERR_SPECALL
), ept
->ftype
);
265 progerr(gettext(ERR_ARGC
), ept
->path
);
272 cfentcmp(const void *p1
, const void *p2
)
274 struct cfextra
*ext1
= *((struct cfextra
**)p1
);
275 struct cfextra
*ext2
= *((struct cfextra
**)p2
);
277 return (strcmp(ext1
->cf_ent
.path
, ext2
->cf_ent
.path
));
281 * If the path at argv[0] has the value of
282 * PKG_INSTALL_ROOT prepended, remove it
285 checkPaths(char *argv
[])
291 * Note- No local copy of argv is needed since this
292 * function is guaranteed to replace argv with a subset of
296 /* We only want to canonize the path if it contains multiple '/'s */
298 canonize_slashes(argv
[0]);
300 if ((root
= get_inst_root()) == NULL
)
302 if (strcmp(root
, "/") != 0) {
303 rootLen
= strlen(root
);
304 if (strncmp(argv
[0], root
, rootLen
) == 0) {