Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/coreutils/mv.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 3  Line 3 
3   * Mini mv implementation for busybox   * Mini mv implementation for busybox
4   *   *
5   * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>   * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
6     * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
7   *   *
8   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9   */   */
# Line 12  Line 13 
13   * Size reduction and improved error checking.   * Size reduction and improved error checking.
14   */   */
15    
16  #include <sys/types.h>  #include "libbb.h"
 #include <sys/stat.h>  
 #include <unistd.h>  
 #include <dirent.h>  
 #include <errno.h>  
 #include <stdlib.h>  
 #include <getopt.h> /* struct option */  
 #include "busybox.h"  
17  #include "libcoreutils/coreutils.h"  #include "libcoreutils/coreutils.h"
18    
19  #if ENABLE_FEATURE_MV_LONG_OPTIONS  #if ENABLE_FEATURE_MV_LONG_OPTIONS
20  static const struct option mv_long_options[] = {  static const char mv_longopts[] ALIGN1 =
21   { "interactive", 0, NULL, 'i' },   "interactive\0" No_argument "i"
22   { "force", 0, NULL, 'f' },   "force\0"       No_argument "f"
23   { 0, 0, 0, 0 }   ;
 };  
24  #endif  #endif
25    
26  #define OPT_FILEUTILS_FORCE       1  #define OPT_FILEUTILS_FORCE       1
27  #define OPT_FILEUTILS_INTERACTIVE 2  #define OPT_FILEUTILS_INTERACTIVE 2
28    
29  static const char fmt[] = "cannot overwrite %sdirectory with %sdirectory";  int mv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
   
30  int mv_main(int argc, char **argv)  int mv_main(int argc, char **argv)
31  {  {
32   struct stat dest_stat;   struct stat dest_stat;
33   const char *last;   const char *last;
34   const char *dest;   const char *dest;
35   unsigned long flags;   unsigned flags;
36   int dest_exists;   int dest_exists;
37   int status = 0;   int status = 0;
38     int copy_flag = 0;
39    
40  #if ENABLE_FEATURE_MV_LONG_OPTIONS  #if ENABLE_FEATURE_MV_LONG_OPTIONS
41   applet_long_options = mv_long_options;   applet_long_options = mv_longopts;
42  #endif  #endif
43   opt_complementary = "f-i:i-f";   // Need at least two arguments
44   flags = getopt32(argc, argv, "fi");   // -f unsets -i, -i unsets -f
45   if (optind + 2 > argc) {   opt_complementary = "-2:f-i:i-f";
46   bb_show_usage();   flags = getopt32(argv, "fi");
47   }   argc -= optind;
   
  last = argv[argc - 1];  
48   argv += optind;   argv += optind;
49     last = argv[argc - 1];
50    
51   if (optind + 2 == argc) {   if (argc == 2) {
52   dest_exists = cp_mv_stat(last, &dest_stat);   dest_exists = cp_mv_stat(last, &dest_stat);
53   if (dest_exists < 0) {   if (dest_exists < 0) {
54   return 1;   return EXIT_FAILURE;
55   }   }
56    
57   if (!(dest_exists & 2)) {   if (!(dest_exists & 2)) { /* last is not a directory */
58   dest = last;   dest = last;
59   goto DO_MOVE;   goto DO_MOVE;
60   }   }
61   }   }
62    
63   do {   do {
64   dest = concat_path_file(last, bb_get_last_path_component(*argv));   dest = concat_path_file(last, bb_get_last_path_component_strip(*argv));
65   dest_exists = cp_mv_stat(dest, &dest_stat);   dest_exists = cp_mv_stat(dest, &dest_stat);
66   if (dest_exists < 0) {   if (dest_exists < 0) {
67   goto RET_1;   goto RET_1;
68   }   }
69    
70  DO_MOVE:   DO_MOVE:
71     if (dest_exists
72   if (dest_exists && !(flags & OPT_FILEUTILS_FORCE) &&   && !(flags & OPT_FILEUTILS_FORCE)
73   ((access(dest, W_OK) < 0 && isatty(0)) ||   && ((access(dest, W_OK) < 0 && isatty(0))
74   (flags & OPT_FILEUTILS_INTERACTIVE))) {      || (flags & OPT_FILEUTILS_INTERACTIVE))
75     ) {
76   if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) {   if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) {
77   goto RET_1; /* Ouch! fprintf failed! */   goto RET_1; /* Ouch! fprintf failed! */
78   }   }
# Line 91  DO_MOVE: Line 84  DO_MOVE:
84   struct stat source_stat;   struct stat source_stat;
85   int source_exists;   int source_exists;
86    
87   if (errno != EXDEV ||   if (errno != EXDEV
88   (source_exists = cp_mv_stat(*argv, &source_stat)) < 1) {   || (source_exists = cp_mv_stat2(*argv, &source_stat, lstat)) < 1
89     ) {
90   bb_perror_msg("cannot rename '%s'", *argv);   bb_perror_msg("cannot rename '%s'", *argv);
91   } else {   } else {
92     static const char fmt[] ALIGN1 =
93     "cannot overwrite %sdirectory with %sdirectory";
94    
95   if (dest_exists) {   if (dest_exists) {
96   if (dest_exists == 3) {   if (dest_exists == 3) {
97   if (source_exists != 3) {   if (source_exists != 3) {
# Line 112  DO_MOVE: Line 109  DO_MOVE:
109   goto RET_1;   goto RET_1;
110   }   }
111   }   }
112   if ((copy_file(*argv, dest,   /* FILEUTILS_RECUR also prevents nasties like
113   FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0) &&   * "read from device and write contents to dst"
114   (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)) {   * instead of "create same device node" */
115     copy_flag = FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS;
116    #if ENABLE_SELINUX
117     copy_flag |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
118    #endif
119     if ((copy_file(*argv, dest, copy_flag) >= 0)
120     && (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)
121     ) {
122   goto RET_0;   goto RET_0;
123   }   }
124   }   }
125  RET_1:   RET_1:
126   status = 1;   status = 1;
127   }   }
128  RET_0:   RET_0:
129   if (dest != last) {   if (dest != last) {
130   free((void *) dest);   free((void *) dest);
131   }   }

Legend:
Removed from v.532  
changed lines
  Added in v.816