00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00101 #include <fs/fs.h>
00102 #include <fs/phatfs.h>
00103 #include <fs/phatvol.h>
00104 #include <fs/phatio.h>
00105 #include <fs/phatutil.h>
00106 #include <fs/phatdir.h>
00107
00108 #include <stdlib.h>
00109 #include <string.h>
00110 #include <ctype.h>
00111 #include <fcntl.h>
00112 #include <errno.h>
00113 #include <time.h>
00114
00115 #if 0
00116
00117 #define NUTDEBUG
00118 #include <stdio.h>
00119 #include <fs/phatdbg.h>
00120 #endif
00121
00126
00128 #define PHAT_MAXDIRENT 65536
00129
00136 static INLINE uint8_t GenShortNameChecksum(char *sfn)
00137 {
00138 uint8_t rc = 0;
00139 int i;
00140
00141 for (i = 0; i < 11; i++) {
00142 rc = ((rc >> 1) | ((rc & 1) << 7)) + (uint8_t)(sfn[i]);
00143 }
00144 return rc;
00145 }
00146
00158 static int GenShortName(NUTFILE * ndp, CONST char *lfn, char *sfn)
00159 {
00160 int rc = -1;
00161 int i;
00162 int got;
00163 PHATDIRENT *entry;
00164 char *xp;
00165
00166
00167 memset(sfn, ' ', 11);
00168
00169
00170 xp = strrchr(lfn, '.');
00171
00172
00173
00174 for (i = 0; i < 11 && *lfn; lfn++) {
00175 if (*lfn == '.') {
00176
00177 if (lfn == xp) {
00178
00179 lfn++;
00180 if (*lfn) {
00181 sfn[8] = toupper(*lfn);
00182 }
00183 i = 9;
00184 }
00185 }
00186 else if (i == 8) {
00187
00188 if (xp == NULL) {
00189
00190 break;
00191 }
00192 lfn = xp + 1;
00193 if (*lfn) {
00194 sfn[i++] = toupper(*lfn);
00195 }
00196 }
00197 else if (*lfn != ' ') {
00198 if (strrchr("+,;=[]", *lfn)) {
00199 sfn[i++] = '_';
00200 }
00201 else {
00202 sfn[i++] = toupper(*lfn);
00203 }
00204 }
00205 }
00206
00207
00208
00209
00210
00211 if ((entry = malloc(sizeof(PHATDIRENT))) != NULL) {
00212 xp = sfn;
00213 for (i = 0; i < 6 && *xp != ' '; i++) {
00214 xp++;
00215 }
00216
00217
00218
00219
00220 for (i = 1; i <= 99 && rc; i++) {
00221 if (i == 10) {
00222 xp--;
00223 }
00224 *xp = '~';
00225 if (i > 9) {
00226 *(xp + 1) = '0' + i / 10;
00227 *(xp + 2) = '0' + i % 10;
00228 }
00229 else {
00230 *(xp + 1) = '0' + i;
00231 }
00232 PhatFilePosRewind((PHATFILE *)ndp->nf_fcb);
00233 for (;;) {
00234
00235 if ((got = PhatFileRead(ndp, entry, sizeof(PHATDIRENT))) != sizeof(PHATDIRENT)) {
00236 if (got) {
00237
00238 i = 9;
00239 }
00240 else {
00241
00242 rc = 0;
00243 }
00244 break;
00245 }
00246 if ((entry->dent_attr & PHAT_FATTR_VOLID) == 0) {
00247 if (entry->dent_name[0] == 0) {
00248
00249 rc = 0;
00250 break;
00251 }
00252 if (memcmp(sfn, (char *)entry->dent_name, 11) == 0) {
00253
00254 break;
00255 }
00256 }
00257 }
00258 }
00259 free(entry);
00260 }
00261 return rc;
00262 }
00263
00273 static int PhatDirEntryAlloc(NUTFILE * ndp, CONST char *fname, PHATDIRENT * entry)
00274 {
00275 int rc;
00276 int pos = 0;
00277 int got;
00278 uint8_t sect;
00279 uint8_t *temp;
00280 NUTDEVICE *dev = ndp->nf_dev;
00281 PHATFILE *dfcb = ndp->nf_fcb;
00282 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00283 PHATDIRENT *dent;
00284 PHATXDIRENT *xdent;
00285 int nwant = 1;
00286 int ngot = 0;
00287 int npos = 0;
00288 int i;
00289 int ci;
00290 uint8_t cks = 0;
00291
00292
00293 if ((rc = MakePhatName(fname, entry->dent_name)) == 1) {
00294
00295 errno = EINVAL;
00296 return -1;
00297 }
00298 if (rc == 0) {
00299 char vname[16];
00300
00301 MakeVisibleName(entry->dent_name, vname);
00302 if (strcmp(fname, vname)) {
00303 rc = 1;
00304 }
00305 }
00306 if (rc) {
00307 if (GenShortName(ndp, fname, (char *)entry->dent_name)) {
00308 errno = EINVAL;
00309 return -1;
00310 }
00311 nwant = (strlen(fname) + 12) / 13 + 1;
00312 cks = GenShortNameChecksum((char *)entry->dent_name);
00313 }
00314
00315
00316 if ((dent = malloc(sizeof(PHATDIRENT))) == NULL) {
00317 return -1;
00318 }
00319
00320
00321
00322
00323 PhatFilePosRewind(dfcb);
00324 rc = -1;
00325 for (;;) {
00326
00327 npos = dfcb->f_pos;
00328 if ((got = PhatFileRead(ndp, dent, sizeof(PHATDIRENT))) < 0) {
00329
00330 break;
00331 }
00332 if (got != sizeof(PHATDIRENT)) {
00333
00334
00335
00336 if (IsFixedRootDir(ndp) ||
00337 dfcb->f_pos >= PHAT_MAXDIRENT * sizeof(PHATDIRENT)) {
00338
00339 errno = EFBIG;
00340 break;
00341 }
00342
00343
00344 if ((temp = malloc(vol->vol_sectsz)) == NULL) {
00345 break;
00346 }
00347 memset(temp, 0, vol->vol_sectsz);
00348 for (sect = vol->vol_clustsz; sect; sect--) {
00349 if (PhatFileWrite(ndp, temp, vol->vol_sectsz) < 0) {
00350
00351 break;
00352 }
00353 }
00354 free(temp);
00355
00356 if (sect == 0) {
00357 if (ngot == 0) {
00358 pos = npos;
00359 }
00360 rc = 0;
00361 }
00362 break;
00363 }
00364 if (dent->dent_name[0] == PHAT_REM_DIRENT || dent->dent_name[0] == 0) {
00365
00366 if (ngot == 0) {
00367 pos = npos;
00368 }
00369 ngot++;
00370 if (ngot >= nwant) {
00371 rc = 0;
00372 break;
00373 }
00374 }
00375 else {
00376 ngot = 0;
00377 }
00378 }
00379 free(dent);
00380
00381 if (rc == 0) {
00382
00383 PhatFilePosSet(ndp, pos);
00384 if ((xdent = malloc(sizeof(PHATXDIRENT))) == NULL) {
00385 return -1;
00386 }
00387 for (ngot = nwant - 1; ngot; ngot--) {
00388 memset(xdent, 0xFF, sizeof(PHATXDIRENT));
00389 xdent->xdent_seq = ngot;
00390 if (ngot == nwant - 1) {
00391 xdent->xdent_seq |= 0x40;
00392 }
00393 xdent->xdent_attr = PHAT_FATTR_LFN;
00394 xdent->xdent_cks = cks;
00395 xdent->xdent_clust = 0;
00396 xdent->xdent_rsvd = 0;
00397
00398 ci = (ngot - 1) * 13;
00399 for (i = 0; i < 13; i++) {
00400 if (ci + i <= strlen(fname)) {
00401 if (i < 5) {
00402 xdent->xdent_uname_1_5[i] = fname[ci + i];
00403 }
00404 else if (i < 11) {
00405 xdent->xdent_uname_6_11[i - 5] = fname[ci + i];
00406 }
00407 else {
00408 xdent->xdent_uname_12_13[i - 11] = fname[ci + i];
00409 }
00410 }
00411 }
00412 if (PhatFileWrite(ndp, xdent, sizeof(PHATXDIRENT)) < 0) {
00413
00414 rc = -1;
00415 break;
00416 }
00417 }
00418 if (PhatFileWrite(ndp, entry, sizeof(PHATDIRENT)) < 0) {
00419
00420 rc = -1;
00421 }
00422 free(xdent);
00423 }
00424 return rc;
00425 }
00426
00439 static int PhatDirEntryRelease(NUTFILE * ndp, uint32_t pos, int lfncnt)
00440 {
00441 uint8_t ch = PHAT_REM_DIRENT;
00442 int i;
00443
00444 for (i = lfncnt; i; i--) {
00445 PhatFilePosSet(ndp, pos - i * sizeof(PHATXDIRENT));
00446 if (PhatFileWrite(ndp, &ch, 1) < 0) {
00447 return -1;
00448 }
00449 }
00450 PhatFilePosSet(ndp, pos);
00451 if (PhatFileWrite(ndp, &ch, 1) < 0) {
00452 return -1;
00453 }
00454 return 0;
00455 }
00456
00467 int PhatDirEntryCreate(NUTFILE * ndp, CONST char *name, int acc, PHATDIRENT * dirent)
00468 {
00469 dirent->dent_attr = (uint8_t) acc;
00470 GetDosTimeStamp(&dirent->dent_ctime, &dirent->dent_cdate);
00471 dirent->dent_adate = dirent->dent_cdate;
00472 dirent->dent_mtime = dirent->dent_ctime;
00473 dirent->dent_mdate = dirent->dent_cdate;
00474
00475 if (PhatDirEntryAlloc(ndp, name, dirent)) {
00476 return -1;
00477 }
00478 #ifdef NUTDEBUG
00479 PhatDbgFileInfo(stdout, "New Dir Entry", ndp->nf_fcb);
00480 #endif
00481 return 0;
00482 }
00483
00491 int PhatDirEntryUpdate(NUTFILE * nfp)
00492 {
00493 int sbn;
00494 NUTDEVICE *dev = nfp->nf_dev;
00495 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00496 PHATFILE *fcb = nfp->nf_fcb;
00497
00498 if (fcb->f_de_dirty) {
00499
00500
00501
00502
00503 if (fcb->f_de_sect) {
00504 #ifdef NUTDEBUG
00505 PhatDbgDirEntry(stdout, "PhatDirEntryUpdate", &fcb->f_dirent);
00506 #endif
00507 if ((sbn = PhatSectorLoad(dev, fcb->f_de_sect)) < 0) {
00508 return -1;
00509 }
00510 memcpy(vol->vol_buf[sbn].sect_data + fcb->f_de_offs, &fcb->f_dirent, sizeof(PHATDIRENT));
00511 vol->vol_buf[sbn].sect_dirty = 1;
00512 }
00513 fcb->f_de_dirty = 0;
00514 }
00515 return 0;
00516 }
00517
00526 static int PhatDirEntryRead(NUTFILE * ndp, PHATFIND * srch)
00527 {
00528 PHATDIRENT *entry = &srch->phfind_ent;
00529 PHATFILE *fcb = ndp->nf_fcb;
00530 PHATXDIRENT *xentry;
00531 char *lfn = NULL;
00532 int lfnpos = 0;
00533 int nxtseq = 0;
00534 int lfncnt = 0;
00535 int i;
00536
00537 for (;;) {
00538
00539 if (PhatFileRead(ndp, entry, sizeof(PHATDIRENT)) != sizeof(PHATDIRENT)) {
00540 break;
00541 }
00542
00543 if (entry->dent_name[0] == PHAT_REM_DIRENT) {
00544 if (lfn) {
00545 free(lfn);
00546 lfn = NULL;
00547 }
00548 }
00549
00550 else if (entry->dent_attr == PHAT_FATTR_LFN) {
00551 xentry = (PHATXDIRENT *)entry;
00552 lfnpos = (xentry->xdent_seq & 0x3F);
00553
00554 if ((nxtseq == 0 && (xentry->xdent_seq & 0x40) != 0) || nxtseq == lfnpos) {
00555 nxtseq = --lfnpos;
00556 lfnpos *= 13;
00557 if (lfnpos + 13 > PHAT_MAX_NAMELEN) {
00558 errno = EINVAL;
00559 break;
00560 }
00561 if (xentry->xdent_seq & 0x40) {
00562 if (lfn == NULL) {
00563 lfn = malloc(PHAT_MAX_NAMELEN + 1);
00564 }
00565 lfn[lfnpos + 13] = 0;
00566 lfncnt = 0;
00567 }
00568 lfncnt++;
00569
00570 for (i = 0; i < 5; i++) {
00571 lfn[lfnpos + i] = (char)xentry->xdent_uname_1_5[i];
00572 }
00573 for (i = 0; i < 6; i++) {
00574 lfn[lfnpos + 5 + i] = (char)xentry->xdent_uname_6_11[i];
00575 }
00576 for (i = 0; i < 2; i++) {
00577 lfn[lfnpos + 11 + i] = (char)xentry->xdent_uname_12_13[i];
00578 }
00579 }
00580 }
00581
00582
00583 else if ((entry->dent_attr & PHAT_FATTR_VOLID) == 0) {
00584
00585 if (entry->dent_name[0] == 0) {
00586 break;
00587 }
00588
00589 srch->phfind_pos = fcb->f_pos - sizeof(PHATDIRENT);
00590 if (lfn && lfnpos == 0) {
00591 strcpy(srch->phfind_name, lfn);
00592 srch->phfind_xcnt = lfncnt;
00593 }
00594 else {
00595 MakeVisibleName(entry->dent_name, srch->phfind_name);
00596 srch->phfind_xcnt = 0;
00597 }
00598 if (lfn) {
00599 free(lfn);
00600 }
00601 nxtseq = 0;
00602 lfncnt = 0;
00603 return 0;
00604 }
00605 else if (lfn) {
00606 free(lfn);
00607 lfn = NULL;
00608 nxtseq = 0;
00609 lfncnt = 0;
00610 }
00611 }
00612 if (lfn) {
00613 free(lfn);
00614 }
00615 return -1;
00616 }
00617
00630 int PhatDirEntryFind(NUTFILE * ndp, CONST char *spec, uint32_t attmsk, PHATFIND * srch)
00631 {
00632 int rc;
00633 PHATFIND *temps;
00634
00635
00636 if ((temps = malloc(sizeof(PHATFIND))) == NULL) {
00637 return -1;
00638 }
00639
00640
00641
00642
00643
00644 PhatFilePosRewind((PHATFILE *)ndp->nf_fcb);
00645 while ((rc = PhatDirEntryRead(ndp, temps)) == 0) {
00646 if ((temps->phfind_ent.dent_attr | attmsk) == attmsk) {
00647 if (strcasecmp(temps->phfind_name, spec) == 0) {
00648
00649 if (srch) {
00650 *srch = *temps;
00651 }
00652 break;
00653 }
00654 }
00655 }
00656 free(temps);
00657
00658 return rc;
00659 }
00660
00671 NUTFILE *PhatDirOpenParent(NUTDEVICE * dev, CONST char *path, CONST char **basename)
00672 {
00673 NUTFILE *rc = NUTFILE_EOF;
00674 char *parent;
00675
00676 if ((parent = GetParentPath(path, basename)) != NULL) {
00677 rc = PhatDirOpen(dev, parent);
00678 free(parent);
00679 }
00680 return rc;
00681 }
00682
00692 int PhatDirRenameEntry(NUTDEVICE * dev, CONST char *old_path, CONST char *new_path)
00693 {
00694 int rc = -1;
00695 CONST char *fname;
00696 NUTFILE *old_ndp;
00697 NUTFILE *new_ndp;
00698 PHATFIND *srch;
00699
00700
00701
00702
00703 if ((old_ndp = PhatDirOpenParent(dev, old_path, &fname)) == NUTFILE_EOF) {
00704 return -1;
00705 }
00706
00707 if ((srch = malloc(sizeof(PHATFIND))) != NULL) {
00708 if ((rc = PhatDirEntryFind(old_ndp, fname, PHAT_FATTR_FILEMASK, srch)) == 0) {
00709 rc = -1;
00710 if ((new_ndp = PhatDirOpenParent(dev, new_path, &fname)) != NUTFILE_EOF) {
00711 if (PhatDirEntryFind(new_ndp, fname, PHAT_FATTR_FILEMASK, NULL) == 0) {
00712 errno = EEXIST;
00713 } else {
00714 if ((rc = PhatDirEntryAlloc(new_ndp, fname, &srch->phfind_ent)) == 0) {
00715 rc = PhatDirEntryRelease(old_ndp, srch->phfind_pos, srch->phfind_xcnt);
00716 }
00717 }
00718 PhatFileClose(new_ndp);
00719 }
00720 }
00721 else {
00722 errno = ENOENT;
00723 }
00724 free(srch);
00725 }
00726 PhatFileClose(old_ndp);
00727
00728 return rc;
00729 }
00730
00739 int PhatDirReleaseChain(NUTDEVICE * dev, PHATDIRENT *dent)
00740 {
00741 int rc = 0;
00742 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00743 uint32_t clust;
00744
00745
00746 if (dent->dent_attr & PHAT_FATTR_RDONLY) {
00747 errno = EACCES;
00748 return -1;
00749 }
00750
00751
00752
00753 clust = dent->dent_clusthi;
00754 clust <<= 16;
00755 clust |= dent->dent_clust;
00756
00757
00758
00759 if (clust >= 2) {
00760
00761 if (vol->vol_type == 32) {
00762 rc = Phat32ReleaseChain(dev, clust);
00763 } else if (vol->vol_type == 16) {
00764 rc = Phat16ReleaseChain(dev, clust);
00765 } else {
00766 rc = Phat12ReleaseChain(dev, clust);
00767 }
00768 }
00769 return rc;
00770 }
00771
00783 int PhatDirDelEntry(NUTDEVICE * dev, CONST char *path, uint32_t flags)
00784 {
00785 int rc = -1;
00786 PHATFIND *srch;
00787 NUTFILE *ndp;
00788 CONST char *fname;
00789
00790
00791 if ((ndp = PhatDirOpenParent(dev, path, &fname)) != NUTFILE_EOF) {
00792 if ((srch = malloc(sizeof(PHATFIND))) != NULL) {
00793
00794 if (PhatDirEntryFind(ndp, fname, flags, srch) == 0) {
00795 if (PhatDirReleaseChain(dev, &srch->phfind_ent) == 0) {
00796 rc = PhatDirEntryRelease(ndp, srch->phfind_pos, srch->phfind_xcnt);
00797 }
00798 }
00799 else {
00800 errno = ENOENT;
00801 }
00802 free(srch);
00803 }
00804 PhatFileClose(ndp);
00805 }
00806 return rc;
00807 }
00808
00817 NUTFILE *PhatDirOpen(NUTDEVICE * dev, CONST char *dpath)
00818 {
00819 NUTFILE *ndp;
00820 PHATFILE *dfcb;
00821 PHATFIND *srch;
00822 char *comp;
00823 char *cp;
00824 int sz;
00825 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00826
00827
00828 if (vol == NULL) {
00829 errno = ENODEV;
00830 return NUTFILE_EOF;
00831 }
00832
00833
00834 if ((ndp = malloc(sizeof(NUTFILE))) == NULL) {
00835 return NUTFILE_EOF;
00836 }
00837 if ((ndp->nf_fcb = malloc(sizeof(PHATFILE))) == NULL) {
00838 free(ndp);
00839 return NUTFILE_EOF;
00840 }
00841 memset(ndp->nf_fcb, 0, sizeof(PHATFILE));
00842 ndp->nf_next = NULL;
00843 ndp->nf_dev = dev;
00844
00845 dfcb = ndp->nf_fcb;
00846 dfcb->f_dirent.dent_attr = PHAT_FATTR_DIR;
00847 dfcb->f_mode = _O_RDONLY;
00848
00849
00850 dfcb->f_clust = vol->vol_root_clust;
00851 dfcb->f_dirent.dent_clusthi = (uint16_t) (vol->vol_root_clust >> 16);
00852 dfcb->f_dirent.dent_clust = (uint16_t) vol->vol_root_clust;
00853
00854 if (*dpath == '/') {
00855 dpath++;
00856 }
00857 if (*dpath) {
00858
00859
00860
00861 if ((comp = malloc(PHAT_MAX_NAMELEN + 1)) == NULL) {
00862 free(dfcb);
00863 free(ndp);
00864 return NUTFILE_EOF;
00865 }
00866 if ((srch = malloc(sizeof(PHATFIND))) == NULL) {
00867 free(comp);
00868 free(dfcb);
00869 free(ndp);
00870 return NUTFILE_EOF;
00871 }
00872
00873
00874
00875
00876 while (*dpath) {
00877
00878 cp = comp;
00879 sz = 0;
00880 while (*dpath) {
00881 if (*dpath == '/') {
00882 dpath++;
00883 break;
00884 }
00885 if (++sz > PHAT_MAX_NAMELEN) {
00886 break;
00887 }
00888 *cp++ = *dpath++;
00889 }
00890 *cp = 0;
00891
00892
00893 if (sz > PHAT_MAX_NAMELEN || PhatDirEntryFind(ndp, comp, PHAT_FATTR_FILEMASK, srch)) {
00894 errno = ENOENT;
00895 free(dfcb);
00896 free(ndp);
00897 ndp = NUTFILE_EOF;
00898 break;
00899 }
00900
00901
00902
00903
00904
00905 dfcb->f_de_sect = PhatClusterSector(ndp, dfcb->f_clust) + dfcb->f_clust_pos;
00906 dfcb->f_de_offs = dfcb->f_sect_pos - 32;
00907
00908
00909 dfcb->f_pde_clusthi = dfcb->f_dirent.dent_clusthi;
00910 dfcb->f_pde_clust = dfcb->f_dirent.dent_clust;
00911
00912 dfcb->f_dirent = srch->phfind_ent;
00913 #ifdef NUTDEBUG
00914 PhatDbgFileInfo(stdout, "Component", dfcb);
00915 #endif
00916
00917
00918
00919
00920 if (dfcb->f_dirent.dent_attr & PHAT_FATTR_DIR) {
00921 if (dfcb->f_dirent.dent_clust == 0 && dfcb->f_dirent.dent_clusthi == 0) {
00922 if (vol->vol_type != 32) {
00923 dfcb->f_de_sect = 0;
00924 }
00925 dfcb->f_dirent.dent_clusthi = (uint16_t) (vol->vol_root_clust >> 16);
00926 dfcb->f_dirent.dent_clust = (uint16_t) vol->vol_root_clust;
00927 }
00928 }
00929
00930
00931
00932
00933 PhatFilePosRewind(dfcb);
00934 dfcb->f_clust_prv = 0;
00935 dfcb->f_mode = _O_RDONLY;
00936 }
00937 free(srch);
00938 free(comp);
00939 }
00940 return ndp;
00941 }
00942
00950 int PhatDirRead(DIR * dir)
00951 {
00952 PHATFIND *srch;
00953 struct dirent *ent;
00954
00955 if ((srch = malloc(sizeof(PHATFIND))) == NULL) {
00956 return -1;
00957 }
00958 if (PhatDirEntryRead(dir->dd_fd, srch)) {
00959 free(srch);
00960 return -1;
00961 }
00962 #ifdef NUTDEBUG
00963 PhatDbgDirEntry(stdout, "Read entry", &srch->phfind_ent);
00964 #endif
00965
00966 ent = (struct dirent *) dir->dd_buf;
00967 memset(dir->dd_buf, 0, sizeof(struct dirent));
00968 ent->d_namlen = (uint8_t) strlen(srch->phfind_name);
00969 strcpy(ent->d_name, srch->phfind_name);
00970 if (srch->phfind_ent.dent_attr & PHAT_FATTR_DIR) {
00971 ent->d_type = 1;
00972 }
00973 free(srch);
00974
00975 return 0;
00976 }
00977
00989 int PhatDirCreate(NUTDEVICE * dev, char *path)
00990 {
00991 NUTFILE *ndp;
00992 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00993 PHATFILE *dfcb;
00994 PHATDIRENT *entry;
00995 uint8_t *buf;
00996 uint32_t sect;
00997 uint32_t clust;
00998
00999
01000
01001
01002 if ((ndp = PhatFileOpen(dev, path, _O_CREAT | _O_RDWR | _O_EXCL, PHAT_FATTR_DIR)) == NUTFILE_EOF) {
01003 return -1;
01004 }
01005 dfcb = ndp->nf_fcb;
01006
01007
01008
01009
01010 if ((clust = AllocFirstCluster(ndp)) < 2) {
01011 PhatFileClose(ndp);
01012 return -1;
01013 }
01014 dfcb->f_clust_prv = clust;
01015 dfcb->f_clust = clust;
01016 if ((buf = malloc(vol->vol_sectsz)) == NULL) {
01017 PhatFileClose(ndp);
01018 return -1;
01019 }
01020 memset(buf, 0, vol->vol_sectsz);
01021 for (sect = vol->vol_clustsz; sect; sect--) {
01022 if (PhatFileWrite(ndp, buf, vol->vol_sectsz) < 0) {
01023
01024 free(buf);
01025 PhatFileClose(ndp);
01026 return -1;
01027 }
01028 }
01029 free(buf);
01030
01031
01032
01033
01034 entry = malloc(sizeof(PHATDIRENT));
01035 *entry = dfcb->f_dirent;
01036 memset(entry->dent_name, ' ', sizeof(entry->dent_name));
01037 entry->dent_name[0] = '.';
01038 PhatFilePosRewind(dfcb);
01039 if (PhatFileWrite(ndp, entry, sizeof(PHATDIRENT)) != sizeof(PHATDIRENT)) {
01040 PhatFileClose(ndp);
01041 free(entry);
01042 return -1;
01043 }
01044
01045
01046
01047
01048
01049 if ((uint16_t) vol->vol_root_clust == dfcb->f_pde_clust &&
01050 vol->vol_root_clust >> 16 == dfcb->f_pde_clusthi) {
01051 entry->dent_clust = 0;
01052 entry->dent_clusthi = 0;
01053 } else {
01054 entry->dent_clust = dfcb->f_pde_clust;
01055 entry->dent_clusthi = dfcb->f_pde_clusthi;
01056 }
01057 entry->dent_name[1] = '.';
01058 if (PhatFileWrite(ndp, entry, sizeof(PHATDIRENT)) != sizeof(PHATDIRENT)) {
01059 PhatFileClose(ndp);
01060 free(entry);
01061 return -1;
01062 }
01063 free(entry);
01064
01065 return PhatFileClose(ndp);
01066 }
01067
01076 int PhatDirRemove(NUTDEVICE * dev, char *path)
01077 {
01078 int rc = -1;
01079 PHATDIRENT *entry;
01080 NUTFILE *ndp;
01081
01082
01083 if (path[0] == '/' && path[1] == 0) {
01084 errno = EBUSY;
01085 return -1;
01086 }
01087
01088 if ((entry = malloc(sizeof(PHATDIRENT))) == NULL) {
01089 return -1;
01090 }
01091
01092
01093
01094
01095
01096 if ((ndp = PhatFileOpen(dev, path, _O_RDONLY, 0)) != NUTFILE_EOF) {
01097 rc = 0;
01098 for (;;) {
01099 rc = PhatFileRead(ndp, entry, sizeof(PHATDIRENT));
01100 if (rc < 0) {
01101 break;
01102 }
01103
01104 if (rc < sizeof(PHATDIRENT) || entry->dent_name[0] == 0) {
01105 rc = 0;
01106 break;
01107 }
01108
01109 if (entry->dent_name[0] == PHAT_REM_DIRENT) {
01110 continue;
01111 }
01112
01113 if ((entry->dent_attr | PHAT_FATTR_FILEMASK) != PHAT_FATTR_FILEMASK) {
01114 continue;
01115 }
01116
01117 if (entry->dent_name[0] == '.' &&
01118 (entry->dent_name[1] == '.' || entry->dent_name[1] == ' ')) {
01119 if (memcmp(" ", &entry->dent_name[2], 9) == 0) {
01120 continue;
01121 }
01122 }
01123 errno = ENOTEMPTY;
01124 rc = -1;
01125 break;
01126 }
01127 PhatFileClose(ndp);
01128 }
01129 free(entry);
01130
01131
01132 if (rc == 0) {
01133 rc = PhatDirDelEntry(dev, path, PHAT_FATTR_DIR);
01134 }
01135 return rc;
01136 }
01137
01147 int PhatDirEntryStatus(NUTDEVICE * dev, CONST char *path, struct stat *stp)
01148 {
01149 int rc;
01150 CONST char *fname;
01151 NUTFILE *ndp;
01152 PHATFIND *srch;
01153 u_int val;
01154
01155
01156 if ((ndp = PhatDirOpenParent(dev, path, &fname)) == NUTFILE_EOF) {
01157 return -1;
01158 }
01159
01160 if ((srch = malloc(sizeof(PHATFIND))) == NULL) {
01161 PhatFileClose(ndp);
01162 return -1;
01163 }
01164 if ((rc = PhatDirEntryFind(ndp, fname, PHAT_FATTR_FILEMASK, srch)) == 0) {
01165 struct _tm t;
01166
01167 memset(&t, 0, sizeof(struct _tm));
01168 val = srch->phfind_ent.dent_mtime;
01169 t.tm_sec = (val & 0x1F) << 1;
01170 t.tm_min = (val >> 5) & 0x3F;
01171 t.tm_hour = (val >> 11) & 0x1F;
01172 val = srch->phfind_ent.dent_mdate;
01173 t.tm_mday = val & 0x1F;
01174 t.tm_mon = ((val >> 5) & 0x0F);
01175 if (t.tm_mon) {
01176 t.tm_mon--;
01177 }
01178 t.tm_year = ((val >> 9) & 0x7F) + 80;
01179 t.tm_isdst = _daylight;
01180 stp->st_mtime = mktime(&t);
01181
01182 stp->st_ino = 0;
01183 stp->st_mode = (srch->phfind_ent.dent_attr & PHAT_FATTR_DIR) != 0;
01184 stp->st_nlink = 0;
01185 stp->st_size = srch->phfind_ent.dent_fsize;
01186 }
01187 free(srch);
01188 PhatFileClose(ndp);
01189
01190 return rc;
01191 }
01192