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
9int 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