/*
 * This file contains functions related to the reading of SUSP and
 * Rock Ridge extensions on an ECMA-119 image.
 */

#ifndef ECMA119_READ_RR_H_
#define ECMA119_READ_RR_H_

#include "libisofs.h"
#include "ecma119.h"
#include "ecma119_read.h"

#define SUSP_SIG(entry, a, b) ( (entry->sig[0] == a) && (entry->sig[1] == b) )

/**
 * The SUSP iterator is used to iterate over the System User Entries
 * of a ECMA-168 directory record.
 * It takes care about Continuation Areas, handles the end of the different
 * system user entries and skip padding areas. Thus, using an iteration
 * we are accessing just to the meaning entries.
 */
struct susp_iterator;

struct susp_iterator *susp_iter_new(struct iso_read_info *info, 
                                    struct ecma119_dir_record *record);

/**
 * Get the next SUSP System User Entry using given iterator.
 * The returned pointer refers directly to an internal buffer and it's not
 * guaranteed to be allocated after calling susp_iter_next() again. Thus,
 * if you need to keep some entry you have to do a copy.
 * 
 * It return NULL when no more entries are available. Also, it will return
 * NULL on error. You must check info->error to distinguish between both
 * situations.
 */
struct susp_sys_user_entry *susp_iter_next(struct susp_iterator* iter);

/**
 * Free a given susp iterator.
 */
void susp_iter_free(struct susp_iterator* iter);

struct susp_CE {
	uint8_t block[8];
	uint8_t offset[8];
	uint8_t len[8];
};

struct susp_SP {
	uint8_t be[1];
	uint8_t ef[1];
	uint8_t len_skp[1];
};

struct susp_ER {
	uint8_t len_id[1];
	uint8_t len_des[1];
	uint8_t len_src[1];
	uint8_t ext_ver[1];
	uint8_t ext_id[1]; /*< up to len_id bytes */
	/* ext_des, ext_src */
};

/** POSIX file attributes. */
struct rr_PX {
	uint8_t mode[8];
	uint8_t links[8];
	uint8_t uid[8];
	uint8_t gid[8];
	uint8_t serial[8];
};

/** Time stamps for a file. */
struct rr_TF {
	uint8_t flags[1];
	uint8_t t_stamps[1];
};

/** Alternate name. */
struct rr_NM {
	uint8_t flags[1];
	uint8_t name[1];
};

/** Link for a relocated directory. */
struct rr_CL {
	uint8_t child_loc[8];
};

/** Sim link. */
struct rr_SL {
	uint8_t flags[1];
	uint8_t comps[1];
};

/**
 * Struct for a SUSP System User Entry
 */
struct susp_sys_user_entry
{
	uint8_t sig[2];
	uint8_t len_sue[1];
	uint8_t version[1];
	union {
		struct susp_CE CE;
		struct susp_SP SP;
		struct susp_ER ER;
		struct rr_PX PX;
		struct rr_TF TF;
		struct rr_NM NM;
		struct rr_CL CL;
		struct rr_SL SL;
	} data; /* 5 to 4+len_sue */
};

/**
 * Fills a struct stat with the values of a Rock Ridge PX entry
 * On error, info->error is set propertly and the function returns != 0
 */
int read_rr_PX(struct iso_read_info *info, struct susp_sys_user_entry *px, 
               struct stat *st);
               
/**
 * Fills a struct stat with the values of a Rock Ridge TF entry
 * On error, info->error is set propertly and the function returns != 0
 */
int read_rr_TF(struct iso_read_info *info, struct susp_sys_user_entry *tf, 
               struct stat *st);
               
/**
 * Apends the content of given Rock Ridge NM entry to \p name
 * On error, returns NULL
 */
char *read_rr_NM(struct susp_sys_user_entry *nm, char *name);
               
/**
 * Apends the components in specified SL entry to \p dest, adding
 * needed '/'.
 * On error, returns NULL
 */
char *read_rr_SL(struct susp_sys_user_entry *sl, char *dest);

#endif /*ECMA119_READ_RR_H_*/