Menu

FATFS_Directory Log in to Edit

FATFS - Directory Operations

Procedures and functions for performing FAT directory operations are documented on this page.

General Considerations

  1. Except where noted, the file system must be open before calling any of this APIs.
  2. File system object names are internally upper-cased where case might be an issue. The application is free to pass mixed or lower case names.
  3. Names returned in the data type Dir_Entry_Type will be upper case.
  4. Some operations may fail if the object name doesn't observer DOS 8.3 naming standards.

API Summary

procedure Open_Dir(Dir : out DCB_Type; OK : out Boolean);
procedure Open_Dir(Dir : out DCB_Type; Dir_Entry : Dir_Entry_Type; OK : out Boolean);
procedure Open_Dir(Dir : in out DCB_Type; Name : String; OK : out Boolean);
procedure Open_Path(Dir : out DCB_Type; Pathname : String; OK : out Boolean);
procedure Search_Dir(Dir : in out DCB_Type; Dir_Entry : out Dir_Entry_Type; Name : String; OK : out Boolean);
procedure Get_Dir_Entry(Dir : in out DCB_Type; Dir_Entry : out Dir_Entry_Type; OK : out Boolean);
procedure Next_Dir_Entry(Dir : in out DCB_Type; Dir_Entry : out Dir_Entry_Type; OK : out Boolean);
procedure Rewind_Dir(Dir : in out DCB_Type);
procedure Close_Dir(Dir : in out DCB_Type);

function Filename(Dir_Entry : Dir_Entry_Type) return String;

procedure Create_Subdir(Dir : in out DCB_Type; Subdir : String; OK : out Boolean);
procedure Create_Path(Dir : out DCB_Type; Pathname : String; OK : out Boolean);
procedure Delete_Subdir(Dir : in out DCB_Type; Subdir : String; OK : out Boolean);
procedure Rename(Dir : in out DCB_Type; Old_Name, New_Name : String; OK : out Boolean);
procedure Update_Attributes(Dir : in out DCB_Type; Dir_Entry : Dir_Entry_Type; OK : out Boolean);

procedure Delete_File(Dir : in out DCB_Type; Name : String; OK : out Boolean);

Data Types

The following are the main data types used in directory operations. Almost all operations use
the directory control block (DCB_Type). This object maintains the current state of an open directory
or subdirectory. Once closed, it is invalid to pass the control block to any API except an open
operation.

The DCB_Type is '''not limited''', allowing it to be copied and assigned to other DCB_Type values. This is sometimes useful to save the state of a directory, prior to opening another subdirectory in the same variable.

Many operations involve a directory entry type (Dir_Entry_Type). These provide access to
file name and attribute information. Note also that E.Filename will contain '.' or '..' for these two special directory entries.

type DCB_Type is private;           -- Directory control block

type Dir_Entry_Type is record
Filename :      String(1..8);
Extension :     String(1..3);
Reserved_7 :    Boolean;
Reserved_6 :    Boolean;
Archive :       Boolean;
Subdirectory :  Boolean;
Volume_Name :   Boolean;
System_File :   Boolean;
Hidden_File :   Boolean;
Read_Only :     Boolean;
Reserved :      String(1..8);
Cluster_High :  Unsigned_16;        -- FAT32 only
Hour :          Hour_Type;
Minute :        Minute_Type;
Second2 :       Seconds2_Type;
Year :          Year_Type;
Month :         Month_Type;
Day :           Day_Type;
First_Cluster : Unsigned_16;
File_Size :     Unsigned_32;
end record;

Open Root Directory

This procedure opens the file system's root directory, saving the state into Dir. OK is set to true if the operation succeeds. The directory is positioned at the first root directory entry.

procedure Open_Dir(Dir : out DCB_Type; OK : out Boolean);

Open Subdirectory

The following procedures open the named subdirectory, in the current directory Dir. When Dir_Entry is provided, the information contained within provides enough information to open that subdirectory, replacing the value in argument Dir.

When the string Name is provided instead, the directory identified by Dir is rewound and searched for Name. If the subdirectory is successfully located, it is opened, with the result placed in Dir.

In both cases, Dir is reopened with the new subdirectory, forgetting the original parent directory. Ok will be returned True when this operation is successful.

