physfs.h
changeset 6 3662cbc014ef
parent 3 0dd785321345
child 8 41e4c6031535
--- a/physfs.h	Thu Jul 05 08:18:39 2001 +0000
+++ b/physfs.h	Thu Jul 05 08:19:01 2001 +0000
@@ -13,18 +13,18 @@
  *  fs_* cvars. If you've ever tinkered with these, then this API will be
  *  familiar to you.
  *
- * With PhysicsFS, you have a single writing path and multiple "search paths"
- *  for reading. You can think of this as a filesystem within a
- *  filesystem. If (on Windows) you were to set the writing directory to
- *  "C:\MyGame\MyWritingDirectory", then no PHYSFS calls could touch anything
- *  above this directory, including the "C:\MyGame" and "C:\" directories.
- *  This prevents an application's internal scripting language from piddling
- *  over c:\config.sys, for example. If you'd rather give PHYSFS full access
- *  to the system's REAL file system, set the writing path to "C:\", but
- *  that's generally A Bad Thing for several reasons.
+ * With PhysicsFS, you have a single writing directory and multiple
+ *  directories (the "search path") for reading. You can think of this as a
+ *  filesystem within a filesystem. If (on Windows) you were to set the
+ *  writing directory to "C:\MyGame\MyWritingDirectory", then no PHYSFS calls
+ *  could touch anything above this directory, including the "C:\MyGame" and
+ *  "C:\" directories. This prevents an application's internal scripting
+ *  language from piddling over c:\config.sys, for example. If you'd rather
+ *  give PHYSFS full access to the system's REAL file system, set the writing
+ *  dir to "C:\", but that's generally A Bad Thing for several reasons.
  *
  * Drive letters are hidden in PhysicsFS once you set up your initial paths.
- *  The search paths create a single, hierarchical directory structure.
+ *  The search path creates a single, hierarchical directory structure.
  *  Not only does this lend itself well to general abstraction with archives,
  *  it also gives better support to operating systems like MacOS and Unix.
  *  Generally speaking, you shouldn't ever hardcode a drive letter; not only
@@ -32,25 +32,26 @@
  *  users to a single drive, too. Use the PhysicsFS abstraction functions and
  *  allow user-defined configuration options, too. When opening a file, you
  *  specify it like it was on a Unix filesystem: if you want to write to
- *  "C:\MyGame\MyConfigFiles\game.cfg", then you might set the write path to
+ *  "C:\MyGame\MyConfigFiles\game.cfg", then you might set the write dir to
  *  "C:\MyGame" and then open "MyConfigFiles/game.cfg". This gives an
  *  abstraction across all platforms. Specifying a file in this way is termed
- *  "platform-independent notation" in this documentation. Specifying a path
- *  as "C:\mydir\myfile" or "MacOS hard drive:My Directory:My File" is termed
- *  "platform-dependent notation". The only time you use platform-dependent
- *  notation is when setting up your write and search paths; after that, all
- *  file access into those paths are done with platform-independent notation.
+ *  "platform-independent notation" in this documentation. Specifying a
+ *  a filename in a form such as "C:\mydir\myfile" or
+ *  "MacOS hard drive:My Directory:My File" is termed "platform-dependent
+ *  notation". The only time you use platform-dependent notation is when
+ *  setting up your write directory and search path; after that, all file
+ *  access into those directories are done with platform-independent notation.
  *
- * All files opened for writing are opened in relation to the write path,
+ * All files opened for writing are opened in relation to the write directory,
  *  which is the root of the writable filesystem. When opening a file for
- *  reading, PhysicsFS goes through it's internal search path. This is NOT the
+ *  reading, PhysicsFS goes through the search path. This is NOT the
  *  same thing as the PATH environment variable. An application using
  *  PhysicsFS specifies directories to be searched which may be actual
  *  directories, or archive files that contain files and subdirectories of
  *  their own. See the end of these docs for currently supported archive
  *  formats.
  *
- * Once a search path is defined, you may open files for reading. If you've
+ * Once the search path is defined, you may open files for reading. If you've
  *  got the following search path defined (to use a win32 example again):
  *
  *    C:\mygame
@@ -58,7 +59,7 @@
  *    D:\mygamescdromdatafiles
  *    C:\mygame\installeddatafiles.zip
  *
