/var/www/restricted/ssh/stm32/www/stm32circle/ STM CircleOS forum / FS directory create

Username:     
Password:     
             

Forum

# 1   2010-05-20 15:25:40 FS directory create

diabolo38
Member
Registered: 2010-03-12
Posts: 50

FS directory create

I diged a lot but Look like  there's no way to create a directory with the current API  right ?

Offline

 

# 2   2010-05-21 06:46:56 FS directory create

yrt
Administrator
From: Grenoble-France
Registered: 2008-06-11
Posts: 520
Website

Re: FS directory create

Effectively, there is no API function for that. You must previously create your folders structure with a PC and the Primer on mass storage mode.

Offline

 

# 3   2010-05-21 07:47:49 FS directory create

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: FS directory create

Hm. I think it could be possible to buid it on top of existing api. This will still require OS modification. I'll post my patch later.

Here is an example of how i will implement it.

Code:

if(!FS_OpenFile(VolumeInfo, "path/to/directory", FS_CREATEDIR, &FileInfo))
{
   FS_Close(&fileInfo); // Directory created or allready exists
}else{
   //Directory is not created
}

UPDATE: Nope. It didn't work. There is a bug in DFS - empty files should not use any clusters at all. Yet in DFS empty file uses a single cluster. This results in directories filled with garbage.

Last edited by ntrf.zns (2010-05-21 08:18:20)

Offline

 

# 4   2010-05-21 10:19:54 FS directory create

diabolo38
Member
Registered: 2010-03-12
Posts: 50

Re: FS directory create

do ypu get to work ? If the empty "directories" contain trash then your are quite close to the solution juste need to make it  "empty" , a two time directory create would be fine for me.

even if i can survive without a primer directori create  it will enable to manage data storage  in a clean way ( one series of numbered file per run  directori each run creat a new dire )
/ --
+/ RUN000
|  +image000.bmp
|  ~
|  +image999.bmp
|
+/ RUN001
   +image000.bmp
   ~
  +image006.bmp

etc...

Offline

 

# 5   2010-05-21 11:04:39 FS directory create

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: FS directory create

UPDATE: trash was caused by wrong cluster numbering. I fixed that. But there is yet another problem - directory owerwrites the last file in the parent directory and fails to cteate on an empty disk.

This looks strange. I tried to use RecWav application to write some files on the pre-formated flash and i'm geting the same result. Looks like there is a bug in DFS file creation process.

Last edited by ntrf.zns (2010-05-21 11:19:42)

Offline

 

# 6   2010-05-21 11:40:57 FS directory create

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: FS directory create

YES! Here is a new functions with CREATEDIR support.

Replace following functions in file dosfs.c:

Code:

NODEBUG uint32_t DFS_GetNext(PVOLINFO volinfo, PDIRINFO dirinfo, PDIRENT dirent)
{
    uint32_t tempint;    // required by DFS_GetFAT

    /* Do we need to read the next sector of the directory?*/
    if (dirinfo->currententry >= SECTOR_SIZE / sizeof(DIRENT)) {
        dirinfo->currententry = 0;
        dirinfo->currentsector++;

        /* Root directory; special case handling */
        /* Note that currentcluster will only ever be zero if both:*/
        /* (a) this is the root directory, and*/
        /* (b) we are on a FAT12/16 volume, where the root dir can't be expanded*/
        if (dirinfo->currentcluster == 0) {
            /* Trying to read past end of root directory?*/
            if (dirinfo->currentsector * (SECTOR_SIZE / sizeof(DIRENT)) >= volinfo->rootentries)
                return DFS_EOF;

            /* Otherwise try to read the next sector*/
            if (DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->rootdir + dirinfo->currentsector, 1))
                return DFS_ERRMISC;
        }

        /* Normal handling*/
        else {
            if (dirinfo->currentsector >= volinfo->secperclus) {
                dirinfo->currentsector = 0;
                if ((dirinfo->currentcluster >= 0xff7 &&  volinfo->filesystem == FAT12) ||
                  (dirinfo->currentcluster >= 0xfff7 &&  volinfo->filesystem == FAT16) ||
                  (dirinfo->currentcluster >= 0x0ffffff7 &&  volinfo->filesystem == FAT32)) {
                  
                      /* We are at the end of the directory chain. If this is a normal*/
                      /* find operation, we should indicate that there is nothing more*/
                      /* to see.*/
                      if (!(dirinfo->flags & DFS_DI_BLANKENT))
                        return DFS_EOF;
                    
                    /* On the other hand, if this is a "find free entry" search,*/
                    /* we need to tell the caller to allocate a new cluster*/
                    else
                        return DFS_ALLOCNEW;
                }
                dirinfo->currentcluster = DFS_GetFAT(volinfo, dirinfo->scratch, &tempint, dirinfo->currentcluster);
            }
            if (DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->dataarea + ((dirinfo->currentcluster - 2) * volinfo->secperclus) + dirinfo->currentsector, 1))
                return DFS_ERRMISC;
        }
    }

    DFS_memcpy(dirent, &(((PDIRENT) dirinfo->scratch)[dirinfo->currententry]), sizeof(DIRENT));

    if (dirent->name[0] == 0) {        /* no more files in this directory*/
    /* If this is a "find blank" then we can reuse this name.*/
        if (dirinfo->flags & DFS_DI_BLANKENT)
        {
            //NTRF: Invalid indexing! Current must be incremented proir to returning OK
            dirinfo->currententry++;
            return DFS_OK;
        }else
            return DFS_EOF;
    }

    if (dirent->name[0] == 0xe5)    /* handle deleted file entries*/
        dirent->name[0] = 0;
    else if( ((dirent->attr & ATTR_LONG_NAME) == ATTR_LONG_NAME) && 
             !(dirinfo->flags & DFS_DI_BLANKENT) ) //NTRF: don't replace longnames with new files
        dirent->name[0] = 0;
    else if (dirent->name[0] == 0x05)    /* handle kanji filenames beginning with 0xE5*/
        dirent->name[0] = 0xe5;

    dirinfo->currententry++;

    return DFS_OK;
}

