Obvious fix.
[AROS.git] / tools / copytoafs / copytoafs.c
blobdb6e530fa6b7f9b95da5243bcfb0bceb09f5057c
1 #include <dirent.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/stat.h>
9 #include "os.h"
10 #include "filehandles1.h"
11 #include "filehandles2.h"
12 #include "misc.h"
13 #include "volumes.h"
15 LONG error;
17 struct PathElement {
18 struct PathElement *next;
19 char *path;
22 struct Config {
23 char *image;
24 struct PathElement *first;
25 char *name;
26 unsigned int size;
27 unsigned int bootblocks;
28 unsigned int reserved;
29 unsigned int type;
32 char *filepart(char *path) {
33 char *ptr;
35 ptr = path+strlen(path);
36 while ((ptr != path) && (*ptr != '/'))
37 ptr--;
38 if (ptr != path)
39 ptr++;
40 return ptr;
43 int copyFile(char *srcpath, char *dstpath, struct Volume *volume) {
44 int fd;
45 char buffer[2048];
46 int retval = 1;
47 char *filename;
48 struct AfsHandle *ah;
49 struct AfsHandle *fah;
50 int len;
51 int written;
52 int size;
53 struct stat st;
55 stat(srcpath, &st);
56 filename = filepart(srcpath);
57 printf("Copying %s to %s ...", filename, dstpath);
58 ah = openf(NULL, &volume->ah, dstpath, MODE_OLDFILE, &error);
59 if (ah != NULL)
61 fd = open(srcpath, O_RDONLY);
62 if (fd != -1)
64 fah = openfile(NULL, ah, filename, MODE_NEWFILE, 0, &error);
65 if (fah != NULL)
67 written=0;
68 while ((len=read(fd, buffer, 2048))>0)
70 size = writef(NULL, fah, buffer, len, &error);
71 written += size;
72 if (size<len)
74 retval = 2;
75 break;
78 if (retval == 2)
80 retval = 1;
81 if (error == ERROR_NO_FREE_STORE)
82 printf("No more space left on device!\nNeed %ld more bytes to write file.\n", st.st_size-written);
83 else
84 printf("%s: error %ld\n", filename, error);
86 else
88 printf("done\n");
89 retval = 0;
91 closef(NULL, fah);
93 else
94 printf("error %ld\n", error);
95 close(fd);
97 else
98 perror(srcpath);
99 closef(NULL, ah);
101 else
102 printf("%s: error %ld\n", dstpath, error);
103 return retval;
106 int makeDir(char *dirname, struct Volume *volume) {
107 int retval = 1;
108 struct AfsHandle *ah;
109 struct AfsHandle *dah;
111 printf("Creating directory %s ...", dirname);
112 ah = openf(NULL, &volume->ah, "", MODE_OLDFILE, &error);
113 if (ah != NULL)
115 dah = createDir(NULL, ah, dirname, 0, &error);
116 if (dah != NULL)
118 closef(NULL, dah);
119 printf("done\n");
120 retval = 0;
122 else
124 if (error == ERROR_OBJECT_EXISTS)
126 printf("was already there\n");
127 retval = 0;
129 else
130 printf("error %ld\n", error);
132 closef(NULL, ah);
134 else
135 printf("error %ld\n", error);
136 return retval;
139 int copyDir(char *path, char *dstpath, struct Volume *volume) {
140 int retval = 1;
141 int error;
142 DIR *dir;
143 struct dirent *de;
144 char *ndpath;
145 char *nrpath;
147 dir = opendir(path);
148 if (dir != NULL)
150 while ((de=readdir(dir)) != NULL)
152 if ((strcmp(de->d_name, ".")!=0) && (strcmp(de->d_name, "..")!=0))
154 ndpath = malloc(strlen(path)+1+strlen(de->d_name)+1);
155 if (ndpath != NULL)
157 struct stat st;
158 sprintf(ndpath, "%s/%s", path, de->d_name);
159 if (stat(ndpath, &st) == 0)
161 if (S_ISDIR(st.st_mode))
163 nrpath = malloc(strlen(path)+1+strlen(de->d_name)+1);
164 if (nrpath != NULL)
166 if (*dstpath == 0)
167 strcpy(nrpath, de->d_name);
168 else
169 sprintf(nrpath, "%s/%s", dstpath, de->d_name);
170 error = makeDir(nrpath, volume);
171 if (error == 0)
172 error = copyDir(ndpath, nrpath, volume);
173 free(nrpath);
174 if (error != 0)
176 retval = 2;
177 break;
180 else
182 printf("No memory!\n");
183 retval = 2;
184 break;
187 else if (S_ISREG(st.st_mode))
189 error = copyFile(ndpath, dstpath, volume);
190 if (error != 0)
192 retval = 2;
193 break;
196 else
198 printf("%s: Unknown file type\n", ndpath);
199 retval = 2;
200 break;
203 else
205 perror(ndpath);
206 retval = 2;
207 break;
209 free(ndpath);
211 else
213 printf("No memory!\n");
214 retval = 2;
215 break;
219 if (retval == 2)
220 retval = 1;
221 else
222 retval = 0;
223 closedir(dir);
225 else
226 perror(path);
227 return retval;
230 int copyPath(char *path, struct Volume *volume) {
231 struct stat st;
233 if (stat(path, &st) == 0)
235 if (S_ISDIR(st.st_mode))
237 return copyDir(path, "", volume);
239 else if (S_ISREG(st.st_mode))
241 /* for now always copy to root */
242 return copyFile(path, "", volume);
244 else
245 printf("Unknown file type\n");
247 else
248 perror(NULL);
249 return 1;
252 int copyData(struct Config *cfg, struct Volume *volume) {
253 struct PathElement *pe;
255 pe = cfg->first;
256 while (pe != NULL)
258 if (copyPath(pe->path, volume) != 0)
259 return 1;
260 pe = pe->next;
262 return 0;
265 int fillFile(char *image, unsigned int size) {
266 char buffer[512]={0};
267 FILE *fh;
268 int retval=0;
269 int i;
271 fh = fopen(image, "w");
272 if (fh != NULL)
274 for (i=0;i<size;i++)
276 if (fwrite(buffer, 512, 1, fh) != 1)
278 retval = 1;
279 break;
282 fclose(fh);
284 else
285 retval = 1;
286 if (retval == 1)
287 perror(image);
288 return retval;
291 int createFile(struct Config *cfg) {
292 struct stat st;
293 int retval = 1;
295 if (stat(cfg->image, &st) == 0)
297 // printf("type=%d blocks=%ld blocksize=%ld\n", st.st_rdev, st.st_blocks, st.st_blksize);
298 if (S_ISBLK(st.st_mode))
300 printf("block device\n");
301 retval=0;
303 else if (S_ISREG(st.st_mode))
305 if (st.st_size == 0)
307 if (fillFile(cfg->image, cfg->size) == 0)
308 retval = 0;
310 else if (st.st_size/512 < cfg->size)
312 printf("%s: File already exists and is too small\n", cfg->image);
314 else
315 retval = 0;
317 else
319 printf("%s: This is not a regular file or blockdevice!\n", cfg->image);
322 else
324 if (errno == ENOENT)
326 if (fillFile(cfg->image, cfg->size) == 0)
327 retval = 0;
329 else
331 perror(cfg->image);
334 return retval;
337 int doWork(struct Config *cfg) {
338 int retval = 1;
339 struct PathElement *pe;
340 struct AFSBase *afsbase=NULL;
341 struct DosEnvec de={0};
342 LONG error;
343 struct Volume *volume;
345 printf("Image: %s\n", cfg->image);
346 printf("Size: %d 512 byte sectors\n", cfg->size);
347 printf("Name: %s\n", cfg->name);
348 printf("Type: ");
349 switch (cfg->type)
351 case 0:
352 printf("Old Filesystem\n");
353 cfg->type = ID_DOS_DISK;
354 break;
355 case 1:
356 printf("Fast Filesystem\n");
357 cfg->type = ID_FFS_DISK;
358 break;
359 case 2:
360 printf("International Old Filesystem\n");
361 cfg->type = ID_INTER_DOS_DISK;
362 break;
363 case 3:
364 printf("International Fast Filesystem\n");
365 cfg->type = ID_INTER_FFS_DISK;
366 break;
368 printf("Path:\n");
369 pe = cfg->first;
370 while (pe != NULL)
372 printf("\t%s\n", pe->path);
373 pe = pe->next;
375 de.de_SizeBlock = 512>>2;
376 de.de_TableSize = 20;
377 de.de_BootBlocks = cfg->bootblocks;
378 de.de_Reserved = cfg->reserved;
379 de.de_NumBuffers = 20;
380 de.de_Surfaces=1;
381 de.de_SectorPerBlock = 1;
382 de.de_BlocksPerTrack=1;
383 de.de_LowCyl = 0;
384 de.de_HighCyl = cfg->size-1;
385 if (createFile(cfg) == 0)
387 volume = initVolume(afsbase, NULL, cfg->image, 0, 0, &de, &error);
388 if (volume != NULL)
390 if ((error == 0) || (error == ERROR_NOT_A_DOS_DISK))
392 if (error == ERROR_NOT_A_DOS_DISK)
394 printf("Initialising disk ...");
395 format(afsbase, volume, cfg->name, cfg->type);
396 newMedium(NULL, volume);
397 printf("done\n");
399 retval = copyData(cfg, volume);
400 flush(afsbase, volume);
402 else
403 printf("Error %ld!\n", error);
404 uninitVolume(afsbase, volume);
406 else
407 printf("Error %ld!\n", error);
409 return retval;
412 void printUsage(char *prg) {
413 printf("Usage: %s [options] <imagefile> <path1> [path2 ...] \n", prg);
414 printf("\t--size\timage size\n"
415 "\t\tThis is either of type int (a multiple of 512) or the special\n"
416 "\t\tvalue 'floppy1440'.\n");
417 printf("\t--reserved\tnumber of reserved blocks (default: 2)\n");
418 printf("\t--bootblock\tnumber of bootblocks (default: 2)\n");
419 printf("\t--name\tlabel of the FS image\n");
420 printf("\t--type\tFS type (OFS, IOFS, FFS, IFFS(default))\n");
421 printf("\t--help\tthis help message\n");
424 void addPathElement(struct Config *cfg, struct PathElement *pe) {
425 struct PathElement *next;
427 next = (struct PathElement *)&cfg->first;
428 while (next->next != NULL)
429 next = next->next;
430 next->next = pe;
431 pe->next = NULL;
434 int parseCommandLine(int argc, char *argv[], struct Config *cfg) {
435 int i;
436 int have_image=0;
437 struct PathElement *pe;
439 cfg->first = NULL;
440 cfg->name = NULL;
441 cfg->type = 3;
442 cfg->reserved = 2;
443 cfg->bootblocks = 2;
444 for (i=1;i<argc;i++)
446 if ((argv[i][0] == '-') && (argv[i][0] == argv[i][1]))
448 if (strcasecmp(argv[i]+2, "help") == 0)
450 printUsage(argv[0]);
451 return 1;
453 else if (strcasecmp(argv[i]+2, "size") == 0)
455 i++;
456 if (i<argc)
458 if (strcasecmp(argv[i], "floppy1440") == 0)
459 cfg->size = 2880;
460 else
462 char *end;
463 cfg->size = strtoul(argv[i], &end, 10);
464 if (end[0] != 0)
466 printf("%s: Integer error\n", argv[i-1]);
467 return 2;
469 if (cfg->size < 8)
471 printf("%s: Value must be at least 8\n", argv[i-1]);
472 return 2;
476 else
478 printf("%s: Missing argument to option\n", argv[i-1]);
479 return 2;
482 else if (strcasecmp(argv[i]+2, "reserved") == 0)
484 i++;
485 if (i<argc)
487 char *end;
488 cfg->reserved = strtoul(argv[i], &end, 10);
489 if (end[0] != 0)
491 printf("%s: Integer error\n", argv[i-1]);
492 return 2;
495 else
497 printf("%s: Missing argument to option\n", argv[i-1]);
498 return 2;
501 else if (strcasecmp(argv[i]+2, "bootblocks") == 0)
503 i++;
504 if (i<argc)
506 char *end;
507 cfg->bootblocks = strtoul(argv[i], &end, 10);
508 if (end[0] != 0)
510 printf("%s: Integer error\n", argv[i-1]);
511 return 2;
514 else
516 printf("%s: Missing argument to option\n", argv[i-1]);
517 return 2;
520 else if (strcasecmp(argv[i]+2, "name") == 0)
522 i++;
523 if (i<argc)
524 cfg->name = argv[i];
525 else
527 printf("%s: Missing argument to option\n", argv[i-1]);
528 return 2;
531 else if (strcasecmp(argv[i]+2, "type") == 0)
533 i++;
534 if (i<argc)
536 if (strcasecmp(argv[i], "OFS") == 0)
537 cfg->type = 0;
538 else if (strcasecmp(argv[i], "IOFS") == 0)
539 cfg->type = 2;
540 else if (strcasecmp(argv[i], "FFS") == 0)
541 cfg->type = 1;
542 else if (strcasecmp(argv[i], "IFFS") == 0)
543 cfg->type = 3;
544 else
546 printf("%s: Unknown fs type\n", argv[i-1]);
547 return 5;
550 else
552 printf("%s: Missing argument to option\n", argv[i-1]);
553 return 2;
556 else
558 printf("%s: Unknown option\n", argv[i]);
559 return 4;
562 else
564 if (have_image==0)
566 cfg->image = argv[i];
567 have_image = 1;
569 else
571 pe = malloc(sizeof(struct PathElement));
572 if (pe == NULL)
574 printf("Not enough memory\n");
575 return 3;
577 pe->path = argv[i];
578 addPathElement(cfg, pe);
582 if (cfg->name == NULL)
583 cfg->name = "SomeDisk";
584 return 0;
587 int main(int argc, char *argv[]) {
588 int error;
589 struct Config cfg;
591 if (argc<3)
593 printUsage(argv[0]);
594 return 1;
596 else
598 error = parseCommandLine(argc, argv, &cfg);
599 if (error == 0)
601 error = doWork(&cfg);
603 else if (error > 1)
605 error = 1;
608 return error;