cpdir.c revision 30259
150477Speter/*-
238465Smsmith * Copyright (C) 1996
339441Smsmith *	David L. Nugent.  All rights reserved.
458713Sjhb *
544780Sdcs * Redistribution and use in source and binary forms, with or without
639857Sjkh * modification, are permitted provided that the following conditions
748351Speter * are met:
839851Speter * 1. Redistributions of source code must retain the above copyright
938465Smsmith *    notice, this list of conditions and the following disclaimer.
1039441Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1159473Sps *    notice, this list of conditions and the following disclaimer in the
1239441Smsmith *    documentation and/or other materials provided with the distribution.
1359087Sps *
1468310Sps * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
1568310Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1668310Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1759087Sps * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
1868310Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1959087Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2039178Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2140555Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2240555Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2339178Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2456992Sluigi * SUCH DAMAGE.
2540877Smsmith */
2656903Sjhb
2756903Sjhb#ifndef lint
2841107Sjkhstatic const char rcsid[] =
2941107Sjkh	"$Id$";
3041107Sjkh#endif /* not lint */
3141107Sjkh
3241107Sjkh#include <err.h>
3356992Sluigi#include <errno.h>
3440877Smsmith#include <fcntl.h>
3538465Smsmith#include <stdio.h>
3638465Smsmith#include <string.h>
3738465Smsmith#include <stdlib.h>
3840338Speter#include <unistd.h>
3940338Speter#include <sys/types.h>
4038465Smsmith#include <sys/stat.h>
4141821Smsmith#include <sys/param.h>
4238465Smsmith#include <dirent.h>
4338465Smsmith
4444243Smsmith#include "pwupd.h"
4538465Smsmith
4638465Smsmithvoid
4738465Smsmithcopymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid)
4838465Smsmith{
4938465Smsmith	int             rc = 0;
5039474Smsmith	char            src[MAXPATHLEN];
5165598Simp	char            dst[MAXPATHLEN];
5265598Simp
5365598Simp	if (mkdir(dir, mode) != 0 && errno != EEXIST) {
5465598Simp		warn("mkdir(%s)", dir);
5565598Simp	} else {
5639474Smsmith		int             infd, outfd;
5765598Simp		struct stat     st;
5865598Simp
5959087Sps		static char     counter = 0;
6039474Smsmith		static char    *copybuf = NULL;
6139441Smsmith
6239646Speter		++counter;
6339646Speter		chown(dir, uid, gid);
6439646Speter		if (skel == NULL || *skel == '\0')
6539441Smsmith			rc = 1;
6639646Speter		else {
6739441Smsmith			DIR            *d = opendir(skel);
6839441Smsmith
6939441Smsmith			if (d != NULL) {
7039646Speter				struct dirent  *e;
7139441Smsmith
7239441Smsmith				while ((e = readdir(d)) != NULL) {
7339441Smsmith					char           *p = e->d_name;
7439441Smsmith
7540555Smsmith					sprintf(src, "%s/%s", skel, p);
7640555Smsmith					if (stat(src, &st) == 0) {
7740555Smsmith						if (strncmp(p, "dot.", 4) == 0)	/* Conversion */
7839664Smsmith							p += 3;
7940884Smsmith						sprintf(dst, "%s/%s", dir, p);
8040884Smsmith						if (S_ISDIR(st.st_mode)) {	/* Recurse for this */
8139664Smsmith							if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0)
8248351Speter								copymkdir(dst, src, (st.st_mode & 0777), uid, gid);
8348351Speter							/*
8438465Smsmith							 * Note: don't propogate 'special' attributes
8538465Smsmith							 */
8642274Smsmith						} else if (S_ISREG(st.st_mode) && (outfd = open(dst, O_RDWR | O_CREAT | O_EXCL, st.st_mode)) != -1) {
8758713Sjhb							if ((infd = open(src, O_RDONLY)) == -1) {
8858713Sjhb								close(outfd);
8942493Smsmith								remove(dst);
9042493Smsmith							} else {
9138465Smsmith								int             b;
9240555Smsmith
9340555Smsmith								/*
9440555Smsmith								 * Allocate our copy buffer if we need to
9540555Smsmith								 */
9641821Smsmith								if (copybuf == NULL)
9742807Smsmith									copybuf = malloc(4096);
9841821Smsmith								while ((b = read(infd, copybuf, 4096)) > 0)
9942268Smsmith									write(outfd, copybuf, b);
10042510Smsmith								close(infd);
10142510Smsmith								close(outfd);
10242510Smsmith								chown(dst, uid, gid);
10342268Smsmith							}
10442268Smsmith						}
10542268Smsmith					}
10642268Smsmith				}
10742268Smsmith				closedir(d);
10842268Smsmith			}
10942268Smsmith		}
11045759Sdcs		if (--counter == 0 && copybuf != NULL) {
11144622Sdcs			free(copybuf);
11245759Sdcs			copybuf = NULL;
11345759Sdcs		}
11445759Sdcs	}
11544622Sdcs}
11644622Sdcs
11744622Sdcs