Code:

NODEBUG uint32_t DFS_OpenFile(PVOLINFO volinfo, uint8_t *path, uint8_t mode, uint8_t *scratch, PFILEINFO fileinfo)
{
    uint8_t tmppath[MAX_PATH];
    uint8_t filename[12];
    uint8_t *p;
    DIRINFO di;
    DIRENT de;
    uint32_t dircluster;

    /* larwe 2006-09-16 +1 zero out file structure*/
    DFS_memset(fileinfo, 0, sizeof(FILEINFO));

    /* save access mode*/
    fileinfo->mode = mode;

    /* Get a local copy of the path. If it's longer than MAX_PATH, abort.*/
    DFS_strncpy((u8 *) tmppath, (u8 *) path, MAX_PATH);
    tmppath[MAX_PATH - 1] = 0;
    if (DFS_strcmp((u8 *) path,(u8 *) tmppath)) {
        return DFS_PATHLEN;
    }

    /* strip leading path separators*/
    while (tmppath[0] == DIR_SEPARATOR)
        DFS_strcpy((u8 *) tmppath, (u8 *) tmppath + 1);

    /* Parse filename off the end of the supplied path*/
    p = tmppath;
    while (*(p++));

    p--;
    while (p > tmppath && *p != DIR_SEPARATOR) /* larwe 9/16/06 ">=" to ">" bugfix*/
        p--;
    if (*p == DIR_SEPARATOR)
        p++;

    DFS_CanonicalToDir(filename, p);

    if (p > tmppath)
        p--;
    if (*p == DIR_SEPARATOR || p == tmppath) // larwe 9/16/06 +"|| p == tmppath" bugfix
        *p = 0;

    /* At this point, if our path was MYDIR/MYDIR2/FILE.EXT, filename = "FILE    EXT" and*/
    /* tmppath = "MYDIR/MYDIR2".*/
    di.scratch = scratch;
    dircluster = di.currentcluster;
    
    if (DFS_OpenDir(volinfo, tmppath, &di))
        return DFS_NOTFOUND;

    while (!DFS_GetNext(volinfo, &di, &de)) {
        if (!DFS_memcmp(de.name, filename, 11)) {
            /* You can't use this function call to open a directory.*/
            //NTRF: allows to create directories
            if ((de.attr & ATTR_DIRECTORY) && (mode != DFS_CREATEDIR))
                return DFS_NOTFOUND;

            fileinfo->volinfo = volinfo;
            fileinfo->pointer = 0;
            /* The reason we store this extra info about the file is so that we can*/
            /* speedily update the file size, modification date, etc. on a file that is*/
            /* opened for writing.*/
            if (di.currentcluster == 0)
                fileinfo->dirsector = volinfo->rootdir + di.currentsector;
            else
                fileinfo->dirsector = volinfo->dataarea + ((di.currentcluster - 2) * volinfo->secperclus) + di.currentsector;
            fileinfo->diroffset = di.currententry - 1;
            if (volinfo->filesystem == FAT32) {
                fileinfo->cluster = (uint32_t) de.startclus_l_l |
                  ((uint32_t) de.startclus_l_h) << 8 |
                  ((uint32_t) de.startclus_h_l) << 16 |
                  ((uint32_t) de.startclus_h_h) << 24;
            }
            else {
                fileinfo->cluster = (uint32_t) de.startclus_l_l |
                  ((uint32_t) de.startclus_l_h) << 8;
            }
            fileinfo->firstcluster = fileinfo->cluster;
            fileinfo->filelen = (uint32_t) de.filesize_0 |
              ((uint32_t) de.filesize_1) << 8 |
              ((uint32_t) de.filesize_2) << 16 |
              ((uint32_t) de.filesize_3) << 24;

            return DFS_OK;
        }
    }

    /* At this point, we KNOW the file does not exist. If the file was opened*/
    /* with write access, we can create it.*/
    if (mode & DFS_WRITE) {
        uint32_t cluster, temp;

        /* Locate or create a directory entry for this file*/
        if (DFS_OK != DFS_GetFreeDirEnt(volinfo, tmppath, &di, &de))
            return DFS_ERRMISC;

        /* put sane values in the directory entry*/
        DFS_memset(&de, 0, sizeof(de));
        DFS_memcpy(de.name, filename, 11);
        de.crttime_l = 0x20;    /* 01:01:00am, Jan 1, 2006.*/
        de.crttime_h = 0x08;
        de.crtdate_l = 0x11;
        de.crtdate_h = 0x34;
        de.lstaccdate_l = 0x11;
        de.lstaccdate_h = 0x34;
        de.wrttime_l = 0x20;
        de.wrttime_h = 0x08;
        de.wrtdate_l = 0x11;
        de.wrtdate_h = 0x34;
        
        //NTRF: create directory
        if(mode == DFS_CREATEDIR) de.attr |= ATTR_DIRECTORY;

        /* allocate a starting cluster for the directory entry*/
        cluster = DFS_GetFreeFAT(volinfo, scratch);

        de.startclus_l_l = cluster & 0xff;
        de.startclus_l_h = (cluster & 0xff00) >> 8;
        de.startclus_h_l = (cluster & 0xff0000) >> 16;
        de.startclus_h_h = (cluster & 0xff000000) >> 24;

        /* update FILEINFO for our caller's sake*/
        fileinfo->volinfo = volinfo;
        fileinfo->pointer = 0;
        /* The reason we store this extra info about the file is so that we can*/
        /* speedily update the file size, modification date, etc. on a file that is*/
        /* opened for writing.*/
        if (di.currentcluster == 0)
            fileinfo->dirsector = volinfo->rootdir + di.currentsector;
        else
            fileinfo->dirsector = volinfo->dataarea + ((di.currentcluster - 2) * volinfo->secperclus) + di.currentsector;
        fileinfo->diroffset = di.currententry - 1;
        fileinfo->cluster = cluster;
        fileinfo->firstcluster = cluster;
        fileinfo->filelen = 0;
        
        /* write the directory entry*/
        /* note that we no longer have the sector containing the directory entry,*/
        /* tragically, so we have to re-read it*/
        if (DFS_ReadSector(volinfo->unit, scratch, fileinfo->dirsector, 1))
            return DFS_ERRMISC;
        DFS_memcpy(&(((PDIRENT) scratch)[di.currententry-1]), &de, sizeof(DIRENT));
        if (DFS_WriteSector(volinfo->unit, scratch, fileinfo->dirsector, 1))
            return DFS_ERRMISC;

        /* Mark newly allocated cluster as end of chain            */
        switch(volinfo->filesystem) {
            case FAT12:        cluster = 0xff8;    break;
            case FAT16:        cluster = 0xfff8;    break;
            case FAT32:        cluster = 0x0ffffff8;    break;
            default:        return DFS_ERRMISC;
        }
        temp = 0;
        DFS_SetFAT(volinfo, scratch, &temp, fileinfo->cluster, cluster);
        
        //Fill new directory with required info
        if(mode == DFS_CREATEDIR)
        {
            if(dircluster <= 2) //Root
                dircluster = 0;
        
            uint32_t startsector = volinfo->dataarea + ((fileinfo->cluster - 2) * volinfo->secperclus);
            uint32_t endsector = startsector + volinfo->secperclus - 1;
            
            DFS_memset(scratch, 0, SECTOR_SIZE);
        
            for(; endsector > startsector; endsector -= 1)
                DFS_WriteSector(volinfo->unit, scratch, endsector, 1);
            
            DFS_memcpy(&(de.name), ".          ", 11);
            de.filesize_0 = 0;
            de.filesize_1 = 0;
            de.filesize_2 = 0;
            de.filesize_3 = 0;
            DFS_memcpy(scratch, &de, sizeof(DIRENT));
            
            DFS_memcpy(&(de.name), "..         ", 11);
            de.startclus_l_l = dircluster & 0xff;
            de.startclus_l_h = (dircluster & 0xff00) >> 8;
            de.startclus_h_l = (dircluster & 0xff0000) >> 16;
            de.startclus_h_h = (dircluster & 0xff000000) >> 24;
            
            DFS_memcpy(scratch + sizeof(DIRENT), &de, sizeof(DIRENT));
            
            DFS_WriteSector(volinfo->unit, scratch, startsector, 1);
        }

        return DFS_OK;
    }

    return DFS_NOTFOUND;
}