- * Then a call to PHYSFS_openread("textfiles/myfile.txt") (note the directory
+ * Then a call to PHYSFS_openRead("textfiles/myfile.txt") (note the directory
  *  separator, lack of drive letter, and lack of dir separator at the start of
  *  the string; this is platform-independent notation) will check for
  *  C:\mygame\textfiles\myfile.txt, then
@@ -68,37 +69,53 @@
  *  that most archive types and platform filesystems store their filenames in
  *  a case-sensitive manner, so you should be careful to specify it correctly.
  *
- * Files opened through PhysicsFS may NOT contain "." or ".." as path
- *  elements. Not only are these meaningless on MacOS, they are a security
- *  hole. Also, symbolic links (which can be found in some archive types and
- *  directly in the filesystem on Unix platforms) are NOT followed until you
- *  call PHYSFS_permitSymbolicLinks(). That's left to your own discretion, as
- *  following a symlink can allow for access outside the write and search
- *  paths. There is no mechanism for creating new symlinks in PhysicsFS.
+ * Files opened through PhysicsFS may NOT contain "." or ".." or ":" as dir
+ *  elements. Not only are these meaningless on MacOS and/or Unix, they are a
+ *  security hole. Also, symbolic links (which can be found in some archive
+ *  types and directly in the filesystem on Unix platforms) are NOT followed
+ *  until you call PHYSFS_permitSymbolicLinks(). That's left to your own
+ *  discretion, as following a symlink can allow for access outside the write
+ *  dir and search paths. There is no mechanism for creating new symlinks in
+ *  PhysicsFS.
  *
- * The write path is not included in the search path unless you specifically
- *  add it. While you CAN change the write path as many times as you like,
- *  you should probably set it once and stick to that path. Remember that
- *  your program will not have permission to write in every directory on
- *  Unix and NT systems.
+ * The write dir is not included in the search path unless you specifically
+ *  add it. While you CAN change the write dir as many times as you like,
+ *  you should probably set it once and stick to it. Remember that your
+ *  program will not have permission to write in every directory on Unix and
+ *  NT systems.
  *
  * All files are opened in binary mode; there is no endline conversion for
  *  textfiles. Other than that, PhysicsFS has some convenience functions for
  *  platform-independence. There is a function to tell you the current
- *  platform's path separator ("\\" on windows, "/" on Unix, ":" on MacOS),
+ *  platform's dir separator ("\\" on windows, "/" on Unix, ":" on MacOS),
  *  which is needed only to set up your search/write paths. There is a
  *  function to tell you what CD-ROM drives contain accessible discs, and a
  *  function to recommend a good search path, etc.
  *
- * A recommended order for a search path is the write path, then the base path,
- *  then the cdrom path, then any archives discovered. Quake 3 does something
+ * A recommended order for the search path is the write dir, then the base dir,
+ *  then the cdrom dir, then any archives discovered. Quake 3 does something
  *  like this, but moves the archives to the start of the search path. Build
  *  Engine games, like Duke Nukem 3D and Blood, place the archives last, and
- *  use the base path for both searching and writing. There is a helper
- *  function (PHYSFS_setSanePaths()) that puts together a basic configuration
+ *  use the base dir for both searching and writing. There is a helper
+ *  function (PHYSFS_setSaneConfig()) that puts together a basic configuration
  *  for you, based on a few parameters. Also see the comments on
- *  PHYSFS_getBasePath(), and PHYSFS_getUserPath() for info on what those
- *  are and how they can help you determine an optimal searchpath.
+ *  PHYSFS_getBaseDir(), and PHYSFS_getUserDir() for info on what those
+ *  are and how they can help you determine an optimal search path.
+ *
+ * PhysicsFS is (sort of) NOT thread safe! The error messages returned by
+ *  PHYSFS_getLastError are unique by thread, but that's it. Generally
+ *  speaking, we'd have to request a mutex at the start of each function,
+ *  and release it before returning. Not only is this REALLY slow, it requires
+ *  a thread lock portability layer to be written. All that work is only
+ *  necessary as a safety if the calling application is poorly written.
+ *  Generally speaking, it is safe to call most functions that don't set state
+ *  simultaneously; you can read and write and open and close different files
+ *  at the same time in different threads, but trying to set the write path in
+ *  one thread while opening a file for writing in another will, at best,
+ *  cause a polite error, but depending on the race condition results, you may
+ *  get a segfault and crash, too. Use your head, and implement you own thread
+ *  locks where needed. Also, consider if you REALLY need a multithreaded
+ *  solution in the first place.
  *
  * While you CAN use stdio/syscall file access in a program that has PHYSFS_*
  *  calls, doing so is not recommended, and you can not use system
@@ -127,7 +144,7 @@
 
 typedef struct __PHYSFS_FILE__
 {
-    unsigned int opaque;
+    void *opaque;
 } PHYSFS_file;
 
 typedef struct __PHYSFS_ARCHIVEINFO__
@@ -139,6 +156,46 @@
 
 /* functions... */
 
+typedef struct __PHYSFS_VERSION__
+{
+    int major;
+    int minor;
+    int patch;
+} PHYSFS_Version;
+
+#define PHYSFS_VER_MAJOR 0
+#define PHYSFS_VER_MINOR 1
+#define PHYSFS_VER_PATCH 0
+
+#define PHYSFS_VERSION(x) { \
+                            x->major = PHYSFS_VER_MAJOR; \
+                            x->minor = PHYSFS_VER_MINOR; \
+                            x->patch = PHYSFS_VER_PATCH; \
+                          }
+
+/**
+ * Get the version of PhysicsFS that is linked against your program. If you
+ *  are using a shared library (DLL) version of PhysFS, then it is possible
+ *  that it will be different than the version you compiled against.
+ *
+ * This is a real function; the macro PHYSFS_VERSION tells you what version
+ *  of PhysFS you compiled against:
+ *
+ * PHYSFS_Version compiled;
+ * PHYSFS_Version linked;
+ *
+ * PHYSFS_VERSION(&compiled);
+ * PHYSFS_getLinkedVersion(&linked);
+ * printf("We compiled against PhysFS version %d.%d.%d ...\n",
+ *           compiled.major, compiled.minor, compiled.patch);
+ * printf("But we linked against PhysFS version %d.%d.%d.\n",
+ *           linked.major, linked.minor, linked.patch);
+ *
+ * This function may be called safely at any time, even before PHYSFS_init().
+ */
+void PHYSFS_getLinkedVersion(PHYSFS_Version *ver);
+
+
 /**
  * Initialize PhysicsFS. This must be called before any other PhysicsFS
  *  function.
@@ -157,6 +214,8 @@
  * Once deinitialized, PHYSFS_init() can be called again to restart the
  *  subsystem.
  *
+ * This function can be used with atexit(), if you feel it's prudent to do so.
+ *
  *  @return nonzero on success, zero on error. Specifics of the error can be
  *          gleaned from PHYSFS_getLastError(). If failure, state of PhysFS is
  *          undefined, and probably badly screwed up.
@@ -171,8 +230,8 @@
  *  convention: if we list "ZIP", you can open a PkZip-compatible archive
  *  with an extension of "XYZ", if you like.
  *
- * The returned value is an array of strings, with a NULL entry to signify the
- *  end of the list:
+ * The returned value is an array of pointers to PHYSFS_ArchiveInfo structures,
+ *  with a NULL entry to signify the end of the list:
  *
  * PHYSFS_ArchiveInfo **i;
  *
@@ -187,7 +246,7 @@
  *
  *   @return READ ONLY Null-terminated array of READ ONLY structures.
  */
