cp.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* cp.c -- copy file
  2. Calling syntax: cp [ -i ] file1 file2
  3. or cp [ -i ] file ... directory
  4. Effect:
  5. The contents of file1 are copied to file2.
  6. In the second form, one or more files are copied into the directory
  7. with their original file names.
  8. Cp will not copy a file into itself.
  9. If -i option is specified, cp will prompt the user whenever
  10. an already existing file is about to be overwritten. Only if the
  11. user types 'y', it will overwrite the file.
  12. Implementation
  13. Parse the options, if any.
  14. Check if there are the right number of arguments.
  15. Record whether the last file is a directory.
  16. For X being each element of argv, except the last one:
  17. Copy the last element of argv to buf.
  18. If buf is the name of a directory, then append X to buf.
  19. infile = Open(X, read)
  20. outfile = creat(buf, mode of X)
  21. Copy the data from infile to outfile.
  22. */
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #define BUFSIZE 512
  27. main(argc, argv)
  28. int argc;
  29. char *argv[];
  30. {
  31. struct stat st; /* File status structure */
  32. unsigned short dev, ino, mode; /* temp variables for st elements */
  33. char buf[BUFSIZE]; /* IO buffer */
  34. char *temp1, *temp2, *temp3;
  35. int retval;
  36. int dirflag = 0; /* True if the last file is a directory */
  37. int inf, outf; /* The input and output file descriptors */
  38. int iflag = 0;
  39. /* Parse the flags, if any */
  40. while ((--argc > 0) && (**(++argv) == '-'))
  41. while (*(++(*argv)) != 0)
  42. switch (**argv)
  43. {
  44. case 'i':
  45. iflag++;
  46. break;
  47. default:
  48. fprintf(stderr, "cp: unknown flag %c.\n", **argv);
  49. return;
  50. }
  51. if (argc < 2)
  52. {
  53. fprintf(stderr, "Usage: cp f1 f2; or cp f1 f2 ... dir\n");
  54. return;
  55. }
  56. stat(argv[argc-1], &st);
  57. if (st.st_mode & S_IFDIR)
  58. dirflag++;
  59. else
  60. if (argc > 2)
  61. {
  62. fprintf(stderr, "Usage: cp f1 f2; or cp f1 f2 ... dir\n");
  63. return;
  64. }
  65. while (argc > 1)
  66. {
  67. temp1 = buf;
  68. temp2 = argv[argc-1];
  69. while ((*temp1++ = *temp2++) != 0);
  70. if (dirflag)
  71. {
  72. temp2 = *argv;
  73. temp3 = temp2;
  74. *(temp1-1) = '/';
  75. while (*temp2 != 0)
  76. if (*temp2++ == '/')
  77. temp3 = temp2;
  78. while ((*temp1++ = *temp3++) != 0);
  79. }
  80. /* Check if the file exists */
  81. retval = stat(*argv, &st);
  82. if (retval < 0)
  83. {
  84. fprintf(stderr, "cp: file %s doesn't exist.\n", *argv);
  85. return;
  86. }
  87. dev = st.st_dev;
  88. ino = st.st_ino;
  89. mode = st.st_mode;
  90. /* Check if the file is a directory */
  91. if (mode & S_IFDIR)
  92. {
  93. fprintf(stderr, "Usage: cp f1 f2; or cp f1 f2 ... dir\n");
  94. return;
  95. }
  96. /* Abort if the file will be copied to itself. Also, ask user
  97. if the file already exists, and iflag is true. */
  98. if (stat(buf, &st) >= 0)
  99. {
  100. if ((st.st_dev == dev) && (st.st_ino == ino))
  101. {
  102. fprintf(stderr, "cp: can't copy %s to itself.\n", *argv);
  103. argv++;
  104. argc--;
  105. continue;
  106. }
  107. if (iflag)
  108. {
  109. retval = fstat(stdin, &st);
  110. if (retval && (st.st_mode & S_IFCHR))
  111. {
  112. printf("cp: file %s already exists. Overwrite? (y or n) ");
  113. putchar(-1);
  114. if (getchar() != 'y')
  115. {
  116. printf(" No.\n");
  117. argv++;
  118. argc--;
  119. continue;
  120. }
  121. else
  122. printf(" Yes.\n");
  123. }
  124. }
  125. }
  126. /* Open the input file */
  127. if ((inf = open(*argv, 0)) == -1)
  128. {
  129. fprintf(stderr, "cp: error opening input file %s.\n", *argv);
  130. return;
  131. }
  132. /* Create the output file */
  133. if ((outf = creat(buf, mode)) == -1)
  134. {
  135. fprintf(stderr, "cp: error creating output file %s.\n", buf);
  136. close(inf);
  137. return;
  138. }
  139. /* Copy the data */
  140. while ((retval = read(inf, buf, BUFSIZE)) != 0)
  141. {
  142. if (retval == -1)
  143. {
  144. fprintf(stderr, "cp: error reading from file %s.\n", *argv);
  145. close(inf);
  146. close(outf);
  147. return;
  148. }
  149. if (write(outf, buf, retval) != retval)
  150. {
  151. fprintf(stderr, "cp: error writing to file.\n");
  152. close(inf);
  153. close(outf);
  154. return;
  155. }
  156. }
  157. argc--;
  158. argv++;
  159. }
  160. }