Now supports creation of the target path if necessary.

Now supports renaming while copying if another target name was given.
Forgot to add license (applies for previous versions as well).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7407 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2004-05-04 02:38:37 +00:00
parent ab647990dc
commit 69a19e8844
@@ -1,4 +1,6 @@
/* /*
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/ */
#include <stdio.h> #include <stdio.h>
@@ -122,7 +124,7 @@ copy_dir(const char *fromPath, const char *toPath)
if (st.st_mode & S_IFDIR) { if (st.st_mode & S_IFDIR) {
char path[1024]; char path[1024];
if ((err = sys_mkdir(1, -1, path, MY_S_IRWXU)) == B_OK) if ((err = sys_mkdir(1, -1, path, S_IRWXU)) == B_OK)
copy_dir(fromName, path); copy_dir(fromName, path);
else else
printf("Could not create directory %s: (%s)\n", path, strerror(err)); printf("Could not create directory %s: (%s)\n", path, strerror(err));
@@ -154,11 +156,8 @@ copy(const char *from, const char *to)
struct stat toStat; struct stat toStat;
status_t status = sys_rstat(1, -1, toPath, &toStat, 1); status_t status = sys_rstat(1, -1, toPath, &toStat, 1);
if (status != B_OK) { // will be evaluated later
fprintf(stderr, "Could not stat \"%s\": %s\n", to, strerror(status));
return status;
}
if (S_ISDIR(fromStat.st_mode)) { if (S_ISDIR(fromStat.st_mode)) {
if (S_ISREG(toStat.st_mode)) { if (S_ISREG(toStat.st_mode)) {
fprintf(stderr, "Target \"%s\" is not a directory\n.", to); fprintf(stderr, "Target \"%s\" is not a directory\n.", to);
@@ -166,14 +165,14 @@ copy(const char *from, const char *to)
} }
return copy_dir(from, toPath); return copy_dir(from, toPath);
} else { } else if (status == B_OK) {
if (S_ISREG(toStat.st_mode)) { if (S_ISREG(toStat.st_mode)) {
// overwrite target file // overwrite target file
return copy_file(from, fromStat, toPath); return copy_file(from, fromStat, toPath);
} else { } else {
// copy into target directory // copy into target directory
strlcat(toPath, "/", B_PATH_NAME_LENGTH); strlcat(toPath, "/", B_PATH_NAME_LENGTH);
const char *fileName = strrchr(from, '/'); const char *fileName = strrchr(from, '/');
if (fileName == NULL) if (fileName == NULL)
fileName = from; fileName = from;
@@ -184,6 +183,58 @@ copy(const char *from, const char *to)
return copy_file(from, fromStat, toPath); return copy_file(from, fromStat, toPath);
} }
} else {
// stat(target) failed, so it doesn't exist yet - if
// the target doesn't end in "/", that's should not
// be a problem, just copy the file under the new name
if (toPath[strlen(toPath) - 1] == '/') {
fprintf(stderr, "Could not stat \"%s\": %s\n", to, strerror(status));
return status;
}
return copy_file(from, fromStat, toPath);
}
}
void
create_target_path(const char *to, bool lastOneIsDirectory)
{
char path[B_PATH_NAME_LENGTH];
snprintf(path, B_PATH_NAME_LENGTH, "/myfs/%s", to);
to = path + 6;
// locate "to" to the start of the file system
while (true) {
char *next = strchr(to, '/');
if (next == NULL && !lastOneIsDirectory || next == NULL && to[0] == '\0')
break;
if (next == to) {
// filter "//" like path parts
to++;
continue;
}
if (next)
next[0] = '\0';
// create path
printf("create path for: %s\n", path);
status_t status = sys_mkdir(1, -1, path, S_IRWXU);
if (status != B_OK && status != B_FILE_EXISTS) {
printf("failed: %s!\n", strerror(status));
break;
}
if (next != NULL) {
next[0] = '/';
to = next + 1;
} else
break;
} }
} }
@@ -191,7 +242,8 @@ copy(const char *from, const char *to)
void void
usage(const char *programName) usage(const char *programName)
{ {
printf("usage: %s <bfs-image> <source-files ...> <target>\n", programName); printf("usage: %s [-p] <bfs-image> <source-files ...> <target>\n"
" -p Creates the target path if necessary\n", programName);
exit(-1); exit(-1);
} }
@@ -199,12 +251,20 @@ usage(const char *programName)
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
bool createTargetPath = false;
const char *programName = strrchr(argv[0], '/'); const char *programName = strrchr(argv[0], '/');
if (programName == NULL) if (programName == NULL)
programName = argv[0]; programName = argv[0];
else else
programName++; programName++;
if (argc > 2 && !strcmp(argv[1], "-p")) {
// read options in an ugly and simple way
createTargetPath = true;
argv++;
argc--;
}
if (argc < 4) if (argc < 4)
usage(programName); usage(programName);
@@ -213,6 +273,11 @@ main(int argc, char **argv)
init_fs(image); init_fs(image);
if (createTargetPath) {
// make sure the target path exists
create_target_path(target, argc > 3 || target[strlen(target) - 1] == '/');
}
for (int32 i = 2; i < argc - 1; i++) { for (int32 i = 2; i < argc - 1; i++) {
printf("copy \"%s\" to \"%s\"\n", argv[i], target); printf("copy \"%s\" to \"%s\"\n", argv[i], target);
if (copy(argv[i], target) < B_OK) if (copy(argv[i], target) < B_OK)