77fbe57ebe9cf2a02bdca81af89057f7fd8a158d
[reactos.git] / tools / rcopy.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sys/stat.h>
5 #ifdef WIN32
6 #include <io.h>
7 #include <dos.h>
8 #else
9 #include <sys/io.h>
10 #include <errno.h>
11 #include <sys/types.h> 
12 #include <dirent.h>
13 #endif
14 #ifndef WIN32
15 #ifndef MAX_PATH
16 #define MAX_PATH 260
17 #endif
18 #define DIR_SEPARATOR_CHAR '/'
19 #define DIR_SEPARATOR_STRING "/"
20 #else
21 #define DIR_SEPARATOR_CHAR '\\'
22 #define DIR_SEPARATOR_STRING "\\"
23 #endif
24
25 char* convert_path(char* origpath)
26 {
27    char* newpath;
28    int i;
29    
30    newpath = strdup(origpath);
31    
32    i = 0;
33    while (newpath[i] != 0)
34      {
35 #ifdef UNIX_PATHS
36         if (newpath[i] == '\\')
37           {
38              newpath[i] = '/';
39           }
40 #else
41 #ifdef DOS_PATHS
42         if (newpath[i] == '/')
43           {
44              newpath[i] = '\\';
45           }
46 #endif  
47 #endif  
48         i++;
49      }
50    return(newpath);
51 }
52
53 #define TRANSFER_SIZE      (65536)
54
55 static void
56 copy_file(char* path1, char* path2)
57 {
58    FILE* in;
59    FILE* out;
60    char* buf;
61    int n_in;
62    int n_out;
63
64    in = fopen(path1, "rb");
65    if (in == NULL)
66      {
67         perror("Cannot open input file");
68         exit(1);
69      }
70
71    out = fopen(path2, "wb");
72    if (out == NULL)
73      {
74         perror("Cannot open output file");
75         fclose(in);
76         exit(1);
77      }
78    
79    buf = malloc(TRANSFER_SIZE);
80    while (!feof(in))
81      {
82         n_in = fread(buf, 1, TRANSFER_SIZE, in);
83         n_out = fwrite(buf, 1, n_in, out);
84         if (n_in != n_out)
85           {
86              perror("Failed to write to output file\n");
87              free(buf);
88              fclose(in);
89              fclose(out);
90              exit(1);
91           }
92      }
93 }
94
95 #ifdef WIN32
96
97 static void
98 copy_directory (char *path1, char *path2)
99 {
100   struct _finddata_t f;
101   int findhandle;
102   char buf[MAX_PATH];
103   char tobuf[MAX_PATH];
104
105   strcpy(buf, path1);
106   if (path1[strlen(path1) - 1] != DIR_SEPARATOR_CHAR)
107     strcat(buf, DIR_SEPARATOR_STRING);
108   strcat(buf, "*.*");
109   findhandle =_findfirst(buf, &f);
110   if (findhandle != 0)
111     {
112       do
113         {
114           if ((f.attrib & _A_SUBDIR) == 0 && f.name[0] != '.')
115             {
116               // Check for an absolute path
117               if (path1[0] == DIR_SEPARATOR_CHAR)
118                 {
119                   strcpy(buf, path1);
120                   strcat(buf, DIR_SEPARATOR_STRING);
121                   strcat(buf, f.name);
122                 }
123               else
124                 {
125                   getcwd(buf, sizeof(buf));
126                   strcat(buf, DIR_SEPARATOR_STRING);
127                   strcat(buf, path1);
128                   if (path1[strlen(path1) - 1] != DIR_SEPARATOR_CHAR)
129                     strcat(buf, DIR_SEPARATOR_STRING);
130                   strcat(buf, f.name);
131                 }
132
133                       //printf("copying file %s\n", buf);
134               if (path2[strlen(path2) - 1] == DIR_SEPARATOR_CHAR)
135                 {
136                   strcpy(tobuf, path2);
137                   strcat(tobuf, f.name);
138                 }
139               else
140                 {
141                   strcpy(tobuf, path2);
142                   strcat(tobuf, DIR_SEPARATOR_STRING);
143                   strcat(tobuf, f.name);
144                 }
145               copy_file(buf, tobuf);
146             }
147         else
148           {
149             //printf("skipping directory '%s'\n", f.name);
150           }
151         }
152        while (_findnext(findhandle, &f) == 0);
153
154       _findclose(findhandle);
155     }
156 }
157
158 #else
159
160 /* Linux version */
161 static void
162 copy_directory (char *path1, char *path2)
163 {
164   DIR *dirp;
165   struct dirent *entry;
166   char *old_end_source;
167   struct stat stbuf;
168   char buf[MAX_PATH];
169   char tobuf[MAX_PATH];
170   char err[400];
171
172   dirp = opendir(path1); 
173
174   if (dirp != NULL)
175     {
176       while ((entry = readdir (dirp)) != NULL)
177           {
178         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
179           continue; // skip self and parent
180
181         if (entry->d_type == DT_REG) // normal file
182                     {
183               // Check for an absolute path
184               if (path1[0] == DIR_SEPARATOR_CHAR)
185                 {
186                   strcpy(buf, path1);
187                   strcat(buf, DIR_SEPARATOR_STRING);
188                   strcat(buf, entry->d_name);
189                 }
190               else
191                 {
192                   getcwd(buf, sizeof(buf));
193                   strcat(buf, DIR_SEPARATOR_STRING);
194                   strcat(buf, path1);
195                   if (path1[strlen(path1) - 1] != DIR_SEPARATOR_CHAR)
196                     strcat(buf, DIR_SEPARATOR_STRING);
197                   strcat(buf, entry->d_name);
198                 }
199               if (stat(buf, &stbuf) == -1)
200                 {
201                   sprintf(err, "Can't access '%s' (%s)\n", buf, strerror(errno));
202                   perror(err);
203                   exit(1);
204                   return;
205                 }
206
207                               //printf("copying file '%s'\n", entry->d_name);
208             if (path2[strlen(path2) - 1] == DIR_SEPARATOR_CHAR)
209               {
210                 strcpy(tobuf, path2);
211                 strcat(tobuf, entry->d_name);
212               }
213             else
214               {
215                 strcpy(tobuf, path2);
216                 strcat(tobuf, DIR_SEPARATOR_STRING);
217                 strcat(tobuf, entry->d_name);
218               }
219             copy_file(buf, tobuf);
220          }
221         else
222           {
223             //printf("skipping directory '%s'\n", entry->d_name);
224           }
225        }
226       closedir (dirp);
227     }
228   else
229     {
230       sprintf(err, "Can't open %s\n", path1);
231       perror(err);
232       exit(1);
233       return;
234     }
235 }
236
237 #endif
238
239 static int
240 is_directory(char *path)
241 {
242   struct stat stbuf;
243   char buf[MAX_PATH];
244   char err[400];
245
246   // Check for an absolute path
247   if (path[0] == DIR_SEPARATOR_CHAR)
248     {
249       strcpy(buf, path);
250     }
251   else
252     {
253       getcwd(buf, sizeof(buf));
254       strcat(buf, DIR_SEPARATOR_STRING);
255       strcat(buf, path);
256     }
257   if (stat(buf, &stbuf) == -1)
258     {
259       /* Assume a destination file */
260       return 0;
261     }
262   if (S_ISDIR(stbuf.st_mode))
263     return 1;
264   else
265     return 0;
266 }
267
268 int main(int argc, char* argv[])
269 {
270    char* path1;
271    char* path2;
272    int dir1;
273    int dir2;
274    
275    if (argc != 3)
276      {
277         fprintf(stderr, "Wrong argument count\n");
278         exit(1);
279      }
280
281    path1 = convert_path(argv[1]);
282    path2 = convert_path(argv[2]);
283
284    dir1 = is_directory(path1);
285    dir2 = is_directory(path2);
286
287    if ((dir1 && !dir2) || (!dir1 && dir2))
288     {
289              perror("None or both paramters must be a directory\n");
290              exit(1);
291     }
292
293    if (dir1)
294      {
295        copy_directory(path1, path2);
296      }
297    else
298      {
299        copy_file(path1, path2);
300      }
301
302    exit(0);
303 }