123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- /* cp.c -- copy file
- Calling syntax: cp [ -i ] file1 file2
- or cp [ -i ] file ... directory
- Effect:
- The contents of file1 are copied to file2.
- In the second form, one or more files are copied into the directory
- with their original file names.
- Cp will not copy a file into itself.
- If -i option is specified, cp will prompt the user whenever
- an already existing file is about to be overwritten. Only if the
- user types 'y', it will overwrite the file.
- Implementation
- Parse the options, if any.
- Check if there are the right number of arguments.
- Record whether the last file is a directory.
- For X being each element of argv, except the last one:
- Copy the last element of argv to buf.
- If buf is the name of a directory, then append X to buf.
- infile = Open(X, read)
- outfile = creat(buf, mode of X)
- Copy the data from infile to outfile.
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #define BUFSIZE 512
- main(argc, argv)
- int argc;
- char *argv[];
- {
- struct stat st; /* File status structure */
- unsigned short dev, ino, mode; /* temp variables for st elements */
- char buf[BUFSIZE]; /* IO buffer */
- char *temp1, *temp2, *temp3;
- int retval;
- int dirflag = 0; /* True if the last file is a directory */
- int inf, outf; /* The input and output file descriptors */
- int iflag = 0;
- /* Parse the flags, if any */
- while ((--argc > 0) && (**(++argv) == '-'))
- while (*(++(*argv)) != 0)
- switch (**argv)
- {
- case 'i':
- iflag++;
- break;
- default:
- fprintf(stderr, "cp: unknown flag %c.\n", **argv);
- return;
- }
- if (argc < 2)
- {
- fprintf(stderr, "Usage: cp f1 f2; or cp f1 f2 ... dir\n");
- return;
- }
- stat(argv[argc-1], &st);
- if (st.st_mode & S_IFDIR)
- dirflag++;
- else
- if (argc > 2)
- {
- fprintf(stderr, "Usage: cp f1 f2; or cp f1 f2 ... dir\n");
- return;
- }
- while (argc > 1)
- {
- temp1 = buf;
- temp2 = argv[argc-1];
- while ((*temp1++ = *temp2++) != 0);
- if (dirflag)
- {
- temp2 = *argv;
- temp3 = temp2;
- *(temp1-1) = '/';
- while (*temp2 != 0)
- if (*temp2++ == '/')
- temp3 = temp2;
- while ((*temp1++ = *temp3++) != 0);
- }
-
- /* Check if the file exists */
- retval = stat(*argv, &st);
- if (retval < 0)
- {
- fprintf(stderr, "cp: file %s doesn't exist.\n", *argv);
- return;
- }
- dev = st.st_dev;
- ino = st.st_ino;
- mode = st.st_mode;
- /* Check if the file is a directory */
- if (mode & S_IFDIR)
- {
- fprintf(stderr, "Usage: cp f1 f2; or cp f1 f2 ... dir\n");
- return;
- }
- /* Abort if the file will be copied to itself. Also, ask user
- if the file already exists, and iflag is true. */
- if (stat(buf, &st) >= 0)
- {
- if ((st.st_dev == dev) && (st.st_ino == ino))
- {
- fprintf(stderr, "cp: can't copy %s to itself.\n", *argv);
- argv++;
- argc--;
- continue;
- }
- if (iflag)
- {
- retval = fstat(stdin, &st);
- if (retval && (st.st_mode & S_IFCHR))
- {
- printf("cp: file %s already exists. Overwrite? (y or n) ");
- putchar(-1);
- if (getchar() != 'y')
- {
- printf(" No.\n");
- argv++;
- argc--;
- continue;
- }
- else
- printf(" Yes.\n");
- }
- }
- }
- /* Open the input file */
- if ((inf = open(*argv, 0)) == -1)
- {
- fprintf(stderr, "cp: error opening input file %s.\n", *argv);
- return;
- }
- /* Create the output file */
- if ((outf = creat(buf, mode)) == -1)
- {
- fprintf(stderr, "cp: error creating output file %s.\n", buf);
- close(inf);
- return;
- }
- /* Copy the data */
- while ((retval = read(inf, buf, BUFSIZE)) != 0)
- {
- if (retval == -1)
- {
- fprintf(stderr, "cp: error reading from file %s.\n", *argv);
- close(inf);
- close(outf);
- return;
- }
- if (write(outf, buf, retval) != retval)
- {
- fprintf(stderr, "cp: error writing to file.\n");
- close(inf);
- close(outf);
- return;
- }
- }
- argc--;
- argv++;
- }
- }
|