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