1 #include <stdio.h> 2 #include <string.h> 3 #include <errno.h> 4 #include <limits.h> 5 #include <sys/stat.h> 6 #include <sys/types.h> 7 8 9 int mv_main(int argc, char *argv[]) 10 { 11 const char* dest; 12 struct stat st; 13 int i; 14 15 if (argc < 3) { 16 fprintf(stderr,"USAGE: %s <source...> <destination>\n", argv[0]); 17 return -1; 18 } 19 20 /* check if destination exists */ 21 dest = argv[argc - 1]; 22 if (stat(dest, &st)) { 23 /* an error, unless the destination was missing */ 24 if (errno != ENOENT) { 25 fprintf(stderr, "failed on %s - %s\n", dest, strerror(errno)); 26 return -1; 27 } 28 st.st_mode = 0; 29 } 30 31 for (i = 1; i < argc - 1; i++) { 32 const char *source = argv[i]; 33 char fullDest[PATH_MAX + 1 + PATH_MAX + 1]; 34 /* assume we build "dest/source", and let rename() fail on pathsize */ 35 if (strlen(dest) + 1 + strlen(source) + 1 > sizeof(fullDest)) { 36 fprintf(stderr, "path too long\n"); 37 return -1; 38 } 39 strcpy(fullDest, dest); 40 41 /* if destination is a directory, concat the source file name */ 42 if (S_ISDIR(st.st_mode)) { 43 const char *fileName = strrchr(source, '/'); 44 if (fullDest[strlen(fullDest)-1] != '/') { 45 strcat(fullDest, "/"); 46 } 47 strcat(fullDest, fileName ? fileName + 1 : source); 48 } 49 50 /* attempt to move it */ 51 if (rename(source, fullDest)) { 52 fprintf(stderr, "failed on '%s' - %s\n", source, strerror(errno)); 53 return -1; 54 } 55 } 56 57 return 0; 58 } 59 60