If the named subdirectory is not opened successfully, Dir remains as it was (except for it's position in the 2nd case). Ok will be returned False in this case.

procedure Open_Dir(Dir : out DCB_Type; Dir_Entry : Dir_Entry_Type; OK : out Boolean);
procedure Open_Dir(Dir : in out DCB_Type; Name : String; OK : out Boolean);

Notes

  1. When supplying Dir_Entry, be careful that the contents of that directory entry remains unaltered. Altering the first cluster number for the directory, could be disastrous.
  2. Argument Name is internally uppercased when required. Note also that long file names are not supported.
  3. The identified object must be a directory object, to be successfully opened.

Open Directory Path

The Open_Path procedure permits the calling application to conveniently open a subdirectory that is several levels deep:

procedure Open_Path(Dir : out DCB_Type; Pathname : String; OK : out Boolean);

It is equivalent to the following:
1. Open root directory
+ Open first/next component as a subdirectory
+ Repeat 2 until all pathname components have been exhausted

The returned value OK is returned when the operation is successful.

Search Directory

The currently open directory/subdirectory specified by Dir is rewound and searched for the file system object Name. If found, the value OK is set to True and the directory content is returned in Dir_Entry. Otherwise OK is returned as False.

procedure Search_Dir(Dir : in out DCB_Type; Dir_Entry : out Dir_Entry_Type; Name : String; OK : out Boolean);

Rewind/Get/Next Directory

An application may use the following API calls to manually scan a directory/subdirectory:

procedure Get_Dir_Entry(Dir : in out DCB_Type; Dir_Entry : out Dir_Entry_Type; OK : out Boolean);
procedure Next_Dir_Entry(Dir : in out DCB_Type; Dir_Entry : out Dir_Entry_Type; OK : out Boolean);
procedure Rewind_Dir(Dir : in out DCB_Type);

Rewind_Dir

This procedure rewinds the Dir object to point to the first directory entry, if any.

Get_Dir_Entry

Returns the directory item that Dir is currently positioned at. In a loop, this should always be the first call after an open/rewind of a directory. Deleted entries and volume entries are bypassed.

Next_Dir_Entry

This procedure advances past the current directory item and returns the next active entry. Deleted entries and volume entries are bypassed.

Close Directory

There is no real underlying "close" operation as such but the variable Dir is marked as closed. Once closed, it will be cause any other directory operations using it to fail (except for open).

procedure Close_Dir(Dir : in out DCB_Type);

The current implementation does not require a close to be performed. However, to protect against future changes that might require it, it is recommended. Closing the Dir object also provides some application protection against unintended use of it.

Filename

This function returns a file system object name from the directory entry type. The file name returned will be in 8.3 format, with trailing blanks and suffix removed if there is none.

function Filename(Dir_Entry : Dir_Entry_Type) return String;

The file system does not need to be open for this call.

Create Subdirectory

The following procedure creates a subdirectory named by argument Subdir, in the directory open in Dir. OK is returned True if the operation succeeds.

procedure Create_Subdir(Dir : in out DCB_Type; Subdir : String; OK : out Boolean);

Create Path

The following procedure calls Create_Subdir as required, for all components found in the argument Pathname (starting from the root directory). The last component in Pathname names the subdirectory to be opened in returned argument Dir. Argument OK is set to true if this open succeeds. Otherwise False indicates an error occurred.

procedure Create_Path(Dir : out DCB_Type; Pathname : String; OK : out Boolean);

Delete Subdirectory

The following procedure deletes the contents of the subdirectory named by Subdir
(found in the directory tracked in argument Dir)
and then removes the subdirectory itself.

Warning: This API should be used with care.

The argument Ok is returned with True if the subdirectory is deleted, but otherwise
False indicates an error occurred. Note that all files and deeper subdirectories are
deleted as part of this operation.

procedure Delete_Subdir(Dir : in out DCB_Type; Subdir : String; OK : out Boolean);

Rename

The following procedure renames an object named Old_Name to the new name New_Name (in the
directory tracked by argument Dir). OK is set to True if the rename succeeds.

procedure Rename(Dir : in out DCB_Type; Old_Name, New_Name : String; OK : out Boolean);

Update Attributes

The following operation updates the directory entry currently positioned at in Dir, with the new
contents of Dir_Entry.

procedure Update_Attributes(Dir : in out DCB_Type; Dir_Entry : Dir_Entry_Type; OK : out Boolean);

Warnings

  1. This is intended only for updating attributes such as Read_Only, Hidden_File or System_File.
  2. Changing other attributes other than date/time components could be disastrous for the file system.
  3. The Update_Attributes should only be called following a Get_Dir_Entry or Next_Dir_Entry. Otherwise other critical values in Dir_Entry_Type will corrupt the file system.

Delete File

The following operation deletes the file named by argument Name, in the directory tracked by Dir. OK is returned as True when the operation succeeds.

procedure Delete_File(Dir : in out DCB_Type; Name : String; OK : out Boolean);

Example 1 - Open File in Subdirectory

Example 1 shows how the variations of the Open_Dir procedure opens first the root directory, and then successive subdirectories.

procedure Example_1 is
   D :     DCB_Type;                   -- Directory control block
   F :     TFCB_Type;                  -- File control block
   OK :    Boolean;                    -- Success/Failure flag
begin

   Open_Dir(D,OK);                     -- Open root directory
   pragma Assert(OK);

   Open_Dir(D,"LOGFILES",OK);          -- Open LOGFILES subdirectory
   pragma Assert(OK);

   Open_Dir(D,"CURRENT",OK);           -- Open LOGFILESCURRENT subdirectory
   pragma Assert(OK);

   Open_File(F,D,"MYLOG.LOG",OK) ;     -- Open LOGFILESCURRENTMYLOG.LOG file
   pragma assert(OK);

Example 2 - Open File in Subdirectory

Example 2 is an easier way to navigate to the subdirectory containing the file to be opened:

with Interfaces;     use Interfaces;
with FATFS;          use FATFS;

procedure Example_2 is
   D :     DCB_Type;                   -- Directory control block
   F :     TFCB_Type;                  -- File control block
   OK :    Boolean;                    -- Success/Failure flag
begin

   Open_Path(D,"LOGFILESCURRENT",OK);
   pragma assert(OK);

   Open_File(F,D,"MYLOG.LOG",OK) ;     -- Open log for reading
   pragma assert(OK);

Example 3 - Scan Directory and Delete

This example shows how to open the root directory and scan it for non-system files. Any file or subdirectory that is not marked with the "System" attribute is then deleted.

The Get_Dir_Entry call returns the first non-deleted directory entry into E. If OK is returned as True, then E contains a valid entry, which is then examined by the loop. The call to Next_Dir_Entry at the bottom of the loop, advances the directory control block and returns the next non-deleted entry.

In the body of the loop, E is examined to see if E.System_File is true (entry represents a system file or directory). If this is False, then E is tested to see if this is a subdirectory or not. Then a subdirectory or file delete is performed, as appropriate.

The first if statement also avoids the '.' and '..' directory entries. This is an important test since we don't want to attempt to delete '.' (the current and root directory), nor the parent directory (which doesn't apply to root directories).

This also points out a special exception regarding '.' in the directory entry names. Normally a 8.3 DOS name is parsed out into E.Filename and E.Extension. However, E.Filename will contain '.' or '..' for these two special directory entries.

with Interfaces;     use Interfaces;
with FATFS;          use FATFS;

procedure Example_3 is
   D :   DCB_Type;                   -- Directory control block
   E :   Dir_Entry_Type;
   F :   TFCB_Type;                  -- File control block
   OK :  Boolean;                    -- Success/Failure flag
begin

   Open_Dir(D,OK);                   -- Open root directory
   pragma Assert(OK);

   Get_Dir_Entry(D,E,OK);            -- Get 1st non-deleted dir entry

   loop
      exit when not OK;

      if ( not E.System_File ) and E.Filename(1) /= '.' then
         if E.Subdirectory then
            Delete_Subdir(D,Filename(E),OK); -- delete subdir and it's contents
            exit when not OK;
         else
            Delete_File(D,Filename(E),OK);   -- delete file
            exit when not OK;
         end if;
      end if;

      Next_Dir_Entry(D,E,OK);         -- Get next non-deleted dir entry
   end loop;

   Close_Dir(D);

Related

Wiki: Fatfs

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.