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 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
34 #include <sys/param.h>
35 #include <sys/types.h>
38 #include <tsol/label.h>
42 #include "setupfiles.h"
44 #define dperror(s) if (flags & DIAG) perror(s)
45 #define dprintf(s, v) if (flags & DBUG) (void) printf(s, v)
46 #define dprintf2(s, v1, v2) if (flags & DBUG) (void) printf(s, v1, v2)
48 static int mkdirs(const char *dir
, const char *target
, int flags
);
49 static int copyfile(const char *min_home
, const char *home
, const char *target
,
51 static int linkfile(const char *min_home
, const char *home
, const char *target
,
56 * __setupfiles - Process copy and link files directions in min $HOME.
58 * Entry pwd = user's password file entry.
59 * min_sl = user's minimum SL.
60 * flags = DBUG, if print debug messages.
61 * DIAG, if print diagnostics (perrors).
62 * IGNE, continue rather than abort on failures.
63 * REPC, if replace existing file.
64 * REPL, if replace existing symbolic link.
65 * process is running as user at correct label.
69 * Returns 0, if success.
72 * Uses COPY, CP, LINK, MAXPATHLEN.
74 * Calls blequal, copyfile, feof, fgets, fopen,
75 * mkdirs, getzoneid, getzonelabelbyid, linkfile, strcat, strcpy,
78 * This program assumes the /zone is the autofs mountpoint for
81 * It also assumes that the user's home directory path is the
82 * the same in each zone, relative to the zone's root.
84 * At this point, the cross-zone automounter only supports home
85 * directories starting with /home
89 __setupfiles(const struct passwd
*pwd
, const m_label_t
*min_sl
, int flags
)
91 m_label_t
*plabel
; /* process label */
92 char home
[MAXPATHLEN
]; /* real path to current $HOME */
93 char min_home
[MAXPATHLEN
]; /* real path to min $HOME */
94 char cl_file
[MAXPATHLEN
]; /* real path to .copy/.link_files */
95 char file
[MAXPATHLEN
]; /* file to copy/link */
96 FILE *clf
; /* .copy/.link_file stream */
97 char zoneroot
[MAXPATHLEN
];
101 zoneid
= getzoneid();
102 if ((plabel
= getzonelabelbyid(zoneid
)) == NULL
) {
104 dperror("setupfiles can't get process label");
108 if (blequal(plabel
, min_sl
)) {
109 /* at min SL no files to setup */
114 /* get current home real path */
116 (void) strlcpy(home
, pwd
->pw_dir
, MAXPATHLEN
);
118 /* Get zone id from min_sl */
120 if ((min_zoneid
= getzoneidbylabel(min_sl
)) == -1) {
122 dperror("setupfiles can't get zoneid for min sl");
127 * Since the global zone home directories aren't public
128 * information, we don't support copy and link files there.
130 if (min_zoneid
== GLOBAL_ZONEID
)
134 * Get zone root path from zone id
136 * Could have used getzonenamebyid() but this assumes that /etc/zones
137 * directory is available, which is not true in labeled zones
140 if (zone_getattr(min_zoneid
, ZONE_ATTR_ROOT
, zoneroot
,
141 sizeof (zoneroot
)) == -1) {
142 dperror("setupfiles can't get zone root path for min sl");
146 (void) snprintf(min_home
, MAXPATHLEN
, "%s%s",
147 zoneroot
, pwd
->pw_dir
);
149 /* process copy files */
151 if ((strlen(min_home
) + strlen(COPY
)) > (MAXPATHLEN
- 1)) {
153 dprintf("setupfiles copy path %s", min_home
);
154 dprintf("%s ", COPY
);
155 dprintf("greater than %d\n", MAXPATHLEN
);
156 errno
= ENAMETOOLONG
;
157 dperror("setupfiles copy path");
161 (void) strcpy(cl_file
, min_home
);
162 (void) strcat(cl_file
, COPY
);
164 if ((clf
= fopen(cl_file
, "r")) != NULL
) {
166 while (fgets(file
, MAXPATHLEN
, clf
) != NULL
) {
168 if (!feof(clf
)) /* remove trailing \n */
169 file
[strlen(file
) - 1] = '\0';
171 dprintf("copy file %s requested\n", file
);
173 /* make any needed subdirectories */
175 if (mkdirs(home
, file
, flags
) != 0) {
177 if ((flags
& IGNE
) == 0)
185 if (copyfile(min_home
, home
, file
, flags
) != 0) {
187 if ((flags
& IGNE
) == 0)
194 } /* while (fgets( ... ) != NULL) */
197 dperror("setupfiles copy file open");
198 dprintf("setupfiles no copyfile %s\n", cl_file
);
199 } /* process copy files */
202 /* process link files */
204 if ((strlen(min_home
) + strlen(LINK
)) > (MAXPATHLEN
- 1)) {
206 dprintf("setupfiles link path %s", min_home
);
207 dprintf("%s ", LINK
);
208 dprintf("greater than %d\n", MAXPATHLEN
);
209 errno
= ENAMETOOLONG
;
210 dperror("setupfiles link path");
214 (void) strcpy(cl_file
, min_home
);
215 (void) strcat(cl_file
, LINK
);
217 if ((clf
= fopen(cl_file
, "r")) != NULL
) {
219 while (fgets(file
, MAXPATHLEN
, clf
) != NULL
) {
221 if (!feof(clf
)) /* remove trailing \n */
222 file
[strlen(file
) - 1] = '\0';
224 dprintf("link file %s requested\n", file
);
226 /* make any needed subdirectories */
228 if (mkdirs(home
, file
, flags
) != 0) {
230 if ((flags
& IGNE
) == 0)
238 if (linkfile(min_home
, home
, file
, flags
) != 0) {
240 if ((flags
& IGNE
) == 0)
246 } /* while (fgets ... ) != NULL) */
249 dperror("setupfiles link file open");
250 dprintf("setupfiles no linkfile %s\n", cl_file
);
251 } /* process link files */
258 * mkdirs - Make any needed subdirectories in target's path.
260 * Entry home = base directory.
261 * file = file to create with intermediate subdirectories.
262 * flags = from __setupfiles -- for dprintf and dperror.
264 * Exit Needed subdirectories made.
266 * Returns 0, if success.
271 * Calls mkdir, strcat, strcpy, strlen, strtok.
275 mkdirs(const char *home
, const char *file
, int flags
)
277 char path
[MAXPATHLEN
];
278 char dir
[MAXPATHLEN
];
281 if ((strlen(home
) + strlen(file
)) > (MAXPATHLEN
- 2)) {
283 dprintf("setupfiles mkdirs path %s", home
);
284 dprintf("/%s ", file
);
285 dprintf("greater than %d\n", MAXPATHLEN
);
286 errno
= ENAMETOOLONG
;
287 dperror("setupfiles mkdirs");
291 (void) strcpy(dir
, file
);
293 if ((tok
= strrchr(dir
, '/')) == NULL
) {
295 dprintf("setupfiles no dirs to make in %s\n", dir
);
299 *tok
= '\000'; /* drop last component, it's the target */
301 (void) strcpy(path
, home
);
303 for (tok
= dir
; tok
= strtok(tok
, "/"); tok
= NULL
) {
305 (void) strcat(path
, "/");
306 (void) strcat(path
, tok
);
308 if ((mkdir(path
, 0777) != 0) && (errno
!= EEXIST
)) {
310 dperror("setupfiles mkdir");
311 dprintf("setupfiles mkdir path %s\n", path
);
315 dprintf("setupfiles dir %s made or already exists\n", path
);
323 * copyfile - Copy a file from the base home directory to the current.
325 * Entry min_home = from home directory.
326 * home = current (to) home directory.
327 * target = file to copy.
328 * flags = from __setupfiles.
329 * REPC, if replace existing file.
333 * Returns 0, if success.
336 * Uses CP, MAXPATHLEN.
338 * Calls access, execlp, exit, lstat, strcat, strcpy, strlen, unlink,
343 copyfile(const char *min_home
, const char *home
, const char *target
, int flags
)
345 char src
[MAXPATHLEN
];
346 char dest
[MAXPATHLEN
];
352 if (snprintf(dest
, sizeof (dest
), "%s/%s", home
, target
) >
354 dprintf("setupfiles copy dest %s", dest
);
355 dprintf("greater than %d\n", sizeof (dest
));
356 errno
= ENAMETOOLONG
;
357 dperror("setupfiles copy to home");
361 if (lstat(dest
, &buf
) == 0) {
365 /* unlink and replace */
367 if (unlink(dest
) != 0) {
369 dperror("setupfiles copy unlink");
370 dprintf("setupfiles copy unable to unlink %s\n",
375 /* target exists and is not to be replaced */
379 } else if (errno
!= ENOENT
) {
380 /* error on target */
382 dperror("setupfiles copy");
383 dprintf("setupfiles copy lstat %s\n", dest
);
389 if (snprintf(src
, sizeof (src
), "%s/%s", min_home
, target
) >
391 dprintf("setupfiles copy path %s", src
);
392 dprintf("greater than %d\n", sizeof (src
));
393 errno
= ENAMETOOLONG
;
394 dperror("setupfiles copy from home");
398 if (access(src
, R_OK
) != 0) {
399 /* can't access source */
401 dperror("setupfiles copy source access");
402 dprintf("setupfiles copy unable to access %s\n", src
);
406 /* attempt the copy */
408 dprintf("setupfiles attempting to copy %s\n", src
);
409 dprintf("\tto %s\n", dest
);
411 if ((child
= vfork()) != 0) { /* parent, wait for child status */
412 int status
; /* child status */
414 (void) waitpid(child
, &status
, 0); /* wait for child */
415 dprintf("setupfiles copy child returned %x\n", status
);
417 /* execute "cp -p min_home home" */
419 if (execlp(CP
, CP
, "-p", src
, dest
, 0) != 0) {
420 /* can't execute cp */
422 dperror("setupfiles copy exec");
423 dprintf("setupfiles copy couldn't exec \"%s -p\"\n",
434 * linkfile - Make a symlink from the the current directory to the base
437 * Entry min_home = from home directory.
438 * home = current (to) home directory.
439 * target = file to copy.
440 * flags = from __setupfiles.
441 * REPL, if replace existing symlink.
443 * Exit File symlinked.
445 * Returns 0, if success.
450 * Calls lstat, symlink, strcat, strcpy, strlen, unlink.
454 linkfile(const char *min_home
, const char *home
, const char *target
, int flags
)
456 char src
[MAXPATHLEN
];
457 char dest
[MAXPATHLEN
];
462 if (snprintf(dest
, sizeof (dest
), "%s/%s", home
, target
) >
464 dprintf("setupfiles link dest %s", dest
);
465 dprintf("greater than %d\n", sizeof (dest
));
466 errno
= ENAMETOOLONG
;
467 dperror("setupfiles link to home");
471 if (lstat(dest
, &buf
) == 0) {
475 /* unlink and replace */
476 if (unlink(dest
) != 0) {
477 dperror("setupfiles link unlink");
478 dprintf("setupfiles link unable to unlink %s\n",
483 /* target exists and is not to be replaced */
486 } else if (errno
!= ENOENT
) {
487 /* error on target */
488 dperror("setupfiles link");
489 dprintf("setupfiles link lstat %s\n", dest
);
493 if (snprintf(src
, sizeof (src
), "%s/%s", min_home
, target
) >
495 dprintf("setupfiles link path %s", src
);
496 dprintf("greater than %d\n", sizeof (src
));
497 errno
= ENAMETOOLONG
;
498 dperror("setupfiles link from home");
502 /* attempt the copy */
504 dprintf("setupfiles attempting to link %s\n", dest
);
505 dprintf("\tto %s\n", src
);
507 if (symlink(src
, dest
) != 0) {
508 dperror("setupfiles link symlink");
509 dprintf("setupfiles link unable to symlink%s\n", "");