123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- /* Copyright (C) 1986 Free Software Foundation, Inc.
- NO WARRANTY
- BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
- NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
- WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
- RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
- WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
- AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
- DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
- CORRECTION.
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
- STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
- WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
- LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
- OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
- USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
- DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
- A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
- PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
- GENERAL PUBLIC LICENSE TO COPY
- 1. You may copy and distribute verbatim copies of this source file
- as you receive it, in any medium, provided that you conspicuously
- and appropriately publish on each copy a valid copyright notice
- "Copyright (C) 1986 Free Software Foundation, Inc"; and include following the
- copyright notice a verbatim copy of the above disclaimer of warranty
- and of this License.
- 2. You may modify your copy or copies of this source file or
- any portion of it, and copy and distribute such modifications under
- the terms of Paragraph 1 above, provided that you also do the following:
- a) cause the modified files to carry prominent notices stating
- that you changed the files and the date of any change; and
- b) cause the whole of any work that you distribute or publish,
- that in whole or in part contains or is a derivative of this
- program or any part thereof, to be freely distributed
- and licensed to all third parties on terms identical to those
- contained in this License Agreement (except that you may choose
- to grant more extensive warranty protection to third parties,
- at your option).
- 3. You may copy and distribute this program or any portion of it in
- compiled, executable or object code form under the terms of Paragraphs
- 1 and 2 above provided that you do the following:
- a) cause each such copy to be accompanied by the
- corresponding machine-readable source code, which must
- be distributed under the terms of Paragraphs 1 and 2 above; or,
- b) cause each such copy to be accompanied by a
- written offer, with no time limit, to give any third party
- free (except for a nominal shipping charge) a machine readable
- copy of the corresponding source code, to be distributed
- under the terms of Paragraphs 1 and 2 above; or,
- c) in the case of a recipient of this program in compiled, executable
- or object code form (without the corresponding source code) you
- shall cause copies you distribute to be accompanied by a copy
- of the written offer of source code which you received along
- with the copy you received.
- 4. You may not copy, sublicense, distribute or transfer this program
- except as expressly provided under this License Agreement. Any attempt
- otherwise to copy, sublicense, distribute or transfer this program is void and
- your rights to use the program under this License agreement shall be
- automatically terminated. However, parties who have received computer
- software programs from you with this License Agreement will not have
- their licenses terminated so long as such parties remain in full compliance.
- */
- /*
- * Mv. Usage is either `mv f1 f2' or `mv f1 f2 ... dir'. In either case,
- * two options, -i and -f, which must be placed before all files, may be
- * specified. The null option, -, indicates that no options, only files,
- * follow and may be used to specify file names beginning with a - sign.
- * The -i option causes mv to require confirmation from the user before
- * performing any move which would destroy an existing file. The -f option,
- * overriding the -i option, causes mv to assume a 'y' answer to all
- * questions it would normally ask (and not ask the questions). There are
- * two questions:
- *
- * Move f1 (removing f2)?
- * Override mode 0nnn for fn?
- *
- * The first one is caused by the -i option, the second by a move which would
- * destroy an existing file when the existing file's mode prohibits writing.
- * This test is slightly different from the test 4.2bsd mv makes; 4.2 mv
- * merely checks whether the user can write the file. This actually checks
- * the write bits in the mode. The difference shows when super-user tries
- * to mv onto a file with no write bits set.
- *
- * Author Mike Parker
- */
- /*
- * This program assumes the following:
- *
- * errno, stat(), access(), rename() semantics as in 4.2
- */
- #include <stdio.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/file.h>
- char *pgm;
- int interactive; /* the -i option */
- int force; /* the -f option */
- int nargs; /* number of arguments to process */
- char **args; /* the remaining arguments */
- /* strip off (and interpret) any leading options from the arguments */
- get_options()
- {
- interactive = 0;
- force = 0;
- while (1)
- {
- if (**args != '-')
- return;
- if (*++*args == '\0')
- {
- args ++;
- nargs --;
- return;
- }
- for (; **args; ++*args)
- switch (**args)
- {
- case 'f':
- force = 1;
- break;
- case 'i':
- interactive = 1;
- break;
- default:
- fprintf (stderr, "%s: bad flag -%c\n", pgm, **args);
- break;
- }
- args ++;
- nargs --;
- }
- }
- /* check whether the file is a directory */
- int
- isdir (fn)
- char *fn;
- {
- struct stat stb;
- return (stat (fn, &stb) >= 0 &&
- (stb.st_mode & S_IFMT) == S_IFDIR);
- }
- main (ac, av)
- int ac;
- char **av;
- {
- pgm = *av++;
- ac --;
- if (*av == 0)
- {
- usage ();
- exit (0);
- }
- args = av;
- nargs = ac;
- get_options ();
- if (nargs < 2) /* too few arguments */
- {
- usage ();
- exit (1);
- }
- if ((nargs > 2) && !isdir (args[nargs-1])) /* >2 args and last not dir */
- {
- fprintf (stderr,
- "%s: when moving multiple files, last argument must be a directory",
- pgm);
- exit (1);
- }
- for (; nargs > 1; args++, nargs--) /* move each arg but last onto the last */
- movefile (args[0], args[nargs-1]);
- }
- /* Move `from' onto `to'. Handles case when to is a directory. */
- movefile (from, to)
- char *from;
- char *to;
- {
- if (isdir (to)) /* target is a directory, build full target filename */
- {
- char *cp;
- char *newto;
- char *rindex();
- int l;
- cp = rindex (from, '/');
- if (cp)
- cp++;
- else
- cp = from;
- l = strlen (to) + 1 + strlen (cp) + 1;
- newto = (char *) alloca (l);
- sprintf (newto, "%s/%s", to, cp);
- to = newto;
- }
- do_move (from, to); /* perform the move */
- }
- /* Used for confirmation of the move in various cases. Reads one line and
- returns true iff that line begins with y or Y. */
- int
- yes()
- {
- char c;
- int rv;
- c = getchar ();
- rv = (c == 'y') || (c == 'Y');
- while (c != '\n')
- c = getchar();
- return rv;
- }
- /* Perform a move. Handles cross-filesystem moves. */
- do_move (from, to)
- char *from;
- char *to;
- {
- extern int errno;
- if (access (to, F_OK) >= 0) /* target exists */
- {
- struct stat stb;
- if (interactive && !force)
- {
- printf ("Move %s (removing %s)? ", from, to);
- if (! yes ())
- return;
- }
- if (stat (to, &stb) < 0) /* we can't stat it?!? */
- {
- fprintf (stderr, "%s: strange error in stat() on %s (%s not moved): ",
- pgm, to, from);
- perror (0);
- return;
- }
- /* check for write access to target */
- if ((access (to, W_OK) < 0 ||
- (stb.st_mode & ((S_IWRITE>>6)*0111)) == 0)
- && !force )
- {
- printf ("Override mode %04o for %s? ", stb.st_mode & 0777f ,to);
- if (! yes ())
- return;
- }
- }
- if (rename (from, to) < 0)
- {
- if (errno == EXDEV) /* rename() failed on cross-filesystem link */
- {
- int ifd;
- int ofd;
- struct stat stb;
- char buf[1024];
- int len;
- /* do the following to perform the move:
- unlink the target
- open both files
- copy the permission bits from the source to the target
- copy the source to the target
- close both files
- if no error so far, unlink the source
- */
- if (unlink (to) < 0)
- {
- fprintf (stderr, "%s: cannot remove %s: ", pgm, to);
- perror (0);
- return;
- }
- ifd = open (from, O_RDONLY, 0);
- if (ifd < 0 )
- {
- fprintf (stderr, "%s: cannot read %s: ", pgm, from);
- perror (0);
- return;
- }
- ofd = open (to, O_WRONLY|O_CREAT|O_TRUNC, 0777);
- if (ofd < 0 )
- {
- close (ifd);
- fprintf (stderr, "%s: cannot create %s: ", pgm, to);
- perror (0);
- return;
- }
- fstat (ifd, &stb); /* can't fail if given good args */
- fchmod (ofd, stb.st_mode & 0777); /* again, can't fail */
- while ((len = read (ifd, buf, sizeof (buf))) > 0)
- {
- int wrote = 0;
- char *bp = buf;
- do
- {
- wrote = write (ofd, bp += wrote, len);
- if (wrote < 0)
- {
- fprintf (stderr,
- "%s: error writing %s while copying from %s, move not completed: ",
- pgm, to, from);
- perror (0);
- close (ifd);
- close (ofd);
- return;
- }
- } while ((len -= wrote) > 0);
- }
- if (len < 0)
- {
- fprintf (stderr,
- "%s: error reading %s while copying to %s, original not removed: ",
- pgm, from, to);
- perror (0);
- close (ifd);
- close (ofd);
- return;
- }
- close (ifd);
- close (ofd);
- if (unlink (from) < 0)
- {
- fprintf (stderr,
- "%s: cannot remove %s after successful copy to %s: ",
- pgm, from, to);
- perror (0);
- return;
- }
- }
- else
- {
- fprintf(stderr,"%s: %s not moved to %s: ",pgm,from,to);
- perror(0);
- }
- }
- }
- /* called to print out the usage message */
- usage()
- {
- fprintf (stderr,
- "Usage: %s [-if] [-] f1 f2 or %s [-if] [-] f1 ... fn dir\n",
- pgm, pgm);
- }
|