-const PHYSFS_ArchiveInfo *PHYSFS_supportedArchiveTypes(void);
+const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void);
 
 
 /**
@@ -202,8 +261,11 @@
 /**
  * Get the last PhysicsFS error message as a null-terminated string.
  *  This will be NULL if there's been no error since the last call to this
- *  function. The pointer returned by this call points to an
- *  internal buffer. Each thread has a unique error state associated with it.
+ *  function. The pointer returned by this call points to an internal buffer.
+ *  Each thread has a unique error state associated with it, but each time
+ *  a new error message is set, it will overwrite the previous one associated
+ *  with that thread. It is safe to call this function at anytime, even
+ *  before PHYSFS_init().
  *
  *   @return READ ONLY string of last error message.
  */
@@ -211,24 +273,24 @@
 
 
 /**
- * Get a platform-dependent path separator. This is "\\" on win32, "/" on Unix,
+ * Get a platform-dependent dir separator. This is "\\" on win32, "/" on Unix,
  *  and ":" on MacOS. It may be more than one character, depending on the
  *  platform, and your code should take that into account. Note that this is
  *  only useful for setting up the search/write paths, since access into those
- *  paths always use '/' (platform-independent notation) to separate
+ *  dirs always use '/' (platform-independent notation) to separate
  *  directories. This is also handy for getting platform-independent access
  *  when using stdio calls.
  *
- *   @return READ ONLY null-terminated string of platform's path separator.
+ *   @return READ ONLY null-terminated string of platform's dir separator.
  */
