reactos/reactos/tools/rcopy.c
2003-12-08 19:17:56 +00:00

319 lines
6.1 KiB
C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef WIN32
#include <io.h>
#include <dos.h>
#else
#include <sys/io.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#endif
#ifndef WIN32
#ifndef MAX_PATH
#define MAX_PATH 260
#endif
#define DIR_SEPARATOR_CHAR '/'
#define DIR_SEPARATOR_STRING "/"
#else
#define DIR_SEPARATOR_CHAR '\\'
#define DIR_SEPARATOR_STRING "\\"
#endif
char *
make_absolute(char *absolute, char *path)
{
#ifndef WIN32
if (path[0] == DIR_SEPARATOR_CHAR)
{
strcpy(absolute, path);
}
else
{
getcwd(absolute, MAX_PATH);
strcat(absolute, DIR_SEPARATOR_STRING);
strcat(absolute, path);
}
#else
_fullpath(absolute, path, MAX_PATH);
#endif
return absolute;
}
char* convert_path(char* origpath)
{
char* newpath;
int i;
//newpath = strdup(origpath);
newpath = malloc(strlen(origpath)+1);
strcpy(newpath, origpath);
i = 0;
while (newpath[i] != 0)
{
#ifdef UNIX_PATHS
if (newpath[i] == '\\')
{
newpath[i] = '/';
}
#else
#ifdef DOS_PATHS
if (newpath[i] == '/')
{
newpath[i] = '\\';
}
#endif
#endif
i++;
}
return(newpath);
}
#define TRANSFER_SIZE (65536)
static void
copy_file(char* path1, char* path2)
{
FILE* in;
FILE* out;
char* buf;
int n_in;
int n_out;
in = fopen(path1, "rb");
if (in == NULL)
{
perror("Cannot open input file");
exit(1);
}
out = fopen(path2, "wb");
if (out == NULL)
{
perror("Cannot open output file");
fclose(in);
exit(1);
}
buf = malloc(TRANSFER_SIZE);
while (!feof(in))
{
n_in = fread(buf, 1, TRANSFER_SIZE, in);
n_out = fwrite(buf, 1, n_in, out);
if (n_in != n_out)
{
perror("Failed to write to output file\n");
free(buf);
fclose(in);
fclose(out);
exit(1);
}
}
}
#ifdef WIN32
static void
copy_directory (char *path1, char *path2)
{
struct _finddata_t f;
int findhandle;
char buf[MAX_PATH];
char tobuf[MAX_PATH];
strcpy(buf, path1);
if (path1[strlen(path1) - 1] != DIR_SEPARATOR_CHAR)
strcat(buf, DIR_SEPARATOR_STRING);
strcat(buf, "*.*");
findhandle =_findfirst(buf, &f);
if (findhandle != 0)
{
do
{
if ((f.attrib & _A_SUBDIR) == 0 && f.name[0] != '.')
{
// Convert to absolute path
make_absolute(buf, path1);
if (path1[strlen(path1) - 1] != DIR_SEPARATOR_CHAR)
strcat(buf, DIR_SEPARATOR_STRING);
strcat(buf, f.name);
//printf("copying file %s\n", buf);
if (path2[strlen(path2) - 1] == DIR_SEPARATOR_CHAR)
{
strcpy(tobuf, path2);
strcat(tobuf, f.name);
}
else
{
strcpy(tobuf, path2);
strcat(tobuf, DIR_SEPARATOR_STRING);
strcat(tobuf, f.name);
}
copy_file(buf, tobuf);
}
else
{
//printf("skipping directory '%s'\n", f.name);
}
}
while (_findnext(findhandle, &f) == 0);
_findclose(findhandle);
}
}
#else
/* Linux version */
static int
is_reg (char *path, char *fn)
{
char buf[MAX_PATH];
char buf2[MAX_PATH];
struct stat sbuf;
strcpy(buf, path);
if (buf[strlen(buf)-1] != '/')
strcat(buf, "/");
strcat(buf, fn);
make_absolute(buf2, buf);
if (stat(buf2, &sbuf) == -1)
return 0;
else {
if (S_ISREG(sbuf.st_mode))
return 1;
else
return 0;
}
}
static void
copy_directory (char *path1, char *path2)
{
DIR *dirp;
struct dirent *entry;
struct stat stbuf;
char buf[MAX_PATH];
char tobuf[MAX_PATH];
char err[400];
dirp = opendir(path1);
if (dirp != NULL)
{
while ((entry = readdir (dirp)) != NULL)
{
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue; // skip self and parent
if (entry->d_type == DT_REG || is_reg(path1, entry->d_name)) // normal file
{
// Convert to absolute path
make_absolute(buf, path1);
if (path1[strlen(path1) - 1] != DIR_SEPARATOR_CHAR)
strcat(buf, DIR_SEPARATOR_STRING);
strcat(buf, entry->d_name);
if (stat(buf, &stbuf) == -1)
{
sprintf(err, "Can't access '%s' (%s)\n", buf, strerror(errno));
perror(err);
exit(1);
return;
}
//printf("copying file '%s'\n", entry->d_name);
if (path2[strlen(path2) - 1] == DIR_SEPARATOR_CHAR)
{
strcpy(tobuf, path2);
strcat(tobuf, entry->d_name);
}
else
{
strcpy(tobuf, path2);
strcat(tobuf, DIR_SEPARATOR_STRING);
strcat(tobuf, entry->d_name);
}
copy_file(buf, tobuf);
}
else
{
//printf("skipping directory '%s'\n", entry->d_name);
}
}
closedir (dirp);
}
else
{
sprintf(err, "Can't open %s\n", path1);
perror(err);
exit(1);
return;
}
}
#endif
static int
is_directory(char *path)
{
struct stat stbuf;
char buf[MAX_PATH];
// Convert to absolute path
make_absolute(buf, path);
if (stat(buf, &stbuf) == -1)
{
/* Assume a destination file */
return 0;
}
if (S_ISDIR(stbuf.st_mode))
return 1;
else
return 0;
}
int main(int argc, char* argv[])
{
char* path1;
char* path2;
int dir1;
int dir2;
if (argc != 3)
{
fprintf(stderr, "Wrong argument count\n");
exit(1);
}
path1 = convert_path(argv[1]);
path2 = convert_path(argv[2]);
dir1 = is_directory(path1);
dir2 = is_directory(path2);
if ((dir1 && !dir2) || (!dir1 && dir2))
{
perror("None or both paramters must be a directory\n");
exit(1);
}
if (dir1)
{
copy_directory(path1, path2);
}
else
{
copy_file(path1, path2);
}
exit(0);
}