# File system routines

These functions are declared in the main Allegro header file:

~~~~c
 #include <allegro5/allegro.h>
~~~~

These functions allow access to the filesystem. This can either be the real
filesystem like your harddrive, or a virtual filesystem like a .zip archive (or
whatever else you or an addon makes it do).

## API: ALLEGRO_FS_ENTRY

Opaque filesystem entry object.
Represents a file or a directory (check with [al_get_fs_entry_mode]).
There are no user accessible member variables.

## API: ALLEGRO_FILE_MODE

Filesystem modes/types

* ALLEGRO_FILEMODE_READ - Readable
* ALLEGRO_FILEMODE_WRITE - Writable
* ALLEGRO_FILEMODE_EXECUTE - Executable
* ALLEGRO_FILEMODE_HIDDEN - Hidden
* ALLEGRO_FILEMODE_ISFILE - Regular file
* ALLEGRO_FILEMODE_ISDIR - Directory

## API: al_create_fs_entry

Creates an [ALLEGRO_FS_ENTRY] object pointing to path on the filesystem.
'path' can be a file or a directory and must not be NULL.

## API: al_destroy_fs_entry

Destroys a fs entry handle. The file or directory represented by it is not
destroyed. If the entry was opened, it is closed before being destroyed.

Does nothing if passed NULL.

## API: al_get_fs_entry_name

Returns the entry's filename path.
Note that the filesystem encoding may not be known and the conversion to UTF-8
could in very rare cases cause this to return an invalid path. Therefore it's
always safest to access the file over its [ALLEGRO_FS_ENTRY] and not the path.

On success returns a read only string which you must not modify or
destroy. Returns NULL on failure.

> Note: prior to 5.1.5 it was written: "... the path will not be an absolute
path if the entry wasn't created from an absolute path". This is no longer
true.

## API: al_update_fs_entry

Updates file status information for a filesystem entry.
File status information is automatically updated when the entry is created,
however you may update it again with this function, e.g. in case it changed.

Returns true on success, false on failure.
Fills in errno to indicate the error.

See also: [al_get_errno], [al_get_fs_entry_atime], [al_get_fs_entry_ctime],
[al_get_fs_entry_mode]

## API: al_get_fs_entry_mode

Returns the entry's mode flags, i.e. permissions and whether the entry
refers to a file or directory.

See also: [al_get_errno], [ALLEGRO_FILE_MODE]

## API: al_get_fs_entry_atime

Returns the time in seconds since the epoch since the entry was last
accessed.

Warning: some filesystems either don't support this flag, or people turn it
off to increase performance.
It may not be valid in all circumstances.

See also: [al_get_fs_entry_ctime], [al_get_fs_entry_mtime],
[al_update_fs_entry]

## API: al_get_fs_entry_ctime

Returns the time in seconds since the epoch this entry was created on the
filesystem.

See also: [al_get_fs_entry_atime], [al_get_fs_entry_mtime],
[al_update_fs_entry]

## API: al_get_fs_entry_mtime

Returns the time in seconds since the epoch since the entry was last
modified.

See also: [al_get_fs_entry_atime], [al_get_fs_entry_ctime],
[al_update_fs_entry]

## API: al_get_fs_entry_size

Returns the size, in bytes, of the given entry.
May not return anything sensible for a directory entry.

See also: [al_update_fs_entry]

## API: al_fs_entry_exists

Check if the given entry exists on in the filesystem.
Returns true if it does exist or false if it doesn't exist, or an error occurred.
Error is indicated in Allegro's errno.

See also: [al_filename_exists]

## API: al_remove_fs_entry

Delete this filesystem entry from the filesystem.  Only files and empty
directories may be deleted.

Returns true on success, and false on failure, error is indicated in Allegro's
errno.

See also: [al_filename_exists]

## API: al_filename_exists

Check if the path exists on the filesystem, without creating an
[ALLEGRO_FS_ENTRY] object explicitly.

See also: [al_fs_entry_exists]

## API: al_remove_filename

Delete the given path from the filesystem, which may be a file or an empty
directory.  This is the same as [al_remove_fs_entry], except it expects the
path as a string.

Returns true on success, and false on failure.
Allegro's errno is filled in to indicate the error.

See also: [al_remove_fs_entry]

## Directory functions

### API: al_open_directory

Opens a directory entry object. You must call this before using [al_read_directory]
on an entry and you must call [al_close_directory] when you no longer need it.

Returns true on success.

See also: [al_read_directory], [al_close_directory]

### API: al_read_directory

Reads the next directory item and returns a filesystem entry for it.

Returns NULL if there are no more entries or if an error occurs. Call
[al_destroy_fs_entry] on the returned entry when you are done with it.

This function will ignore any files or directories named `.` or `..` which may
exist on certain platforms and may signify the current and the parent directory.

See also: [al_open_directory], [al_close_directory]

### API: al_close_directory

Closes a previously opened directory entry object.

Returns true on success, false on failure and fills in Allegro's errno to
indicate the error.

See also: [al_open_directory], [al_read_directory]

### API: al_get_current_directory

Returns the path to the current working directory, or NULL on failure.
The returned path is dynamically allocated and must be destroyed with
[al_free].

Allegro's errno is filled in to indicate the error if there is a failure.
This function may not be implemented on some (virtual) filesystems.

See also: [al_get_errno], [al_free]

### API: al_change_directory

Changes the current working directory to 'path'.

Returns true on success, false on error.

### API: al_make_directory

Creates a new directory on the filesystem.  This function also creates any
parent directories as needed.

Returns true on success (including if the directory already exists), otherwise
returns false on error.  Fills in Allegro's errno to indicate the error.

