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