morpheus-base

morpheus base system
git clone git://git.2f30.org/morpheus-base
Log | Files | Refs

cp.c (3081B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <dirent.h>
      3 #include <errno.h>
      4 #include <fcntl.h>
      5 #include <limits.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <sys/stat.h>
     10 #include <sys/types.h>
     11 #include <unistd.h>
     12 #include <utime.h>
     13 
     14 #include "../fs.h"
     15 #include "../text.h"
     16 #include "../util.h"
     17 
     18 int cp_aflag = 0;
     19 int cp_fflag = 0;
     20 int cp_Pflag = 0;
     21 int cp_pflag = 0;
     22 int cp_rflag = 0;
     23 int cp_vflag = 0;
     24 int cp_status = 0;
     25 
     26 int
     27 cp(const char *s1, const char *s2)
     28 {
     29 	FILE *f1, *f2;
     30 	char *ns1, *ns2;
     31 	long size1, size2;
     32 	struct dirent *d;
     33 	struct stat st;
     34 	struct utimbuf ut;
     35 	char buf[PATH_MAX];
     36 	DIR *dp;
     37 	int r;
     38 
     39 	if (cp_vflag)
     40 		printf("'%s' -> '%s'\n", s1, s2);
     41 
     42 	r = cp_Pflag ? lstat(s1, &st) : stat(s1, &st);
     43 	if (r < 0) {
     44 		weprintf("%s %s:", cp_Pflag ? "lstat" : "stat", s1);
     45 		cp_status = 1;
     46 		return 0;
     47 	}
     48 
     49 	if (S_ISLNK(st.st_mode)) {
     50 		if (readlink(s1, buf, sizeof(buf) - 1) >= 0) {
     51 			if (cp_fflag)
     52 				unlink(s2);
     53 			if (symlink(buf, s2) != 0) {
     54 				weprintf("%s: can't create '%s'\n", argv0, s2);
     55 				cp_status = 1;
     56 				return 0;
     57 			}
     58 		}
     59 		goto preserve;
     60 	}
     61 
     62 	if (S_ISDIR(st.st_mode)) {
     63 		if (!cp_rflag)
     64 			eprintf("%s: is a directory\n", s1);
     65 
     66 		if (!(dp = opendir(s1)))
     67 			eprintf("opendir %s:", s1);
     68 
     69 		if (mkdir(s2, st.st_mode) < 0 && errno != EEXIST)
     70 			eprintf("mkdir %s:", s2);
     71 
     72 		apathmax(&ns1, &size1);
     73 		apathmax(&ns2, &size2);
     74 		while ((d = readdir(dp))) {
     75 			if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) {
     76 				r = snprintf(ns1, size1, "%s/%s", s1, d->d_name);
     77 				if (r >= size1 || r < 0) {
     78 					eprintf("%s/%s: filename too long\n",
     79 						s1, d->d_name);
     80 				}
     81 				r = snprintf(ns2, size2, "%s/%s", s2, d->d_name);
     82 				if (r >= size2 || r < 0) {
     83 					eprintf("%s/%s: filename too long\n",
     84 						s2, d->d_name);
     85 				}
     86 				fnck(ns1, ns2, cp);
     87 			}
     88 		}
     89 		closedir(dp);
     90 		free(ns1);
     91 		free(ns2);
     92 		goto preserve;
     93 	}
     94 
     95 	if (cp_aflag) {
     96 		if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) ||
     97 		    S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode)) {
     98 			unlink(s2);
     99 			if (mknod(s2, st.st_mode, st.st_rdev) < 0) {
    100 				weprintf("%s: can't create '%s':", argv0, s2);
    101 				cp_status = 1;
    102 				return 0;
    103 			}
    104 			goto preserve;
    105 		}
    106 	}
    107 
    108 	if (!(f1 = fopen(s1, "r"))) {
    109 		weprintf("fopen %s:", s1);
    110 		cp_status = 1;
    111 		return 0;
    112 	}
    113 
    114 	if (!(f2 = fopen(s2, "w"))) {
    115 		if (cp_fflag) {
    116 			unlink(s2);
    117 			if (!(f2 = fopen(s2, "w"))) {
    118 				weprintf("fopen %s:", s2);
    119 				cp_status = 1;
    120 				return 0;
    121 			}
    122 		} else {
    123 			weprintf("fopen %s:", s2);
    124 			cp_status = 1;
    125 			return 0;
    126 		}
    127 	}
    128 	concat(f1, s1, f2, s2);
    129 	/* preserve permissions by default */
    130 	fchmod(fileno(f2), st.st_mode);
    131 	fclose(f2);
    132 	fclose(f1);
    133 
    134 preserve:
    135 	if (cp_aflag || cp_pflag) {
    136 		if (!(S_ISLNK(st.st_mode))) {
    137 			/* timestamp */
    138 			ut.actime = st.st_atime;
    139 			ut.modtime = st.st_mtime;
    140 			utime(s2, &ut);
    141 		}
    142 		/* preserve owner ? */
    143 		if (S_ISLNK(st.st_mode))
    144 			r = lchown(s2, st.st_uid, st.st_gid);
    145 		else
    146 			r = chown(s2, st.st_uid, st.st_gid);
    147 		if (r < 0) {
    148 			weprintf("cp: can't preserve ownership of '%s':", s2);
    149 			cp_status = 1;
    150 		}
    151 	}
    152 	return 0;
    153 }