ae50aeaf9662e24327184ed0486da8855a8b8072
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
20 DWORD
get_fattime(void)
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 void print_help(const char* name
)
60 printf("Syntax: %s image_file [list of commands]\n\n", name
);
62 printf("Commands: [Note: both '/' and '-' are accepted as command prefixes.]\n");
64 printf("Commands:\n");
66 // printf(" -format <sectors> [<filesystem>] [<custom header label>]\n"
67 printf(" -format <sectors> [<custom header label>]\n"
68 " Formats the disk image.\n");
69 printf(" -boot <sector file>\n"
70 " Writes a new boot sector.\n");
71 printf(" -add <src path> <dst path>\n"
72 " Copies an external file or directory into the image.\n");
73 printf(" -extract <src path> <dst path>\n"
74 " Copies a file or directory from the image into an external file\n"
76 printf(" -move <src path> <new path>\n"
77 " Moves/renames a file or directory.\n");
78 printf(" -copy <src path> <new path>\n"
79 " Copies a file or directory.\n");
80 printf(" -mkdir <src path> <new path>\n"
81 " Creates a directory.\n");
82 printf(" -rmdir <src path> <new path>\n"
83 " Creates a directory.\n");
84 printf(" -list [<pattern>]\n"
85 " Lists files a directory (defaults to root).\n");
88 #define PRINT_HELP_AND_QUIT() \
91 print_help(oargv[0]); \
95 int is_command(const char* parg
)
98 return (parg
[0] == '/') || (parg
[0] == '-');
100 return (parg
[0] == '-');
104 #define NEED_PARAMS(_min_, _max_) \
106 if (nargs < _min_) { printf("Too few args for command %s.\n" , argv[-1]); PRINT_HELP_AND_QUIT(); } \
107 if (nargs > _max_) { printf("Too many args for command %s.\n", argv[-1]); PRINT_HELP_AND_QUIT(); } \
117 r
= f_mount(&g_Filesystem
, "0:", 0);
125 #define NEED_MOUNT() \
126 do { ret = need_mount(); if(ret) \
128 printf("Error: could not mount disk (%d).\n", ret); \
132 int main(int oargc
, char* oargv
[])
135 int argc
= oargc
- 1;
136 char** argv
= oargv
+ 1;
138 // first parameter must be the image file.
141 PRINT_HELP_AND_QUIT();
144 if (is_command(argv
[0]))
146 printf("Error: first parameter must be a filename, found '%s' instead.\n", argv
[0]);
147 PRINT_HELP_AND_QUIT();
150 if (disk_openimage(0, argv
[0]))
152 printf("Error: could not open image file '%s'.\n", argv
[0]);
166 if (!is_command(parg
))
168 printf("Error: Expected a command, found '%s' instead.\n", parg
);
169 PRINT_HELP_AND_QUIT();
176 // find next command, to calculare number of args
177 while ((argv
[i
] != NULL
) && !is_command(argv
[i
++]))
180 if (strcmp(parg
, "format") == 0)
182 // NOTE: The fs driver detects which FAT format fits best based on size
187 // Arg 1: number of sectors
188 sectors
= atoi(argv
[0]);
192 printf("Error: Sectors must be > 0\n");
197 disk_ioctl(0, SET_SECTOR_COUNT
, §ors
);
201 ret
= f_mkfs("0:", 1, sectors
< 4096 ? 1 : 8);
204 printf("ERROR: Formatting drive: %d.\n", ret
);
208 // Arg 2: custom header label (optional)
211 #define FAT_VOL_LABEL_LEN 11
212 char vol_label
[2 + FAT_VOL_LABEL_LEN
+ 1]; // Null-terminated buffer
213 char* label
= vol_label
+ 2; // The first two characters are reserved for the drive number "0:"
217 int len
= strlen(argv
[1]);
219 if (len
<= FAT_VOL_LABEL_LEN
)
221 // Verify each character (should be printable ASCII)
222 // and copy it in uppercase.
223 for (i
= 0; i
< len
; i
++)
225 ch
= toupper(argv
[1][i
]);
226 if ((ch
< 0x20) || !isprint(ch
))
237 // Pad the label with spaces
238 while (len
< FAT_VOL_LABEL_LEN
)
251 printf("Error: header label is limited to 11 printable uppercase ASCII symbols.");
256 if (disk_read(0, buff
, 0, 1))
258 printf("Error: unable to read existing boot sector from image.");
263 if (g_Filesystem
.fs_type
== FS_FAT32
)
265 memcpy(buff
+ 71, label
, FAT_VOL_LABEL_LEN
);
269 memcpy(buff
+ 43, label
, FAT_VOL_LABEL_LEN
);
272 if (disk_write(0, buff
, 0, 1))
274 printf("Error: unable to write new boot sector to image.");
279 // Set also the directory volume label
280 memcpy(vol_label
, "0:", 2);
281 vol_label
[2 + FAT_VOL_LABEL_LEN
] = '\0';
282 f_setlabel(vol_label
);
285 else if (strcmp(parg
, "boot") == 0)
288 BYTE
* temp
= buff
+ 1024;
294 fe
= fopen(argv
[0], "rb");
297 printf("Error: unable to open external file '%s' for reading.", argv
[0]);
302 if (!fread(buff
, 512, 1, fe
))
304 printf("Error: unable to read boot sector from file '%s'.", argv
[0]);
314 if (disk_read(0, temp
, 0, 1))
316 printf("Error: unable to read existing boot sector from image.");
321 if (g_Filesystem
.fs_type
== FS_FAT32
)
323 printf("TODO: writing boot sectors for FAT32 images not yet supported.");
329 #define FAT16_HEADER_START 3
330 #define FAT16_HEADER_END 62
332 memcpy(buff
+ FAT16_HEADER_START
, temp
+ FAT16_HEADER_START
, FAT16_HEADER_END
- FAT16_HEADER_START
);
335 if (disk_write(0, buff
, 0, 1))
337 printf("Error: unable to write new boot sector to image.");
342 else if (strcmp(parg
, "add") == 0)
353 // Arg 1: external file to add
354 // Arg 2: virtual filename
356 fe
= fopen(argv
[0], "rb");
359 printf("Error: unable to open external file '%s' for reading.", argv
[0]);
364 if (f_open(&fv
, argv
[1], FA_WRITE
| FA_CREATE_ALWAYS
))
366 printf("Error: unable to open file '%s' for writing.", argv
[1]);
372 while ((rdlen
= fread(buff
, 1, sizeof(buff
), fe
)) > 0)
374 f_write(&fv
, buff
, rdlen
, &wrlen
);
380 else if (strcmp(parg
, "extract") == 0)
391 // Arg 1: virtual file to extract
392 // Arg 2: external filename
394 if (f_open(&fe
, argv
[0], FA_READ
))
396 printf("Error: unable to open file '%s' for reading.", argv
[0]);
401 fv
= fopen(argv
[1], "wb");
404 printf("Error: unable to open external file '%s' for writing.", argv
[1]);
410 while ((f_read(&fe
, buff
, sizeof(buff
), &rdlen
) == 0) && (rdlen
> 0))
412 fwrite(buff
, 1, rdlen
, fv
);
418 else if (strcmp(parg
, "move") == 0)
423 // Arg 1: src path & filename
424 // Arg 2: new path & filename
426 if (f_rename(argv
[0], argv
[1]))
427 printf("Error moving/renaming '%s' to '%s'", argv
[0], argv
[1]);
429 else if (strcmp(parg
, "copy") == 0)
439 // Arg 1: src path & filename
440 // Arg 2: new path & filename
442 if (f_open(&fe
, argv
[0], FA_READ
))
444 printf("Error: unable to open file '%s' for reading.", argv
[0]);
448 if (f_open(&fv
, argv
[1], FA_WRITE
| FA_CREATE_ALWAYS
))
450 printf("Error: unable to open file '%s' for writing.", argv
[1]);
456 while ((f_read(&fe
, buff
, sizeof(buff
), &rdlen
) == 0) && (rdlen
> 0))
458 f_write(&fv
, buff
, rdlen
, &wrlen
);
464 else if (strcmp(parg
, "mkdir") == 0)
470 // Arg 1: folder path
473 else if (strcmp(parg
, "delete") == 0)
479 // Arg 1: file/folder path (cannot delete non-empty folders)
482 else if (strcmp(parg
, "list") == 0)
486 FILINFO info
= { 0 };
491 // Arg 1: folder path (optional)
498 if (f_opendir(&dir
, root
))
500 printf("Error opening directory '%s'.\n", root
);
505 printf("Listing directory contents of: %s\n", root
);
507 info
.lfname
= lfname
;
508 info
.lfsize
= sizeof(lfname
)-1;
509 while ((!f_readdir(&dir
, &info
)) && (strlen(info
.fname
) > 0))
511 if (strlen(info
.lfname
) > 0)
512 printf(" - %s (%s)\n", info
.lfname
, info
.fname
);
514 printf(" - %s\n", info
.fname
);
519 printf("Error: Unknown or invalid command: %s\n", argv
[-1]);
520 PRINT_HELP_AND_QUIT();