Now add define into the /* File access modes*/ block in dosfs.h file:

Code:

// File access modes
#define DFS_READ        1            // read-only
#define DFS_WRITE        2            // write-only
#define DFS_CREATEDIR   (2+4)       // NTRF: create dir

And add similiar defines into the fs.h and circle_api.h files:

Code:

/* File access modes*/
#define FS_READ        1            // read-only
#define FS_WRITE        2            // write-only
#define FS_CREATEDIR   (2+4)       // NTRF: create dir

Add them into the CircleOS distribution, build it and put the result (Primer2_obj/Primer2_circle.elf) file into the <RIDE7_InstallDir>/Lib/ARM/CircleOS.
See this for details.

You will also have to update copy of circle_api.h in your project.

And here is a small exmple of hot to use it:

Code:

VOLINFO volume_info;
FILEINFO file_info;

//Mount file system
uint32_t StartMBR=FS_Mount(MMCSD_SDIO);

// Open volume on first partition (0)
if (FS_GetVolumeInfo(0, StartMBR, &volume_info))
{
    DRAW_Puts("\nErr: GetVolInfo");
    return -1;
}
if (FS_OpenFile(&volume_info, "TESTDIR", FS_CREATEDIR, &file_info))
{
    DRAW_Puts("\n Err op: DirCreate");
    return -1;
}else{
    FS_Close(&file_info);
}

