/*
			    Endeavour Object
 */

#ifndef EDV_OBJ_H
#define EDV_OBJ_H

#include <sys/types.h>
#include <sys/stat.h>
#include <glib.h>
#include "edv_types.h"


typedef struct _edv_object_struct	edv_object_struct;
#define EDV_OBJECT(p)	((edv_object_struct *)(p))


/*
 *	Link Flags:
 */
typedef enum {
	EDV_OBJECT_LINK_VALID		= (1 << 0),	/* Not dangling */
	EDV_OBJECT_LINK_TAR_DIRECTORY	= (1 << 1),	/* Ultimately links to
							 * a directory */
	EDV_OBJECT_LINK_TAR_GRAND_PARENT = (1 << 2)	/* Target is a grand
							 * parent, hints
							 * infinate recursion */
} edv_object_link_flags;


/*
 *	Object:
 */
struct _edv_object_struct {

	/* Type */
	edv_object_type	type;

	/* Name */
	gchar		*name,
			*full_path;	/* Always an absolute path */

	/* Index Location */
	gulong		device_index,	/* Index of the device that this
					 * object resides on (which device) */

			index;		/* Index on the device that this
					 * object resides at (where on the
					 * device) */

	/* Size */
	gulong		size;		/* In bytes */

	/* Link (for type EDV_OBJECT_TYPE_LINK) */
	gchar		*link_value;
	edv_object_link_flags	link_flags;

	/* Permissions */
	edv_permission_flags	permissions;

	/* Time Stamps */
	gulong		access_time,	/* In systime seconds */
			modify_time,
			change_time;

	/* Ownership */
	gint		owner_id,
			group_id;

	/* Device Type (for type EDV_OBJECT_TYPE_DEVICE_*) */
	gint		device_type;	/* Device major and minor numbers
					 * (used only if object type is
					 * one of EDV_OBJECT_TYPE_DEVICE_*
					 *
					 * Use EDVGetDeviceNumbers() to
					 * parse this value casted as a
					 * (dev_t) */

	/* Misc */
	gulong		block_size;	/* Optimul block transfer size for
					 * reading/writing of this object
					 * (in bytes) */

	gulong		blocks;		/* Blocks allocated to this object */

	gint		hard_links;	/* Number of hard links to this object */

};

#define EDV_OBJECT_IS_FILE(p)		(((p) != NULL) ? \
 ((p)->type == EDV_OBJECT_TYPE_FILE) : FALSE)
#define EDV_OBJECT_IS_DIRECTORY(p)	(((p) != NULL) ? \
 ((p)->type == EDV_OBJECT_TYPE_DIRECTORY) : FALSE)
#define EDV_OBJECT_IS_LINK(p)		(((p) != NULL) ? \
 ((p)->type == EDV_OBJECT_TYPE_LINK) : FALSE)
#define EDV_OBJECT_IS_DEVICE_BLOCK(p)	(((p) != NULL) ? \
 ((p)->type == EDV_OBJECT_TYPE_DEVICE_BLOCK) : FALSE)
#define EDV_OBJECT_IS_DEVICE_CHARACTER(p)	(((p) != NULL) ? \
 ((p)->type == EDV_OBJECT_TYPE_DEVICE_CHARACTER) : FALSE)
#define EDV_OBJECT_IS_FIFO(p)		(((p) != NULL) ? \
 ((p)->type == EDV_OBJECT_TYPE_FIFO) : FALSE)
#define EDV_OBJECT_IS_SOCKET(p)           (((p) != NULL) ? \
 ((p)->type == EDV_OBJECT_TYPE_SOCKET) : FALSE)

#define EDV_OBJECT_IS_LINK_VALID(p)	(((p) != NULL) ? \
 ((p)->link_flags & EDV_OBJECT_LINK_VALID) : FALSE)
#define EDV_OBJECT_IS_LINK_TAR_DIRECTORY(p)	(((p) != NULL) ? \
 ((p)->link_flags & EDV_OBJECT_LINK_TAR_DIRECTORY) : FALSE)      
#define EDV_OBJECT_IS_LINK_TAR_GRAND_PARENT(p)	(((p) != NULL) ? \
 ((p)->link_flags & EDV_OBJECT_LINK_TAR_GRAND_PARENT) : FALSE)


/* Type */
extern edv_object_type EDVObjectGetTypeFromStatMode(const mode_t m);
extern mode_t EDVObjectGetTypeFromEDVType(const edv_object_type type);

/* Type Name */
extern const gchar *EDVObjectGetTypeName(const edv_object_type type);
extern const gchar *EDVObjectGetTypeNameLower(const edv_object_type type);

/* Permissions */
extern edv_permission_flags EDVObjectGetPermissionsFromStatMode(
	const mode_t m
);
extern mode_t EDVObjectGetPermissionsFromEDVPermissions(
	const edv_permission_flags permissions
);

/* Comparing */
extern gboolean EDVObjectCompareIndex(
	edv_object_struct *obj1, edv_object_struct *obj2
);
extern gboolean EDVObjectCompareIndexWithStat(
	edv_object_struct *obj, const struct stat *stat_buf
);

/* Object */
extern edv_object_struct *EDVObjectNew(void);
extern edv_object_struct *EDVObjectCopy(const edv_object_struct *obj);
extern void EDVObjectSetPath(
	edv_object_struct *obj, const gchar *path
);
extern void EDVObjectSetPath2(
	edv_object_struct *obj,
	const gchar *parent, const gchar *name
);
extern void EDVObjectSetStat(
	edv_object_struct *obj, const struct stat *lstat_buf
);
extern void EDVObjectUpdateLinkFlags(edv_object_struct *obj);
extern void EDVObjectDelete(edv_object_struct *obj);


#endif	/* EDV_OBJ_H */
