fix properties
[AROS.git] / tools / copytoafs / copytoafs.c
blob34457c36f7aa4c4e75b3a66dc7e79d73852a4187
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 ULONG 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, FMF_READ);
59 if (ah != NULL)
61 fd = open(srcpath, O_RDONLY);
62 if (fd != -1)
64 fah = openfile(NULL, ah, filename, FMF_READ | FMF_WRITE | FMF_CREATE | FMF_LOCK | FMF_CLEAR, 0);
65 if (fah != NULL)
67 written=0;
68 while ((len=read(fd, buffer, 2048))>0)
70 size = writef(NULL, fah, buffer, len);
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, "", FMF_READ);
113 if (ah != NULL)
115 dah = createDir(NULL, ah, dirname, 0);
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");
302 else if (S_ISREG(st.st_mode))
304 if (st.st_size == 0)
306 if (fillFile(cfg->image, cfg->size) == 0)
307 retval = 0;
309 else if (st.st_size/512 < cfg->size)
311 printf("%s: File already exists and is too small\n", cfg->image);
313 else
314 retval = 0;
316 else
318 printf("%s: This is not a regular file or blockdevice!\n", cfg->image);
321 else
323 if (errno == ENOENT)
325 if (fillFile(cfg->image, cfg->size) == 0)
326 retval = 0;
328 else
330 perror(cfg->image);
333 return retval;
336 int doWork(struct Config *cfg) {
337 int retval = 1;
338 struct PathElement *pe;
339 struct AFSBase *afsbase=NULL;
340 struct DosEnvec de={0};
341 LONG error;
342 struct Volume *volume;
344 printf("Image: %s\n", cfg->image);
345 printf("Size: %d 512 byte sectors\n", cfg->size);
346 printf("Name: %s\n", cfg->name);
347 printf("Type: ");
348 switch (cfg->type)
350 case 0:
351 printf("Old Filesystem\n");
352 cfg->type = ID_DOS_DISK;
353 break;
354 case 1:
355 printf("Fast Filesystem\n");
356 cfg->type = ID_FFS_DISK;
357 break;
358 case 2:
359 printf("International Old Filesystem\n");
360 cfg->type = ID_INTER_DOS_DISK;
361 break;
362 case 3:
363 printf("International Fast Filesystem\n");
364 cfg->type = ID_INTER_FFS_DISK;
365 break;
367 printf("Path:\n");
368 pe = cfg->first;
369 while (pe != NULL)
371 printf("\t%s\n", pe->path);
372 pe = pe->next;
374 de.de_SizeBlock = 512>>2;
375 de.de_TableSize = 20;
376 de.de_BootBlocks = cfg->bootblocks;
377 de.de_Reserved = cfg->reserved;
378 de.de_NumBuffers = 20;
379 de.de_Surfaces=1;
380 de.de_SectorPerBlock = 1;
381 de.de_BlocksPerTrack=1;
382 de.de_LowCyl = 0;
383 de.de_HighCyl = cfg->size-1;
384 if (createFile(cfg) == 0)
386 volume = initVolume(afsbase, NULL, cfg->image, 0, &de, &error);
387 if (volume != NULL)
389 if ((error == 0) || (error == ERROR_NOT_A_DOS_DISK))
391 if (error == ERROR_NOT_A_DOS_DISK)
393 printf("Initialising disk ...");
394 format(afsbase, volume, cfg->name, cfg->type);
395 newMedium(NULL, volume);
396 printf("done\n");
398 retval = copyData(cfg, volume);
399 flush(afsbase, volume);
401 else
402 printf("Error %ld!\n", error);
403 uninitVolume(afsbase, volume);
405 else
406 printf("Error %ld!\n", error);
408 return retval;
411 void printUsage(char *prg) {
412 printf("Usage: %s [options] <imagefile> <path1> [path2 ...] \n", prg);
413 printf("\t--size\timage size\n"
414 "\t\tThis is either of type int (a multiple of 512) or the special\n"
415 "\t\tvalue 'floppy1440'.\n");
416 printf("\t--reserved\tnumber of reserved blocks (default: 2)\n");
417 printf("\t--bootblock\tnumber of bootblocks (default: 2)\n");
418 printf("\t--name\tlabel of the FS image\n");
419 printf("\t--type\tFS type (OFS, IOFS, FFS, IFFS(default))\n");
420 printf("\t--help\tthis help message\n");
423 void addPathElement(struct Config *cfg, struct PathElement *pe) {
424 struct PathElement *next;
426 next = (struct PathElement *)&cfg->first;
427 while (next->next != NULL)
428 next = next->next;
429 next->next = pe;
430 pe->next = NULL;
433 int parseCommandLine(int argc, char *argv[], struct Config *cfg) {
434 int i;
435 int have_image=0;
436 struct PathElement *pe;
438 cfg->first = NULL;
439 cfg->name = NULL;
440 cfg->type = 3;
441 cfg->reserved = 2;
442 cfg->bootblocks = 2;
443 for (i=1;i<argc;i++)
445 if ((argv[i][0] == '-') && (argv[i][0] == argv[i][1]))
447 if (strcasecmp(argv[i]+2, "help") == 0)
449 printUsage(argv[0]);
450 return 1;
452 else if (strcasecmp(argv[i]+2, "size") == 0)
454 i++;
455 if (i<argc)
457 if (strcasecmp(argv[i], "floppy1440") == 0)
458 cfg->size = 2880;
459 else
461 char *end;
462 cfg->size = strtoul(argv[i], &end, 10);
463 if (end[0] != 0)
465 printf("%s: Integer error\n", argv[i-1]);
466 return 2;
468 if (cfg->size < 8)
470 printf("%s: Value must be at least 8\n", argv[i-1]);
471 return 2;
475 else
477 printf("%s: Missing argument to option\n", argv[i-1]);
478 return 2;
481 else if (strcasecmp(argv[i]+2, "reserved") == 0)
483 i++;
484 if (i<argc)
486 char *end;
487 cfg->reserved = strtoul(argv[i], &end, 10);
488 if (end[0] != 0)
490 printf("%s: Integer error\n", argv[i-1]);
491 return 2;
494 else
496 printf("%s: Missing argument to option\n", argv[i-1]);
497 return 2;
500 else if (strcasecmp(argv[i]+2, "bootblocks") == 0)
502 i++;
503 if (i<argc)
505 char *end;
506 cfg->bootblocks = strtoul(argv[i], &end, 10);
507 if (end[0] != 0)
509 printf("%s: Integer error\n", argv[i-1]);
510 return 2;
513 else
515 printf("%s: Missing argument to option\n", argv[i-1]);
516 return 2;
519 else if (strcasecmp(argv[i]+2, "name") == 0)
521 i++;
522 if (i<argc)
523 cfg->name = argv[i];
524 else
526 printf("%s: Missing argument to option\n", argv[i-1]);
527 return 2;
530 else if (strcasecmp(argv[i]+2, "type") == 0)
532 i++;
533 if (i<argc)
535 if (strcasecmp(argv[i], "OFS") == 0)
536 cfg->type = 0;
537 else if (strcasecmp(argv[i], "IOFS") == 0)
538 cfg->type = 2;
539 else if (strcasecmp(argv[i], "FFS") == 0)
540 cfg->type = 1;
541 else if (strcasecmp(argv[i], "IFFS") == 0)
542 cfg->type = 3;
543 else
545 printf("%s: Unknown fs type\n", argv[i-1]);
546 return 5;
549 else
551 printf("%s: Missing argument to option\n", argv[i-1]);
552 return 2;
555 else
557 printf("%s: Unknown option\n", argv[i]);
558 return 4;
561 else
563 if (have_image==0)
565 cfg->image = argv[i];
566 have_image = 1;
568 else
570 pe = malloc(sizeof(struct PathElement));
571 if (pe == NULL)
573 printf("Not enough memory\n");
574 return 3;
576 pe->path = argv[i];
577 addPathElement(cfg, pe);
581 if (cfg->name == NULL)
582 cfg->name = "SomeDisk";
583 return 0;
586 int main(int argc, char *argv[]) {
587 int error;
588 struct Config cfg;
590 if (argc<3)
592 printUsage(argv[0]);
593 return 1;
595 else
597 error = parseCommandLine(argc, argv, &cfg);
598 if (error == 0)
600 error = doWork(&cfg);
602 else if (error > 1)
604 error = 1;
607 return error;