]> git.cameronkatri.com Git - pw-darwin.git/blob - pw/cpdir.c
pw(8) -- a backend utility to manage the user and group databases.
[pw-darwin.git] / pw / cpdir.c
1 /*-
2 * Copyright (c) 1996 by David L. Nugent <davidn@blaze.net.au>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by David L. Nugent.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE DAVID L. NUGENT ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id$
33 */
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <fcntl.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <dirent.h>
42 #include <unistd.h>
43 #include <sys/param.h>
44 #include <errno.h>
45
46 #include "pwupd.h"
47
48 void
49 copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid)
50 {
51 int rc = 0;
52 char src[MAXPATHLEN];
53 char dst[MAXPATHLEN];
54
55 if (mkdir(dir, mode) != 0 && errno != EEXIST) {
56 sprintf(src, "mkdir(%s)", dir);
57 perror(src);
58 } else {
59 int infd, outfd;
60 struct stat st;
61
62 static char counter = 0;
63 static char *copybuf = NULL;
64
65 ++counter;
66 chown(dir, uid, gid);
67 if (skel == NULL || *skel == '\0')
68 rc = 1;
69 else {
70 DIR *d = opendir(skel);
71
72 if (d != NULL) {
73 struct dirent *e;
74
75 while ((e = readdir(d)) != NULL) {
76 char *p = e->d_name;
77
78 sprintf(src, "%s/%s", skel, p);
79 if (stat(src, &st) == 0) {
80 if (strncmp(p, "dot.", 4) == 0) /* Conversion */
81 p += 3;
82 sprintf(dst, "%s/%s", dir, p);
83 if (S_ISDIR(st.st_mode)) { /* Recurse for this */
84 if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0)
85 copymkdir(dst, src, (st.st_mode & 0777), uid, gid);
86 /*
87 * Note: don't propogate 'special' attributes
88 */
89 } else if (S_ISREG(st.st_mode) && (outfd = open(dst, O_RDWR | O_CREAT | O_EXCL, st.st_mode)) != -1) {
90 if ((infd = open(src, O_RDONLY)) == -1) {
91 close(outfd);
92 remove(dst);
93 } else {
94 int b;
95
96 /*
97 * Allocate our copy buffer if we need to
98 */
99 if (copybuf == NULL)
100 copybuf = malloc(4096);
101 while ((b = read(infd, copybuf, 4096)) > 0)
102 write(outfd, copybuf, b);
103 close(infd);
104 close(outfd);
105 chown(dst, uid, gid);
106 }
107 }
108 }
109 }
110 closedir(d);
111 }
112 }
113 if (--counter == 0 && copybuf != NULL) {
114 free(copybuf);
115 copybuf = NULL;
116 }
117 }
118 }