From mboxrd@z Thu Jan 1 00:00:00 1970 From: Nils Stec Subject: Re: [PATCH] elkscmd/file_utils/cp.c: add options -b, -n, -v, -u and updated usage Date: Wed, 01 Apr 2015 13:41:04 +0200 Message-ID: <551BD950.40406@gmail.com> References: <551BD4F2.5030909@gmail.com> <551BD737.8040602@jodybruchon.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------010600080702050709030409" Return-path: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type; bh=spTpdP3kjGBxIhVmF2+6QAiFoIUUhksc+iFD4XeNjXw=; b=oQYEbdDSs7QtiiWS9OHi8plrrcKBGEIyA7XQS/1d07OVlu4uAadfsQ1TD+RFVUjcgi 00P86Qf98ZzhPyUfRaiRqTrSiPwd2L+bEZuYyb9qUhqCRL7G82e2O2KtXi9kzz07rjhw jwXvUrreFVchVq2m1YyZCX+xW3X5E5aHPbfnmDDgpsukB8QTp2YtoEfCyXZuSm9cDu+H eOaC3TULdAnBkQYQ3I5BcfBDlGp/44RNUE5jn6aKQD7YhboP/8c8neEkyplV+DMtVcym 5IE7/jcn1sFkktyhlp9EQRFCCYIyE9r9/Xw0W0/wXrGFnb0UDG1ysl7ZTmqgkoFlYPAe pFEQ== In-Reply-To: <551BD737.8040602@jodybruchon.com> Sender: linux-8086-owner@vger.kernel.org List-ID: To: ELKS This is a multi-part message in MIME format. --------------010600080702050709030409 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit On 04/01/2015 01:32 PM, Jody Bruchon wrote: > On 4/1/2015 7:22 AM, Nils Stec wrote: > + * Returns -1 if OPT_NOCLOBBER is set and a file is skipped if existent. > ... > + } else if (ISFLAG(OPT_NOCLOBBER)) { > + return -1; > ... > + retval = copyfile(srcname, destname, 0); > + if (!retval) goto error_copy; > > This causes an error to be returned if someone asks for no clobbering. > Doing what is asked for by the user should never be an error condition > and should return success unless a true error occurred (i.e. write > errors). Here's example output when using the -n switch with GNU > coreutils 'cp' and testing for any error conditions: > > $ ls -l foo bar > bar: > total 0 > -rw-r--r-- 1 user user 0 Apr 1 07:31 1 > -rw-r--r-- 1 user user 0 Apr 1 07:31 2 > > foo: > total 12 > -rw-r--r-- 1 user user 4 Apr 1 07:31 1 > -rw-r--r-- 1 user user 4 Apr 1 07:31 2 > -rw-r--r-- 1 user user 4 Apr 1 07:31 3 > $ cp -n foo/* bar/ || echo error > $ cp -n foo/* bar/ && echo success > success > $ ls -l foo bar > bar: > total 4 > -rw-r--r-- 1 user user 0 Apr 1 07:31 1 > -rw-r--r-- 1 user user 0 Apr 1 07:31 2 > -rw-r--r-- 1 user user 4 Apr 1 07:32 3 > > foo: > total 12 > -rw-r--r-- 1 user user 4 Apr 1 07:31 1 > -rw-r--r-- 1 user user 4 Apr 1 07:31 2 > -rw-r--r-- 1 user user 4 Apr 1 07:31 3 > $ > > -- > To unsubscribe from this list: send the line "unsubscribe linux-8086" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html --------------010600080702050709030409 Content-Type: text/x-patch; name="patch-cp-add_options_004.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="patch-cp-add_options_004.diff" diff --git a/elkscmd/file_utils/cp.c b/elkscmd/file_utils/cp.c index 6e23864..2e413e9 100644 --- a/elkscmd/file_utils/cp.c +++ b/elkscmd/file_utils/cp.c @@ -20,11 +20,25 @@ #include #include #include +#include #define BUF_SIZE 4096 static char *buf; +/* macros for flag setting/clearing/testing */ +#define ISFLAG(a) ((flags & a) == a) +#define SETFLAG(a) (flags |= a) +#define CLRFLAG(a) (flags &= ~(a)) + +/* some flags for command-line-options */ +static uint16_t flags; +#define OPT_NOCLOBBER 0x0001 +#define OPT_VERBOSE 0x0002 +#define OPT_INTERACTIVE 0x0004 +#define OPT_BACKUP 0x0008 +#define OPT_BACKUPMADE 0x0010 +#define OPT_UPDATE 0x0020 /* * Build a path name from the specified directory name and file name. @@ -78,15 +92,38 @@ int copyfile(char *srcname, char *destname, int setmodes) struct stat statbuf1; struct stat statbuf2; struct utimbuf times; + static char backupname[PATHLEN]; + /* source nonexistent */ if (stat(srcname, &statbuf1) < 0) { perror(srcname); return 0; } + /* destination nonexistent */ if (stat(destname, &statbuf2) < 0) { statbuf2.st_ino = -1; statbuf2.st_dev = -1; + } else { /* destination existent */ + if (ISFLAG(OPT_BACKUP)) { + strcpy(backupname, destname); + strcat(backupname, "~"); + rename(destname, backupname); + SETFLAG(OPT_BACKUPMADE); + } else if (ISFLAG(OPT_UPDATE)) { + /* if dest is newer than source, don't overwrite it */ + if (statbuf1.st_mtime < statbuf2.st_mtime) return 1; + } else if (ISFLAG(OPT_NOCLOBBER)) { + return 1; + } else if (ISFLAG(OPT_INTERACTIVE)) { + /* TODO fix this, getchar wants return */ + /* + * fprintf(stderr, "really overwrite '%s'? (y/n) \n", destname); + if(getchar() != 'y') { + return -1; + } + */ + } } if ((statbuf1.st_dev == statbuf2.st_dev) && @@ -143,9 +180,14 @@ int copyfile(char *srcname, char *destname, int setmodes) (void) utime(destname, ×); } + if (ISFLAG(OPT_BACKUPMADE) && ISFLAG(OPT_VERBOSE)) { + fprintf(stderr, "`%s' -> `%s' (backup: `%s')\n", srcname, destname, backupname); + CLRFLAG(OPT_BACKUPMADE); + } + else if (ISFLAG(OPT_VERBOSE)) + fprintf(stderr, "`%s' -> `%s'\n", srcname, destname); return 1; - error_exit: close(rfd); close(wfd); @@ -157,37 +199,76 @@ error_exit: int main(int argc, char **argv) { int dirflag; + int arg_cnt; + int opt_cnt; + int retval; + unsigned int file_count; char *srcname; char *destname; char *lastarg; if (argc < 3) goto usage; + /* lastarg is copy destination */ lastarg = argv[argc - 1]; dirflag = isadir(lastarg); - if ((argc > 3) && !dirflag) { - fprintf(stderr, "%s: not a directory\n", lastarg); + flags = 0; + opt_cnt = 0; + + arg_cnt = 1; /* start at argv[1] */ + while(arg_cnt < argc) { + if (!strcmp(argv[arg_cnt], "-n")) { + SETFLAG(OPT_NOCLOBBER); + } else if (!strcmp(argv[arg_cnt], "-v")) { + SETFLAG(OPT_VERBOSE); + } else if (!strcmp(argv[arg_cnt], "-i")) { + SETFLAG(OPT_INTERACTIVE); + } else if (!strcmp(argv[arg_cnt], "-u")) { + SETFLAG(OPT_UPDATE); + } else if (!strcmp(argv[arg_cnt], "-b")) { + SETFLAG(OPT_BACKUP); + } else if (!strcmp(argv[arg_cnt], "-h")) goto usage; + else break; + opt_cnt++; + arg_cnt++; + } + opt_cnt++; + + /* if multiple files are specified, last one must be a directory */ + if ((argc > (opt_cnt + 2)) && !dirflag) { + fprintf(stderr, "%s is not a directory\n", lastarg); exit(1); } buf = malloc(BUF_SIZE); - while (argc-- > 2) { - srcname = argv[1]; + file_count = 0; + while (argc-- > (opt_cnt + 1)) { + srcname = argv[opt_cnt+file_count]; destname = lastarg; if (dirflag) destname = buildname(destname, srcname); - if (!copyfile(*++argv, destname, 0)) goto error_copy; + retval = copyfile(srcname, destname, 0); + if (!retval) goto error_copy; + file_count++; } free(buf); + exit(0); error_copy: fprintf(stderr, "Failed to copy %s -> %s\n", srcname, destname); exit(1); usage: - fprintf(stderr, "usage: %s source_file dest_file\n", argv[0]); - fprintf(stderr, " %s file1 file2 ... dest_directory\n", argv[0]); + fprintf(stderr, "usage: %s [options] source_file dest_file\n", argv[0]); + fprintf(stderr, " %s [options] file1 file2 ... dest_directory\n", argv[0]); + fprintf(stderr, "options: -b make a backup of each exisiting destination file\n"); + fprintf(stderr, " -b overrides -u (update)\n"); + fprintf(stderr, " -n no overwriting, no clobber\n"); + fprintf(stderr, " -v be verbose\n"); +/* fprintf(stderr, " -i interactive, prompt before overwrite\n"); + fprintf(stderr, " -b, -u and -n override interactive mode\n");*/ + fprintf(stderr, " -u copy only if source file is newer than destination file\n"); exit(1); } --------------010600080702050709030409--