summaryrefslogtreecommitdiffstats
path: root/pw/cpdir.c
diff options
context:
space:
mode:
authorLukas Ertl <le@FreeBSD.org>2007-03-30 13:18:52 +0000
committerLukas Ertl <le@FreeBSD.org>2007-03-30 13:18:52 +0000
commit77c6ad53f0f3b4e6c4ba6be6907a50c9f8d156b5 (patch)
tree0d1c3e99da65574004132abbc370224a72821fad /pw/cpdir.c
parent8cd5bb1ca1f135a89d9b504c6ebf7edfc89e550a (diff)
downloadpw-darwin-77c6ad53f0f3b4e6c4ba6be6907a50c9f8d156b5.tar.gz
pw-darwin-77c6ad53f0f3b4e6c4ba6be6907a50c9f8d156b5.tar.zst
pw-darwin-77c6ad53f0f3b4e6c4ba6be6907a50c9f8d156b5.zip
Do the right thing with symlinks in the skeleton directory.
PR: bin/63659
Diffstat (limited to 'pw/cpdir.c')
-rw-r--r--pw/cpdir.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/pw/cpdir.c b/pw/cpdir.c
index 1eba348..f370421 100644
--- a/pw/cpdir.c
+++ b/pw/cpdir.c
@@ -48,6 +48,8 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid
{
char src[MAXPATHLEN];
char dst[MAXPATHLEN];
+ char lnk[MAXPATHLEN];
+ int len;
if (mkdir(dir, mode) != 0 && errno != EEXIST) {
warn("mkdir(%s)", dir);
@@ -71,7 +73,7 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid
if (snprintf(src, sizeof(src), "%s/%s", skel, p) >= (int)sizeof(src))
warn("warning: pathname too long '%s/%s' (skel not copied)", skel, p);
- else if (stat(src, &st) == 0) {
+ else if (lstat(src, &st) == 0) {
if (strncmp(p, "dot.", 4) == 0) /* Conversion */
p += 3;
if (snprintf(dst, sizeof(dst), "%s/%s", dir, p) >= (int)sizeof(dst))
@@ -81,6 +83,10 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid
if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0)
copymkdir(dst, src, (st.st_mode & 0777), uid, gid);
chflags(dst, st.st_flags); /* propogate flags */
+ } else if (S_ISLNK(st.st_mode) && (len = readlink(src, lnk, sizeof(lnk))) != -1) {
+ lnk[len] = '\0';
+ symlink(lnk, dst);
+ lchown(dst, uid, gid);
/*
* Note: don't propogate special attributes
* but do propogate file flags