2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS FAT Image Creator
4 * FILE: tools/fatten/fatten.c
5 * PURPOSE: FAT Image Creator (for EFI Boot)
6 * PROGRAMMERS: David Quintana
13 #include "fatfs/diskio.h"
15 static FATFS g_Filesystem
;
16 static int isMounted
= 0;
17 static char buff
[32768];
19 // tool needed by fatfs
22 /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
23 /* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
29 timeinfo
= localtime(&rawtime
);
34 DWORD Second
: 5; // div 2
39 DWORD Year
: 7; // year-1980
49 timeinfo
->tm_year
- 80,
57 int is_command(const char* parg
)
60 return (parg
[0] == '/') || (parg
[0] == '-');
62 return (parg
[0] == '-');
66 #define NEED_PARAMS(_min_,_max_) \
68 if(nargs<_min_) { printf("Too few args for command %s.\n",argv[-1]); PRINT_HELP_AND_QUIT(); } \
69 if(nargs>_max_) { printf("Too many args for command %s.\n",argv[-1]); PRINT_HELP_AND_QUIT(); } \
79 r
= f_mount(&g_Filesystem
, "0:", 0);
87 #define NEED_MOUNT() \
88 do { ret = need_mount(); if(ret) \
90 printf("Error: could not mount disk (%d). \n", ret); \
91 PRINT_HELP_AND_QUIT(); \
94 void print_help(char const * const name
)
96 printf("Syntax: %s image_file [list of commands]\n\n", name
);
98 printf("Commands: [Note: both '/' and '-' are accepted as command prefixes.]\n");
100 printf("Commands:\n");
102 printf(" -format <sectors> [<filesystem>]\n"
103 " Formats the disk image.\n");
104 printf(" -boot <sector file> [<custom header label>]\n"
105 " Writes a new boot sector.\n");
106 printf(" -add <src path> <dst path>\n"
107 " Copies an external file or directory into the image.\n");
108 printf(" -extract <src path> <dst path>\n"
109 " Copies a file or directory from the image into an external file\n"
111 printf(" -move <src path> <new path>\n"
112 " Moves/renames a file or directory.\n");
113 printf(" -copy <src path> <new path>\n"
114 " Copies a file or directory.\n");
115 printf(" -mkdir <src path> <new path>\n"
116 " Creates a directory.\n");
117 printf(" -rmdir <src path> <new path>\n"
118 " Creates a directory.\n");
119 printf(" -list [<pattern>]\n"
120 " Lists files a directory (defaults to root).\n");
123 #define PRINT_HELP_AND_QUIT() \
126 print_help(oargv[0]); \
130 int main(int oargc
, char* oargv
[])
133 int argc
= oargc
- 1;
134 char** argv
= oargv
+ 1;
136 // first parameter must be the image file.
139 PRINT_HELP_AND_QUIT();
142 if (is_command(argv
[0]))
144 printf("Error: first parameter must be a filename, found '%s' instead. \n", argv
[0]);
145 PRINT_HELP_AND_QUIT();
148 if (disk_openimage(0, argv
[0]))
150 printf("Error: could not open image file '%s'. \n", argv
[0]);
151 PRINT_HELP_AND_QUIT();
163 if (!is_command(parg
))
165 printf("Error: Expected a command, found '%s' instead. \n", parg
);
166 PRINT_HELP_AND_QUIT();
173 // find next command, to calculare number of args
174 while ((argv
[i
] != NULL
) && !is_command(argv
[i
++]))
177 if (strcmp(parg
, "format") == 0)
179 // NOTE: The fs driver detects which FAT format fits best based on size
184 // Arg 1: number of sectors
185 sectors
= atoi(argv
[0]);
189 printf("Error: Sectors must be > 0\n");
194 disk_ioctl(0, SET_SECTOR_COUNT
, §ors
);
198 ret
= f_mkfs("0:", 1, sectors
< 4096 ? 1 : 8);
201 printf("ERROR: Formatting drive: %d.\n", ret
);
202 PRINT_HELP_AND_QUIT();
205 // Arg 2: custom header label (optional)
211 int len
= strlen(argv
[1]);
215 // Copy and verify each character
216 for (i
= 0; i
< len
; i
++)
218 char ch
= argv
[1][i
];
221 if (!isupper(ch
) && !isspace(ch
))
230 // Pad the label with spaces
244 printf("Error: header label is limited to 8 uppercase letters and spaces.");
249 if (disk_read(0, buff
, 0, 1))
251 printf("Error: unable to read existing boot sector from image.");
257 if (g_Filesystem
.fs_type
== FS_FAT32
)
259 memcpy(buff
+ 71, label
, 8);
263 memcpy(buff
+ 43, label
, 8);
266 if (disk_write(0, buff
, 0, 1))
268 printf("Error: unable to write new boot sector to image.");
275 else if (strcmp(parg
, "boot") == 0)
278 BYTE
* temp
= buff
+ 1024;
284 fe
= fopen(argv
[0], "rb");
288 printf("Error: unable to open external file '%s' for reading.", argv
[0]);
293 if(!fread(buff
, 512, 1, fe
))
295 printf("Error: unable to read boot sector from file '%s'.", argv
[0]);
302 if(disk_read(0, temp
, 0, 1))
304 printf("Error: unable to read existing boot sector from image.");
309 if (g_Filesystem
.fs_type
== FS_FAT32
)
311 printf("TODO: writing boot sectors for FAT32 images not yet supported.");
317 #define FAT16_HEADER_START 3
318 #define FAT16_HEADER_END 62
320 memcpy(buff
+ FAT16_HEADER_START
, temp
+ FAT16_HEADER_START
, FAT16_HEADER_END
- FAT16_HEADER_START
);
323 if (disk_write(0, buff
, 0, 1))
325 printf("Error: unable to write new boot sector to image.");
332 else if (strcmp(parg
, "add") == 0)
343 // Arg 1: external file to add
344 // Arg 2: virtual filename
346 fe
= fopen(argv
[0], "rb");
350 printf("Error: unable to open external file '%s' for reading.", argv
[0]);
355 if (f_open(&fv
, argv
[1], FA_WRITE
| FA_CREATE_ALWAYS
))
357 printf("Error: unable to open file '%s' for writing.", argv
[1]);
363 while ((rdlen
= fread(buff
, 1, sizeof(buff
), fe
)) > 0)
365 f_write(&fv
, buff
, rdlen
, &wrlen
);
371 else if (strcmp(parg
, "extract") == 0)
382 // Arg 1: virtual file to extract
383 // Arg 2: external filename
385 if (f_open(&fe
, argv
[0], FA_READ
))
387 printf("Error: unable to open file '%s' for reading.", argv
[0]);
392 fv
= fopen(argv
[1], "wb");
396 printf("Error: unable to open external file '%s' for writing.", argv
[1]);
402 while ((f_read(&fe
, buff
, sizeof(buff
), &rdlen
) == 0) && (rdlen
> 0))
404 fwrite(buff
, 1, rdlen
, fv
);
410 else if (strcmp(parg
, "move") == 0)
415 // Arg 1: src path & filename
416 // Arg 2: new path & filename
418 if (f_rename(argv
[0], argv
[1]))
419 printf("Error moving/renaming '%s' to '%s'", argv
[0], argv
[1]);
421 else if (strcmp(parg
, "copy") == 0)
431 // Arg 1: src path & filename
432 // Arg 2: new path & filename
434 if (f_open(&fe
, argv
[0], FA_READ
))
436 printf("Error: unable to open file '%s' for reading.", argv
[0]);
440 if (f_open(&fv
, argv
[1], FA_WRITE
| FA_CREATE_ALWAYS
))
442 printf("Error: unable to open file '%s' for writing.", argv
[1]);
448 while ((f_read(&fe
, buff
, sizeof(buff
), &rdlen
) == 0) && (rdlen
> 0))
450 f_write(&fv
, buff
, rdlen
, &wrlen
);
456 else if (strcmp(parg
, "mkdir") == 0)
462 // Arg 1: folder path
465 else if (strcmp(parg
, "delete") == 0)
471 // Arg 1: file/folder path (cannot delete non-empty folders)
474 else if (strcmp(parg
, "list") == 0)
478 FILINFO info
= { 0 };
483 // Arg 1: folder path (optional)
490 if (f_opendir(&dir
, root
))
492 printf("Error opening directory '%s'.\n", root
);
497 printf("Listing directory contents of: %s\n", root
);
499 info
.lfname
= lfname
;
501 while ((!f_readdir(&dir
, &info
)) && (strlen(info
.fname
) > 0))
503 if (strlen(info
.lfname
) > 0)
504 printf(" - %s (%s)\n", info
.lfname
, info
.fname
);
506 printf(" - %s\n", info
.fname
);
511 printf("Error: Unknown or invalid command: %s\n", argv
[-1]);
512 PRINT_HELP_AND_QUIT();