35#define PATH_NAME_MAX 1023
41 ((uint32_t)le16toh(p->dir_ent.start) | \
42 (fs->fat_bits == 32 ? le16toh(p->dir_ent.starthi) << 16 : 0))
44#define MODIFY(p,i,v) \
48 fs_write(p->offset+offsetof(DIR_ENT,i), \
49 sizeof(p->dir_ent.i),&p->dir_ent.i); \
53#define MODIFY_START(p,v,fs) \
58 if (!__v) die("Oops, deleting FAT32 root dir!"); \
59 fs->root_cluster = __v; \
60 p->dir_ent.start = htole16(__v&0xffff); \
61 p->dir_ent.starthi = htole16(__v>>16); \
63 fs_write(offsetof(struct boot_sector,root_cluster), \
64 sizeof(((struct boot_sector *)0)->root_cluster), \
68 MODIFY(p,start,htole16((__v)&0xffff)); \
69 if (fs->fat_bits == 32) \
70 MODIFY(p,starthi,htole16((__v)>>16)); \
76 static int curr_num = 0;
79 if (
fs->root_cluster) {
85 clu_num =
fs->root_cluster;
87 while (clu_num > 0 && clu_num != -1) {
95 if ((
i %
fs->cluster_size) == 0) {
106 die(
"Root directory has no cluster allocated!");
107 for (clu_num = prev + 1; clu_num != prev; clu_num++) {
110 if (clu_num >=
fs->data_clusters + 2)
117 die(
"Root directory full and no free cluster");
122 memset(&d2, 0,
sizeof(d2));
124 for (
i = 0;
i <
fs->cluster_size;
i +=
sizeof(DIR_ENT))
127 memset(de, 0,
sizeof(DIR_ENT));
133 clu_num =
fs->root_cluster;
136 while (clu_num > 0 && clu_num != -1) {
137 fs_read(offset2,
sizeof(DIR_ENT), &d2);
139 !
strncmp((
const char *)d2.name, (
const char *)de->name,
142 i +=
sizeof(DIR_ENT);
143 offset2 +=
sizeof(DIR_ENT);
144 if ((
i %
fs->cluster_size) == 0) {
151 if (clu_num == 0 || clu_num == -1)
153 if (++curr_num >= 10000)
154 die(
"Unable to create unique name");
161 int next_free = 0, scan;
172 if (next_free ==
fs->root_entries)
173 die(
"Root directory is full.");
174 offset =
fs->root_start + next_free *
sizeof(DIR_ENT);
175 memset(de, 0,
sizeof(DIR_ENT));
181 for (scan = 0; scan <
fs->root_entries; scan++)
182 if (scan != next_free &&
186 if (scan ==
fs->root_entries)
188 if (++curr_num >= 10000)
189 die(
"Unable to create unique name");
216 die(
"Path name too long.");
230 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0 };
247 (
time & 31) * 2 + 60 * ((
time >> 5) & 63) + (
time >> 11) * 3600 +
248 86400 * ((
date & 31) - 1 +
day_n[
month] + (year / 4) + year * 365 -
249 ((year & 3) == 0 &&
month < 2 ? 1 : 0) + 3653);
258 static char temp[100];
269 _snprintf(tmp,
sizeof(tmp),
"%d:%d:%d %d.%d.%d",
281 static char temp[100];
298 int i, spc, suspicious = 0;
299 const char *bad_chars =
atari_format ?
"*?\\/:" :
"*?<>|\"\\/:";
301 const unsigned char *
ext =
name + 8;
305 if (
strncmp((
const char *)
name,
"EA DATA SF", 11) == 0 ||
306 strncmp((
const char *)
name,
"WP ROOT SF", 11) == 0)
329 for (
i = 0;
i < 8;
i++) {
339 for (
i = 0;
i < 3;
i++) {
395 for (cluster =
FSTART(
file,
fs); cluster > 0 && cluster <
407 if ((deleting = !clusters))
409 while (walk > 0 && walk != -1) {
413 else if ((deleting = !--clusters))
433 for (walk =
first; walk; walk = walk->
next)
442 file->dir_ent.lcase &= ~FAT_NO_83NAME;
456 die(
"Too many files need repair.");
459 die(
"Can't generate a unique name.");
465 unsigned char name[46];
466 unsigned char *walk, *here;
471 printf(
"Cannot rename FAT32 root dir\n");
473 VfatPrint(
"Cannot rename FAT32 root dir\n" );
482 if ((here = (
unsigned char *)
strchr((
const char *)
name,
'\n')))
484 for (walk = (
unsigned char *)
strrchr((
const char *)
name, 0);
485 walk >=
name && (*walk ==
' ' || *walk ==
'\t'); walk--) ;
487 for (walk =
name; *walk ==
' ' || *walk ==
'\t'; walk++) ;
492 file->dir_ent.lcase &= ~FAT_NO_83NAME;
521 printf(
"1) Drop it\n2) Auto-rename\n3) Rename\n"
522 "4) Convert to directory\n");
528 printf(
" Auto-renaming it.\n");
553 printf(
"Root contains directory \"%s\". Dropping it.\n",
name);
569 printf(
"%s\n Directory has non-zero size. Fixing it.\n",
572 printf(
"%s\n Directory has non-zero size.%s\n",
583 printf(
"%s\n Start (%lu) does not point to parent (%lu)\n",
597 if (
fs->root_cluster &&
expect ==
fs->root_cluster)
600 printf(
"%s\n Start (%lu) does not point to .. (%lu)\n",
611 printf(
"%s\n Start does point to root directory. Deleting dir. \n",
614 printf(
"%s\n Start does point to root directory.%s\n",
623 printf(
"%s\n Bad start cluster 1. Truncating file.\n",
626 die(
"Bad FAT32 root directory! (bad start cluster 1)\n");
635 (
"%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n",
637 (
unsigned long)(
fs->data_clusters + 1));
639 (
"%s\n Start cluster beyond limit (%lu > %lu).%s\n",
641 (
unsigned long)(
fs->data_clusters + 1),
642 (
rw) ?
" Truncating file." :
"");
645 die(
"Bad FAT32 root directory! (start cluster beyond limit: %lu > %lu)\n",
647 (
unsigned long)(
fs->data_clusters + 1));
661 printf(
"%s\n Contains a %s cluster (%lu). Assuming EOF.\n",
664 printf(
"%s\n Contains a %s cluster (%lu).%s\n",
666 (
rw) ?
" Assuming EOF." :
"");
678 die(
"FAT32 root dir starts with a bad cluster!");
692 (
"%s\n File size is %u bytes, cluster chain length is > %llu "
695 (
unsigned long long)clusters *
fs->cluster_size,
701 (
"%s\n File size is %u bytes, cluster chain length is > %llu "
704 (
unsigned long long)clusters *
fs->cluster_size);
714 for (walk =
FSTART(owner,
fs); walk > 0 && walk != -1; walk =
726 printf(
" Truncating second to %llu bytes because first "
727 "is FAT32 root dir.\n",
728 (
unsigned long long)clusters *
fs->cluster_size);
735 printf(
" Truncating first to %llu bytes because second "
736 "is FAT32 root dir.\n",
737 (
unsigned long long)clusters2 *
fs->cluster_size);
740 printf(
"1) Truncate first to %llu bytes%s\n"
741 "2) Truncate second to %llu bytes\n",
742 (
unsigned long long)clusters2 *
fs->cluster_size,
744 (
unsigned long long)clusters *
fs->cluster_size);
749 printf(
" Truncating second to %llu bytes.\n",
750 (
unsigned long long)clusters *
fs->cluster_size);
755 if ((do_trunc != 2 &&
rw)
756 && ((do_trunc == 1 &&
rw)
761 for (
this =
FSTART(owner,
fs);
this > 0 &&
this != -1;
this =
773 while (
this > 0 &&
this != -1) {
784 die(
"Internal error: didn't find cluster %d in chain"
785 " starting at %d", curr,
FSTART(owner,
fs));
805 (
"%s\n File size is %u bytes, cluster chain length is %llu bytes."
808 (
unsigned long long)clusters *
fs->cluster_size,
809 (
unsigned long long)clusters *
fs->cluster_size);
829 int dot, dotdot,
skip, redo;
836 for (walk =
root; *walk; walk = &(*walk)->
next)
841 if (*
root &&
parent && good + bad > 4 && bad > good / 2) {
842 printf(
"%s\n Has a large number of bad entries. (%d/%d)\n",
845 printf(
" Not dropping root directory.\n");
851 printf(
" Not dropping it in auto-mode.\n");
852 else if (
get_key(
"yn",
"Drop directory ? (y/n)") ==
'y') {
859 dot = dotdot = redo = 0;
867 *walk = (*walk)->
next;
879 printf(
" Bad short file name (%s).\n",
882 printf(
"%s\n Bad short file name (%s).\n",
886 printf(
"1) Drop file\n2) Rename file\n3) Auto-rename\n"
892 printf(
" Auto-renaming it.\n");
899 walk = &(*walk)->
next;
918 scan = &(*walk)->
next;
920 while (*scan && !
skip) {
922 !
memcmp((*walk)->dir_ent.name, (*scan)->dir_ent.name,
924 printf(
"%s\n Duplicate directory entry.\n First %s\n",
929 (
"1) Drop first\n2) Drop second\n3) Rename first\n"
930 "4) Rename second\n5) Auto-rename first\n"
931 "6) Auto-rename second\n");
936 printf(
" Auto-renaming second.\n");
943 *walk = (*walk)->
next;
948 *scan = (*scan)->
next;
962 printf(
" Renamed to %s\n",
967 printf(
" Renamed to %s\n",
975 scan = &(*scan)->
next;
981 walk = &(*walk)->
next;
984 dot = dotdot = redo = 0;
988 printf(
"%s\n \".\" is missing. Can't fix this yet.\n",
991 printf(
"%s\n \"..\" is missing. Can't fix this yet.\n",
1008 uint32_t walk, prev, clusters, next_clu;
1010 prev = clusters = 0;
1011 for (walk =
FSTART(
file,
fs); walk > 1 && walk <
fs->data_clusters + 2;
1020 if (owner ==
file) {
1021 printf(
"%s\n Circular cluster chain. Truncating to %lu "
1023 clusters == 1 ?
"" :
"s");
1027 die(
"Bad FAT32 root directory! (bad start cluster)\n");
1040 printf(
"%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n",
1041 path_name(
file), (
unsigned long)clusters, (
unsigned long)walk);
1055 for (walk =
FSTART(
file,
fs); walk > 1 && walk <
fs->data_clusters + 2;
1069 clusters =
left = (le32toh(
file->dir_ent.
size) +
fs->cluster_size - 1) /
1075 while (
left && (walk >= 2) && (walk <
fs->data_clusters + 2)) {
1080 if (!curEntry.
value)
1094 printf(
"Warning: Did only undelete %lu of %lu cluster%s.\n",
1095 (
unsigned long)clusters -
left, (
unsigned long)clusters, clusters == 1 ?
"" :
"s");
1128 memset(&de, 0,
sizeof de);
1131 de.start =
htole16(
fs->root_cluster & 0xffff);
1132 de.starthi =
htole16((
fs->root_cluster >> 16) & 0xffff);
1136 die(
"Can't undelete directories.");
1152 new->next =
new->first =
NULL;
1157 *
chain = &
new->next;
1184 while (clu_num > 0 && clu_num != -1) {
1187 i +=
sizeof(DIR_ENT);
1188 if (!(
i %
fs->cluster_size))
1240 if (
fs->root_cluster) {
1243 for (
i = 0;
i <
fs->root_entries;
i++)
char * strcat(char *DstString, const char *SrcString)
int strcmp(const char *String1, const char *String2)
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
ACPI_SIZE strlen(const char *String)
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
char * strcpy(char *DstString, const char *SrcString)
char * strchr(const char *String, int ch)
void restart(int argc, const char *argv[])
int puts(const char *string)
static const WCHAR empty[]
static const WCHAR *const ext[]
static HRESULT get_owner(VARIANT *user, VARIANT *domain, VARIANT *retval)
static const WCHAR month[12][4]
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
static time_t date_dos2unix(unsigned short time, unsigned short date)
static void add_file(DOS_FS *fs, DOS_FILE ***chain, DOS_FILE *parent, off_t offset, FDSC **cp)
static int check_dir(DOS_FS *fs, DOS_FILE **root, int dots)
static void drop_file(DOS_FS *fs, DOS_FILE *file)
static void rename_file(DOS_FILE *file)
static int scan_dir(DOS_FS *fs, DOS_FILE *this, FDSC **cp)
static int bad_name(DOS_FILE *file)
static void new_dir(void)
int scan_root(DOS_FS *fs)
static int subdirs(DOS_FS *fs, DOS_FILE *parent, FDSC **cp)
static int check_file(DOS_FS *fs, DOS_FILE *file)
static void truncate_file(DOS_FS *fs, DOS_FILE *file, uint32_t clusters)
static void auto_rename(DOS_FILE *file)
#define MODIFY_START(p, v, fs)
static char * path_name(DOS_FILE *file)
off_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern, int gen_name)
static void lfn_remove(off_t from, off_t to)
static void undelete(DOS_FS *fs, DOS_FILE *file)
static char * file_stat(DOS_FILE *file)
static int handle_dot(DOS_FS *fs, DOS_FILE *file, int dots)
static int check_files(DOS_FS *fs, DOS_FILE *start)
GLuint GLuint GLsizei GLenum type
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
void lfn_add_slot(DIR_ENT *de, off_t dir_offset)
void lfn_check_orphaned(void)
void lfn_fix_checksum(off_t from, off_t to, const char *short_name)
char * lfn_get(DIR_ENT *de, off_t *lfn_offset)
#define memcpy(s1, s2, n)
#define sprintf(buf, format,...)
static unsigned int number
static IBackgroundCopyFile * test_file
NTSYSAPI VOID NTAPI RtlSecondsSince1970ToTime(_In_ ULONG SecondsSince1970, _Out_ PLARGE_INTEGER Time)
const char * root_entries[]
static const struct notification read_test[]
static unsigned __int64 next
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
_CRTIMP struct tm *__cdecl localtime(const time_t *_Time)
void * qalloc(void **root, int size)
char get_key(const char *valid, const char *prompt)
uint32_t next_cluster(DOS_FS *fs, uint32_t cluster)
void set_owner(DOS_FS *fs, uint32_t cluster, DOS_FILE *owner)
int bad_cluster(DOS_FS *fs, uint32_t cluster)
off_t cluster_start(DOS_FS *fs, uint32_t cluster)
void get_fat(FAT_ENTRY *entry, void *fat, uint32_t cluster, DOS_FS *fs)
void set_fat(DOS_FS *fs, uint32_t cluster, int32_t new)
void file_modify(FDSC **curr, char *fixed)
int file_cvt(unsigned char *name, unsigned char *fixed)
FD_TYPE file_type(FDSC **curr, char *fixed)
FDSC ** file_cd(FDSC **curr, char *fixed)
int fs_test(off_t pos, int size)
void fs_read(off_t pos, int size, void *data)
void fs_write(off_t pos, int size, void *data)
size_t CDECL strftime(char *str, size_t max, const char *format, const struct tm *mstm)
#define new(TYPE, numElems)
VOID VfatPrint(PCHAR Format,...)