|  | #include <stdio.h> | 
|  | #include <string.h> | 
|  | #include <errno.h> | 
|  | #include <limits.h> | 
|  | #include <sys/stat.h> | 
|  | #include <sys/types.h> | 
|  |  | 
|  |  | 
|  | int mv_main(int argc, char *argv[]) | 
|  | { | 
|  | const char* dest; | 
|  | struct stat st; | 
|  | int i; | 
|  |  | 
|  | if (argc < 3) { | 
|  | fprintf(stderr,"USAGE: %s <source...> <destination>\n", argv[0]); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* check if destination exists */ | 
|  | dest = argv[argc - 1]; | 
|  | if (stat(dest, &st)) { | 
|  | /* an error, unless the destination was missing */ | 
|  | if (errno != ENOENT) { | 
|  | fprintf(stderr, "failed on %s - %s\n", dest, strerror(errno)); | 
|  | return -1; | 
|  | } | 
|  | st.st_mode = 0; | 
|  | } | 
|  |  | 
|  | for (i = 1; i < argc - 1; i++) { | 
|  | const char *source = argv[i]; | 
|  | char fullDest[PATH_MAX + 1 + PATH_MAX + 1]; | 
|  | /* assume we build "dest/source", and let rename() fail on pathsize */ | 
|  | if (strlen(dest) + 1 + strlen(source) + 1 > sizeof(fullDest)) { | 
|  | fprintf(stderr, "path too long\n"); | 
|  | return -1; | 
|  | } | 
|  | strcpy(fullDest, dest); | 
|  |  | 
|  | /* if destination is a directory, concat the source file name */ | 
|  | if (S_ISDIR(st.st_mode)) { | 
|  | const char *fileName = strrchr(source, '/'); | 
|  | if (fullDest[strlen(fullDest)-1] != '/') { | 
|  | strcat(fullDest, "/"); | 
|  | } | 
|  | strcat(fullDest, fileName ? fileName + 1 : source); | 
|  | } | 
|  |  | 
|  | /* attempt to move it */ | 
|  | if (rename(source, fullDest)) { | 
|  | fprintf(stderr, "failed on '%s' - %s\n", source, strerror(errno)); | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  |