/**
 * @file libcomprex/directory.h Directory structures
 * 
 * $Id: directory.h,v 1.19 2003/01/01 06:22:35 chipx86 Exp $
 *
 * @Copyright (C) 2001-2003 The GNUpdate Project.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */
#ifndef _LIBCOMPREX_DIRECTORY_H_
#define _LIBCOMPREX_DIRECTORY_H_

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _CxFsNode        CxDirectory;     /**< CxDirectory */
typedef struct _CxDirectoryData CxDirectoryData; /**< Directory data. */

#include <libcomprex/fsnode.h>
#include <libcomprex/file.h>

/**
 * The data specific to a directory node.
 */
struct _CxDirectoryData
{
	char *physPath;           /**< Physical path to the directory */
	
	CxFsNode *children;       /**< First child node.              */
	CxFsNode *lastChild;      /**< Last child node.               */

	unsigned int subdirCount; /**< Number of subdirectories.      */
	unsigned int fileCount;   /**< Number of files.               */
};

/**************************************************************************/
/** @name Structure (De)allocation Functions                              */
/**************************************************************************/
/*@{*/

/**
 * Creates a new CxDirectory structure.
 *
 * This does NOT create a new directory. For that, use cxMkDir().
 *
 * @return A new, empty CxDirectory structure.
 *
 * @see cxDestroyDirectory()
 */
CxDirectory *cxNewDirectory(void);

/**
 * Destroys a CxDirectory structure.
 *
 * @param dir The CxDirectory to destroy.
 *
 * @see cxNewDirectory()
 */
void cxDestroyDirectory(CxDirectory *dir);

/*@}*/

/**************************************************************************/
/** @name Attribute Modification Functions                                */
/**************************************************************************/
/*@{*/

/**
 * Sets the archive that owns the directory.
 *
 * This should only be used by libcomprex.
 *
 * @param dir     The directory.
 * @param archive The archive that owns this directory.
 *
 * @see cxGetDirArchive()
 */
void cxSetDirArchive(CxDirectory *dir, CxArchive *archive);

/**
 * Sets the specified directory's parent directory.
 *
 * @param dir    The directory.
 * @param parent The parent directory.
 *
 * @see cxGetDirParent()
 */
void cxSetDirParent(CxDirectory *dir, CxDirectory *parent);

/**
 * Sets the base directory name of this directory.
 *
 * @param dir  The directory.
 * @param name The base directory name.
 *
 * @see cxGetDirName()
 */
void cxSetDirName(CxDirectory *dir, const char *name);

/**
 * Sets the full physical path to the directory.
 *
 * @param dir  The directory.
 * @param path The physical path to the directory.
 *
 * @see cxSetDirPath()
 * @see cxGetDirPhysicalPath()
 * @see cxGetDirPath()
 */
void cxSetDirPhysicalPath(CxDirectory *dir, const char *path);

/**
 * Sets the mode of the specified directory.
 *
 * @param dir  The directory.
 * @param mode The mode to be set.
 *
 * @see cxGetDirMode()
 */
void cxSetDirMode(CxDirectory *dir, mode_t mode);

/**
 * Sets the group ID of the specified directory.
 *
 * @param dir  The directory.
 * @param gid  The group ID.
 *
 * @see cxGetFileGid()
 */
void cxSetDirGid(CxDirectory *dir, gid_t gid);

/**
 * Sets the user ID of the specified directory.
 *
 * @param dir  The directory.
 * @param uid  The user ID.
 *
 * @see cxGetDirUid()
 */
void cxSetDirUid(CxDirectory *dir, uid_t uid);

/**
 * Set the timestamp of the specified directory.
 *
 * @param dir  The directory.
 * @param date The date/time timestamp in seconds since the epoch.
 *
 * @see cxGetDirDate()
 */
void cxSetDirDate(CxDirectory *dir, time_t date);

/**
 * Sets whether or not the file is stored locally.
 *
 * If the directory is located online, or within an archive, this should be 0.
 * Otherwise, this should be 1.
 *
 * @param dir     The directory.
 * @param isLocal 1 if the file is stored locally; 0 otherwise.
 *
 * @see cxIsDirLocal()
 */
