cpdir.c revision 20302
11558Srgrimes/*-
21558Srgrimes * Copyright (C) 1996
31558Srgrimes *	David L. Nugent.  All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes *
141558Srgrimes * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
151558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
181558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241558Srgrimes * SUCH DAMAGE.
251558Srgrimes *
261558Srgrimes *	$Id: cpdir.c,v 1.1.1.2 1996/12/09 23:55:15 joerg Exp $
271558Srgrimes */
281558Srgrimes
291558Srgrimes#include <stdio.h>
30114589Sobrien#include <string.h>
311558Srgrimes#include <stdlib.h>
3238036Scharnier#include <fcntl.h>
331558Srgrimes#include <sys/types.h>
341558Srgrimes#include <sys/stat.h>
351558Srgrimes#include <dirent.h>
361558Srgrimes#include <unistd.h>
371558Srgrimes#include <sys/param.h>
3841684Sbde#include <errno.h>
39114589Sobrien
4038036Scharnier#include "pwupd.h"
41114589Sobrien
42114589Sobrienvoid
431558Srgrimescopymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid)
441558Srgrimes{
451558Srgrimes	int             rc = 0;
461558Srgrimes	char            src[MAXPATHLEN];
471558Srgrimes	char            dst[MAXPATHLEN];
481558Srgrimes
491558Srgrimes	if (mkdir(dir, mode) != 0 && errno != EEXIST) {
5038036Scharnier		sprintf(src, "mkdir(%s)", dir);
511558Srgrimes		perror(src);
52114763Sobrien	} else {
531558Srgrimes		int             infd, outfd;
541558Srgrimes		struct stat     st;
551558Srgrimes
561558Srgrimes		static char     counter = 0;
571558Srgrimes		static char    *copybuf = NULL;
581558Srgrimes
591558Srgrimes		++counter;
601558Srgrimes		chown(dir, uid, gid);
611558Srgrimes		if (skel == NULL || *skel == '\0')
621558Srgrimes			rc = 1;
631558Srgrimes		else {
641558Srgrimes			DIR            *d = opendir(skel);
651558Srgrimes
661558Srgrimes			if (d != NULL) {
671558Srgrimes				struct dirent  *e;
681558Srgrimes
691558Srgrimes				while ((e = readdir(d)) != NULL) {
70227081Sed					char           *p = e->d_name;
711558Srgrimes
721558Srgrimes					sprintf(src, "%s/%s", skel, p);
7332399Salex					if (stat(src, &st) == 0) {
7432399Salex						if (strncmp(p, "dot.", 4) == 0)	/* Conversion */
7532399Salex							p += 3;
7632399Salex						sprintf(dst, "%s/%s", dir, p);
7732399Salex						if (S_ISDIR(st.st_mode)) {	/* Recurse for this */
7832399Salex							if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0)
7932399Salex								copymkdir(dst, src, (st.st_mode & 0777), uid, gid);
8032399Salex							/*
8132399Salex							 * Note: don't propogate 'special' attributes
8232399Salex							 */
8332399Salex						} else if (S_ISREG(st.st_mode) && (outfd = open(dst, O_RDWR | O_CREAT | O_EXCL, st.st_mode)) != -1) {
8432399Salex							if ((infd = open(src, O_RDONLY)) == -1) {
851558Srgrimes								close(outfd);
861558Srgrimes								remove(dst);
871558Srgrimes							} else {
881558Srgrimes								int             b;
891558Srgrimes
901558Srgrimes								/*
9148078Sru								 * Allocate our copy buffer if we need to
9279749Sdd								 */
9379749Sdd								if (copybuf == NULL)
941558Srgrimes									copybuf = malloc(4096);
95197560Sdelphij								while ((b = read(infd, copybuf, 4096)) > 0)
96238968Sdes									write(outfd, copybuf, b);
97197560Sdelphij								close(infd);
98197560Sdelphij								close(outfd);
99197560Sdelphij								chown(dst, uid, gid);
100197560Sdelphij							}
101197560Sdelphij						}
102197560Sdelphij					}
103197560Sdelphij				}
1041558Srgrimes				closedir(d);
105140796Sdelphij			}
106140796Sdelphij		}
1071558Srgrimes		if (--counter == 0 && copybuf != NULL) {
108140796Sdelphij			free(copybuf);
1091558Srgrimes			copybuf = NULL;
11079749Sdd		}
1111558Srgrimes	}
1121558Srgrimes}
1131558Srgrimes
1141558Srgrimes