1f875b4ebSrica /* 2f875b4ebSrica * CDDL HEADER START 3f875b4ebSrica * 4f875b4ebSrica * The contents of this file are subject to the terms of the 5f875b4ebSrica * Common Development and Distribution License (the "License"). 6f875b4ebSrica * You may not use this file except in compliance with the License. 7f875b4ebSrica * 8f875b4ebSrica * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9f875b4ebSrica * or http://www.opensolaris.org/os/licensing. 10f875b4ebSrica * See the License for the specific language governing permissions 11f875b4ebSrica * and limitations under the License. 12f875b4ebSrica * 13f875b4ebSrica * When distributing Covered Code, include this CDDL HEADER in each 14f875b4ebSrica * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15f875b4ebSrica * If applicable, add the following below this CDDL HEADER, with the 16f875b4ebSrica * fields enclosed by brackets "[]" replaced with your own identifying 17f875b4ebSrica * information: Portions Copyright [yyyy] [name of copyright owner] 18f875b4ebSrica * 19f875b4ebSrica * CDDL HEADER END 20f875b4ebSrica */ 21f875b4ebSrica 22f875b4ebSrica /* 23*7b0bedd4SRic Aleshire * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24f875b4ebSrica * Use is subject to license terms. 25f875b4ebSrica */ 26f875b4ebSrica 27f875b4ebSrica #include <errno.h> 28f875b4ebSrica #include <pwd.h> 29f875b4ebSrica #include <stdio.h> 30f875b4ebSrica #include <stdlib.h> 31f875b4ebSrica #include <string.h> 32f875b4ebSrica #include <unistd.h> 33f875b4ebSrica 34f875b4ebSrica #include <sys/param.h> 35f875b4ebSrica #include <sys/types.h> 36f875b4ebSrica #include <sys/wait.h> 37f875b4ebSrica 38f875b4ebSrica #include <tsol/label.h> 39f875b4ebSrica #include <zone.h> 40f875b4ebSrica #include <sys/stat.h> 41f875b4ebSrica 42f875b4ebSrica #include "setupfiles.h" 43f875b4ebSrica 44f875b4ebSrica #define dperror(s) if (flags & DIAG) perror(s) 45f875b4ebSrica #define dprintf(s, v) if (flags & DBUG) (void) printf(s, v) 46f875b4ebSrica #define dprintf2(s, v1, v2) if (flags & DBUG) (void) printf(s, v1, v2) 47f875b4ebSrica 48f875b4ebSrica static int mkdirs(const char *dir, const char *target, int flags); 49f875b4ebSrica static int copyfile(const char *min_home, const char *home, const char *target, 50f875b4ebSrica int flags); 51f875b4ebSrica static int linkfile(const char *min_home, const char *home, const char *target, 52f875b4ebSrica int flags); 53f875b4ebSrica 54f875b4ebSrica 55f875b4ebSrica /* 56f875b4ebSrica * __setupfiles - Process copy and link files directions in min $HOME. 57f875b4ebSrica * 58f875b4ebSrica * Entry pwd = user's password file entry. 59f875b4ebSrica * min_sl = user's minimum SL. 60f875b4ebSrica * flags = DBUG, if print debug messages. 61f875b4ebSrica * DIAG, if print diagnostics (perrors). 62f875b4ebSrica * IGNE, continue rather than abort on failures. 63f875b4ebSrica * REPC, if replace existing file. 64f875b4ebSrica * REPL, if replace existing symbolic link. 65f875b4ebSrica * process is running as user at correct label. 66f875b4ebSrica * 67f875b4ebSrica * Exit None. 68f875b4ebSrica * 69f875b4ebSrica * Returns 0, if success. 70f875b4ebSrica * errno, if failure. 71f875b4ebSrica * 72f875b4ebSrica * Uses COPY, CP, LINK, MAXPATHLEN. 73f875b4ebSrica * 74*7b0bedd4SRic Aleshire * Calls blequal, copyfile, feof, fgets, fopen, 75f875b4ebSrica * mkdirs, getzoneid, getzonelabelbyid, linkfile, strcat, strcpy, 76f875b4ebSrica * strlen. 77f875b4ebSrica * 78f875b4ebSrica * This program assumes the /zone is the autofs mountpoint for 79f875b4ebSrica * cross-zone mounts. 80f875b4ebSrica * 81f875b4ebSrica * It also assumes that the user's home directory path is the 82f875b4ebSrica * the same in each zone, relative to the zone's root. 83f875b4ebSrica * 84f875b4ebSrica * At this point, the cross-zone automounter only supports home 85f875b4ebSrica * directories starting with /home 86f875b4ebSrica */ 87f875b4ebSrica 88f875b4ebSrica int 89*7b0bedd4SRic Aleshire __setupfiles(const struct passwd *pwd, const m_label_t *min_sl, int flags) 90f875b4ebSrica { 91*7b0bedd4SRic Aleshire m_label_t *plabel; /* process label */ 92f875b4ebSrica char home[MAXPATHLEN]; /* real path to current $HOME */ 93f875b4ebSrica char min_home[MAXPATHLEN]; /* real path to min $HOME */ 94f875b4ebSrica char cl_file[MAXPATHLEN]; /* real path to .copy/.link_files */ 95f875b4ebSrica char file[MAXPATHLEN]; /* file to copy/link */ 96f875b4ebSrica FILE *clf; /* .copy/.link_file stream */ 97f875b4ebSrica char zoneroot[MAXPATHLEN]; 98f875b4ebSrica zoneid_t zoneid; 99f875b4ebSrica zoneid_t min_zoneid; 100f875b4ebSrica 101f875b4ebSrica zoneid = getzoneid(); 102f875b4ebSrica if ((plabel = getzonelabelbyid(zoneid)) == NULL) { 103f875b4ebSrica 104f875b4ebSrica dperror("setupfiles can't get process label"); 105f875b4ebSrica return (errno); 106f875b4ebSrica } 107f875b4ebSrica 108f875b4ebSrica if (blequal(plabel, min_sl)) { 109f875b4ebSrica /* at min SL no files to setup */ 110f875b4ebSrica 111f875b4ebSrica return (0); 112f875b4ebSrica } 113f875b4ebSrica 114f875b4ebSrica /* get current home real path */ 115f875b4ebSrica 116f875b4ebSrica (void) strlcpy(home, pwd->pw_dir, MAXPATHLEN); 117f875b4ebSrica 118f875b4ebSrica /* Get zone id from min_sl */ 119f875b4ebSrica 120f875b4ebSrica if ((min_zoneid = getzoneidbylabel(min_sl)) == -1) { 121f875b4ebSrica 122f875b4ebSrica dperror("setupfiles can't get zoneid for min sl"); 123f875b4ebSrica return (errno); 124f875b4ebSrica } 125f875b4ebSrica 126f875b4ebSrica /* 127f875b4ebSrica * Since the global zone home directories aren't public 128f875b4ebSrica * information, we don't support copy and link files there. 129f875b4ebSrica */ 130f875b4ebSrica if (min_zoneid == GLOBAL_ZONEID) 131f875b4ebSrica return (0); 132f875b4ebSrica 133f875b4ebSrica /* 134f875b4ebSrica * Get zone root path from zone id 135f875b4ebSrica * 136f875b4ebSrica * Could have used getzonenamebyid() but this assumes that /etc/zones 137f875b4ebSrica * directory is available, which is not true in labeled zones 138f875b4ebSrica */ 139f875b4ebSrica 140f875b4ebSrica if (zone_getattr(min_zoneid, ZONE_ATTR_ROOT, zoneroot, 141f875b4ebSrica sizeof (zoneroot)) == -1) { 142f875b4ebSrica dperror("setupfiles can't get zone root path for min sl"); 143f875b4ebSrica return (errno); 144f875b4ebSrica } 145f875b4ebSrica 146f875b4ebSrica (void) snprintf(min_home, MAXPATHLEN, "%s%s", 147f875b4ebSrica zoneroot, pwd->pw_dir); 148f875b4ebSrica 149f875b4ebSrica /* process copy files */ 150f875b4ebSrica 151f875b4ebSrica if ((strlen(min_home) + strlen(COPY)) > (MAXPATHLEN - 1)) { 152f875b4ebSrica 153f875b4ebSrica dprintf("setupfiles copy path %s", min_home); 154f875b4ebSrica dprintf("%s ", COPY); 155f875b4ebSrica dprintf("greater than %d\n", MAXPATHLEN); 156f875b4ebSrica errno = ENAMETOOLONG; 157f875b4ebSrica dperror("setupfiles copy path"); 158f875b4ebSrica return (errno); 159f875b4ebSrica } 160f875b4ebSrica 161f875b4ebSrica (void) strcpy(cl_file, min_home); 162f875b4ebSrica (void) strcat(cl_file, COPY); 163f875b4ebSrica 164f875b4ebSrica if ((clf = fopen(cl_file, "r")) != NULL) { 165f875b4ebSrica 166f875b4ebSrica while (fgets(file, MAXPATHLEN, clf) != NULL) { 167f875b4ebSrica 168f875b4ebSrica if (!feof(clf)) /* remove trailing \n */ 169f875b4ebSrica file[strlen(file) - 1] = '\0'; 170f875b4ebSrica 171f875b4ebSrica dprintf("copy file %s requested\n", file); 172f875b4ebSrica 173f875b4ebSrica /* make any needed subdirectories */ 174f875b4ebSrica 175f875b4ebSrica if (mkdirs(home, file, flags) != 0) { 176f875b4ebSrica 177f875b4ebSrica if ((flags & IGNE) == 0) 178f875b4ebSrica return (errno); 179f875b4ebSrica else 180f875b4ebSrica continue; 181f875b4ebSrica } 182f875b4ebSrica 183f875b4ebSrica /* copy the file */ 184f875b4ebSrica 185f875b4ebSrica if (copyfile(min_home, home, file, flags) != 0) { 186f875b4ebSrica 187f875b4ebSrica if ((flags & IGNE) == 0) 188f875b4ebSrica return (errno); 189f875b4ebSrica else 190f875b4ebSrica continue; 191f875b4ebSrica 192f875b4ebSrica } 193f875b4ebSrica 194f875b4ebSrica } /* while (fgets( ... ) != NULL) */ 195f875b4ebSrica } else { 196f875b4ebSrica if (errno != ENOENT) 197f875b4ebSrica dperror("setupfiles copy file open"); 198f875b4ebSrica dprintf("setupfiles no copyfile %s\n", cl_file); 199f875b4ebSrica } /* process copy files */ 200f875b4ebSrica 201f875b4ebSrica 202f875b4ebSrica /* process link files */ 203f875b4ebSrica 204f875b4ebSrica if ((strlen(min_home) + strlen(LINK)) > (MAXPATHLEN - 1)) { 205f875b4ebSrica 206f875b4ebSrica dprintf("setupfiles link path %s", min_home); 207f875b4ebSrica dprintf("%s ", LINK); 208f875b4ebSrica dprintf("greater than %d\n", MAXPATHLEN); 209f875b4ebSrica errno = ENAMETOOLONG; 210f875b4ebSrica dperror("setupfiles link path"); 211f875b4ebSrica return (errno); 212f875b4ebSrica } 213f875b4ebSrica 214f875b4ebSrica (void) strcpy(cl_file, min_home); 215f875b4ebSrica (void) strcat(cl_file, LINK); 216f875b4ebSrica 217f875b4ebSrica if ((clf = fopen(cl_file, "r")) != NULL) { 218f875b4ebSrica 219f875b4ebSrica while (fgets(file, MAXPATHLEN, clf) != NULL) { 220f875b4ebSrica 221f875b4ebSrica if (!feof(clf)) /* remove trailing \n */ 222f875b4ebSrica file[strlen(file) - 1] = '\0'; 223f875b4ebSrica 224f875b4ebSrica dprintf("link file %s requested\n", file); 225f875b4ebSrica 226f875b4ebSrica /* make any needed subdirectories */ 227f875b4ebSrica 228f875b4ebSrica if (mkdirs(home, file, flags) != 0) { 229f875b4ebSrica 230f875b4ebSrica if ((flags & IGNE) == 0) 231f875b4ebSrica return (errno); 232f875b4ebSrica else 233f875b4ebSrica continue; 234f875b4ebSrica } 235f875b4ebSrica 236f875b4ebSrica /* link the file */ 237f875b4ebSrica 238f875b4ebSrica if (linkfile(min_home, home, file, flags) != 0) { 239f875b4ebSrica 240f875b4ebSrica if ((flags & IGNE) == 0) 241f875b4ebSrica return (errno); 242f875b4ebSrica else 243f875b4ebSrica continue; 244f875b4ebSrica } 245f875b4ebSrica 246f875b4ebSrica } /* while (fgets ... ) != NULL) */ 247f875b4ebSrica } else { 248f875b4ebSrica if (errno != ENOENT) 249f875b4ebSrica dperror("setupfiles link file open"); 250f875b4ebSrica dprintf("setupfiles no linkfile %s\n", cl_file); 251f875b4ebSrica } /* process link files */ 252f875b4ebSrica 253f875b4ebSrica return (0); 254f875b4ebSrica } /* setupfiles() */ 255f875b4ebSrica 256f875b4ebSrica 257f875b4ebSrica /* 258f875b4ebSrica * mkdirs - Make any needed subdirectories in target's path. 259f875b4ebSrica * 260f875b4ebSrica * Entry home = base directory. 261f875b4ebSrica * file = file to create with intermediate subdirectories. 262f875b4ebSrica * flags = from __setupfiles -- for dprintf and dperror. 263f875b4ebSrica * 264f875b4ebSrica * Exit Needed subdirectories made. 265f875b4ebSrica * 266f875b4ebSrica * Returns 0, if success. 267f875b4ebSrica * errno, if failure. 268f875b4ebSrica * 269f875b4ebSrica * Uses MAXPATHLEN. 270f875b4ebSrica * 271f875b4ebSrica * Calls mkdir, strcat, strcpy, strlen, strtok. 272f875b4ebSrica */ 273f875b4ebSrica 274f875b4ebSrica static int 275f875b4ebSrica mkdirs(const char *home, const char *file, int flags) 276f875b4ebSrica { 277f875b4ebSrica char path[MAXPATHLEN]; 278f875b4ebSrica char dir[MAXPATHLEN]; 279f875b4ebSrica char *tok; 280f875b4ebSrica 281f875b4ebSrica if ((strlen(home) + strlen(file)) > (MAXPATHLEN - 2)) { 282f875b4ebSrica 283f875b4ebSrica dprintf("setupfiles mkdirs path %s", home); 284f875b4ebSrica dprintf("/%s ", file); 285f875b4ebSrica dprintf("greater than %d\n", MAXPATHLEN); 286f875b4ebSrica errno = ENAMETOOLONG; 287f875b4ebSrica dperror("setupfiles mkdirs"); 288f875b4ebSrica return (errno); 289f875b4ebSrica } 290f875b4ebSrica 291f875b4ebSrica (void) strcpy(dir, file); 292f875b4ebSrica 293f875b4ebSrica if ((tok = strrchr(dir, '/')) == NULL) { 294f875b4ebSrica 295f875b4ebSrica dprintf("setupfiles no dirs to make in %s\n", dir); 296f875b4ebSrica return (0); 297f875b4ebSrica } 298f875b4ebSrica 299f875b4ebSrica *tok = '\000'; /* drop last component, it's the target */ 300f875b4ebSrica 301f875b4ebSrica (void) strcpy(path, home); 302f875b4ebSrica 303f875b4ebSrica for (tok = dir; tok = strtok(tok, "/"); tok = NULL) { 304f875b4ebSrica 305f875b4ebSrica (void) strcat(path, "/"); 306f875b4ebSrica (void) strcat(path, tok); 307f875b4ebSrica 308f875b4ebSrica if ((mkdir(path, 0777) != 0) && (errno != EEXIST)) { 309f875b4ebSrica 310f875b4ebSrica dperror("setupfiles mkdir"); 311f875b4ebSrica dprintf("setupfiles mkdir path %s\n", path); 312f875b4ebSrica return (errno); 313f875b4ebSrica } 314f875b4ebSrica 315f875b4ebSrica dprintf("setupfiles dir %s made or already exists\n", path); 316f875b4ebSrica } 317f875b4ebSrica 318f875b4ebSrica return (0); 319f875b4ebSrica } /* mkdirs() */ 320f875b4ebSrica 321f875b4ebSrica 322f875b4ebSrica /* 323f875b4ebSrica * copyfile - Copy a file from the base home directory to the current. 324f875b4ebSrica * 325f875b4ebSrica * Entry min_home = from home directory. 326f875b4ebSrica * home = current (to) home directory. 327f875b4ebSrica * target = file to copy. 328f875b4ebSrica * flags = from __setupfiles. 329f875b4ebSrica * REPC, if replace existing file. 330f875b4ebSrica * 331f875b4ebSrica * Exit File copied. 332f875b4ebSrica * 333f875b4ebSrica * Returns 0, if success. 334f875b4ebSrica * errno, if failure. 335f875b4ebSrica * 336f875b4ebSrica * Uses CP, MAXPATHLEN. 337f875b4ebSrica * 338f875b4ebSrica * Calls access, execlp, exit, lstat, strcat, strcpy, strlen, unlink, 339f875b4ebSrica * vfork, waitpid. 340f875b4ebSrica */ 341f875b4ebSrica 342f875b4ebSrica static int 343f875b4ebSrica copyfile(const char *min_home, const char *home, const char *target, int flags) 344f875b4ebSrica { 345f875b4ebSrica char src[MAXPATHLEN]; 346f875b4ebSrica char dest[MAXPATHLEN]; 347f875b4ebSrica struct stat buf; 348f875b4ebSrica pid_t child; 349f875b4ebSrica 350f875b4ebSrica /* prepare target */ 351f875b4ebSrica 352f875b4ebSrica if (snprintf(dest, sizeof (dest), "%s/%s", home, target) > 353f875b4ebSrica sizeof (dest) - 1) { 354f875b4ebSrica dprintf("setupfiles copy dest %s", dest); 355f875b4ebSrica dprintf("greater than %d\n", sizeof (dest)); 356f875b4ebSrica errno = ENAMETOOLONG; 357f875b4ebSrica dperror("setupfiles copy to home"); 358f875b4ebSrica return (errno); 359f875b4ebSrica } 360f875b4ebSrica 361f875b4ebSrica if (lstat(dest, &buf) == 0) { 362f875b4ebSrica /* target exists */ 363f875b4ebSrica 364f875b4ebSrica if (flags & REPC) { 365f875b4ebSrica /* unlink and replace */ 366f875b4ebSrica 367f875b4ebSrica if (unlink(dest) != 0) { 368f875b4ebSrica 369f875b4ebSrica dperror("setupfiles copy unlink"); 370f875b4ebSrica dprintf("setupfiles copy unable to unlink %s\n", 371f875b4ebSrica dest); 372f875b4ebSrica return (errno); 373f875b4ebSrica } 374f875b4ebSrica } else { 375f875b4ebSrica /* target exists and is not to be replaced */ 376f875b4ebSrica 377f875b4ebSrica return (0); 378f875b4ebSrica } 379f875b4ebSrica } else if (errno != ENOENT) { 380f875b4ebSrica /* error on target */ 381f875b4ebSrica 382f875b4ebSrica dperror("setupfiles copy"); 383f875b4ebSrica dprintf("setupfiles copy lstat %s\n", dest); 384f875b4ebSrica return (errno); 385f875b4ebSrica } 386f875b4ebSrica 387f875b4ebSrica /* prepare source */ 388f875b4ebSrica 389f875b4ebSrica if (snprintf(src, sizeof (src), "%s/%s", min_home, target) > 390f875b4ebSrica sizeof (src) - 1) { 391f875b4ebSrica dprintf("setupfiles copy path %s", src); 392f875b4ebSrica dprintf("greater than %d\n", sizeof (src)); 393f875b4ebSrica errno = ENAMETOOLONG; 394f875b4ebSrica dperror("setupfiles copy from home"); 395f875b4ebSrica return (errno); 396f875b4ebSrica } 397f875b4ebSrica 398f875b4ebSrica if (access(src, R_OK) != 0) { 399f875b4ebSrica /* can't access source */ 400f875b4ebSrica 401f875b4ebSrica dperror("setupfiles copy source access"); 402f875b4ebSrica dprintf("setupfiles copy unable to access %s\n", src); 403f875b4ebSrica return (errno); 404f875b4ebSrica } 405f875b4ebSrica 406f875b4ebSrica /* attempt the copy */ 407f875b4ebSrica 408f875b4ebSrica dprintf("setupfiles attempting to copy %s\n", src); 409f875b4ebSrica dprintf("\tto %s\n", dest); 410f875b4ebSrica 411f875b4ebSrica if ((child = vfork()) != 0) { /* parent, wait for child status */ 412f875b4ebSrica int status; /* child status */ 413f875b4ebSrica 414f875b4ebSrica (void) waitpid(child, &status, 0); /* wait for child */ 415f875b4ebSrica dprintf("setupfiles copy child returned %x\n", status); 416f875b4ebSrica } else { 417f875b4ebSrica /* execute "cp -p min_home home" */ 418f875b4ebSrica 419f875b4ebSrica if (execlp(CP, CP, "-p", src, dest, 0) != 0) { 420f875b4ebSrica /* can't execute cp */ 421f875b4ebSrica 422f875b4ebSrica dperror("setupfiles copy exec"); 423f875b4ebSrica dprintf("setupfiles copy couldn't exec \"%s -p\"\n", 424f875b4ebSrica CP); 425f875b4ebSrica exit(2); 426f875b4ebSrica } 427f875b4ebSrica } 428f875b4ebSrica 429f875b4ebSrica return (0); 430f875b4ebSrica } /* copyfile() */ 431f875b4ebSrica 432f875b4ebSrica 433f875b4ebSrica /* 434f875b4ebSrica * linkfile - Make a symlink from the the current directory to the base 435f875b4ebSrica * home directory. 436f875b4ebSrica * 437f875b4ebSrica * Entry min_home = from home directory. 438f875b4ebSrica * home = current (to) home directory. 439f875b4ebSrica * target = file to copy. 440f875b4ebSrica * flags = from __setupfiles. 441f875b4ebSrica * REPL, if replace existing symlink. 442f875b4ebSrica * 443f875b4ebSrica * Exit File symlinked. 444f875b4ebSrica * 445f875b4ebSrica * Returns 0, if success. 446f875b4ebSrica * errno, if failure. 447f875b4ebSrica * 448f875b4ebSrica * Uses MAXPATHLEN. 449f875b4ebSrica * 450f875b4ebSrica * Calls lstat, symlink, strcat, strcpy, strlen, unlink. 451f875b4ebSrica */ 452f875b4ebSrica 453f875b4ebSrica static int 454f875b4ebSrica linkfile(const char *min_home, const char *home, const char *target, int flags) 455f875b4ebSrica { 456f875b4ebSrica char src[MAXPATHLEN]; 457f875b4ebSrica char dest[MAXPATHLEN]; 458f875b4ebSrica struct stat buf; 459f875b4ebSrica 460f875b4ebSrica /* prepare target */ 461f875b4ebSrica 462f875b4ebSrica if (snprintf(dest, sizeof (dest), "%s/%s", home, target) > 463f875b4ebSrica sizeof (dest) - 1) { 464f875b4ebSrica dprintf("setupfiles link dest %s", dest); 465f875b4ebSrica dprintf("greater than %d\n", sizeof (dest)); 466f875b4ebSrica errno = ENAMETOOLONG; 467f875b4ebSrica dperror("setupfiles link to home"); 468f875b4ebSrica return (errno); 469f875b4ebSrica } 470f875b4ebSrica 471f875b4ebSrica if (lstat(dest, &buf) == 0) { 472f875b4ebSrica /* target exists */ 473f875b4ebSrica 474f875b4ebSrica if (flags & REPL) { 475f875b4ebSrica /* unlink and replace */ 476f875b4ebSrica if (unlink(dest) != 0) { 477f875b4ebSrica dperror("setupfiles link unlink"); 478f875b4ebSrica dprintf("setupfiles link unable to unlink %s\n", 479f875b4ebSrica dest); 480f875b4ebSrica return (errno); 481f875b4ebSrica } 482f875b4ebSrica } else { 483f875b4ebSrica /* target exists and is not to be replaced */ 484f875b4ebSrica return (0); 485f875b4ebSrica } 486f875b4ebSrica } else if (errno != ENOENT) { 487f875b4ebSrica /* error on target */ 488f875b4ebSrica dperror("setupfiles link"); 489f875b4ebSrica dprintf("setupfiles link lstat %s\n", dest); 490f875b4ebSrica return (errno); 491f875b4ebSrica } 492f875b4ebSrica 493f875b4ebSrica if (snprintf(src, sizeof (src), "%s/%s", min_home, target) > 494f875b4ebSrica sizeof (src) - 1) { 495f875b4ebSrica dprintf("setupfiles link path %s", src); 496f875b4ebSrica dprintf("greater than %d\n", sizeof (src)); 497f875b4ebSrica errno = ENAMETOOLONG; 498f875b4ebSrica dperror("setupfiles link from home"); 499f875b4ebSrica return (errno); 500f875b4ebSrica } 501f875b4ebSrica 502f875b4ebSrica /* attempt the copy */ 503f875b4ebSrica 504f875b4ebSrica dprintf("setupfiles attempting to link %s\n", dest); 505f875b4ebSrica dprintf("\tto %s\n", src); 506f875b4ebSrica 507f875b4ebSrica if (symlink(src, dest) != 0) { 508f875b4ebSrica dperror("setupfiles link symlink"); 509f875b4ebSrica dprintf("setupfiles link unable to symlink%s\n", ""); 510f875b4ebSrica return (errno); 511f875b4ebSrica } 512f875b4ebSrica 513f875b4ebSrica return (0); 514f875b4ebSrica } /* linkfile */ 515