-const char *PHYSFS_getPathSeparator(void);
+const char *PHYSFS_getDirSeparator(void);
 
 
 /**
- * Get an array of paths to available CD-ROM drives.
+ * Get an array of dirs to available CD-ROM drives.
  *
- * The paths returned are platform-dependent ("D:\" on Win32, "/cdrom" or
- *  whatnot on Unix). Paths are only returned if there is a disc ready and
+ * The dirs returned are platform-dependent ("D:\" on Win32, "/cdrom" or
+ *  whatnot on Unix). Dirs are only returned if there is a disc ready and
  *  accessible in the drive. So if you've got two drives (D: and E:), and only
  *  E: has a disc in it, then that's all you get. If the user inserts a disc
  *  in D: and you call this function again, you get both drives. If, on a
@@ -240,8 +302,8 @@
  *
  * char **i;
  *
- * for (i = PHYSFS_getCdRomPaths(); *i != NULL; i++)
- *     printf("cdrom path [%s] is available.\n", *i);
+ * for (i = PHYSFS_getCdRomDirs(); *i != NULL; i++)
+ *     printf("cdrom dir [%s] is available.\n", *i);
  *
  * This call may block while drives spin up. Be forewarned.
  *
@@ -250,82 +312,82 @@
  *
  *   @return Null-terminated array of null-terminated strings.
  */
-char **PHYSFS_getCdRomPaths(void);
+char **PHYSFS_getCdRomDirs(void);
 
 
 /**
  * Helper function.
  *
- * Get the "base path". This is the directory where the application was run
+ * Get the "base dir". This is the directory where the application was run
  *  from, which is probably the installation directory, and may or may not
  *  be the process's current working directory.
  *
- * You should probably use the base path in your search path.
+ * You should probably use the base dir in your search path.
  *
- *  @return READ ONLY string of base path in platform-dependent notation.
+ *  @return READ ONLY string of base dir in platform-dependent notation.
  */
-const char *PHYSFS_getBasePath(void);
+const char *PHYSFS_getBaseDir(void);
 
 
 /**
  * Helper function.
  *
- * Get the "user path". This is meant to be a suggestion of where a specific
+ * Get the "user dir". This is meant to be a suggestion of where a specific
  *  user of the system can store files. On Unix, this is her home directory.
  *  On systems with no concept of multiple home directories (MacOS, win95),
- *  this will default to something like "C:\mybasepath\users\username"
+ *  this will default to something like "C:\mybasedir\users\username"
  *  where "username" will either be the login name, or "default" if the
  *  platform doesn't support multiple users, either.
  *
- * You should probably use the user path as the basis for your write path, and
+ * You should probably use the user dir as the basis for your write dir, and
  *  also put it near the beginning of your search path.
  *
- *  @return READ ONLY string of user path in platform-dependent notation.
+ *  @return READ ONLY string of user dir in platform-dependent notation.
  */
-const char *PHYSFS_getUserPath(void);
+const char *PHYSFS_getUserDir(void);
 
 
 /**
- * Get the current write path. The default write path is NULL.
+ * Get the current write dir. The default write dir is NULL.
  *
- *  @return READ ONLY string of write path in platform-dependent notation,
+ *  @return READ ONLY string of write dir in platform-dependent notation,
  *           OR NULL IF NO WRITE PATH IS CURRENTLY SET.
  */
