file.c (mtools-4.0.35.tar.bz2) | : | file.c (mtools-4.0.36.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
*/ | */ | |||
#include "sysincludes.h" | #include "sysincludes.h" | |||
#include "msdos.h" | #include "msdos.h" | |||
#include "stream.h" | #include "stream.h" | |||
#include "mtools.h" | #include "mtools.h" | |||
#include "fsP.h" | #include "fsP.h" | |||
#include "file.h" | #include "file.h" | |||
#include "htable.h" | #include "htable.h" | |||
#include "dirCache.h" | #include "dirCache.h" | |||
#include "buffer.h" | ||||
typedef struct File_t { | typedef struct File_t { | |||
Class_t *Class; | struct Stream_t head; | |||
int refs; | ||||
struct Fs_t *Fs; /* Filesystem that this fat file belongs to */ | struct Stream_t *Buffer; | |||
Stream_t *Buffer; | ||||
int (*map)(struct File_t *this, uint32_t where, uint32_t *len, int mode, | int (*map)(struct File_t *this, uint32_t where, uint32_t *len, int mode, | |||
mt_off_t *res); | mt_off_t *res); | |||
uint32_t FileSize; | uint32_t FileSize; | |||
/* How many bytes do we project to need for this file | /* How many bytes do we project to need for this file | |||
(includes those already in FileSize) */ | (includes those already in FileSize) */ | |||
uint32_t preallocatedSize; | uint32_t preallocatedSize; | |||
/* How many clusters we have asked the lower layer to reserve | /* How many clusters we have asked the lower layer to reserve | |||
skipping to change at line 60 | skipping to change at line 60 | |||
unsigned int PreviousAbsCluNr; | unsigned int PreviousAbsCluNr; | |||
/* Relative position of previous cluster */ | /* Relative position of previous cluster */ | |||
unsigned int PreviousRelCluNr; | unsigned int PreviousRelCluNr; | |||
direntry_t direntry; | direntry_t direntry; | |||
size_t hint; | size_t hint; | |||
struct dirCache_t *dcp; | struct dirCache_t *dcp; | |||
unsigned int loopDetectRel; | unsigned int loopDetectRel; | |||
unsigned int loopDetectAbs; | unsigned int loopDetectAbs; | |||
uint32_t where; | ||||
} File_t; | } File_t; | |||
static Class_t FileClass; | static Class_t FileClass; | |||
static T_HashTable *filehash; | static T_HashTable *filehash; | |||
static File_t *getUnbufferedFile(Stream_t *Stream) | static File_t *getUnbufferedFile(Stream_t *Stream) | |||
{ | { | |||
while(Stream->Class != &FileClass) | while(Stream->Class != &FileClass) | |||
Stream = Stream->Next; | Stream = Stream->Next; | |||
return (File_t *) Stream; | return (File_t *) Stream; | |||
} | } | |||
static inline Fs_t *_getFs(File_t *File) | ||||
{ | ||||
return (Fs_t *) File->head.Next; | ||||
} | ||||
Fs_t *getFs(Stream_t *Stream) | Fs_t *getFs(Stream_t *Stream) | |||
{ | { | |||
return getUnbufferedFile(Stream)->Fs; | return (Fs_t *)getUnbufferedFile(Stream)->head.Next; | |||
} | } | |||
struct dirCache_t **getDirCacheP(Stream_t *Stream) | struct dirCache_t **getDirCacheP(Stream_t *Stream) | |||
{ | { | |||
return &getUnbufferedFile(Stream)->dcp; | return &getUnbufferedFile(Stream)->dcp; | |||
} | } | |||
direntry_t *getDirentry(Stream_t *Stream) | direntry_t *getDirentry(Stream_t *Stream) | |||
{ | { | |||
return &getUnbufferedFile(Stream)->direntry; | return &getUnbufferedFile(Stream)->direntry; | |||
skipping to change at line 102 | skipping to change at line 109 | |||
if(bytes % clus_size) | if(bytes % clus_size) | |||
ret++; | ret++; | |||
return ret; | return ret; | |||
} | } | |||
static int recalcPreallocSize(File_t *This) | static int recalcPreallocSize(File_t *This) | |||
{ | { | |||
uint32_t currentClusters, neededClusters; | uint32_t currentClusters, neededClusters; | |||
unsigned int clus_size; | unsigned int clus_size; | |||
uint32_t neededPrealloc; | uint32_t neededPrealloc; | |||
Fs_t *Fs = This->Fs; | Fs_t *Fs = _getFs(This); | |||
#if 0 | #if 0 | |||
if(This->FileSize & 0xc0000000) { | if(This->FileSize & 0xc0000000) { | |||
fprintf(stderr, "Bad filesize\n"); | fprintf(stderr, "Bad filesize\n"); | |||
} | } | |||
if(This->preallocatedSize & 0xc0000000) { | if(This->preallocatedSize & 0xc0000000) { | |||
fprintf(stderr, "Bad preallocated size %x\n", | fprintf(stderr, "Bad preallocated size %x\n", | |||
(int) This->preallocatedSize); | (int) This->preallocatedSize); | |||
} | } | |||
#endif | #endif | |||
skipping to change at line 223 | skipping to change at line 230 | |||
if (begin != end) | if (begin != end) | |||
printf("-%lu", end); | printf("-%lu", end); | |||
printf("> "); | printf("> "); | |||
} | } | |||
begin = end = n; | begin = end = n; | |||
printf("<%lu", begin); | printf("<%lu", begin); | |||
} else { | } else { | |||
end++; | end++; | |||
} | } | |||
first = 0; | first = 0; | |||
n = fatDecode(This->Fs, n); | n = fatDecode(_getFs(This), n); | |||
rel++; | rel++; | |||
if(loopDetect(This, rel, n) < 0) | if(loopDetect(This, rel, n) < 0) | |||
n = 1; | n = 1; | |||
} while (n <= This->Fs->last_fat && n != 1); | } while (n <= _getFs(This)->last_fat && n != 1); | |||
if(!first) { | if(!first) { | |||
if (begin != end) | if (begin != end) | |||
printf("-%lu", end); | printf("-%lu", end); | |||
printf(">"); | printf(">"); | |||
} | } | |||
} | } | |||
void printFatWithOffset(Stream_t *Stream, off_t offset) { | void printFatWithOffset(Stream_t *Stream, off_t offset) { | |||
File_t *This = getUnbufferedFile(Stream); | File_t *This = getUnbufferedFile(Stream); | |||
uint32_t n; | uint32_t n; | |||
unsigned int rel; | unsigned int rel; | |||
off_t clusSize; | off_t clusSize; | |||
n = This->FirstAbsCluNr; | n = This->FirstAbsCluNr; | |||
if(!n) { | if(!n) { | |||
printf("Root directory or empty file\n"); | printf("Root directory or empty file\n"); | |||
return; | return; | |||
} | } | |||
clusSize = This->Fs->cluster_size * This->Fs->sector_size; | clusSize = _getFs(This)->cluster_size * _getFs(This)->sector_size; | |||
rel = 0; | rel = 0; | |||
while(offset >= clusSize) { | while(offset >= clusSize) { | |||
n = fatDecode(This->Fs, n); | n = fatDecode(_getFs(This), n); | |||
rel++; | rel++; | |||
if(loopDetect(This, rel, n) < 0) | if(loopDetect(This, rel, n) < 0) | |||
return; | return; | |||
if(n > This->Fs->last_fat) | if(n > _getFs(This)->last_fat) | |||
return; | return; | |||
offset -= clusSize; | offset -= clusSize; | |||
} | } | |||
printf("%lu", (unsigned long) n); | printf("%lu", (unsigned long) n); | |||
} | } | |||
static int normal_map(File_t *This, uint32_t where, uint32_t *len, int mode, | static int normal_map(File_t *This, uint32_t where, uint32_t *len, int mode, | |||
mt_off_t *res) | mt_off_t *res) | |||
{ | { | |||
unsigned int offset; | unsigned int offset; | |||
size_t end; | size_t end; | |||
uint32_t NrClu; /* number of clusters to read */ | uint32_t NrClu; /* number of clusters to read */ | |||
uint32_t RelCluNr; | uint32_t RelCluNr; | |||
uint32_t CurCluNr; | uint32_t CurCluNr; | |||
uint32_t NewCluNr; | uint32_t NewCluNr; | |||
uint32_t AbsCluNr; | uint32_t AbsCluNr; | |||
uint32_t clus_size; | uint32_t clus_size; | |||
Fs_t *Fs = This->Fs; | Fs_t *Fs = _getFs(This); | |||
*res = 0; | *res = 0; | |||
clus_size = Fs->cluster_size * Fs->sector_size; | clus_size = Fs->cluster_size * Fs->sector_size; | |||
offset = where % clus_size; | offset = where % clus_size; | |||
if (mode == MT_READ) | if (mode == MT_READ) | |||
maximize(*len, This->FileSize - where); | maximize(*len, This->FileSize - where); | |||
if (*len == 0 ) | if (*len == 0 ) | |||
return 0; | return 0; | |||
if (This->FirstAbsCluNr < 2){ | if (This->FirstAbsCluNr < 2){ | |||
if( mode == MT_READ || *len == 0){ | if( mode == MT_READ || *len == 0){ | |||
*len = 0; | *len = 0; | |||
return 0; | return 0; | |||
} | } | |||
NewCluNr = get_next_free_cluster(This->Fs, 1); | NewCluNr = get_next_free_cluster(_getFs(This), 1); | |||
if (NewCluNr == 1 ){ | if (NewCluNr == 1 ){ | |||
errno = ENOSPC; | errno = ENOSPC; | |||
return -2; | return -2; | |||
} | } | |||
hash_remove(filehash, (void *) This, This->hint); | hash_remove(filehash, (void *) This, This->hint); | |||
This->FirstAbsCluNr = NewCluNr; | This->FirstAbsCluNr = NewCluNr; | |||
hash_add(filehash, (void *) This, &This->hint); | hash_add(filehash, (void *) This, &This->hint); | |||
fatAllocate(This->Fs, NewCluNr, Fs->end_fat); | fatAllocate(_getFs(This), NewCluNr, Fs->end_fat); | |||
} | } | |||
RelCluNr = where / clus_size; | RelCluNr = where / clus_size; | |||
if (RelCluNr >= This->PreviousRelCluNr){ | if (RelCluNr >= This->PreviousRelCluNr){ | |||
CurCluNr = This->PreviousRelCluNr; | CurCluNr = This->PreviousRelCluNr; | |||
AbsCluNr = This->PreviousAbsCluNr; | AbsCluNr = This->PreviousAbsCluNr; | |||
} else { | } else { | |||
CurCluNr = 0; | CurCluNr = 0; | |||
AbsCluNr = This->FirstAbsCluNr; | AbsCluNr = This->FirstAbsCluNr; | |||
} | } | |||
NrClu = (offset + *len - 1) / clus_size; | NrClu = (offset + *len - 1) / clus_size; | |||
while (CurCluNr <= RelCluNr + NrClu){ | while (CurCluNr <= RelCluNr + NrClu){ | |||
if (CurCluNr == RelCluNr){ | if (CurCluNr == RelCluNr){ | |||
/* we have reached the beginning of our zone. Save | /* we have reached the beginning of our zone. Save | |||
* coordinates */ | * coordinates */ | |||
This->PreviousRelCluNr = RelCluNr; | This->PreviousRelCluNr = RelCluNr; | |||
This->PreviousAbsCluNr = AbsCluNr; | This->PreviousAbsCluNr = AbsCluNr; | |||
} | } | |||
NewCluNr = fatDecode(This->Fs, AbsCluNr); | NewCluNr = fatDecode(_getFs(This), AbsCluNr); | |||
if (NewCluNr == 1 || NewCluNr == 0){ | if (NewCluNr == 1 || NewCluNr == 0){ | |||
fprintf(stderr,"Fat problem while decoding %d %x\n", | fprintf(stderr,"Fat problem while decoding %d %x\n", | |||
AbsCluNr, NewCluNr); | AbsCluNr, NewCluNr); | |||
exit(1); | exit(1); | |||
} | } | |||
if(CurCluNr == RelCluNr + NrClu) | if(CurCluNr == RelCluNr + NrClu) | |||
break; | break; | |||
if (NewCluNr > Fs->last_fat && mode == MT_WRITE){ | if (NewCluNr > Fs->last_fat && mode == MT_WRITE){ | |||
/* if at end, and writing, extend it */ | /* if at end, and writing, extend it */ | |||
NewCluNr = get_next_free_cluster(This->Fs, AbsCluNr); | NewCluNr = get_next_free_cluster(_getFs(This), AbsCluNr); | |||
if (NewCluNr == 1 ){ /* no more space */ | if (NewCluNr == 1 ){ /* no more space */ | |||
errno = ENOSPC; | errno = ENOSPC; | |||
return -2; | return -2; | |||
} | } | |||
fatAppend(This->Fs, AbsCluNr, NewCluNr); | fatAppend(_getFs(This), AbsCluNr, NewCluNr); | |||
} | } | |||
if (CurCluNr < RelCluNr && NewCluNr > Fs->last_fat){ | if (CurCluNr < RelCluNr && NewCluNr > Fs->last_fat){ | |||
*len = 0; | *len = 0; | |||
return 0; | return 0; | |||
} | } | |||
if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1) | if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1) | |||
break; | break; | |||
CurCluNr++; | CurCluNr++; | |||
skipping to change at line 379 | skipping to change at line 386 | |||
*res = sectorsToBytes(Fs, | *res = sectorsToBytes(Fs, | |||
(This->PreviousAbsCluNr-2) * Fs->cluster_size + | (This->PreviousAbsCluNr-2) * Fs->cluster_size + | |||
Fs->clus_start) + to_mt_off_t(offset); | Fs->clus_start) + to_mt_off_t(offset); | |||
return 1; | return 1; | |||
} | } | |||
static int root_map(File_t *This, uint32_t where, uint32_t *len, | static int root_map(File_t *This, uint32_t where, uint32_t *len, | |||
int mode UNUSEDP, mt_off_t *res) | int mode UNUSEDP, mt_off_t *res) | |||
{ | { | |||
Fs_t *Fs = This->Fs; | Fs_t *Fs = _getFs(This); | |||
if(Fs->dir_len * Fs->sector_size < where) { | if(Fs->dir_len * Fs->sector_size < where) { | |||
*len = 0; | *len = 0; | |||
errno = ENOSPC; | errno = ENOSPC; | |||
return -2; | return -2; | |||
} | } | |||
maximize(*len, Fs->dir_len * Fs->sector_size - where); | maximize(*len, Fs->dir_len * Fs->sector_size - where); | |||
if (*len == 0) | if (*len == 0) | |||
return 0; | return 0; | |||
*res = sectorsToBytes(Fs, Fs->dir_start) + | *res = sectorsToBytes(Fs, Fs->dir_start) + | |||
to_mt_off_t(where); | to_mt_off_t(where); | |||
return 1; | return 1; | |||
} | } | |||
static ssize_t read_file(Stream_t *Stream, char *buf, mt_off_t iwhere, | static ssize_t read_file(Stream_t *Stream, char *buf, size_t ilen) | |||
size_t ilen) | ||||
{ | { | |||
DeclareThis(File_t); | DeclareThis(File_t); | |||
mt_off_t pos; | mt_off_t pos; | |||
int err; | int err; | |||
uint32_t where = truncMtOffTo32u(iwhere); | ||||
uint32_t len = truncSizeTo32u(ilen); | uint32_t len = truncSizeTo32u(ilen); | |||
ssize_t ret; | ||||
Stream_t *Disk = This->Fs->Next; | Stream_t *Disk = _getFs(This)->head.Next; | |||
err = This->map(This, where, &len, MT_READ, &pos); | err = This->map(This, This->where, &len, MT_READ, &pos); | |||
if(err <= 0) | if(err <= 0) | |||
return err; | return err; | |||
return READS(Disk, buf, pos, len); | ret = PREADS(Disk, buf, pos, len); | |||
if(ret < 0) | ||||
return ret; | ||||
This->where += (size_t) ret; | ||||
return ret; | ||||
} | } | |||
static ssize_t write_file(Stream_t *Stream, char *buf, | static ssize_t write_file(Stream_t *Stream, char *buf, size_t ilen) | |||
mt_off_t iwhere, size_t ilen) | ||||
{ | { | |||
DeclareThis(File_t); | DeclareThis(File_t); | |||
mt_off_t pos; | mt_off_t pos; | |||
ssize_t ret; | ssize_t ret; | |||
uint32_t requestedLen; | uint32_t requestedLen; | |||
uint32_t bytesWritten; | uint32_t bytesWritten; | |||
Stream_t *Disk = This->Fs->Next; | Stream_t *Disk = _getFs(This)->head.Next; | |||
uint32_t where = truncMtOffTo32u(iwhere); | uint32_t maxLen = UINT32_MAX-This->where; | |||
uint32_t maxLen = UINT32_MAX-where; | ||||
uint32_t len; | uint32_t len; | |||
int err; | int err; | |||
if(ilen > maxLen) { | if(ilen > maxLen) { | |||
len = maxLen; | len = maxLen; | |||
} else | } else | |||
len = (uint32_t) ilen; | len = (uint32_t) ilen; | |||
requestedLen = len; | requestedLen = len; | |||
err = This->map(This, where, &len, MT_WRITE, &pos); | err = This->map(This, This->where, &len, MT_WRITE, &pos); | |||
if( err <= 0) | if( err <= 0) | |||
return err; | return err; | |||
if(batchmode) | if(batchmode) | |||
ret = force_write(Disk, buf, pos, len); | ret = force_pwrite(Disk, buf, pos, len); | |||
else | else | |||
ret = WRITES(Disk, buf, pos, len); | ret = PWRITES(Disk, buf, pos, len); | |||
if(ret < 0) | if(ret < 0) | |||
/* Error occured */ | /* Error occured */ | |||
return ret; | return ret; | |||
if((uint32_t)ret > requestedLen) | if((uint32_t)ret > requestedLen) | |||
/* More data than requested may be written to lower | /* More data than requested may be written to lower | |||
* levels if batch mode is active, in order to "pad" | * levels if batch mode is active, in order to "pad" | |||
* the last cluster of a file, so that we don't have | * the last cluster of a file, so that we don't have | |||
* to read that back from disk */ | * to read that back from disk */ | |||
bytesWritten = requestedLen; | bytesWritten = requestedLen; | |||
else | else | |||
bytesWritten = (uint32_t)ret; | bytesWritten = (uint32_t)ret; | |||
if (where + bytesWritten > This->FileSize ) | This->where += bytesWritten; | |||
This->FileSize = where + bytesWritten; | if (This->where > This->FileSize ) | |||
This->FileSize = This->where; | ||||
recalcPreallocSize(This); | recalcPreallocSize(This); | |||
return (ssize_t)bytesWritten; | return (ssize_t) bytesWritten; | |||
} | ||||
static ssize_t pread_file(Stream_t *Stream, char *buf, mt_off_t where, | ||||
size_t ilen) { | ||||
DeclareThis(File_t); | ||||
This->where = truncMtOffTo32u(where); | ||||
return read_file(Stream, buf, ilen); | ||||
} | ||||
static ssize_t pwrite_file(Stream_t *Stream, char *buf, mt_off_t where, | ||||
size_t ilen) { | ||||
DeclareThis(File_t); | ||||
This->where = truncMtOffTo32u(where); | ||||
return write_file(Stream, buf, ilen); | ||||
} | } | |||
/* | /* | |||
* Convert an MSDOS time & date stamp to the Unix time() format | * Convert an MSDOS time & date stamp to the Unix time() format | |||
*/ | */ | |||
static int month[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, | static int month[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, | |||
0, 0, 0 }; | 0, 0, 0 }; | |||
static __inline__ time_t conv_stamp(struct directory *dir) | static __inline__ time_t conv_stamp(struct directory *dir) | |||
{ | { | |||
skipping to change at line 538 | skipping to change at line 561 | |||
if(type) | if(type) | |||
*type = This->direntry.dir.attr & ATTR_DIR; | *type = This->direntry.dir.attr & ATTR_DIR; | |||
if(address) | if(address) | |||
*address = This->FirstAbsCluNr; | *address = This->FirstAbsCluNr; | |||
return 0; | return 0; | |||
} | } | |||
static int free_file(Stream_t *Stream) | static int free_file(Stream_t *Stream) | |||
{ | { | |||
DeclareThis(File_t); | DeclareThis(File_t); | |||
Fs_t *Fs = This->Fs; | Fs_t *Fs = _getFs(This); | |||
fsReleasePreallocateClusters(Fs, This->preallocatedClusters); | fsReleasePreallocateClusters(Fs, This->preallocatedClusters); | |||
FREE(&This->direntry.Dir); | FREE(&This->direntry.Dir); | |||
freeDirCache(Stream); | freeDirCache(Stream); | |||
return hash_remove(filehash, (void *) Stream, This->hint); | return hash_remove(filehash, (void *) Stream, This->hint); | |||
} | } | |||
static int flush_file(Stream_t *Stream) | static int flush_file(Stream_t *Stream) | |||
{ | { | |||
DeclareThis(File_t); | DeclareThis(File_t); | |||
direntry_t *entry = &This->direntry; | direntry_t *entry = &This->direntry; | |||
skipping to change at line 579 | skipping to change at line 602 | |||
size > This->preallocatedSize) { | size > This->preallocatedSize) { | |||
This->preallocatedSize = size; | This->preallocatedSize = size; | |||
return recalcPreallocSize(This); | return recalcPreallocSize(This); | |||
} else | } else | |||
return 0; | return 0; | |||
} | } | |||
static Class_t FileClass = { | static Class_t FileClass = { | |||
read_file, | read_file, | |||
write_file, | write_file, | |||
pread_file, | ||||
pwrite_file, | ||||
flush_file, /* flush */ | flush_file, /* flush */ | |||
free_file, /* free */ | free_file, /* free */ | |||
0, /* get_geom */ | 0, /* get_geom */ | |||
get_file_data, | get_file_data, | |||
pre_allocate_file, | pre_allocate_file, | |||
get_dosConvert_pass_through, | get_dosConvert_pass_through, | |||
0 /* discard */ | 0 /* discard */ | |||
}; | }; | |||
static unsigned int getAbsCluNr(File_t *This) | static unsigned int getAbsCluNr(File_t *This) | |||
skipping to change at line 601 | skipping to change at line 626 | |||
return This->FirstAbsCluNr; | return This->FirstAbsCluNr; | |||
if(isRootDir((Stream_t *) This)) | if(isRootDir((Stream_t *) This)) | |||
return 0; | return 0; | |||
return 1; | return 1; | |||
} | } | |||
static uint32_t func1(void *Stream) | static uint32_t func1(void *Stream) | |||
{ | { | |||
DeclareThis(File_t); | DeclareThis(File_t); | |||
return getAbsCluNr(This) ^ (uint32_t) (unsigned long) This->Fs; | return getAbsCluNr(This) ^ (uint32_t) (unsigned long) This->head.Next; | |||
} | } | |||
static uint32_t func2(void *Stream) | static uint32_t func2(void *Stream) | |||
{ | { | |||
DeclareThis(File_t); | DeclareThis(File_t); | |||
return getAbsCluNr(This); | return getAbsCluNr(This); | |||
} | } | |||
static int comp(void *Stream, void *Stream2) | static int comp(void *Stream, void *Stream2) | |||
{ | { | |||
DeclareThis(File_t); | DeclareThis(File_t); | |||
File_t *This2 = (File_t *) Stream2; | File_t *This2 = (File_t *) Stream2; | |||
return This->Fs != This2->Fs || | return _getFs(This) != _getFs(This2) || | |||
getAbsCluNr(This) != getAbsCluNr(This2); | getAbsCluNr(This) != getAbsCluNr(This2); | |||
} | } | |||
static void init_hash(void) | static void init_hash(void) | |||
{ | { | |||
static int is_initialised=0; | static int is_initialised=0; | |||
if(!is_initialised){ | if(!is_initialised){ | |||
make_ht(func1, func2, comp, 20, &filehash); | make_ht(func1, func2, comp, 20, &filehash); | |||
is_initialised = 1; | is_initialised = 1; | |||
skipping to change at line 640 | skipping to change at line 665 | |||
static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first, | static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first, | |||
uint32_t size, direntry_t *entry) | uint32_t size, direntry_t *entry) | |||
{ | { | |||
Stream_t *Stream = GetFs(Dir); | Stream_t *Stream = GetFs(Dir); | |||
DeclareThis(Fs_t); | DeclareThis(Fs_t); | |||
File_t Pattern; | File_t Pattern; | |||
File_t *File; | File_t *File; | |||
init_hash(); | init_hash(); | |||
This->refs++; | This->head.refs++; | |||
if(first != 1){ | if(first != 1){ | |||
/* we use the illegal cluster 1 to mark newly created files. | /* we use the illegal cluster 1 to mark newly created files. | |||
* do not manage those by hashtable */ | * do not manage those by hashtable */ | |||
Pattern.Fs = This; | init_head(&Pattern.head, &FileClass, &This->head); | |||
Pattern.Class = &FileClass; | ||||
if(first || (entry && !IS_DIR(entry))) | if(first || (entry && !IS_DIR(entry))) | |||
Pattern.map = normal_map; | Pattern.map = normal_map; | |||
else | else | |||
Pattern.map = root_map; | Pattern.map = root_map; | |||
Pattern.FirstAbsCluNr = first; | Pattern.FirstAbsCluNr = first; | |||
Pattern.loopDetectRel = 0; | Pattern.loopDetectRel = 0; | |||
Pattern.loopDetectAbs = first; | Pattern.loopDetectAbs = first; | |||
if(!hash_lookup(filehash, (T_HashTableEl) &Pattern, | if(!hash_lookup(filehash, (T_HashTableEl) &Pattern, | |||
(T_HashTableEl **)&File, 0)){ | (T_HashTableEl **)&File, 0)){ | |||
File->refs++; | File->head.refs++; | |||
This->refs--; | This->head.refs--; | |||
return (Stream_t *) File; | return (Stream_t *) File; | |||
} | } | |||
} | } | |||
File = New(File_t); | File = New(File_t); | |||
if (!File) | if (!File) | |||
return NULL; | return NULL; | |||
init_head(&File->head, &FileClass, &This->head); | ||||
File->Buffer = NULL; | ||||
File->dcp = 0; | File->dcp = 0; | |||
File->preallocatedClusters = 0; | File->preallocatedClusters = 0; | |||
File->preallocatedSize = 0; | File->preallocatedSize = 0; | |||
/* memorize dir for date and attrib */ | /* memorize dir for date and attrib */ | |||
File->direntry = *entry; | File->direntry = *entry; | |||
if(entry->entry == -3) | if(entry->entry == -3) | |||
File->direntry.Dir = (Stream_t *) File; /* root directory */ | File->direntry.Dir = (Stream_t *) File; /* root directory */ | |||
else | else | |||
COPY(File->direntry.Dir); | COPY(File->direntry.Dir); | |||
File->where = 0; | ||||
File->Class = &FileClass; | ||||
File->Fs = This; | ||||
if(first || (entry && !IS_DIR(entry))) | if(first || (entry && !IS_DIR(entry))) | |||
File->map = normal_map; | File->map = normal_map; | |||
else | else | |||
File->map = root_map; /* FAT 12/16 root directory */ | File->map = root_map; /* FAT 12/16 root directory */ | |||
if(first == 1) | if(first == 1) | |||
File->FirstAbsCluNr = 0; | File->FirstAbsCluNr = 0; | |||
else | else | |||
File->FirstAbsCluNr = first; | File->FirstAbsCluNr = first; | |||
File->loopDetectRel = 0; | File->loopDetectRel = 0; | |||
File->loopDetectAbs = 0; | File->loopDetectAbs = 0; | |||
File->PreviousRelCluNr = 0xffff; | File->PreviousRelCluNr = 0xffff; | |||
File->FileSize = size; | File->FileSize = size; | |||
File->refs = 1; | ||||
File->Buffer = 0; | ||||
hash_add(filehash, (void *) File, &File->hint); | hash_add(filehash, (void *) File, &File->hint); | |||
return (Stream_t *) File; | return (Stream_t *) File; | |||
} | } | |||
static void bufferize(Stream_t **Dir) | ||||
{ | ||||
Stream_t *BDir; | ||||
File_t *file = (File_t *) *Dir; | ||||
if(!*Dir) | ||||
return; | ||||
if(file->Buffer){ | ||||
(*Dir)->refs--; | ||||
file->Buffer->refs++; | ||||
*Dir = file->Buffer; | ||||
return; | ||||
} | ||||
BDir = buf_init(*Dir, 64*16384, 512, MDIR_SIZE); | ||||
if(!BDir){ | ||||
FREE(Dir); | ||||
*Dir = NULL; | ||||
} else { | ||||
file->Buffer = BDir; | ||||
*Dir = BDir; | ||||
} | ||||
} | ||||
Stream_t *OpenRoot(Stream_t *Dir) | Stream_t *OpenRoot(Stream_t *Dir) | |||
{ | { | |||
unsigned int num; | unsigned int num; | |||
direntry_t entry; | direntry_t entry; | |||
uint32_t size; | uint32_t size; | |||
Stream_t *file; | Stream_t *file; | |||
memset(&entry, 0, sizeof(direntry_t)); | memset(&entry, 0, sizeof(direntry_t)); | |||
num = fat32RootCluster(Dir); | num = fat32RootCluster(Dir); | |||
End of changes. 42 change blocks. | ||||
48 lines changed or deleted | 95 lines changed or added |