grub2: bring back build of aros-side grub2 tools
[AROS.git] / tools / copytoafs / copytoafs.c
blobd93786224f48955bcb1ab0c13d37ad428ca5e0a0
1 /*
2 Copyright © 1995-2014, 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)
87 printf("No more space left on device!\nNeed %ld more bytes to write file.\n", st.st_size-written);
88 else
89 printf("%s: error %ld\n", filename, (long int)error);
91 else
93 printf("done\n");
94 retval = 0;
96 closef(NULL, fah);
98 else
99 printf("error %ld\n", (long int)error);
100 close(fd);
102 else
103 perror(srcpath);
104 closef(NULL, ah);
106 else
107 printf("%s: error %ld\n", dstpath, (long int)error);
108 return retval;
111 int makeDir(char *dirname, struct Volume *volume) {
112 int retval = 1;
113 struct AfsHandle *ah;
114 struct AfsHandle *dah;
116 printf("Creating directory %s ...", dirname);
117 ah = openf(NULL, &volume->ah, "", MODE_OLDFILE, &error);
118 if (ah != NULL)
120 dah = createDir(NULL, ah, dirname, 0, &error);
121 if (dah != NULL)
123 closef(NULL, dah);
124 printf("done\n");
125 retval = 0;
127 else
129 if (error == ERROR_OBJECT_EXISTS)
131 printf("was already there\n");
132 retval = 0;
134 else
135 printf("error %ld\n", (long)error);
137 closef(NULL, ah);
139 else
140 printf("error %ld\n", (long)error);
141 return retval;
144 int copyDir(char *path, char *dstpath, struct Volume *volume) {
145 int retval = 1;
146 int error;
147 DIR *dir;
148 struct dirent *de;
149 char *ndpath;
150 char *nrpath;
152 dir = opendir(path);
153 if (dir != NULL)
155 while ((de=readdir(dir)) != NULL)
157 if ((strcmp(de->d_name, ".")!=0) && (strcmp(de->d_name, "..")!=0))
159 ndpath = malloc(strlen(path)+1+strlen(de->d_name)+1);
160 if (ndpath != NULL)
162 struct stat st;
163 sprintf(ndpath, "%s/%s", path, de->d_name);
164 if (stat(ndpath, &st) == 0)
166 if (S_ISDIR(st.st_mode))
168 nrpath = malloc(strlen(path)+1+strlen(de->d_name)+1);
169 if (nrpath != NULL)
171 if (*dstpath == 0)
172 strcpy(nrpath, de->d_name);
173 else
174 sprintf(nrpath, "%s/%s", dstpath, de->d_name);
175 error = makeDir(nrpath, volume);
176 if (error == 0)
177 error = copyDir(ndpath, nrpath, volume);
178 free(nrpath);
179 if (error != 0)
181 retval = 2;
182 break;
185 else
187 printf("No memory!\n");
188 retval = 2;
189 break;
192 else if (S_ISREG(st.st_mode))
194 error = copyFile(ndpath, dstpath, volume);
195 if (error != 0)
197 retval = 2;
198 break;
201 else
203 printf("%s: Unknown file type\n", ndpath);
204 retval = 2;
205 break;
208 else
210 perror(ndpath);
211 retval = 2;
212 break;
214 free(ndpath);
216 else
218 printf("No memory!\n");
219 retval = 2;
220 break;
224 if (retval == 2)
225 retval = 1;
226 else
227 retval = 0;
228 closedir(dir);
230 else
231 perror(path);
232 return retval;
235 int copyPath(char *path, struct Volume *volume) {
236 struct stat st;
238 if (stat(path, &st) == 0)
240 if (S_ISDIR(st.st_mode))
242 return copyDir(path, "", volume);
244 else if (S_ISREG(st.st_mode))
246 /* for now always copy to root */
247 return copyFile(path, "", volume);
249 else
250 printf("Unknown file type\n");
252 else
253 perror(NULL);
254 return 1;
257 int copyData(struct Config *cfg, struct Volume *volume) {
258 struct PathElement *pe;
260 pe = cfg->first;
261 while (pe != NULL)
263 if (copyPath(pe->path, volume) != 0)
264 return 1;
265 pe = pe->next;
267 return 0;
270 int fillFile(char *image, unsigned int size) {
271 char buffer[512]={0};
272 FILE *fh;
273 int retval=0;
274 int i;
276 fh = fopen(image, "w");
277 if (fh != NULL)
279 for (i=0;i<size;i++)
281 if (fwrite(buffer, 512, 1, fh) != 1)
283 retval = 1;
284 break;
287 fclose(fh);
289 else
290 retval = 1;
291 if (retval == 1)
292 perror(image);
293 return retval;
296 int createFile(struct Config *cfg) {
297 struct stat st;
298 int retval = 1;
300 if (stat(cfg->image, &st) == 0)
302 // printf("type=%d blocks=%ld blocksize=%ld\n", st.st_rdev, st.st_blocks, st.st_blksize);
303 if (S_ISBLK(st.st_mode))
305 printf("block device\n");
306 retval=0;
308 else if (S_ISREG(st.st_mode))
310 if (st.st_size == 0)
312 if (fillFile(cfg->image, cfg->size) == 0)
313 retval = 0;
315 else if (st.st_size/512 < cfg->size)
317 printf("%s: File already exists and is too small\n", cfg->image);
319 else
320 retval = 0;
322 else
324 printf("%s: This is not a regular file or blockdevice!\n", cfg->image);
327 else
329 if (errno == ENOENT)
331 if (fillFile(cfg->image, cfg->size) == 0)
332 retval = 0;
334 else
336 perror(cfg->image);
339 return retval;
342 int doWork(struct Config *cfg) {
343 int retval = 1;
344 struct PathElement *pe;
345 struct AFSBase *afsbase=NULL;
346 struct DosEnvec de={0};
347 LONG error;
348 struct Volume *volume;
350 printf("Image: %s\n", cfg->image);
351 printf("Size: %d 512 byte sectors\n", cfg->size);
352 printf("Name: %s\n", cfg->name);
353 printf("Type: ");
354 switch (cfg->type)
356 case 0:
357 printf("Old Filesystem\n");
358 cfg->type = ID_DOS_DISK;
359 break;
360 case 1:
361 printf("Fast Filesystem\n");
362 cfg->type = ID_FFS_DISK;
363 break;
364 case 2:
365 printf("International Old Filesystem\n");
366 cfg->type = ID_INTER_DOS_DISK;
367 break;
368 case 3:
369 printf("International Fast Filesystem\n");
370 cfg->type = ID_INTER_FFS_DISK;
371 break;
373 printf("Path:\n");
374 pe = cfg->first;
375 while (pe != NULL)
377 printf("\t%s\n", pe->path);
378 pe = pe->next;
380 de.de_SizeBlock = 512>>2;
381 de.de_TableSize = 20;
382 de.de_BootBlocks = cfg->bootblocks;
383 de.de_Reserved = cfg->reserved;
384 de.de_NumBuffers = 20;
385 de.de_Surfaces=1;
386 de.de_SectorPerBlock = 1;
387 de.de_BlocksPerTrack=1;
388 de.de_LowCyl = 0;
389 de.de_HighCyl = cfg->size-1;
390 if (createFile(cfg) == 0)
392 volume = initVolume(afsbase, NULL, cfg->image, 0, 0, &de, &error);
393 if (volume != NULL)
395 if ((error == 0) || (error == ERROR_NOT_A_DOS_DISK))
397 if (error == ERROR_NOT_A_DOS_DISK)
399 printf("Initialising disk ...");
400 format(afsbase, volume, cfg->name, cfg->type);
401 newMedium(NULL, volume);
402 printf("done\n");
404 retval = copyData(cfg, volume);
405 flush(afsbase, volume);
407 else
408 printf("Error %ld!\n", (long)error);
409 uninitVolume(afsbase, volume);
411 else
412 printf("Error %ld!\n", (long)error);
414 return retval;
417 void printUsage(char *prg) {
418 printf("Usage: %s [options] <imagefile> <path1> [path2 ...] \n", prg);
419 printf("\t--size\timage size\n"
420 "\t\tThis is either of type int (a multiple of 512) or the special\n"
421 "\t\tvalue 'floppy1440'.\n");
422 printf("\t--reserved\tnumber of reserved blocks (default: 2)\n");
423 printf("\t--bootblock\tnumber of bootblocks (default: 2)\n");
424 printf("\t--name\tlabel of the FS image\n");
425 printf("\t--type\tFS type (OFS, IOFS, FFS, IFFS(default))\n");
426 printf("\t--help\tthis help message\n");
429 void addPathElement(struct Config *cfg, struct PathElement *pe) {
430 struct PathElement *next;
432 next = (struct PathElement *)&cfg->first;
433 while (next->next != NULL)
434 next = next->next;
435 next->next = pe;
436 pe->next = NULL;
439 int parseCommandLine(int argc, char *argv[], struct Config *cfg) {
440 int i;
441 int have_image=0;
442 struct PathElement *pe;
444 cfg->first = NULL;
445 cfg->name = NULL;
446 cfg->type = 3;
447 cfg->reserved = 2;
448 cfg->bootblocks = 2;
449 for (i=1;i<argc;i++)
451 if ((argv[i][0] == '-') && (argv[i][0] == argv[i][1]))
453 if (strcasecmp(argv[i]+2, "help") == 0)
455 printUsage(argv[0]);
456 return 1;
458 else if (strcasecmp(argv[i]+2, "size") == 0)
460 i++;
461 if (i<argc)
463 if (strcasecmp(argv[i], "floppy1440") == 0)
464 cfg->size = 2880;
465 else
467 char *end;
468 cfg->size = strtoul(argv[i], &end, 10);
469 if (end[0] != 0)
471 printf("%s: Integer error\n", argv[i-1]);
472 return 2;
474 if (cfg->size < 8)
476 printf("%s: Value must be at least 8\n", argv[i-1]);
477 return 2;
481 else
483 printf("%s: Missing argument to option\n", argv[i-1]);
484 return 2;
487 else if (strcasecmp(argv[i]+2, "reserved") == 0)
489 i++;
490 if (i<argc)
492 char *end;
493 cfg->reserved = strtoul(argv[i], &end, 10);
494 if (end[0] != 0)
496 printf("%s: Integer error\n", argv[i-1]);
497 return 2;
500 else
502 printf("%s: Missing argument to option\n", argv[i-1]);
503 return 2;
506 else if (strcasecmp(argv[i]+2, "bootblocks") == 0)
508 i++;
509 if (i<argc)
511 char *end;
512 cfg->bootblocks = strtoul(argv[i], &end, 10);
513 if (end[0] != 0)
515 printf("%s: Integer error\n", argv[i-1]);
516 return 2;
519 else
521 printf("%s: Missing argument to option\n", argv[i-1]);
522 return 2;
525 else if (strcasecmp(argv[i]+2, "name") == 0)
527 i++;
528 if (i<argc)
529 cfg->name = argv[i];
530 else
532 printf("%s: Missing argument to option\n", argv[i-1]);
533 return 2;
536 else if (strcasecmp(argv[i]+2, "type") == 0)
538 i++;
539 if (i<argc)
541 if (strcasecmp(argv[i], "OFS") == 0)
542 cfg->type = 0;
543 else if (strcasecmp(argv[i], "IOFS") == 0)
544 cfg->type = 2;
545 else if (strcasecmp(argv[i], "FFS") == 0)
546 cfg->type = 1;
547 else if (strcasecmp(argv[i], "IFFS") == 0)
548 cfg->type = 3;
549 else
551 printf("%s: Unknown fs type\n", argv[i-1]);
552 return 5;
555 else
557 printf("%s: Missing argument to option\n", argv[i-1]);
558 return 2;
561 else
563 printf("%s: Unknown option\n", argv[i]);
564 return 4;
567 else
569 if (have_image==0)
571 cfg->image = argv[i];
572 have_image = 1;
574 else
576 pe = malloc(sizeof(struct PathElement));
577 if (pe == NULL)
579 printf("Not enough memory\n");
580 return 3;
582 pe->path = argv[i];
583 addPathElement(cfg, pe);
587 if (cfg->name == NULL)
588 cfg->name = "SomeDisk";
589 return 0;
592 int main(int argc, char *argv[]) {
593 int error;
594 struct Config cfg;
596 if (argc<3)
598 printUsage(argv[0]);
599 return 1;
601 else
603 error = parseCommandLine(argc, argv, &cfg);
604 if (error == 0)
606 error = doWork(&cfg);
608 else if (error > 1)
610 error = 1;
613 return error;