added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / tools / copytoafs / copytoafs.c
blob825cfbc516dcb27b1ecdceac9c6714d2cb61064c
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_BlocksPerTrack=1;
381 de.de_LowCyl = 0;
382 de.de_HighCyl = cfg->size-1;
383 if (createFile(cfg) == 0)
385 volume = initVolume(afsbase, NULL, cfg->image, 0, &de, &error);
386 if (volume != NULL)
388 if ((error == 0) || (error == ERROR_NOT_A_DOS_DISK))
390 if (error == ERROR_NOT_A_DOS_DISK)
392 printf("Initialising disk ...");
393 format(afsbase, volume, cfg->name, cfg->type);
394 newMedium(NULL, volume);
395 printf("done\n");
397 retval = copyData(cfg, volume);
398 flush(afsbase, volume);
400 else
401 printf("Error %ld!\n", error);
402 uninitVolume(afsbase, volume);
404 else
405 printf("Error %ld!\n", error);
407 return retval;
410 void printUsage(char *prg) {
411 printf("Usage: %s [options] <imagefile> <path1> [path2 ...] \n", prg);
412 printf("\t--size\timage size\n"
413 "\t\tThis is either of type int (a multiple of 512) or the special\n"
414 "\t\tvalue 'floppy1440'.\n");
415 printf("\t--reserved\tnumber of reserved blocks (default: 2)\n");
416 printf("\t--bootblock\tnumber of bootblocks (default: 2)\n");
417 printf("\t--name\tlabel of the FS image\n");
418 printf("\t--type\tFS type (OFS, IOFS, FFS, IFFS(default))\n");
419 printf("\t--help\tthis help message\n");
422 void addPathElement(struct Config *cfg, struct PathElement *pe) {
423 struct PathElement *next;
425 next = (struct PathElement *)&cfg->first;
426 while (next->next != NULL)
427 next = next->next;
428 next->next = pe;
429 pe->next = NULL;
432 int parseCommandLine(int argc, char *argv[], struct Config *cfg) {
433 int i;
434 int have_image=0;
435 struct PathElement *pe;
437 cfg->first = NULL;
438 cfg->name = NULL;
439 cfg->type = 3;
440 cfg->reserved = 2;
441 cfg->bootblocks = 2;
442 for (i=1;i<argc;i++)
444 if ((argv[i][0] == '-') && (argv[i][0] == argv[i][1]))
446 if (strcasecmp(argv[i]+2, "help") == 0)
448 printUsage(argv[0]);
449 return 1;
451 else if (strcasecmp(argv[i]+2, "size") == 0)
453 i++;
454 if (i<argc)
456 if (strcasecmp(argv[i], "floppy1440") == 0)
457 cfg->size = 2880;
458 else
460 char *end;
461 cfg->size = strtoul(argv[i], &end, 10);
462 if (end[0] != 0)
464 printf("%s: Integer error\n", argv[i-1]);
465 return 2;
467 if (cfg->size < 8)
469 printf("%s: Value must be at least 8\n", argv[i-1]);
470 return 2;
474 else
476 printf("%s: Missing argument to option\n", argv[i-1]);
477 return 2;
480 else if (strcasecmp(argv[i]+2, "reserved") == 0)
482 i++;
483 if (i<argc)
485 char *end;
486 cfg->reserved = strtoul(argv[i], &end, 10);
487 if (end[0] != 0)
489 printf("%s: Integer error\n", argv[i-1]);
490 return 2;
493 else
495 printf("%s: Missing argument to option\n", argv[i-1]);
496 return 2;
499 else if (strcasecmp(argv[i]+2, "bootblocks") == 0)
501 i++;
502 if (i<argc)
504 char *end;
505 cfg->bootblocks = strtoul(argv[i], &end, 10);
506 if (end[0] != 0)
508 printf("%s: Integer error\n", argv[i-1]);
509 return 2;
512 else
514 printf("%s: Missing argument to option\n", argv[i-1]);
515 return 2;
518 else if (strcasecmp(argv[i]+2, "name") == 0)
520 i++;
521 if (i<argc)
522 cfg->name = argv[i];
523 else
525 printf("%s: Missing argument to option\n", argv[i-1]);
526 return 2;
529 else if (strcasecmp(argv[i]+2, "type") == 0)
531 i++;
532 if (i<argc)
534 if (strcasecmp(argv[i], "OFS") == 0)
535 cfg->type = 0;
536 else if (strcasecmp(argv[i], "IOFS") == 0)
537 cfg->type = 2;
538 else if (strcasecmp(argv[i], "FFS") == 0)
539 cfg->type = 1;
540 else if (strcasecmp(argv[i], "IFFS") == 0)
541 cfg->type = 3;
542 else
544 printf("%s: Unknown fs type\n", argv[i-1]);
545 return 5;
548 else
550 printf("%s: Missing argument to option\n", argv[i-1]);
551 return 2;
554 else
556 printf("%s: Unknown option\n", argv[i]);
557 return 4;
560 else
562 if (have_image==0)
564 cfg->image = argv[i];
565 have_image = 1;
567 else
569 pe = malloc(sizeof(struct PathElement));
570 if (pe == NULL)
572 printf("Not enough memory\n");
573 return 3;
575 pe->path = argv[i];
576 addPathElement(cfg, pe);
580 if (cfg->name == NULL)
581 cfg->name = "SomeDisk";
582 return 0;
584 int main(int argc, char *argv[]) {
585 int error;
586 struct Config cfg;
588 if (argc<3)
590 printUsage(argv[0]);
591 return 1;
593 else
595 error = parseCommandLine(argc, argv, &cfg);
596 if (error == 0)
598 error = doWork(&cfg);
600 else if (error > 1)
602 error = 1;
605 return error;