-const char *PHYSFS_getWritePath(char *buffer, int bufferSize);
+const char *PHYSFS_getWriteDir(void);
 
 
 /**
- * Set a new write path. This will override the previous setting. If the
+ * Set a new write dir. This will override the previous setting. If the
  *  directory or a parent directory doesn't exist in the physical filesystem,
  *  PhysicsFS will attempt to create them as needed.
  *
- * This call will fail (and fail to change the write path) if the current path
- *  still has files open in it.
+ * This call will fail (and fail to change the write dir) if the current
+ *  write dir still has files open in it.
  *
- *   @param newPath The new directory to be the root of the write path,
+ *   @param newDir The new directory to be the root of the write dir,
  *                   specified in platform-dependent notation. Setting to NULL
- *                   disables the write path, so no files can be opened for
+ *                   disables the write dir, so no files can be opened for
  *                   writing via PhysicsFS.
  *  @return non-zero on success, zero on failure. All attempts to open a file
  *           for writing via PhysicsFS will fail until this call succeeds.
  *           Specifics of the error can be gleaned from PHYSFS_getLastError().
  *
  */
-int PHYSFS_setWritePath(const char *newPath);
+int PHYSFS_setWriteDir(const char *newDir);
 
 
 /**
  * Add a directory or archive to the search path. If this is a duplicate, the
  *  entry is not added again, even though the function succeeds.
  *
- *   @param newPath directory or archive to add to the path, in
+ *   @param newDir directory or archive to add to the path, in
  *                   platform-dependent notation.
  *   @param appendToPath nonzero to append to search path, zero to prepend.
- *  @return nonzero if added to path, zero on failure (bogus archive, path
+ *  @return nonzero if added to path, zero on failure (bogus archive, dir
  *                   missing, etc). Specifics of the error can be
  *                   gleaned from PHYSFS_getLastError().
  */
-int PHYSFS_addToSearchPath(const char *newPath, int appendToPath);
+int PHYSFS_addToSearchPath(const char *newDir, int appendToPath);
 
 
 /**
@@ -337,11 +399,11 @@
  * This call will fail (and fail to remove from the path) if the element still
  *  has files open in it.
  *
- *    @param oldPath dir/archive to remove.
+ *    @param oldDir dir/archive to remove.
  *   @return nonzero on success, zero on failure.
  *            Specifics of the error can be gleaned from PHYSFS_getLastError().
  */
-int PHYSFS_removeFromSearchPath(const char *oldPath);
+int PHYSFS_removeFromSearchPath(const char *oldDir);
 
 
 /**
@@ -358,7 +420,8 @@
  * When you are done with the returned information, you may dispose of the
  *  resources by calling PHYSFS_freeList() with the returned pointer.
  *
- *   @return Null-terminated array of null-terminated strings.
+ *   @return Null-terminated array of null-terminated strings. NULL if there
+ *            was a problem (read: OUT OF MEMORY).
  */
 char **PHYSFS_getSearchPath(void);
 
@@ -366,8 +429,8 @@
 /**
  * Helper function.
  *
- * Set up sane, default paths. The write path will be set to
- *  "userpath/.appName", which is created if it doesn't exist.
+ * Set up sane, default paths. The write dir will be set to
+ *  "userdir/.appName", which is created if it doesn't exist.
  *
  * The above is sufficient to make sure your program's configuration directory
  *  is separated from other clutter, and platform-independent. The period
@@ -375,12 +438,12 @@
  *
  *  The search path will be:
  *
- *    - The Write Path (created if it doesn't exist)
- *    - The Write Path/appName (created if it doesn't exist)
- *    - The Base Path (PHYSFS_getBasePath())
- *    - The Base Path/appName (if it exists)
- *    - All found CD-ROM paths (optionally)
- *    - All found CD-ROM paths/appName (optionally, and if they exist)
+ *    - The Write Dir (created if it doesn't exist)
+ *    - The Write Dir/appName (created if it doesn't exist)
+ *    - The Base Dir (PHYSFS_getBaseDir())
+ *    - The Base Dir/appName (if it exists)
+ *    - All found CD-ROM dirs (optionally)
+ *    - All found CD-ROM dirs/appName (optionally, and if they exist)
  *
  * These directories are then searched for files ending with the extension
  *  (archiveExt), which, if they are valid and supported archives, will also
@@ -412,23 +475,23 @@
  *    @param archivesFirst Non-zero to prepend the archives to the search path.
  *                          Zero to append them. Ignored if !(archiveExt).
  */
