sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

commit 323c45edb7a553e473730dbbcf238a5ad9a8fbb5
parent 35959cd1c41272d6342b3befc054d9f505552e66
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Mon, 21 Jul 2014 16:27:20 +0000

cp: improvements

- improve copying block, char devices, fifo and sockets with -a.
- improve exit status code.

Diffstat:
Mcp.c | 2+-
Mfs.h | 1+
Mutil/cp.c | 72+++++++++++++++++++++++++++++++++++++++++++++---------------------------
3 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/cp.c b/cp.c @@ -49,5 +49,5 @@ main(int argc, char *argv[]) if(argc > 2 && !(stat(argv[argc-1], &st) == 0 && S_ISDIR(st.st_mode))) eprintf("%s: not a directory\n", argv[argc-1]); enmasse(argc, argv, cp); - return EXIT_SUCCESS; + return cp_status; } diff --git a/fs.h b/fs.h @@ -7,6 +7,7 @@ extern bool cp_fflag; extern bool cp_pflag; extern bool cp_rflag; extern bool cp_vflag; +extern int cp_status; extern bool rm_fflag; extern bool rm_rflag; diff --git a/util/cp.c b/util/cp.c @@ -1,14 +1,15 @@ /* See LICENSE file for copyright and license details. */ #include <dirent.h> #include <errno.h> +#include <fcntl.h> +#include <limits.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <sys/stat.h> #include <sys/types.h> -#include <limits.h> +#include <unistd.h> #include <utime.h> #include "../fs.h" @@ -21,6 +22,7 @@ bool cp_fflag = false; bool cp_pflag = false; bool cp_rflag = false; bool cp_vflag = false; +int cp_status = EXIT_SUCCESS; int cp(const char *s1, const char *s2) @@ -35,27 +37,26 @@ cp(const char *s1, const char *s2) DIR *dp; int r; + if(cp_vflag) + printf("'%s' -> '%s'\n", s1, s2); + if(cp_dflag == true) r = lstat(s1, &st); else r = stat(s1, &st); - if(cp_vflag) - printf("'%s' -> '%s'\n", s1, s2); - if(r == 0) { if(cp_dflag == true && S_ISLNK(st.st_mode)) { - if(cp_fflag == true) - remove(s2); - if(readlink(s1, buf, sizeof(buf) - 1) >= 0) - symlink(buf, s2); - - /* preserve owner ? */ - if(cp_aflag == true || cp_pflag == true) { - if(lchown(s2, st.st_uid, st.st_gid) == -1) - weprintf("cp: can't preserve ownership of '%s':", s2); + if(readlink(s1, buf, sizeof(buf) - 1) >= 0) { + if(cp_fflag == true); + unlink(s2); + if(symlink(buf, s2) != 0) { + weprintf("%s: can't create '%s'\n", argv0, s2); + cp_status = EXIT_FAILURE; + return 0; + } } - return 0; + goto preserve; } if(S_ISDIR(st.st_mode)) { if (!cp_rflag) @@ -70,8 +71,7 @@ cp(const char *s1, const char *s2) apathmax(&ns1, &size1); apathmax(&ns2, &size2); while((d = readdir(dp))) { - if(strcmp(d->d_name, ".") - && strcmp(d->d_name, "..")) { + if(strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { r = snprintf(ns1, size1, "%s/%s", s1, d->d_name); if(r >= size1 || r < 0) { eprintf("%s/%s: filename too long\n", @@ -85,26 +85,38 @@ cp(const char *s1, const char *s2) fnck(ns1, ns2, cp); } } - closedir(dp); free(ns1); free(ns2); goto preserve; } } + + if(cp_aflag == true) { + if(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || + S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode)) { + unlink(s2); + if(mknod(s2, st.st_mode, st.st_rdev) < 0) { + weprintf("%s: can't create '%s':", argv0, s2); + cp_status = EXIT_FAILURE; + return 0; + } + goto preserve; + } + } + if(!(f1 = fopen(s1, "r"))) eprintf("fopen %s:", s1); if(!(f2 = fopen(s2, "w"))) { if (cp_fflag == true) { unlink(s2); - if (!(f2 = fopen(s2, "w"))) + if(!(f2 = fopen(s2, "w"))) eprintf("fopen %s:", s2); } else { eprintf("fopen %s:", s2); } } - concat(f1, s1, f2, s2); fchmod(fileno(f2), st.st_mode); fclose(f2); @@ -112,15 +124,21 @@ cp(const char *s1, const char *s2) preserve: if(cp_aflag == true || cp_pflag == true) { - /* timestamp */ - ut.actime = st.st_atime; - ut.modtime = st.st_mtime; - utime(s2, &ut); - + if(!(S_ISLNK(st.st_mode))) { + /* timestamp */ + ut.actime = st.st_atime; + ut.modtime = st.st_mtime; + utime(s2, &ut); + } /* preserve owner ? */ - if(chown(s2, st.st_uid, st.st_gid) == -1) + if(S_ISLNK(st.st_mode)) + r = lchown(s2, st.st_uid, st.st_gid); + else + r = chown(s2, st.st_uid, st.st_gid); + if(r == -1) { weprintf("cp: can't preserve ownership of '%s':", s2); + cp_status = EXIT_FAILURE; + } } - return 0; }