Last edited by ntrf.zns (2010-05-21 11:45:43)

Offline

 

# 7   2010-05-21 15:25:41 FS directory create

diabolo38
Member
Registered: 2010-03-12
Posts: 50

Re: FS directory create

Many thanks i'll give it  a try and let you know (might not be before next monday if i do not fix the ride install issue on my laptop)

Offline

 

# 8   2010-05-21 18:42:00 FS directory create

ShadowPhoenix
Member
Registered: 2009-02-11
Posts: 57

Re: FS directory create

Wouldn't it be cleaner to make a new function that creates Directory? smile

Offline

 

# 9   2010-05-21 19:54:38 FS directory create

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: FS directory create

You'll have to modify a few more functions anyway. And technicaly crating directory in FAT32 is the same as creating file, so adding another function would be waste of flash memory.
And there's also a fix for wrong directory entry numbering.

Last edited by ntrf.zns (2010-05-21 20:00:10)

Offline

 

# 10   2010-05-24 15:13:50 FS directory create

diabolo38
Member
Registered: 2010-03-12
Posts: 50

Re: FS directory create

it work great
By the way is it possible to keep mulitple file open on the same directori with the current FS ? I somehow feel this is should be fine but did anybody tried and could confirm ?

thanks again

Last edited by diabolo38 (2010-05-24 15:25:03)

Offline

 

# 11   2010-05-24 16:59:50 FS directory create

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: FS directory create

Yes. It's posible to keep two files open unless you try to open a file for reading and writing at the same time. It won't fail but you will have wrong offsets when reading.

Last edited by ntrf.zns (2010-05-24 17:00:43)

Offline

 

# 12   2010-06-18 13:24:57 FS directory create

yrt
Administrator
From: Grenoble-France
Registered: 2008-06-11
Posts: 520
Website

Re: FS directory create

I also tried it, and it works great.
Thanks a lot Ntrf

Offline

 

# 13   2010-06-18 15:11:53 FS directory create

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: FS directory create

Don't integrate it into the CircleOS!!!

Wait a few more weeks and i'll release a bigger patch for FS (faster, smaller and longnamed). Right now i don't have time for that.

Offline

 

Board footer