-void PHYSFS_setSanePaths(const char *appName, const char *archiveExt,
-                         int includeCdRoms, int archivesFirst);
+void PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
+                          int includeCdRoms, int archivesFirst);
 
 
 /**
  * Create a directory. This is specified in platform-independent notation in
- *  relation to the write path. All missing parent directories are also
+ *  relation to the write dir. All missing parent directories are also
  *  created if they don't exist.
  *
- * So if you've got the write path set to "C:\mygame\writepath" and call
+ * So if you've got the write dir set to "C:\mygame\writedir" and call
  *  PHYSFS_mkdir("downloads/maps") then the directories
- *  "C:\mygame\writepath\downloads" and "C:\mygame\writepath\downloads\maps"
+ *  "C:\mygame\writedir\downloads" and "C:\mygame\writedir\downloads\maps"
  *  will be created if possible. If the creation of "maps" fails after we
  *  have successfully created "downloads", then the function leaves the
  *  created directory behind and reports failure.
  *
- *   @param dirname New path to create.
+ *   @param dirname New dir to create.
  *  @return nonzero on success, zero on error. Specifics of the error can be
  *          gleaned from PHYSFS_getLastError().
  */
@@ -437,13 +500,13 @@
 
 /**
  * Delete a file or directory. This is specified in platform-independent
- *  notation in relation to the write path.
+ *  notation in relation to the write dir.
  *
  * A directory must be empty before this call can delete it.
  *
- * So if you've got the write path set to "C:\mygame\writepath" and call
+ * So if you've got the write dir set to "C:\mygame\writedir" and call
  *  PHYSFS_delete("downloads/maps/level1.map") then the file
- *  "C:\mygame\writepath\downloads\maps\level1.map" is removed from the
+ *  "C:\mygame\writedir\downloads\maps\level1.map" is removed from the
  *  physical filesystem, if it exists and the operating system permits the
  *  deletion.
  *
@@ -500,15 +563,15 @@
  *    @return READ ONLY string of element of search path containing the
  *             the file in question. NULL if not found.
  */
-const char *PHYSFS_getRealPath(const char *filename);
+const char *PHYSFS_getRealDir(const char *filename);
 
 
 
 /**
  * Get a file listing of a search path's directory. Matching directories are
- *  interpolated. That is, if "C:\mypath" is in the search path and contains a
+ *  interpolated. That is, if "C:\mydir" is in the search path and contains a
  *  directory "savegames" that contains "x.sav", "y.sav", and "z.sav", and
- *  there is also a "C:\userpath" in the search path that has a "savegames"
+ *  there is also a "C:\userdir" in the search path that has a "savegames"
  *  subdirectory with "w.sav", then the following code:
  *
  * ------------------------------------------------
@@ -530,18 +593,21 @@
  * We've got [w.sav].
  * ------------------------------------------------
  *
+ * Feel free to sort the list however you like. We only promise there will
+ *  be no duplicates, but not what order the final list will come back in.
+ *
  * Don't forget to call PHYSFS_freeList() with the return value from this
  *  function when you are done with it.
  *
- *    @param path directory in platform-independent notation to enumerate.
+ *    @param dir directory in platform-independent notation to enumerate.
  *   @return Null-terminated array of null-terminated strings.
  */
-char **PHYSFS_enumerateFiles(const char *path);
+char **PHYSFS_enumerateFiles(const char *dir);
 
 
 /**
  * Open a file for writing, in platform-independent notation and in relation
- *  to the write path as the root of the writable filesystem. The specified
+ *  to the write dir as the root of the writable filesystem. The specified
  *  file is created if it doesn't exist. If it does exist, it is truncated to
  *  zero bytes, and the writing offset is set to the start.
  *
@@ -554,7 +620,7 @@
 
 /**
  * Open a file for writing, in platform-independent notation and in relation
- *  to the write path as the root of the writable filesystem. The specified
+ *  to the write dir as the root of the writable filesystem. The specified
  *  file is created if it doesn't exist. If it does exist, the writing offset
  *  is set to the end of the file, so the first write will be the byte after
  *  the end.