void cxSetDirLocal(CxDirectory *dir, char isLocal);

/*@}*/

/**************************************************************************/
/** @name Attribute Retrieval Functions                                   */
/**************************************************************************/
/*@{*/

/**
 * Returns the archive that owns the specified directory.
 *
 * @param dir The directory.
 *
 * @return The archive that owns this directory.
 *
 * @see cxSetDirArchive()
 */
CxArchive *cxGetDirArchive(CxDirectory *dir);

/**
 * Returns the specified directory's parent directory.
 *
 * @param dir The directory.
 *
 * @return The specified directory's parent directory.
 *
 * @see cxSetDirParent()
 */
CxDirectory *cxGetDirParent(CxDirectory *dir);

/**
 * Returns the base directory name of the specified directory.
 *
 * @param dir The directory.
 *
 * @return The base directory name of the specified directory.
 *
 * @see cxSetDirName()
 */
const char *cxGetDirName(CxDirectory *dir);

/**
 * Returns the full path name of the specified directory.
 *
 * @param dir The directory.
 *
 * @return The full path name.
 *
 * @see cxSetDirPath()
 */
const char *cxGetDirPath(CxDirectory *dir);

/**
 * Returns the number of files in the specified directory.
 *
 * @param dir The directory.
 *
 * @return The number of files in the specified directory.
 *
 * @see cxGetSubDirCount()
 */
unsigned int cxGetFileCount(CxDirectory *dir);

/**
 * Returns the full physical path to the directory.
 *
 * If the directory is non-local, this will be a temporary directory.
 *
 * @param dir The directory.
 *
 * @return The physical path to the directory.
 *
 * @see cxSetDirPhysicalPath()
 * @see cxGetDirPath()
 * @see cxSetDirPath()
 */
const char *cxGetDirPhysicalPath(CxDirectory *dir);

/**
 * Return the mode of the specified directory.
 *
 * @param dir  The directory.
 *
 * @return The directory's mode.
 *
 * @see cxSetDirMode()
 */
mode_t cxGetDirMode(CxDirectory *dir);

/**
 * Returns the user ID of the specified directory.
 *
 * @param dir  The directory.
 *
 * @return The user ID of the specified directory.
 *
 * @see cxSetDirUid()
 */
uid_t cxGetDirUid(CxDirectory *dir);

/**
 * Returns the group ID of the specified directory.
 *
 * @param dir The directory.
 *
 * @returns The group ID of the specified directory.
 *
 * @see cxSetDirGid()
 */
gid_t cxGetDirGid(CxDirectory *dir);

/**
 * Returns the timestamp of the specified directory.
 *
 * @param dir The directory.
 *
 * @return The date/time timestamp in seconds since the epoch.
 *
 * @see cxSetDirDate(CxDirectory *dir)
 */
time_t cxGetDirDate(CxDirectory *dir);

/**
 * Returns whether or not the directory is stored locally
 *
 * If the directory is located online, or within an archive, this will be 0.
 * Otherwise, this will be 1.
 *
 * @param dir The directory.
 *
 * @return 1 if the file is stored locally; 0 otherwise.
 * 
 * @see cxSetDirLocal()
 */
char cxIsDirLocal(CxDirectory *dir);

/**
 * Returns the number of subdirectories in the specified directory.
 *
 * @param dir The directory.
 *
 * @return The number of subdirectories in the specified directory.
 *
 * @see cxGetFileCount()
 */
unsigned int cxGetSubDirCount(CxDirectory *dir);

/*@}*/

/**************************************************************************/
/** @name Directory Processing Functions                                  */
/**************************************************************************/
/*@{*/

/**
 * Returns the subdirectory specified in the path.
 *
 * @param base The base directory.
 * @param path The path.
 *
 * @return The subdirectory, or @c NULL if not found.
 *
 * @see cxGetFile()
 */
CxDirectory *cxGetDirectory(CxDirectory *base, const char *path);

/**
 * Returns the file specified in the path.
 *
 * @param base The base directory.
 * @param path The path.
 *
 * @return The file, or @c NULL if not found.
 *
 * @see cxGetDirectory()
 */
CxFile *cxGetFile(CxDirectory *base, const char *path);

