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
00108 #include <fs/fs.h>
00109 #include <fs/phatfs.h>
00110 #include <fs/phatvol.h>
00111 #include <fs/phatio.h>
00112 #include <fs/phatutil.h>
00113 #include <fs/phatdir.h>
00114
00115 #include <stdlib.h>
00116 #include <string.h>
00117 #include <ctype.h>
00118 #include <fcntl.h>
00119 #include <errno.h>
00120 #include <time.h>
00121 #include <memdebug.h>
00122
00123 #if 0
00124
00125 #define NUTDEBUG
00126 #include <stdio.h>
00127 #include <fs/phatdbg.h>
00128 #endif
00129
00134
00136 #define PHAT_MAXDIRENT 65536
00137
00144 static INLINE uint8_t GenShortNameChecksum(char *sfn)
00145 {
00146 uint8_t rc = 0;
00147 int i;
00148
00149 for (i = 0; i < 11; i++) {
00150 rc = ((rc >> 1) | ((rc & 1) << 7)) + (uint8_t)(sfn[i]);
00151 }
00152 return rc;
00153 }
00154
00166 static int GenShortName(NUTFILE * ndp, CONST char *lfn, char *sfn)
00167 {
00168 int rc = -1;
00169 int i;
00170 int got;
00171 PHATDIRENT *entry;
00172 char *xp;
00173
00174
00175 memset(sfn, ' ', 11);
00176
00177
00178 xp = strrchr(lfn, '.');
00179
00180
00181
00182 for (i = 0; i < 11 && *lfn; lfn++) {
00183 if (*lfn == '.') {
00184
00185 if (lfn == xp) {
00186
00187 lfn++;
00188 if (*lfn) {
00189 sfn[8] = toupper((unsigned char)*lfn);
00190 }
00191 i = 9;
00192 }
00193 }
00194 else if (i == 8) {
00195
00196 if (xp == NULL) {
00197
00198 break;
00199 }
00200 lfn = xp + 1;
00201 if (*lfn) {
00202 sfn[i++] = toupper((unsigned char)*lfn);
00203 }
00204 }
00205 else if (*lfn != ' ') {
00206 if (strrchr("+,;=[]", *lfn)) {
00207 sfn[i++] = '_';
00208 }
00209 else {
00210 sfn[i++] = toupper((unsigned char)*lfn);
00211 }
00212 }
00213 }
00214
00215
00216
00217
00218
00219 if ((entry = malloc(sizeof(PHATDIRENT))) != NULL) {
00220 xp = sfn;
00221 for (i = 0; i < 6 && *xp != ' '; i++) {
00222 xp++;
00223 }
00224
00225
00226
00227
00228 for (i = 1; i <= 99 && rc; i++) {
00229 if (i == 10) {
00230 xp--;
00231 }
00232 *xp = '~';
00233 if (i > 9) {
00234 *(xp + 1) = '0' + i / 10;
00235 *(xp + 2) = '0' + i % 10;
00236 }
00237 else {
00238 *(xp + 1) = '0' + i;
00239 }
00240 PhatFilePosRewind((PHATFILE *)ndp->nf_fcb);
00241 for (;;) {
00242
00243 if ((got = PhatFileRead(ndp, entry, sizeof(PHATDIRENT))) != sizeof(PHATDIRENT)) {
00244 if (got) {
00245
00246 i = 9;
00247 }
00248 else {
00249
00250 rc = 0;
00251 }
00252 break;
00253 }
00254 if ((entry->dent_attr & PHAT_FATTR_VOLID) == 0) {
00255 if (entry->dent_name[0] == 0) {
00256
00257 rc = 0;
00258 break;
00259 }
00260 if (memcmp(sfn, (char *)entry->dent_name, 11) == 0) {
00261
00262 break;
00263 }
00264 }
00265 }
00266 }
00267 free(entry);
00268 }
00269 return rc;
00270 }
00271
00281 static int PhatDirEntryAlloc(NUTFILE * ndp, CONST char *fname, PHATDIRENT * entry)
00282 {
00283 int rc;
00284 int pos = 0;
00285 int got;
00286 uint8_t sect;
00287 uint8_t *temp;
00288 NUTDEVICE *dev = ndp->nf_dev;
00289 PHATFILE *dfcb = ndp->nf_fcb;
00290 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00291 PHATDIRENT *dent;
00292 PHATXDIRENT *xdent;
00293 int nwant = 1;
00294 int ngot = 0;
00295 int npos = 0;
00296 int i;
00297 int ci;
00298 uint8_t cks = 0;
00299
00300
00301 if ((rc = MakePhatName(fname, entry->dent_name)) == 1) {
00302
00303 errno = EINVAL;
00304 return -1;
00305 }
00306 if (rc == 0) {
00307 char vname[16];
00308
00309 MakeVisibleName(entry->dent_name, vname);
00310 if (strcmp(fname, vname)) {
00311 rc = 1;
00312 }
00313 }
00314 if (rc) {
00315 if (GenShortName(ndp, fname, (char *)entry->dent_name)) {
00316 errno = EINVAL;
00317 return -1;
00318 }
00319 nwant = (strlen(fname) + 12) / 13 + 1;
00320 cks = GenShortNameChecksum((char *)entry->dent_name);
00321 }
00322
00323
00324 if ((dent = malloc(sizeof(PHATDIRENT))) == NULL) {
00325 return -1;
00326 }
00327
00328
00329
00330
00331 PhatFilePosRewind(dfcb);
00332 rc = -1;
00333 for (;;) {
00334
00335 npos = dfcb->f_pos;
00336 if ((got = PhatFileRead(ndp, dent, sizeof(PHATDIRENT))) < 0) {
00337
00338 break;
00339 }
00340 if (got != sizeof(PHATDIRENT)) {
00341
00342
00343
00344 if (IsFixedRootDir(ndp) ||
00345 dfcb->f_pos >= PHAT_MAXDIRENT * sizeof(PHATDIRENT)) {
00346
00347 errno = EFBIG;
00348 break;
00349 }
00350
00351
00352 if ((temp = malloc(vol->vol_sectsz)) == NULL) {
00353 break;
00354 }
00355 memset(temp, 0, vol->vol_sectsz);
00356 for (sect = vol->vol_clustsz; sect; sect--) {
00357 if (PhatFileWrite(ndp, temp, vol->vol_sectsz) < 0) {
00358
00359 break;
00360 }
00361 }
00362 free(temp);
00363
00364 if (sect == 0) {
00365 if (ngot == 0) {
00366 pos = npos;
00367 }
00368 rc = 0;
00369 }
00370 break;
00371 }
00372 if (dent->dent_name[0] == PHAT_REM_DIRENT || dent->dent_name[0] == 0) {
00373
00374 if (ngot == 0) {
00375 pos = npos;
00376 }
00377 ngot++;
00378 if (ngot >= nwant) {
00379 rc = 0;
00380 break;
00381 }
00382 }
00383 else {
00384 ngot = 0;
00385 }
00386 }
00387 free(dent);
00388
00389 if (rc == 0) {
00390
00391 PhatFilePosSet(ndp, pos);
00392 if ((xdent = malloc(sizeof(PHATXDIRENT))) == NULL) {
00393 return -1;
00394 }
00395 for (ngot = nwant - 1; ngot; ngot--) {
00396 memset(xdent, 0xFF, sizeof(PHATXDIRENT));
00397 xdent->xdent_seq = ngot;
00398 if (ngot == nwant - 1) {
00399 xdent->xdent_seq |= 0x40;
00400 }
00401 xdent->xdent_attr = PHAT_FATTR_LFN;
00402 xdent->xdent_cks = cks;
00403 xdent->xdent_clust = 0;
00404 xdent->xdent_rsvd = 0;
00405
00406 ci = (ngot - 1) * 13;
00407 for (i = 0; i < 13; i++) {
00408 if (ci + i <= strlen(fname)) {
00409 if (i < 5) {
00410 xdent->xdent_uname_1_5[i] = fname[ci + i];
00411 }
00412 else if (i < 11) {
00413 xdent->xdent_uname_6_11[i - 5] = fname[ci + i];
00414 }
00415 else {
00416 xdent->xdent_uname_12_13[i - 11] = fname[ci + i];
00417 }
00418 }
00419 }
00420 if (PhatFileWrite(ndp, xdent, sizeof(PHATXDIRENT)) < 0) {
00421
00422 rc = -1;
00423 break;
00424 }
00425 }
00426 if (PhatFileWrite(ndp, entry, sizeof(PHATDIRENT)) < 0) {
00427
00428 rc = -1;
00429 }
00430 free(xdent);
00431 }
00432 return rc;
00433 }
00434
00447 static int PhatDirEntryRelease(NUTFILE * ndp, uint32_t pos, int lfncnt)
00448 {
00449 uint8_t ch = PHAT_REM_DIRENT;
00450 int i;
00451
00452 for (i = lfncnt; i; i--) {
00453 PhatFilePosSet(ndp, pos - i * sizeof(PHATXDIRENT));
00454 if (PhatFileWrite(ndp, &ch, 1) < 0) {
00455 return -1;
00456 }
00457 }
00458 PhatFilePosSet(ndp, pos);
00459 if (PhatFileWrite(ndp, &ch, 1) < 0) {
00460 return -1;
00461 }
00462 return 0;
00463 }
00464
00475 int PhatDirEntryCreate(NUTFILE * ndp, CONST char *name, int acc, PHATDIRENT * dirent)
00476 {
00477 dirent->dent_attr = (uint8_t) acc;
00478 GetDosTimeStamp(&dirent->dent_ctime, &dirent->dent_cdate);
00479 dirent->dent_adate = dirent->dent_cdate;
00480 dirent->dent_mtime = dirent->dent_ctime;
00481 dirent->dent_mdate = dirent->dent_cdate;
00482
00483 if (PhatDirEntryAlloc(ndp, name, dirent)) {
00484 return -1;
00485 }
00486 #ifdef NUTDEBUG
00487 PhatDbgFileInfo(stdout, "New Dir Entry", ndp->nf_fcb);
00488 #endif
00489 return 0;
00490 }
00491
00499 int PhatDirEntryUpdate(NUTFILE * nfp)
00500 {
00501 int sbn;
00502 NUTDEVICE *dev = nfp->nf_dev;
00503 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00504 PHATFILE *fcb = nfp->nf_fcb;
00505
00506 if (fcb->f_de_dirty) {
00507
00508
00509
00510
00511 if (fcb->f_de_sect) {
00512 #ifdef NUTDEBUG
00513 PhatDbgDirEntry(stdout, "PhatDirEntryUpdate", &fcb->f_dirent);
00514 #endif
00515 if ((sbn = PhatSectorLoad(dev, fcb->f_de_sect)) < 0) {
00516 return -1;
00517 }
00518 memcpy(vol->vol_buf[sbn].sect_data + fcb->f_de_offs, &fcb->f_dirent, sizeof(PHATDIRENT));
00519 vol->vol_buf[sbn].sect_dirty = 1;
00520 }
00521 fcb->f_de_dirty = 0;
00522 }
00523 return 0;
00524 }
00525
00534 static int PhatDirEntryRead(NUTFILE * ndp, PHATFIND * srch)
00535 {
00536 PHATDIRENT *entry = &srch->phfind_ent;
00537 PHATFILE *fcb = ndp->nf_fcb;
00538 PHATXDIRENT *xentry;
00539 char *lfn = NULL;
00540 int lfnpos = 0;
00541 int nxtseq = 0;
00542 int lfncnt = 0;
00543 int i;
00544
00545 for (;;) {
00546
00547 if (PhatFileRead(ndp, entry, sizeof(PHATDIRENT)) != sizeof(PHATDIRENT)) {
00548 break;
00549 }
00550
00551 if (entry->dent_name[0] == PHAT_REM_DIRENT) {
00552 if (lfn) {
00553 free(lfn);
00554 lfn = NULL;
00555 }
00556 }
00557
00558 else if (entry->dent_attr == PHAT_FATTR_LFN) {
00559 xentry = (PHATXDIRENT *)entry;
00560 lfnpos = (xentry->xdent_seq & 0x3F);
00561
00562 if ((nxtseq == 0 && (xentry->xdent_seq & 0x40) != 0) || nxtseq == lfnpos) {
00563 nxtseq = --lfnpos;
00564 lfnpos *= 13;
00565 if (lfnpos + 13 > PHAT_MAX_NAMELEN) {
00566 errno = EINVAL;
00567 break;
00568 }
00569 if (xentry->xdent_seq & 0x40) {
00570 if (lfn == NULL) {
00571 lfn = malloc(PHAT_MAX_NAMELEN + 1);
00572 }
00573 lfn[lfnpos + 13] = 0;
00574 lfncnt = 0;
00575 }
00576 lfncnt++;
00577
00578 for (i = 0; i < 5; i++) {
00579 lfn[lfnpos + i] = (char)xentry->xdent_uname_1_5[i];
00580 }
00581 for (i = 0; i < 6; i++) {
00582 lfn[lfnpos + 5 + i] = (char)xentry->xdent_uname_6_11[i];
00583 }
00584 for (i = 0; i < 2; i++) {
00585 lfn[lfnpos + 11 + i] = (char)xentry->xdent_uname_12_13[i];
00586 }
00587 }
00588 }
00589
00590
00591 else if ((entry->dent_attr & PHAT_FATTR_VOLID) == 0) {
00592
00593 if (entry->dent_name[0] == 0) {
00594 break;
00595 }
00596
00597 srch->phfind_pos = fcb->f_pos - sizeof(PHATDIRENT);
00598 if (lfn && lfnpos == 0) {
00599 strcpy(srch->phfind_name, lfn);
00600 srch->phfind_xcnt = lfncnt;
00601 }
00602 else {
00603 MakeVisibleName(entry->dent_name, srch->phfind_name);
00604 srch->phfind_xcnt = 0;
00605 }
00606 if (lfn) {
00607 free(lfn);
00608 }
00609 nxtseq = 0;
00610 lfncnt = 0;
00611 return 0;
00612 }
00613 else if (lfn) {
00614 free(lfn);
00615 lfn = NULL;
00616 nxtseq = 0;
00617 lfncnt = 0;
00618 }
00619 }
00620 if (lfn) {
00621 free(lfn);
00622 }
00623 return -1;
00624 }
00625
00638 int PhatDirEntryFind(NUTFILE * ndp, CONST char *spec, uint32_t attmsk, PHATFIND * srch)
00639 {
00640 int rc;
00641 PHATFIND *temps;
00642
00643
00644 if ((temps = malloc(sizeof(PHATFIND))) == NULL) {
00645 return -1;
00646 }
00647
00648
00649
00650
00651
00652 PhatFilePosRewind((PHATFILE *)ndp->nf_fcb);
00653 while ((rc = PhatDirEntryRead(ndp, temps)) == 0) {
00654 if ((temps->phfind_ent.dent_attr | attmsk) == attmsk) {
00655 if (strcasecmp(temps->phfind_name, spec) == 0) {
00656
00657 if (srch) {
00658 *srch = *temps;
00659 }
00660 break;
00661 }
00662 }
00663 }
00664 free(temps);
00665
00666 return rc;
00667 }
00668
00679 NUTFILE *PhatDirOpenParent(NUTDEVICE * dev, CONST char *path, CONST char **basename)
00680 {
00681 NUTFILE *rc = NUTFILE_EOF;
00682 char *parent;
00683
00684 if ((parent = GetParentPath(path, basename)) != NULL) {
00685 rc = PhatDirOpen(dev, parent);
00686 free(parent);
00687 }
00688 return rc;
00689 }
00690
00700 int PhatDirRenameEntry(NUTDEVICE * dev, CONST char *old_path, CONST char *new_path)
00701 {
00702 int rc = -1;
00703 CONST char *fname;
00704 NUTFILE *old_ndp;
00705 NUTFILE *new_ndp;
00706 PHATFIND *srch;
00707
00708
00709
00710
00711 if ((old_ndp = PhatDirOpenParent(dev, old_path, &fname)) == NUTFILE_EOF) {
00712 return -1;
00713 }
00714
00715 if ((srch = malloc(sizeof(PHATFIND))) != NULL) {
00716 if ((rc = PhatDirEntryFind(old_ndp, fname, PHAT_FATTR_FILEMASK, srch)) == 0) {
00717 rc = -1;
00718 if ((new_ndp = PhatDirOpenParent(dev, new_path, &fname)) != NUTFILE_EOF) {
00719 if (PhatDirEntryFind(new_ndp, fname, PHAT_FATTR_FILEMASK, NULL) == 0) {
00720 errno = EEXIST;
00721 } else {
00722 if ((rc = PhatDirEntryAlloc(new_ndp, fname, &srch->phfind_ent)) == 0) {
00723 rc = PhatDirEntryRelease(old_ndp, srch->phfind_pos, srch->phfind_xcnt);
00724 }
00725 }
00726 PhatFileClose(new_ndp);
00727 }
00728 }
00729 else {
00730 errno = ENOENT;
00731 }
00732 free(srch);
00733 }
00734 PhatFileClose(old_ndp);
00735
00736 return rc;
00737 }
00738
00747 int PhatDirReleaseChain(NUTDEVICE * dev, PHATDIRENT *dent)
00748 {
00749 int rc = 0;
00750 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00751 uint32_t clust;
00752
00753
00754 if (dent->dent_attr & PHAT_FATTR_RDONLY) {
00755 errno = EACCES;
00756 return -1;
00757 }
00758
00759
00760
00761 clust = dent->dent_clusthi;
00762 clust <<= 16;
00763 clust |= dent->dent_clust;
00764
00765
00766
00767 if (clust >= 2) {
00768
00769 if (vol->vol_type == 32) {
00770 rc = Phat32ReleaseChain(dev, clust);
00771 } else if (vol->vol_type == 16) {
00772 rc = Phat16ReleaseChain(dev, clust);
00773 } else {
00774 rc = Phat12ReleaseChain(dev, clust);
00775 }
00776 }
00777 return rc;
00778 }
00779
00791 int PhatDirDelEntry(NUTDEVICE * dev, CONST char *path, uint32_t flags)
00792 {
00793 int rc = -1;
00794 PHATFIND *srch;
00795 NUTFILE *ndp;
00796 CONST char *fname;
00797
00798
00799 if ((ndp = PhatDirOpenParent(dev, path, &fname)) != NUTFILE_EOF) {
00800 if ((srch = malloc(sizeof(PHATFIND))) != NULL) {
00801
00802 if (PhatDirEntryFind(ndp, fname, flags, srch) == 0) {
00803 if (PhatDirReleaseChain(dev, &srch->phfind_ent) == 0) {
00804 rc = PhatDirEntryRelease(ndp, srch->phfind_pos, srch->phfind_xcnt);
00805 }
00806 }
00807 else {
00808 errno = ENOENT;
00809 }
00810 free(srch);
00811 }
00812 PhatFileClose(ndp);
00813 }
00814 return rc;
00815 }
00816
00825 NUTFILE *PhatDirOpen(NUTDEVICE * dev, CONST char *dpath)
00826 {
00827 NUTFILE *ndp;
00828 PHATFILE *dfcb;
00829 PHATFIND *srch;
00830 char *comp;
00831 char *cp;
00832 int sz;
00833 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00834
00835
00836 if (vol == NULL) {
00837 errno = ENODEV;
00838 return NUTFILE_EOF;
00839 }
00840
00841
00842 if ((ndp = malloc(sizeof(NUTFILE))) == NULL) {
00843 return NUTFILE_EOF;
00844 }
00845 if ((ndp->nf_fcb = malloc(sizeof(PHATFILE))) == NULL) {
00846 free(ndp);
00847 return NUTFILE_EOF;
00848 }
00849 memset(ndp->nf_fcb, 0, sizeof(PHATFILE));
00850 ndp->nf_next = NULL;
00851 ndp->nf_dev = dev;
00852
00853 dfcb = ndp->nf_fcb;
00854 dfcb->f_dirent.dent_attr = PHAT_FATTR_DIR;
00855 dfcb->f_mode = _O_RDONLY;
00856
00857
00858 dfcb->f_clust = vol->vol_root_clust;
00859 dfcb->f_dirent.dent_clusthi = (uint16_t) (vol->vol_root_clust >> 16);
00860 dfcb->f_dirent.dent_clust = (uint16_t) vol->vol_root_clust;
00861
00862 if (*dpath == '/') {
00863 dpath++;
00864 }
00865 if (*dpath) {
00866
00867
00868
00869 if ((comp = malloc(PHAT_MAX_NAMELEN + 1)) == NULL) {
00870 free(dfcb);
00871 free(ndp);
00872 return NUTFILE_EOF;
00873 }
00874 if ((srch = malloc(sizeof(PHATFIND))) == NULL) {
00875 free(comp);
00876 free(dfcb);
00877 free(ndp);
00878 return NUTFILE_EOF;
00879 }
00880
00881
00882
00883
00884 while (*dpath) {
00885
00886 cp = comp;
00887 sz = 0;
00888 while (*dpath) {
00889 if (*dpath == '/') {
00890 dpath++;
00891 break;
00892 }
00893 if (++sz > PHAT_MAX_NAMELEN) {
00894 break;
00895 }
00896 *cp++ = *dpath++;
00897 }
00898 *cp = 0;
00899
00900
00901 if (sz > PHAT_MAX_NAMELEN || PhatDirEntryFind(ndp, comp, PHAT_FATTR_FILEMASK, srch)) {
00902 errno = ENOENT;
00903 free(dfcb);
00904 free(ndp);
00905 ndp = NUTFILE_EOF;
00906 break;
00907 }
00908
00909
00910
00911
00912
00913 dfcb->f_de_sect = PhatClusterSector(ndp, dfcb->f_clust) + dfcb->f_clust_pos;
00914 dfcb->f_de_offs = dfcb->f_sect_pos - 32;
00915
00916
00917 dfcb->f_pde_clusthi = dfcb->f_dirent.dent_clusthi;
00918 dfcb->f_pde_clust = dfcb->f_dirent.dent_clust;
00919
00920 dfcb->f_dirent = srch->phfind_ent;
00921 #ifdef NUTDEBUG
00922 PhatDbgFileInfo(stdout, "Component", dfcb);
00923 #endif
00924
00925
00926
00927
00928 if (dfcb->f_dirent.dent_attr & PHAT_FATTR_DIR) {
00929 if (dfcb->f_dirent.dent_clust == 0 && dfcb->f_dirent.dent_clusthi == 0) {
00930 if (vol->vol_type != 32) {
00931 dfcb->f_de_sect = 0;
00932 }
00933 dfcb->f_dirent.dent_clusthi = (uint16_t) (vol->vol_root_clust >> 16);
00934 dfcb->f_dirent.dent_clust = (uint16_t) vol->vol_root_clust;
00935 }
00936 }
00937
00938
00939
00940
00941 PhatFilePosRewind(dfcb);
00942 dfcb->f_clust_prv = 0;
00943 dfcb->f_mode = _O_RDONLY;
00944 }
00945 free(srch);
00946 free(comp);
00947 }
00948 return ndp;
00949 }
00950
00958 int PhatDirRead(DIR * dir)
00959 {
00960 PHATFIND *srch;
00961 struct dirent *ent;
00962
00963 if ((srch = malloc(sizeof(PHATFIND))) == NULL) {
00964 return -1;
00965 }
00966 if (PhatDirEntryRead(dir->dd_fd, srch)) {
00967 free(srch);
00968 return -1;
00969 }
00970 #ifdef NUTDEBUG
00971 PhatDbgDirEntry(stdout, "Read entry", &srch->phfind_ent);
00972 #endif
00973
00974 ent = (struct dirent *) dir->dd_buf;
00975 memset(dir->dd_buf, 0, sizeof(struct dirent));
00976 ent->d_namlen = (uint8_t) strlen(srch->phfind_name);
00977 strcpy(ent->d_name, srch->phfind_name);
00978 if (srch->phfind_ent.dent_attr & PHAT_FATTR_DIR) {
00979 ent->d_type = 1;
00980 }
00981 free(srch);
00982
00983 return 0;
00984 }
00985
00997 int PhatDirCreate(NUTDEVICE * dev, char *path)
00998 {
00999 NUTFILE *ndp;
01000 PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
01001 PHATFILE *dfcb;
01002 PHATDIRENT *entry;
01003 uint8_t *buf;
01004 uint32_t sect;
01005 uint32_t clust;
01006
01007
01008
01009
01010 if ((ndp = PhatFileOpen(dev, path, _O_CREAT | _O_RDWR | _O_EXCL, PHAT_FATTR_DIR)) == NUTFILE_EOF) {
01011 return -1;
01012 }
01013 dfcb = ndp->nf_fcb;
01014
01015
01016
01017
01018 if ((clust = AllocFirstCluster(ndp)) < 2) {
01019 PhatFileClose(ndp);
01020 return -1;
01021 }
01022 dfcb->f_clust_prv = clust;
01023 dfcb->f_clust = clust;
01024 if ((buf = malloc(vol->vol_sectsz)) == NULL) {
01025 PhatFileClose(ndp);
01026 return -1;
01027 }
01028 memset(buf, 0, vol->vol_sectsz);
01029 for (sect = vol->vol_clustsz; sect; sect--) {
01030 if (PhatFileWrite(ndp, buf, vol->vol_sectsz) < 0) {
01031
01032 free(buf);
01033 PhatFileClose(ndp);
01034 return -1;
01035 }
01036 }
01037 free(buf);
01038
01039
01040
01041
01042 entry = malloc(sizeof(PHATDIRENT));
01043 *entry = dfcb->f_dirent;
01044 memset(entry->dent_name, ' ', sizeof(entry->dent_name));
01045 entry->dent_name[0] = '.';
01046 PhatFilePosRewind(dfcb);
01047 if (PhatFileWrite(ndp, entry, sizeof(PHATDIRENT)) != sizeof(PHATDIRENT)) {
01048 PhatFileClose(ndp);
01049 free(entry);
01050 return -1;
01051 }
01052
01053
01054
01055
01056
01057 if ((uint16_t) vol->vol_root_clust == dfcb->f_pde_clust &&
01058 vol->vol_root_clust >> 16 == dfcb->f_pde_clusthi) {
01059 entry->dent_clust = 0;
01060 entry->dent_clusthi = 0;
01061 } else {
01062 entry->dent_clust = dfcb->f_pde_clust;
01063 entry->dent_clusthi = dfcb->f_pde_clusthi;
01064 }
01065 entry->dent_name[1] = '.';
01066 if (PhatFileWrite(ndp, entry, sizeof(PHATDIRENT)) != sizeof(PHATDIRENT)) {
01067 PhatFileClose(ndp);
01068 free(entry);
01069 return -1;
01070 }
01071 free(entry);
01072
01073 return PhatFileClose(ndp);
01074 }
01075
01084 int PhatDirRemove(NUTDEVICE * dev, char *path)
01085 {
01086 int rc = -1;
01087 PHATDIRENT *entry;
01088 NUTFILE *ndp;
01089
01090
01091 if (path[0] == '/' && path[1] == 0) {
01092 errno = EBUSY;
01093 return -1;
01094 }
01095
01096 if ((entry = malloc(sizeof(PHATDIRENT))) == NULL) {
01097 return -1;
01098 }
01099
01100
01101
01102
01103
01104 if ((ndp = PhatFileOpen(dev, path, _O_RDONLY, 0)) != NUTFILE_EOF) {
01105 rc = 0;
01106 for (;;) {
01107 rc = PhatFileRead(ndp, entry, sizeof(PHATDIRENT));
01108 if (rc < 0) {
01109 break;
01110 }
01111
01112 if (rc < sizeof(PHATDIRENT) || entry->dent_name[0] == 0) {
01113 rc = 0;
01114 break;
01115 }
01116
01117 if (entry->dent_name[0] == PHAT_REM_DIRENT) {
01118 continue;
01119 }
01120
01121 if ((entry->dent_attr | PHAT_FATTR_FILEMASK) != PHAT_FATTR_FILEMASK) {
01122 continue;
01123 }
01124
01125 if (entry->dent_name[0] == '.' &&
01126 (entry->dent_name[1] == '.' || entry->dent_name[1] == ' ')) {
01127 if (memcmp(" ", &entry->dent_name[2], 9) == 0) {
01128 continue;
01129 }
01130 }
01131 errno = ENOTEMPTY;
01132 rc = -1;
01133 break;
01134 }
01135 PhatFileClose(ndp);
01136 }
01137 free(entry);
01138
01139
01140 if (rc == 0) {
01141 rc = PhatDirDelEntry(dev, path, PHAT_FATTR_DIR);
01142 }
01143 return rc;
01144 }
01145
01155 int PhatDirEntryStatus(NUTDEVICE * dev, CONST char *path, struct stat *stp)
01156 {
01157 int rc;
01158 CONST char *fname;
01159 NUTFILE *ndp;
01160 PHATFIND *srch;
01161 unsigned int val;
01162
01163
01164 if ((ndp = PhatDirOpenParent(dev, path, &fname)) == NUTFILE_EOF) {
01165 return -1;
01166 }
01167
01168 if ((srch = malloc(sizeof(PHATFIND))) == NULL) {
01169 PhatFileClose(ndp);
01170 return -1;
01171 }
01172 if ((rc = PhatDirEntryFind(ndp, fname, PHAT_FATTR_FILEMASK, srch)) == 0) {
01173 struct _tm t;
01174
01175 memset(&t, 0, sizeof(struct _tm));
01176 val = srch->phfind_ent.dent_mtime;
01177 t.tm_sec = (val & 0x1F) << 1;
01178 t.tm_min = (val >> 5) & 0x3F;
01179 t.tm_hour = (val >> 11) & 0x1F;
01180 val = srch->phfind_ent.dent_mdate;
01181 t.tm_mday = val & 0x1F;
01182 t.tm_mon = ((val >> 5) & 0x0F);
01183 if (t.tm_mon) {
01184 t.tm_mon--;
01185 }
01186 t.tm_year = ((val >> 9) & 0x7F) + 80;
01187 t.tm_isdst = _daylight;
01188 stp->st_mtime = mktime(&t);
01189
01190 stp->st_ino = 0;
01191 stp->st_mode = (srch->phfind_ent.dent_attr & PHAT_FATTR_DIR) != 0;
01192 stp->st_nlink = 0;
01193 stp->st_size = srch->phfind_ent.dent_fsize;
01194 }
01195 free(srch);
01196 PhatFileClose(ndp);
01197
01198 return rc;
01199 }
01200