blob: 92c3a1ddb55881395e1727ed8ac36b451b04866e [file] [log] [blame] [raw]
/* mv - toolbox
Copyright 2007-2015 PC GO Ld.
Copyright 2015 libdll.so
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#if defined _WIN32 && !defined _WIN32_WNT_NATIVE
#define lstat stat
#endif
int mv_main(int argc, char *argv[]) {
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];
size_t dest_len = strlen(dest);
if(stat(dest, &st) < 0) {
/* an error, unless the destination was missing */
if(errno != ENOENT) {
fprintf(stderr, "%s: failed on %s - %s\n", argv[0], dest, strerror(errno));
return -1;
} else if(argc > 3) {
fprintf(stderr, "%s: %s: %s\n", argv[0], dest, strerror(ENOTDIR));
return 1;
}
st.st_mode = 0;
}
//printf("%s is a dir? %s\n", dest, S_ISDIR(st.st_mode)? "true" : "false");
if(argc > 3 && !S_ISDIR(st.st_mode)) {
fprintf(stderr, "%s: %s: %s\n", argv[0], dest, strerror(ENOTDIR));
return 1;
}
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(dest_len + 1 + strlen(source) + 1 > sizeof(fullDest)) {
fprintf(stderr, "%s: path too long\n", argv[0]);
return 2;
}
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);
}
if(lstat(source, &st) < 0) {
perror(source);
return 3;
}
if(strcmp(source, fullDest) == 0) {
fprintf(stderr, "%s: %s: source and destination are same\n", argv[0], source);
return 4;
}
/* attempt to move it */
if(rename(source, fullDest) < 0) {
//perror("mv");
perror(argv[0]);
return 4;
}
}
return 0;
}