/*@}*/

/**************************************************************************/
/** @name Directory Modification Functions                                */
/**************************************************************************/
/*@{*/

/**
 * Creates a directory.
 *
 * This is equivalent to mkdir -p. That is, it will create each directory
 * in the path if they don't exist.
 * 
 * @param base The base directory.
 * @param path The path of directories to create.
 *
 * @return The inner-most subdirectory.
 */
CxDirectory *cxMkDir(CxDirectory *base, const char *path);

/**
 * Adds a file to the directory.
 *
 * Note that this won't actually create a file in that directory.
 * This just modifies the structure itself!
 *
 * The directory will claim the reference on @a file, and will delete
 * the structure when @a dir is deleted. If you wish to keep @a file
 * intact, you must claim a reference to it using CX_LINK().
 *
 * @param dir  The directory.
 * @param file The file to add.
 *
 * @see CxFile
 * @see cxDirAddSubDir()
 * @see cxDirRemoveFile()
 * @see cxDirRemoveSubDir()
 */
void cxDirAddFile(CxDirectory *dir, CxFile *file);

/**
 * Adds a subdirectory to a directory.
 *
 * Note that this won't actually create a subdirectory in that directory.
 * This just modifies the structure itself!
 *
 * The directory will claim the reference on @a subdir, and will delete
 * the structure when @a dir is deleted. If you wish to keep @a subdir
 * intact, you must claim a reference to it using CX_LINK().
 *
 * @param dir    The directory.
 * @param subdir The subdirectory to add.
 *
 * @see CxDirectory
 * @see cxDirAddFile()
 * @see cxDirRemoveFile()
 * @see cxDirRemoveSubDir()
 */
void cxDirAddSubDir(CxDirectory *dir, CxDirectory *subdir);

/**
 * Removes a file from the directory.
 *
 * Note that this won't actually remove the file from the archive.
 * This just modifies the structure itself!
 *
 * @param dir  The directory.
 * @param file The file to remove.
 *
 * @see CxFile
 * @see cxDirAddFile()
 * @see cxDirAddSubDir()
 * @see cxDirRemoveSubDir()
 */
void cxDirRemoveFile(CxDirectory *dir, CxFile *file);

/**
 * Removes a subdirectory from the directory.
 *
 * Note that this won't actually remove the subdirectory from the archive.
 * This just modifies the structure itself!
 *
 * @param dir    The directory.
 * @param subdir The subdirectory to remove.
 *
 * @see CxFile
 * @see cxDirAddFile()
 * @see cxDirAddSubDir()
 * @see cxDirRemoveFile()
 */
void cxDirRemoveSubDir(CxDirectory *dir, CxDirectory *subdir);

/*@}*/

/**************************************************************************/
/** @name Iteration Functions                                             */
/**************************************************************************/
/*@{*/

/**
 * Returns the first file in the directory.
 *
 * @param dir The directory.
 *
 * @return The first file in the directory.
 *
 * @see cxGetFirstSubDir()
 * @see cxGetNextFile()
 * @see cxGetPreviousFile()
 */
CxFile *cxGetFirstFile(CxDirectory *dir);

/**
 * Returns the first subdirectory in the directory.
 *
 * @param dir The directory.
 *
 * @return The first subdirectory in the directory.
 *
 * @see cxGetFirstFile()
 * @see cxGetNextDir()
 * @see cxGetPreviousDir()
 */
CxDirectory *cxGetFirstSubDir(CxDirectory *dir);

/**
 * Returns the previous directory in a list of directories.
 *
 * @param dir The current directory.
 *
 * @return The previous directory in the list.
 *
 * @see cxGetFirstSubDir()
 * @see cxGetNextDir()
 */
CxDirectory *cxGetPreviousDir(CxDirectory *dir);

/**
 * Returns the next directory in a list of directories.
 *
 * @param dir The current directory.
 *
 * @return The next directory in the list.
 *
 * @see cxGetFirstSubDir()
 * @see cxGetPreviousDir()
 */
CxDirectory *cxGetNextDir(CxDirectory *dir);

/*@}*/

#ifdef __cplusplus
}
#endif

#endif /* _LIBCOMPREX_DIRECTORY_H_ */

