From mboxrd@z Thu Jan 1 00:00:00 1970 From: Nils Stec Subject: [PATCH] elkscmd/file_utils/cp.c: add options -b, -n, -v, -u and updated usage Date: Wed, 01 Apr 2015 13:22:26 +0200 Message-ID: <551BD4F2.5030909@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------040006080007060709000108" 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 :content-type; bh=NOoN1LNm9rVjWq9+xYMiM6srB/xxW7hx0AwBV9zZIUU=; b=Onb9d9FKhWyU3nCJqGPP0py7/Dmpw7v8IIidAJqpK/coRjkbi/H5G2Uv+WOqEMALTZ fUm7MhpgydeZW55OUq8ZJklsJCzXdzu3gce8ZVK789Ruh48ND9r2mj1t4+zewsGOoXzB wj2Gh5Jc/OCVbNzyb73MoakWpxKIRobXkFkMNU2R9tHZsv2FRpWwuoDck1v9oxic8CCy zktaPKKFRpEm7PgED3O2/TFHhdL2SyYUduMR5yyLBR9Dt+0jPXYxNSFCRKJPoZ0KLKAX skc0Pga8h5+LMZrF5C+EOlwqEwRBGrEi4lbvsuLTTQCfVlzernHA0pyeGpe6T9W1tvTS Ybzw== Sender: linux-8086-owner@vger.kernel.org List-ID: To: ELKS This is a multi-part message in MIME format. --------------040006080007060709000108 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Here's my updated patch. I think this attempt is better than the first, if you still find something annoying i will fix/change it. This patch add some command line options to cp: -b make backup if file exists -n no clobber -v be verbose -u overwrite if source is newer than destintation file I also tried to add "-i" (interactive), but i still need to figure out how to ask for just one keypress (y/n) without pressing return... Everything for that is prepared, in usage-text -i is commented out. Hope you like this, Nils --------------040006080007060709000108 Content-Type: text/x-patch; name="patch-cp-add_options_002.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="patch-cp-add_options_002.diff" diff --git a/elkscmd/file_utils/cp.c b/elkscmd/file_utils/cp.c index 6e23864..b881af0 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. @@ -67,6 +81,9 @@ int isadir(char *name) * and modes. Returns 1 if successful, or 0 on a failure with an * error message output. (Failure is not indicated if the attributes cannot * be set.) + * + * Returns -1 if OPT_NOCLOBBER is set and a file is skipped if existent. + * This "skipped-file-indicator" is not used atm. */ int copyfile(char *srcname, char *destname, int setmodes) { @@ -78,15 +95,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 +183,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 +202,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); } --------------040006080007060709000108--