revert commit 56204.
[AROS.git] / tools / copytoafs / copytoafs.c
blobf1dba5cd5a626b62ee4b48a95ee8686a452ba535
1 /*
2 Copyright © 1995-2019, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <dirent.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/stat.h>
14 #include "os.h"
15 #include "filehandles1.h"
16 #include "filehandles2.h"
17 #include "misc.h"
18 #include "volumes.h"
20 SIPTR error;
22 struct PathElement {
23 struct PathElement *next;
24 char *path;
27 struct Config {
28 char *image;
29 struct PathElement *first;
30 char *name;
31 unsigned int size;
32 unsigned int bootblocks;
33 unsigned int reserved;
34 unsigned int type;
37 char *filepart(char *path) {
38 char *ptr;
40 ptr = path+strlen(path);
41 while ((ptr != path) && (*ptr != '/'))
42 ptr--;
43 if (ptr != path)
44 ptr++;
45 return ptr;
48 int copyFile(char *srcpath, char *dstpath, struct Volume *volume) {
49 int fd;
50 char buffer[2048];
51 int retval = 1;
52 char *filename;
53 struct AfsHandle *ah;
54 struct AfsHandle *fah;
55 int len;
56 int written;
57 int size;
58 struct stat st;
60 stat(srcpath, &st);
61 filename = filepart(srcpath);
62 printf("Copying %s to %s ...", filename, dstpath);
63 ah = openf(NULL, &volume->ah, dstpath, MODE_OLDFILE, &error);
64 if (ah != NULL)
66 fd = open(srcpath, O_RDONLY);
67 if (fd != -1)
69 fah = openfile(NULL, ah, filename, MODE_NEWFILE, 0, &error);
70 if (fah != NULL)
72 written=0;
73 while ((len=read(fd, buffer, 2048))>0)
75 size = writef(NULL, fah, buffer, len, &error);
76 written += size;
77 if (size<len)
79 retval = 2;
80 break;
83 if (retval == 2)
85 retval = 1;
86 if (error == ERROR_NO_FREE_STORE)
88 printf("No more space left on device!\nNeed %lld more bytes to write file.\n", (long long int)(st.st_size-written));
90 else
91 printf("%s: error %ld\n", filename, (long int)error);
93 else
95 printf("done\n");
96 retval = 0;
98 closef(NULL, fah);
100 else
101 printf("error %ld\n", (long int)error);
102 close(fd);
104 else
105 perror(srcpath);
106 closef(NULL, ah);
108 else
109 printf("%s: error %ld\n", dstpath, (long int)error);
110 return retval;
113 int makeDir(char *dirname, struct Volume *volume) {
114 int retval = 1;
115 struct AfsHandle *ah;
116 struct AfsHandle *dah;
118 printf("Creating directory %s ...", dirname);
119 ah = openf(NULL, &volume->ah, "", MODE_OLDFILE, &error);
120 if (ah != NULL)
122 dah = createDir(NULL, ah, dirname, 0, &error);
123 if (dah != NULL)
125 closef(NULL, dah);
126 printf("done\n");
127 retval = 0;
129 else
131 if (error == ERROR_OBJECT_EXISTS)
133 printf("was already there\n");
134 retval = 0;
136 else
137 printf("error %ld\n", (long)error);
139 closef(NULL, ah);
141 else
142 printf("error %ld\n", (long)error);
143 return retval;
146 int copyDir(char *path, char *dstpath, struct Volume *volume) {
147 int retval = 1;
148 int error;
149 DIR *dir;
150 struct dirent *de;
151 char *ndpath;
152 char *nrpath;
154 dir = opendir(path);
155 if (dir != NULL)
157 while ((de=readdir(dir)) != NULL)
159 if ((strcmp(de->d_name, ".")!=0) && (strcmp(de->d_name, "..")!=0))
161 ndpath = malloc(strlen(path)+1+strlen(de->d_name)+1);
162 if (ndpath != NULL)
164 struct stat st;
165 sprintf(ndpath, "%s/%s", path, de->d_name);
166 if (stat(ndpath, &st) == 0)
168 if (S_ISDIR(st.st_mode))
170 nrpath = malloc(strlen(path)+1+strlen(de->d_name)+1);
171 if (nrpath != NULL)
173 if (*dstpath == 0)
174 strcpy(nrpath, de->d_name);
175 else
176 sprintf(nrpath, "%s/%s", dstpath, de->d_name);
177 error = makeDir(nrpath, volume);
178 if (error == 0)
179 error = copyDir(ndpath, nrpath, volume);
180 free(nrpath);
181 if (error != 0)
183 retval = 2;
184 break;
187 else
189 printf("No memory!\n");
190 retval = 2;
191 break;
194 else if (S_ISREG(st.st_mode))
196 error = copyFile(ndpath, dstpath, volume);
197 if (error != 0)
199 retval = 2;
200 break;
203 else
205 printf("%s: Unknown file type\n", ndpath);
206 retval = 2;
207 break;
210 else
212 perror(ndpath);
213 retval = 2;
214 break;
216 free(ndpath);
218 else
220 printf("No memory!\n");
221 retval = 2;
222 break;
226 if (retval == 2)
227 retval = 1;
228 else
229 retval = 0;
230 closedir(dir);
232 else
233 perror(path);
234 return retval;
237 int copyPath(char *path, struct Volume *volume) {
238 struct stat st;
240 if (stat(path, &st) == 0)
242 if (S_ISDIR(st.st_mode))
244 return copyDir(path, "", volume);
246 else if (S_ISREG(st.st_mode))
248 /* for now always copy to root */
249 return copyFile(path, "", volume);
251 else
252 printf("Unknown file type\n");
254 else
255 perror(NULL);
256 return 1;
259 int copyData(struct Config *cfg, struct Volume *volume) {
260 struct PathElement *pe;
262 pe = cfg->first;
263 while (pe != NULL)
265 if (copyPath(pe->path, volume) != 0)
266 return 1;
267 pe = pe->next;
269 return 0;
272 int fillFile(char *image, unsigned int size) {
273 char buffer[512]={0};
274 FILE *fh;
275 int retval=0;
276 int i;
278 fh = fopen(image, "w");
279 if (fh != NULL)
281 for (i=0;i<size;i++)
283 if (fwrite(buffer, 512, 1, fh) != 1)
285 retval = 1;
286 break;
289 fclose(fh);
291 else
292 retval = 1;
293 if (retval == 1)
294 perror(image);
295 return retval;
298 int createFile(struct Config *cfg) {
299 struct stat st;
300 int retval = 1;
302 if (stat(cfg->image, &st) == 0)
304 // printf("type=%d blocks=%ld blocksize=%ld\n", st.st_rdev, st.st_blocks, st.st_blksize);
305 if (S_ISBLK(st.st_mode))
307 printf("block device\n");
308 retval=0;
310 else if (S_ISREG(st.st_mode))
312 if (st.st_size == 0)
314 if (fillFile(cfg->image, cfg->size) == 0)
315 retval = 0;
317 else if (st.st_size/512 < cfg->size)
319 printf("%s: File already exists and is too small\n", cfg->image);
321 else
322 retval = 0;
324 else
326 printf("%s: This is not a regular file or blockdevice!\n", cfg->image);
329 else
331 if (errno == ENOENT)
333 if (fillFile(cfg->image, cfg->size) == 0)
334 retval = 0;
336 else
338 perror(cfg->image);
341 return retval;
344 int doWork(struct Config *cfg) {
345 int retval = 1;
346 struct PathElement *pe;
347 struct AFSBase *afsbase=NULL;
348 struct DosEnvec de={0};
349 LONG error;
350 struct Volume *volume;
352 printf("Image: %s\n", cfg->image);
353 printf("Size: %d 512 byte sectors\n", cfg->size);
354 printf("Name: %s\n", cfg->name);
355 printf("Type: ");
356 switch (cfg->type)
358 case 0:
359 printf("Old Filesystem\n");
360 cfg->type = ID_DOS_DISK;
361 break;
362 case 1:
363 printf("Fast Filesystem\n");
364 cfg->type = ID_FFS_DISK;
365 break;
366 case 2:
367 printf("International Old Filesystem\n");
368 cfg->type = ID_INTER_DOS_DISK;
369 break;
370 case 3:
371 printf("International Fast Filesystem\n");
372 cfg->type = ID_INTER_FFS_DISK;
373 break;
375 printf("Path:\n");
376 pe = cfg->first;
377 while (pe != NULL)
379 printf("\t%s\n", pe->path);
380 pe = pe->next;
382 de.de_SizeBlock = 512>>2;
383 de.de_TableSize = 20;
384 de.de_BootBlocks = cfg->bootblocks;
385 de.de_Reserved = cfg->reserved;
386 de.de_NumBuffers = 20;
387 de.de_Surfaces=1;
388 de.de_SectorPerBlock = 1;
389 de.de_BlocksPerTrack=1;
390 de.de_LowCyl = 0;
391 de.de_HighCyl = cfg->size-1;
392 if (createFile(cfg) == 0)
394 volume = initVolume(afsbase, NULL, cfg->image, 0, 0, &de, &error);
395 if (volume != NULL)
397 if ((error == 0) || (error == ERROR_NOT_A_DOS_DISK))
399 if (error == ERROR_NOT_A_DOS_DISK)
401 printf("Initialising disk ...");
402 format(afsbase, volume, cfg->name, cfg->type);
403 newMedium(NULL, volume);
404 printf("done\n");
406 retval = copyData(cfg, volume);
407 flush(afsbase, volume);
409 else
410 printf("Error %ld!\n", (long)error);
411 uninitVolume(afsbase, volume);
413 else
414 printf("Error %ld!\n", (long)error);
416 return retval;
419 void printUsage(char *prg) {
420 printf("Usage: %s [options] <imagefile> <path1> [path2 ...] \n", prg);
421 printf("\t--size\timage size\n"
422 "\t\tThis is either of type int (a multiple of 512) or the special\n"
423 "\t\tvalue 'floppy1440'.\n");
424 printf("\t--reserved\tnumber of reserved blocks (default: 2)\n");
425 printf("\t--bootblock\tnumber of bootblocks (default: 2)\n");
426 printf("\t--name\tlabel of the FS image\n");
427 printf("\t--type\tFS type (OFS, IOFS, FFS, IFFS(default))\n");
428 printf("\t--help\tthis help message\n");
431 void addPathElement(struct Config *cfg, struct PathElement *pe) {
432 struct PathElement *next;
434 next = (struct PathElement *)&cfg->first;
435 while (next->next != NULL)
436 next = next->next;
437 next->next = pe;
438 pe->next = NULL;
441 int parseCommandLine(int argc, char *argv[], struct Config *cfg) {
442 int i;
443 int have_image=0;
444 struct PathElement *pe;
446 cfg->first = NULL;
447 cfg->name = NULL;
448 cfg->type = 3;
449 cfg->reserved = 2;
450 cfg->bootblocks = 2;
451 for (i=1;i<argc;i++)
453 if ((argv[i][0] == '-') && (argv[i][0] == argv[i][1]))
455 if (strcasecmp(argv[i]+2, "help") == 0)
457 printUsage(argv[0]);
458 return 1;
460 else if (strcasecmp(argv[i]+2, "size") == 0)
462 i++;
463 if (i<argc)
465 if (strcasecmp(argv[i], "floppy1440") == 0)
466 cfg->size = 2880;
467 else
469 char *end;
470 cfg->size = strtoul(argv[i], &end, 10);
471 if (end[0] != 0)
473 printf("%s: Integer error\n", argv[i-1]);
474 return 2;
476 if (cfg->size < 8)
478 printf("%s: Value must be at least 8\n", argv[i-1]);
479 return 2;
483 else
485 printf("%s: Missing argument to option\n", argv[i-1]);
486 return 2;
489 else if (strcasecmp(argv[i]+2, "reserved") == 0)
491 i++;
492 if (i<argc)
494 char *end;
495 cfg->reserved = strtoul(argv[i], &end, 10);
496 if (end[0] != 0)
498 printf("%s: Integer error\n", argv[i-1]);
499 return 2;
502 else
504 printf("%s: Missing argument to option\n", argv[i-1]);
505 return 2;
508 else if (strcasecmp(argv[i]+2, "bootblocks") == 0)
510 i++;
511 if (i<argc)
513 char *end;
514 cfg->bootblocks = strtoul(argv[i], &end, 10);
515 if (end[0] != 0)
517 printf("%s: Integer error\n", argv[i-1]);
518 return 2;
521 else
523 printf("%s: Missing argument to option\n", argv[i-1]);
524 return 2;
527 else if (strcasecmp(argv[i]+2, "name") == 0)
529 i++;
530 if (i<argc)
531 cfg->name = argv[i];
532 else
534 printf("%s: Missing argument to option\n", argv[i-1]);
535 return 2;
538 else if (strcasecmp(argv[i]+2, "type") == 0)
540 i++;
541 if (i<argc)
543 if (strcasecmp(argv[i], "OFS") == 0)
544 cfg->type = 0;
545 else if (strcasecmp(argv[i], "IOFS") == 0)
546 cfg->type = 2;
547 else if (strcasecmp(argv[i], "FFS") == 0)
548 cfg->type = 1;
549 else if (strcasecmp(argv[i], "IFFS") == 0)
550 cfg->type = 3;
551 else
553 printf("%s: Unknown fs type\n", argv[i-1]);
554 return 5;
557 else
559 printf("%s: Missing argument to option\n", argv[i-1]);
560 return 2;
563 else
565 printf("%s: Unknown option\n", argv[i]);
566 return 4;
569 else
571 if (have_image==0)
573 cfg->image = argv[i];
574 have_image = 1;
576 else
578 pe = malloc(sizeof(struct PathElement));
579 if (pe == NULL)
581 printf("Not enough memory\n");
582 return 3;
584 pe->path = argv[i];
585 addPathElement(cfg, pe);
589 if (cfg->name == NULL)
590 cfg->name = "SomeDisk";
591 return 0;
594 int main(int argc, char *argv[]) {
595 int error;
596 struct Config cfg;
598 if (argc<3)
600 printUsage(argv[0]);
601 return 1;
603 else
605 error = parseCommandLine(argc, argv, &cfg);
606 if (error == 0)
608 error = doWork(&cfg);
610 else if (error > 1)
612 error = 1;
615 return error;