/* vim: set noet ts=8 sts=8 sw=8 : */

/**
 * \file tree.h
 *
 * Declare the structure of a libisofs filesystem tree. The files in this
 * tree can come from either the local filesystem or from another .iso image
 * (for multisession).
 *
 * This tree preserves as much information as it can about the files; names
 * are stored in UTF-8 and we preserve POSIX attributes. This tree does
 * *not* include information that is necessary for writing out, for example,
 * an ISO level 1 tree. That information will go in a different tree because
 * the structure is sufficiently different.
 */

#ifndef LIBISO_TREE_H
#define LIBISO_TREE_H

#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>

#include "libisofs.h"

/**
 * A node in the filesystem tree.
 */
struct iso_tree_node
{
	/*
	 * Reference counter:
	 * 	- When created, refcount is set to 1
	 *  - One node is automatically free when free the tree (i.e., dir) it 
	 *    belongs, and the tree is automatically freed when the volume it
	 *    belongs is also freed.
	 *  - If the user deon't add the tree to a volume, (s)he has to free the
	 *    tree.
	 *  - If the user doesn't add a node to a tree (dir), for example after
	 *    taken it with iso_tree_node_take(), it should free the node when
	 *    no more needed.
	 *  - If the user wants an own ref, it should call iso_tree_node_ref()
	 *    function to get that ref, and free the node when no more needed.
	 */
	int refcount;
	struct iso_tree_node_dir *parent;
	char *name;
	struct stat attrib;	/**< The POSIX attributes of this node as
				  * documented in "man 2 stat". */
				  
	int hide_flags; /**< If the node is to be hidden in RR/ISO or
	                 *   Joilet tree */
	enum tree_node_from procedence; /**< Procedence of the node. */
	enum iso_tree_node_type type; /**< Type of the node. */
};

/**
 * A node in the filesystem tree that represents a regular file
 */
struct iso_tree_node_file
{
	struct iso_tree_node node;
	
	int sort_weight; /**< It sorts the order in which the file data is
	                  *   written to the CD image. Higher weighting files
	                  *   are written at the beginning of image */
	
	union {
		char *path; /**< the path of the file on local filesystem */
		uint32_t block; /**< If the file is from a previous session.
		                 *   Maybe we can put this in iso_tree_node later. 
		                 */
	} loc;
};

/**
 * A node in the filesystem tree that represents a symbolic link
 */
struct iso_tree_node_symlink
{
	struct iso_tree_node node;
	
	char *dest; /**< Destination of the link */
};

/**
 * A directory on the filesystem tree
 */
struct iso_tree_node_dir
{
	struct iso_tree_node node;

	size_t nchildren;	/**< The number of children of this
				  * directory (if this is a directory). */
	struct iso_tree_node **children;
};

/**
 * Tree node that corresponds to some El-Torito artifact.
 * This can be either the boot catalog or a bootable image.
 */
struct iso_tree_node_boot
{
	struct iso_tree_node node;
	unsigned int img:1; /*< 1 if img, 0 if catalog */
	union {
		char *path; /**< the path of the file on local filesystem */
		uint32_t block; /**< If the file is from a previous session.*/
	} loc;
};

/**
 * An iterator for directory children.
 */
struct iso_tree_iter
{
	struct iso_tree_node_dir *dir;
	int index;
};

/**
 * A function that prints verbose information about a directory.
 *
 * \param dir The directory about which to print information.
 * \param data Unspecified function-dependent data.
 * \param spaces The number of spaces to prepend to the output.
 *
 * \see iso_tree_print_verbose
 */
typedef void (*print_dir_callback) (const struct iso_tree_node *dir,
				    void *data,
				    int spaces);
/**
 * A function that prints verbose information about a file.
 *
 * \param dir The file about which to print information.
 * \param data Unspecified function-dependent data.
 * \param spaces The number of spaces to prepend to the output.
 *
 * \see iso_tree_print_verbose
 */
typedef void (*print_file_callback) (const struct iso_tree_node *file,
				     void *data,
				     int spaces);

/**
 * Recursively print a directory heirarchy. For each node in the directory
 * heirarchy, call a callback function to print information more verbosely.
 *
 * \param root The root of the directory heirarchy to print.
 * \param dir The callback function to call for each directory in the tree.
 * \param file The callback function to call for each file in the tree.
 * \param callback_data The data to pass to the callback functions.
 * \param spaces The number of spaces to prepend to the output.
 *
 * \pre \p root is not NULL.
 * \pre Neither of the callback functions modifies the directory heirarchy.
 */
void iso_tree_print_verbose(const struct iso_tree_node *root,
			    print_dir_callback dir,
			    print_file_callback file,
			    void *callback_data,
			    int spaces);

#define ISO_ISDIR(n) (n->type == LIBISO_NODE_DIR)
#define ISO_ISREG(n) (n->type == LIBISO_NODE_FILE)
#define ISO_ISLNK(n) (n->type == LIBISO_NODE_SYMLINK)
#define ISO_ISBOOT(n) (n->type == LIBISO_NODE_BOOT)

#endif /* LIBISO_TREE_H */