hschumann2/TempleOS-Source-Code
0847
1 2I64 FSize(CFile *f)3{//Report size of opened file in bytes.4 if (f)5 return f->de.size;6 else7 return 0;8}9 10CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0)11{//Allows flags "r","w","w+". "c" for contiguous.12//(It uses StrOcc() for 'w', 'r', '+', 'c')13 CFile *f=CAlloc(sizeof(CFile));14 CDirContext *dirc;15 U8 *full_name;16 Bool contiguous=StrOcc(flags,'c');17 18 f->clus=INVALID_CLUS;19 f->fblk_num=0;20 if (cnt>0)21 f->max_blk=cnt-1;22 else23 f->max_blk=I64_MAX;24 f->file_clus_num=INVALID_CLUS;25 full_name=FileNameAbs(filename);26 f->dv=Let2Drv(*full_name);27 if (f->dv->fs_type==FSt_REDSEA)28 contiguous=TRUE;29 if (contiguous) {30 f->flags|=FF_CONTIGUOUS;31 if (f->dv->fs_type!=FSt_REDSEA &&32 !(FileAttr(filename) & RS_ATTR_CONTIGUOUS))33 throw('File');34 }35 f->clus_buf=CAlloc(f->dv->spc<<BLK_SIZE_BITS);36 if (StrOcc(flags,'w')) {37 f->flags=f->flags|FF_WRITE|FF_NEEDS_WRITE;38 if (StrOcc(flags,'+')) {39 if (FileFind(full_name,&f->de,FUF_JUST_FILES)) {40 Free(full_name);41 if (contiguous)42 f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;43 return f;44 }45 } else46 Del(full_name,,,FALSE);47 f->de.full_name=full_name;48 f->flags|=FF_NEW_FILE;49 if (dirc=DirContextNew(full_name)) {50 StrCpy(f->de.name,dirc->mask);51 if (cnt>0) {//We pre-alloc the whole thing.52 f->de.clus=ClusAlloc(f->dv,0,53 (cnt+f->dv->spc-1)/f->dv->spc,contiguous);54 f->de.size=cnt<<BLK_SIZE_BITS;55 DirNew(dirc->dv,Fs->cur_dir,&f->de,TRUE);56 f->flags&=~FF_NEW_FILE;57 }58 DirContextDel(dirc);59 return f;60 }61 } else {62 if (FileFind(full_name,&f->de,FUF_JUST_FILES)) {63 Free(full_name);64 f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;65 return f;66 }67 }68 Free(f->clus_buf);69 Free(full_name);70 Free(f);71 return NULL;72}73 74U0 FClose(CFile *f)75{//Close CFile, updating directory.76 CDirContext *dirc;77 if (f) {78 if (f->flags & FF_BUF_DIRTY) {79 ClusWrite(f->dv,f->clus_buf,f->clus,1);80 f->flags&=~FF_BUF_DIRTY;81 }82 if (f->flags & FF_NEEDS_WRITE) {83 if (dirc=DirContextNew(f->de.full_name)) {84 if (!(f->flags & FF_USE_OLD_DATETIME))85 f->de.datetime=Now;86 if (f->flags & FF_NEW_FILE)87 DirNew(dirc->dv,Fs->cur_dir,&f->de,TRUE);88 else89 DirNew(dirc->dv,Fs->cur_dir,&f->de,FALSE);90 DirContextDel(dirc);91 } else92 throw('File');93 }94 Free(f->clus_buf);95 Free(f->de.full_name);96 Free(f);97 }98}99 100I64 FSetClus(CFile *f,I64 c,I64 blk,Bool read)101{102 CDrv *dv=f->dv;103 I64 i;104 if (f->clus!=c) {105 if (f->flags & FF_BUF_DIRTY) {106 i=dv->spc;107 if (f->max_blk!=I64_MAX) {108 i=f->max_blk+1-f->file_clus_num*dv->spc;109 if (i>dv->spc)110 i=dv->spc;111 }112 ClusBlkWrite(dv,f->clus_buf,f->clus,i);113 f->flags=f->flags & ~FF_BUF_DIRTY;114 }115 f->clus=c;116 f->file_clus_num=blk/dv->spc;117 if (read) {118 i=dv->spc;119 if (f->max_blk!=I64_MAX) {120 i=f->max_blk+1-f->file_clus_num*dv->spc;121 if (i>dv->spc)122 i=dv->spc;123 }124 c=ClusBlkRead(dv,f->clus_buf,c,i);125 }126 }127 return c;128}129 130Bool FBlkRead(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)131{//Read [nth,n+cnt) blks of file.132 CDrv *dv=f->dv;133 I64 spc=dv->spc,i,j,c=f->de.clus;134 if (!f || !dv) return FALSE;135 if (blk==FFB_NEXT_BLK)136 blk=f->fblk_num;137 if (blk+cnt-1>f->max_blk)138 return FALSE;139 if (cnt<=0) return TRUE;140 141 if (f->flags & FF_CONTIGUOUS) {142 BlkRead(dv,buf,Clus2Blk(dv,c)+blk,cnt);143 blk+=cnt;144 } else {145 i=blk/spc;146 if (0<=f->file_clus_num<=i) {147 c=f->clus;148 i-=f->file_clus_num;149 }150 if (i>0)151 c=ClusNumNext(dv,c,i);152 153 if (i=blk%spc) {154 c=FSetClus(f,c,blk,TRUE);155 if (cnt<spc-i)156 j=cnt;157 else158 j=spc-i;159 MemCpy(buf,f->clus_buf+i<<BLK_SIZE_BITS,j<<BLK_SIZE_BITS);160 buf+=j<<BLK_SIZE_BITS;161 cnt-=j;162 blk+=j;163 }164 while (cnt>=spc) {165 c=FSetClus(f,c,blk,TRUE);166 MemCpy(buf,f->clus_buf,spc<<BLK_SIZE_BITS);167 buf+=spc<<BLK_SIZE_BITS;168 cnt-=spc;169 blk+=spc;170 }171 if (cnt>0) {172 c=FSetClus(f,c,blk,TRUE);173 MemCpy(buf,f->clus_buf,cnt<<BLK_SIZE_BITS);174 buf+=cnt<<BLK_SIZE_BITS;175 blk+=cnt;176 }177 }178 f->fblk_num=blk;179 return TRUE;180}181 182Bool FBlkWrite(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)183{//Write [nth,n+cnt) blks of file.184 CDrv *dv=f->dv;185 I64 spc=dv->spc,i,j,c=f->de.clus,c1;186 if (!f || !dv) return FALSE;187 if (blk==FFB_NEXT_BLK)188 blk=f->fblk_num;189 if (blk+cnt-1>f->max_blk)190 return FALSE;191 if (!(f->flags & FF_WRITE))192 return FALSE;193 if (cnt<=0) return TRUE;194 if (f->flags & FF_CONTIGUOUS) {195 BlkWrite(dv,buf,Clus2Blk(dv,c)+blk,cnt);196 blk+=cnt;197 } else {198 if (!c) {199 c=ClusAlloc(dv,0,1,FALSE);200 f->file_clus_num=0;201 f->clus=c;202 f->de.clus=c;203 f->flags|=FF_NEEDS_WRITE|FF_NEW_FILE;204 }205 i=blk/spc;206 if (0<=f->file_clus_num<=i) {207 c=f->clus;208 i-=f->file_clus_num;209 }210 while (i>0) {211 c1=c;212 c=ClusNumNext(dv,c1,1);213 if (c==INVALID_CLUS) {214 c=ClusAlloc(dv,c1,i,FALSE);215 if (i>1)216 c=ClusNumNext(dv,c,i-1);217 break;218 } else219 i--;220 }221 222 if (i=blk%spc) {223 FSetClus(f,c,blk,TRUE);224 if (cnt<spc-i)225 j=cnt;226 else227 j=spc-i;228 MemCpy(f->clus_buf+BLK_SIZE*i,buf,j<<BLK_SIZE_BITS);229 f->flags|=FF_BUF_DIRTY;230 buf+=j<<BLK_SIZE_BITS;231 cnt-=j;232 blk+=j;233 if (cnt>0) {234 c1=c;235 c=ClusNumNext(dv,c1,1);236 if (c==INVALID_CLUS)237 c=ClusAlloc(dv,c1,1,FALSE);238 }239 }240 while (cnt>=spc) {241 FSetClus(f,c,blk,FALSE);242 MemCpy(f->clus_buf,buf,spc<<BLK_SIZE_BITS);243 f->flags|=FF_BUF_DIRTY;244 buf+=spc<<BLK_SIZE_BITS;245 cnt-=spc;246 blk+=spc;247 if (cnt>0) {248 c1=c;249 c=ClusNumNext(dv,c1,1);250 if (c==INVALID_CLUS)251 c=ClusAlloc(dv,c1,1,FALSE);252 }253 }254 if (cnt>0) {255 FSetClus(f,c,blk,TRUE);256 MemCpy(f->clus_buf,buf,cnt<<BLK_SIZE_BITS);257 f->flags|=FF_BUF_DIRTY;258 buf+=cnt<<BLK_SIZE_BITS;259 blk+=cnt;260 }261 if (f->de.size<blk<<BLK_SIZE_BITS)262 f->de.size=blk<<BLK_SIZE_BITS;263 }264 f->fblk_num=blk;265 return TRUE;266}267 