See also: [al_get_errno]

### API: al_open_fs_entry

Open an [ALLEGRO_FILE] handle to a filesystem entry, for the given access mode.
This is like calling [al_fopen] with the name of the filesystem entry, but uses
the appropriate file interface, not whatever was set with the latest call to
[al_set_new_file_interface].

Returns the handle on success, NULL on error.

See also: [al_fopen]

### API: ALLEGRO_FOR_EACH_FS_ENTRY_RESULT

Return values for the callbacks of [al_for_each_fs_entry] and
for that function itself.

* ALLEGRO_FOR_EACH_FS_ENTRY_ERROR - An error ocurred.
* ALLEGRO_FOR_EACH_FS_ENTRY_OK - Continue normally and recurse into directories.
* ALLEGRO_FOR_EACH_FS_ENTRY_SKIP - Continue but do NOT recusively descend.
* ALLEGRO_FOR_EACH_FS_ENTRY_STOP - Stop iterating and return.

See also: [al_for_each_fs_entry]

Since: 5.1.9

### API: al_for_each_fs_entry

This function takes the [ALLEGRO_FS_ENTRY] `dir`, which should
represent a directory, and  looks for any other file system entries
that are in it. This function will then call the callback function `callback`
once for every filesystem entry in the directory `dir`.

The callback `callback` must be of type `int callback(ALLEGRO_FS_ENTRY *
entry, void * extra)`. The `callback` will be called with a pointer
to an [ALLEGRO_FS_ENTRY] that matches one file or directory in `dir`,
and the pointer passed in the `extra` parameter to [al_for_each_fs_entry].

When `callback` returns `ALLEGRO_FOR_EACH_FS_ENTRY_STOP` or
`ALLEGRO_FOR_EACH_FS_ENTRY_ERROR`, iteration will stop immediately
and [al_for_each_fs_entry]  will return the value the `callback` returned.

When `callback` returns `ALLEGRO_FOR_EACH_FS_ENTRY_OK` iteration will continue
normally, and if the [ALLEGRO_FS_ENTRY] parameter of `callback`
is a directory, [al_for_each_fs_entry] will call itself
on that directory. Therefore the function will recusively descend into that
directory.

However, when `callback` returns `ALLEGRO_FOR_EACH_FS_ENTRY_SKIP` iteration
will continue, but [al_for_each_fs_entry] will NOT recurse into the
[ALLEGRO_FS_ENTRY] parameter of `callback` even if it is a directory.

This function will skip any files or directories named `.` or `..`
which may exist on certain platforms and may signify the current and the
parent directory. The `callback` will not be called for files
or directories with such a name.

Returns ALLEGRO_FOR_EACH_FS_ENTRY_OK if successful, or
ALLEGRO_FOR_EACH_FS_ENTRY_ERROR if something went wrong in
processing the directory. In that case it will use [al_set_errno] to indicate
the type of error which occurred. This function returns
ALLEGRO_FOR_EACH_FS_ENTRY_STOP in case iteration was stopped by making
`callback` return that value. In this case, [al_set_errno] will not be used.

See also: [ALLEGRO_FOR_EACH_FS_ENTRY_RESULT]

Since: 5.1.9

## Alternative filesystem functions

By default, Allegro uses platform specific filesystem functions for things like
directory access. However if for example the files of your game are not in
the local filesystem but inside some file archive, you can provide your own
set of functions (or use an addon which does this for you, for example our
physfs addon allows access to the most common archive formats).

### API: ALLEGRO_FS_INTERFACE

The available functions you can provide for a filesystem. They are:

~~~
   ALLEGRO_FS_ENTRY *  fs_create_entry   (const char *path);
   void                fs_destroy_entry  (ALLEGRO_FS_ENTRY *e);
   const char *        fs_entry_name     (ALLEGRO_FS_ENTRY *e);
   bool                fs_update_entry   (ALLEGRO_FS_ENTRY *e);
   uint32_t            fs_entry_mode     (ALLEGRO_FS_ENTRY *e);
   time_t              fs_entry_atime    (ALLEGRO_FS_ENTRY *e);
   time_t              fs_entry_mtime    (ALLEGRO_FS_ENTRY *e);
   time_t              fs_entry_ctime    (ALLEGRO_FS_ENTRY *e);
   off_t               fs_entry_size     (ALLEGRO_FS_ENTRY *e);
   bool                fs_entry_exists   (ALLEGRO_FS_ENTRY *e);
   bool                fs_remove_entry   (ALLEGRO_FS_ENTRY *e);

   bool                fs_open_directory (ALLEGRO_FS_ENTRY *e);
   ALLEGRO_FS_ENTRY *  fs_read_directory (ALLEGRO_FS_ENTRY *e);
   bool                fs_close_directory(ALLEGRO_FS_ENTRY *e);

   bool                fs_filename_exists(const char *path);
   bool                fs_remove_filename(const char *path);
   char *              fs_get_current_directory(void);
   bool                fs_change_directory(const char *path);
   bool                fs_make_directory(const char *path);

   ALLEGRO_FILE *      fs_open_file(ALLEGRO_FS_ENTRY *e);
~~~

### API: al_set_fs_interface

Set the [ALLEGRO_FS_INTERFACE] table for the calling thread.

See also: [al_set_standard_fs_interface], [al_store_state],
[al_restore_state].

### API: al_set_standard_fs_interface

Return the [ALLEGRO_FS_INTERFACE] table to the default, for the calling
thread.

See also: [al_set_fs_interface].

### API: al_get_fs_interface

Return a pointer to the [ALLEGRO_FS_INTERFACE] table in effect
for the calling thread.

See also: [al_store_state], [al_restore_state].

