/*
 * stat.h - SAM-FS file information definitions.
 *
 * Defines the SAM-FS file information structure and functions.
 * The POSIX stat structure and associated macros are used to allow
 * the sam_stat structure to be used on various client machine
 * architectures.
 *
 */

/*
 *    SAM-QFS_notice_begin
 *
 *      Solaris 2.x Sun Storage & Archiving Management File System
 *
 *		Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
 *
 *		U.S. Government Rights - Commercial software. Government users are
 *	subject to the Sun Microsystems, Inc. standard license agreement and applicable
 *	provisions of the FAR and its supplements.
 *
 *      	Use is subject to license terms. Sun, Sun Microsystems and the Sun logo
 *	are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S.
 *	and other countries.
 *
 *    SAM-QFS_notice_end
 */

/*
 *	LGPL NOTICE
 *
 *	This library is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation; either
 *	version 2.1 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
 *	Lesser General Public License for more details.
 *
 *	You should have received a copy of the GNU Lesser General Public
 *	License along with this library; if not, write to the Free Software
 *	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

/*
 * $Revision$
 */

#ifdef sun
#pragma ident "$Revision$"
#endif


#ifndef	SAM_STAT_H
#define	SAM_STAT_H

#ifdef linux
#include <sam/linux_types.h>	/* u_longlong_t */
#endif /* linux */

#ifdef  __cplusplus
extern "C" {
#endif

#define	MAX_ARCHIVE		4
#define	SAM_MIN_SEGMENT_SIZE	(1024*1024) 	/* Minimum segment size in bytes */

/*
 * If sam/stat.h and sys/stat.h are needed in the same module, then
 * sys/stat.h must be included before sam/stat.h.
 * The following is provided to avoid compilation errors:
 */
#if defined(_SYS_STAT_H) || defined(_LINUX_STAT_H)
#undef st_atime
#undef st_mtime
#undef st_ctime
#undef S_ISBLK
#undef S_ISCHR
#undef S_ISDIR
#undef S_ISFIFO
#undef S_ISGID
#undef S_ISREG
#undef S_ISUID
#undef S_ISLNK
#undef S_ISSOCK

#ifdef	linux
#undef S_IRWXU
#undef S_IRUSR
#undef S_IWUSR
#undef S_IXUSR
#undef S_IRWXG
#undef S_IRGRP
#undef S_IWGRP
#undef S_IXGRP
#undef S_IRWXO
#undef S_IROTH
#undef S_IWOTH
#undef S_IXOTH
#endif	/* linux */

#endif /* defined(_SYS_STAT_H) */

/*
 *	NOTE that in order to pass the following structures from a 64-bit
 *	kernel to a 32-bit application, we need to conditionally define the
 *	positions of the 32-bit time and the pad differently for SPARC and X86.
 */

/*
 * Begin: 32-bit align copyin() structs for amd64 only due to 32-bit x86 ABI
 */
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack(4)
#endif

#if defined(__sparcv9) || defined(__amd64) || defined(linux)

struct sam_copy_s {					/* For each archive copy. */
	u_longlong_t 	position;			/* Location of archive file */
	time_t		creation_time;			/* Time archive copy created */
	uint_t		offset;				/* Location of copy in archive file - */
							/* in units of 512 bytes */
	ushort_t	flags;
	short		n_vsns;				/* Number of VSNs the archive used */
	char		media[4];			/* Media type */
	char		vsn[32];			/* VSN */
};

struct sam_stat {
	/* POSIX stat structure. */
	uint_t		st_mode;			/* File mode */
	uint_t		st_ino;				/* File serial number */
#ifdef  sun
	dev_t		st_dev;				/* ID of the device containing the file */
#endif  /* sun */
#ifdef  linux
	ushort_t	st_dev;				/* ID of the device containing the file */
#endif  /* linux */
	uint_t		st_nlink;			/* Number of links */
	uint_t		st_uid;				/* User ID of the file's owner */
	uint_t		st_gid;				/* Group ID of the file's owner */
	u_longlong_t 	st_size;			/* The file size in bytes */
	time_t 		st_atime;			/* Time of last access */
	time_t 		st_mtime;			/* Time of last data modification */
	time_t 		st_ctime;			/* Time of last file status change */

	/* SAM-FS information. */
	time_t 		attribute_time;			/* Time attributes last changed */
	time_t 		creation_time;			/* Time inode created */
	time_t 		residence_time;			/* Time file changed residence */
	struct 		sam_copy_s copy[MAX_ARCHIVE];
	uint_t		attr;				/* File attributes */
	uchar_t		cs_algo;			/* Checksum algorithm indicator */
	uchar_t		flags;				/* Flags:  staging, stage err, etc. */
	uchar_t		stripe_width;			/* Stripe width set by setfa -s */
	uchar_t		stripe_group;			/* Stripe group set by setfa -g */
	uint_t 		gen;				/* File generation number */
	uint_t 		partial_size;			/* Partial size in kilobytes */
#ifdef	sun
	dev_t		rdev;				/* ID of device if S_IFBLK or S_IFCHR */
#endif 	/* sun */
#ifdef linux
	ushort_t	rdev;				/* ID of device if S_IFBLK or S_IFCHR */
#endif /* linux */
	u_longlong_t 	st_blocks;			/* Block count in units of 512 byte blocks */
	uint_t 		segment_size;			/* Segment size in megabytes (SS_SEGMENT_A) */
	uint_t 		segment_number;			/* Number of this segment */
							/* 0 - SS_SEGMENT_F, 1 .. n - SS_SEGMENT_S */
	uint_t 		stage_ahead;			/* Number of segments to stage ahead */
	uint_t 		admin_id;			/* admin ID; inherited from dir */
	uint_t 		allocahead;			/* Allocate ahead size set by setfa -A */
	uint_t 		pad9;
	u_longlong_t 	cs_val[2];			/* 128 bit checksum */
};

#else   /* __sparcv9 || __amd64 || linux */

struct sam_copy_s {					/* For each archive copy. */
	u_longlong_t 	position;			/* Location of archive file */
#if 	defined(__i386)
	time_t		creation_time;			/* Time archive copy created */
	ulong_t		pad0;
#else
	ulong_t		pad0;
	time_t		creation_time;			/* Time archive copy created */
#endif	/* __i386 */
	ulong_t		offset;				/* Location of copy in archive file - */
							/*	in units of 512 bytes */
	ushort_t 	flags;
	short		n_vsns;				/* Number of VSNs the archive used */
	char		media[4];			/* Media type */
	char		vsn[32];			/* VSN */
};

struct sam_stat {
	/* POSIX stat structure. */
	ulong_t		st_mode;			/* File mode */
	ulong_t		st_ino;				/* File serial number */
	dev_t		st_dev;				/* ID of the device containing the file */
	long		pad1;
	ulong_t		st_nlink;			/* Number of links */
	ulong_t		st_uid;				/* User ID of the file's owner */
	ulong_t		st_gid;				/* Group ID of the file's owner */
	u_longlong_t 	st_size;			/* The file size in bytes */
#if 	defined(__i386)
	time_t		st_atime;			/* Time of last access */
	ulong_t		pad2;
	time_t		st_mtime;			/* Time of last data modification */
	ulong_t		pad3;
	time_t		st_ctime;			/* Time of last file status change */
	ulong_t		pad4;

	/* SAM-FS information. */
	time_t		attribute_time;			/* Time attributes last changed */
	ulong_t		pad5;
	time_t		creation_time;			/* Time inode created */
	ulong_t		pad6;
	time_t		residence_time;			/* Time file changed residence */
	ulong_t		pad7;
#else	/* __i386 */
	ulong_t		pad2;
	time_t		st_atime;			/* Time of last access */
	ulong_t		pad3;
	time_t		st_mtime;			/* Time of last data modification */
	ulong_t		pad4;
	time_t		st_ctime;			/* Time of last file status change */

	/* SAM-FS information. */
	ulong_t		pad5;
	time_t		attribute_time;			/* Time attributes last changed */
	ulong_t		pad6;
	time_t		creation_time;			/* Time inode created */
	ulong_t		pad7;
	time_t		residence_time;			/* Time file changed residence */
#endif	/* __i386 */
	struct		sam_copy_s copy[MAX_ARCHIVE];
	uint_t		attr;				/* File attributes */
	uchar_t 	cs_algo;			/* Checksum algorithm indicator */
	uchar_t		flags;				/* Flags:  staging, stage err, etc. */
	uchar_t		stripe_width;			/* Stripe width set by setfa -s */
	uchar_t		stripe_group;			/* Stripe group set by setfa -g */
	ulong_t		gen;				/* File generation number */
	ulong_t		partial_size;			/* Partial size in kilobytes */
	dev_t		rdev;				/* ID of device if S_IFBLK or S_IFCHR */
	ulong_t		pad8;
	u_longlong_t 	st_blocks;			/* Block count in units of 512 byte blocks */
	ulong_t 	segment_size;			/* Segment size in megabytes (SS_SEGMENT_A) */
	ulong_t 	segment_number;			/* Number of this segment */
							/* 0 - SS_SEGMENT_F, 1 .. n - SS_SEGMENT_S */
	uint_t 		stage_ahead;			/* Number of segments to stage ahead */
	ulong_t 	admin_id;			/* admin ID; inherited from dir */
	ulong_t 	allocahead;			/* Allocate ahead size set by setfa -A */
	ulong_t 	pad9;
	u_longlong_t 	cs_val[2];			/* 128 bit checksum */
};

#endif   /* __sparcv9 || __amd64 || linux */


#define	SAM_SECTION_SIZE(n) (sizeof (struct sam_section) * n)

struct sam_section {					/* For each archive copy volume section */
	char		vsn[32];			/* VSN */
	u_longlong_t 	length;				/* Section length of file on this volume */
	u_longlong_t 	position;			/* Position of archive file for this section */
	u_longlong_t 	offset;				/* Location of copy section in archive file */
};

/*
 * End: 32-bit align copyin() structs for amd64 only due to 32-bit x86 ABI
 */
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack()
#endif

/*
 * POSIX symbols.
 */

#define	S_IRWXU 	00700				/* read, write, execute: owner */
#define	S_IRUSR 	00400				/* read permission: owner */
#define	S_IWUSR 	00200				/* write permission: owner */
#define	S_IXUSR 	00100				/* execute permission: owner */
#define	S_IRWXG 	00070				/* read, write, execute: group */
#define	S_IRGRP 	00040				/* read permission: group */
#define	S_IWGRP 	00020				/* write permission: group */
#define	S_IXGRP 	00010				/* execute permission: group */
#define	S_IRWXO 	00007				/* read, write, execute: other */
#define	S_IROTH 	00004				/* read permission: other */

#define	S_IWOTH 	00002				/* write permission: other */
#define	S_IXOTH 	00001				/* execute permission: other */

#define	S_ISBLK(mode)  	(((mode)&0xf000) == 0x6000)
#define	S_ISCHR(mode)  	(((mode)&0xf000) == 0x2000)
#define	S_ISDIR(mode)  	(((mode)&0xf000) == 0x4000)
#define	S_ISFIFO(mode) 	(((mode)&0xf000) == 0x1000)
#define	S_ISGID(mode)  	((mode)&0x400)   		/* set group id on execution */
#define	S_ISREG(mode)  	(((mode)&0xf000) == 0x8000)
#define	S_ISUID(mode)  	((mode)&0x800)   		/* set user id on execution */
#define	S_ISLNK(mode)  	(((mode)&0xf000) == 0xa000)
#define	S_ISSOCK(mode) 	(((mode)&0xf000) == 0xc000)

/*
 * SAMFS attributes mapped into sam_stat but not in inode (ino_status_t).
 */
#define	SS_SAMFS	0x00000800			/* SAM-FS file */
#define	SS_ARCHIVE_R 	0x00002000			/* Re-archive */
#define	SS_ARCHIVED  	0x00010000			/* File has at least one archive copy */
#define	SS_DATA_V	0x00040000 			/* File requires data verification */
#define	SS_AIO		0x00080000 			/* AIO Char Device file */
#define	SS_ARCHIVE_A 	0x08000000			/* Archive immediate */

/*
 * SAMFS attributes from the inode.
 */
#define	SS_REMEDIA   	0x00000001			/* Removable media file */
#define	SS_RELEASE_A 	0x00000002			/* Release after archive */
#define	SS_RELEASE_N 	0x00000004			/* Release never (nodrop) */
#define	SS_STAGE_N   	0x00000008			/* Stage never (direct) */

#define	SS_DAMAGED   	0x00000010			/* File is damaged - not online and no copy */
#define	SS_RELEASE_P 	0x00000020			/* Release partial (bof_online) */
#define	SS_ARCHIVE_N 	0x00000040			/* Archive never (noarch) */
#define	SS_STAGE_A	0x00000080			/* Stage associative (stageall) */

#define	SS_CSVAL	0x00000100			/* Valid checksum exists in inode */
#define	SS_CSUSE	0x00000200			/* Checksum will be used upon stage */
#define	SS_CSGEN	0x00000400			/* Checksum will be generated upon archive */
/*	SS_SAMFS	0x00000800			used by sam_stat() - see above */

#define	SS_ARCHDONE  	0x00001000			/* File has all required archiving done */
/*	SS_ARCHIVE_R    0x00002000    			used by sam_stat() - see above */
#define	SS_PARTIAL   	0x00004000			/* Partial extents are online */
#define	SS_OFFLINE   	0x00008000			/* File is offline */

/*	SS_ARCHIVED   	0x00010000    			used by sam_stat() - see above */
#define	SS_SEGMENT_A 	0x00020000			/* Segment attribute */
/*	SS_DATA_V    	0x00040000			   used by sam_stat() - see above */
/*	SS_AIO		0x00080000			used by sam_stat() - see above */

#define	SS_ARCHIVE_C 	0x00100000			/* Archive concurrent */
#define	SS_DIRECTIO  	0x00200000			/* Directio */
#define	SS_ARCHIVE_I 	0x00400000			/* Archive inconsistent copies */
#define	SS_WORM		0x00800000			/* Read only attribute (worm_attr) */

#define	SS_READONLY  	0x01000000			/* Read only file enabled (worm_set) */
#define	SS_SEGMENT_S 	0x02000000			/* This is a segment of a segmented file */
#define	SS_SEGMENT_F 	0x04000000			/* Stage/archive this file in segments */
/*	SS_ARCHIVE_A    0x08000000			used by sam_stat() - see above */

#define	SS_SETFA_S   	0x10000000			/* Stripe width set by setfa -s */
#define	SS_SETFA_G   	0x20000000			/* Stripe group set by setfa -g */

#define	SS_DFACL	0x40000000			/* Default access control list present */
#define	SS_ACL		0x80000000			/* Access control list present */

#define	SS_ISSAMFS(attr)	(((attr)&SS_SAMFS) != 0)
#define	SS_ISREMEDIA(attr)   	(((attr)&SS_REMEDIA) != 0)
#define	SS_ISARCHIVED(attr)  	(((attr)&SS_ARCHIVED) != 0)
#define	SS_ISARCHDONE(attr)  	(((attr)&SS_ARCHDONE) != 0)
#define	SS_ISDAMAGED(attr)   	(((attr)&SS_DAMAGED) != 0)
#define	SS_ISOFFLINE(attr)   	(((attr)&SS_OFFLINE) != 0)
#define	SS_ISPARTIAL(attr)   	(((attr)&SS_PARTIAL) != 0)
#define	SS_ISARCHIVE_C(attr) 	(((attr)&SS_ARCHIVE_C) != 0)
#define	SS_ISARCHIVE_I(attr) 	(((attr)&SS_ARCHIVE_I) != 0)
#define	SS_ISARCHIVE_N(attr) 	(((attr)&SS_ARCHIVE_N) != 0)
#define	SS_ISARCHIVE_A(attr) 	(((attr)&SS_ARCHIVE_A) != 0)
#define	SS_ISARCHIVE_R(attr) 	(((attr)&SS_ARCHIVE_R) != 0)
#define	SS_ISRELEASE_A(attr) 	(((attr)&SS_RELEASE_A) != 0)
#define	SS_ISRELEASE_N(attr) 	(((attr)&SS_RELEASE_N) != 0)
#define	SS_ISRELEASE_P(attr) 	(((attr)&SS_RELEASE_P) != 0)
#define	SS_ISSTAGE_A(attr)   	(((attr)&SS_STAGE_A) != 0)
#define	SS_ISSTAGE_N(attr)   	(((attr)&SS_STAGE_N) != 0)
#define	SS_ISSEGMENT_A(attr) 	(((attr)&SS_SEGMENT_A) != 0)
#define	SS_ISSEGMENT_S(attr) 	(((attr)&SS_SEGMENT_S) != 0)
#define	SS_ISSEGMENT_F(attr) 	(((attr)&SS_SEGMENT_F) != 0)
#define	SS_ISCSGEN(attr)	(((attr)&SS_CSGEN) != 0)
#define	SS_ISCSUSE(attr)	(((attr)&SS_CSUSE) != 0)
#define	SS_ISCSVAL(attr)	(((attr)&SS_CSVAL) != 0)
#define	SS_ISDIRECTIO(attr)  	(((attr)&SS_DIRECTIO) != 0)
#define	SS_ISSTAGE_M(attr)   	(((attr)&SS_STAGE_M) != 0)
#define	SS_ISWORM(attr)		(((attr)&SS_WORM) != 0)
#define	SS_ISREADONLY(attr)  	(((attr)&SS_READONLY) != 0)
#define	SS_ISSETFA_G(attr)   	(((attr)&SS_SETFA_G) != 0)
#define	SS_ISSETFA_S(attr)   	(((attr)&SS_SETFA_S) != 0)
#define	SS_ISDFACL(attr)	(((attr)&SS_DFACL) != 0)
#define	SS_ISACL(attr)		(((attr)&SS_ACL) != 0)
#define	SS_ISDATAV(attr)	(((attr)&SS_DATA_V) != 0)
#define	SS_ISAIO(attr)		(((attr)&SS_AIO) != 0)

/*
 * SAMFS flags.
 */

#define	SS_STAGING		0x01	/* Stage is pending on the file */
#define	SS_STAGEFAIL		0x02	/* Error occurred on last stage attempt */

#define	SS_ISSTAGING(flags)	(((flags)&SS_STAGING) != 0)
#define	SS_ISSTAGEFAIL(flags)	(((flags)&SS_STAGEFAIL) != 0)

/*
 * Copy flag masks.
 */
#define	CF_STALE		0x0001	/* This archive copy is stale */
#define	CF_REARCH		0x0002	/* Copy is to be rearchived */
#define	CF_ARCH_I		0x0004	/* Copy is to be archived immediately */
#define	CF_VERIFIED		0x0008	/* Copy has been verified */
#define	CF_DAMAGED		0x0010	/* This archive copy is damaged */
#define	CF_UNARCHIVED		0x0020	/* This archive copy was unarchived */
#define	CF_INCONSISTENT 	0x0040	/* This archive copy is inconsistent */
#define	CF_ARCHIVED		0x0080	/* This archive copy made */

int sam_stat(const char *path, struct sam_stat *buf, size_t bufsize);
int sam_lstat(const char *path, struct sam_stat *buf, size_t bufsize);
int sam_vsn_stat(const char *path, int copy, struct sam_section *buf,
	size_t bufsize);
int sam_segment_vsn_stat(const char *path, int copy, int segment_index,
	struct sam_section *buf, size_t bufsize);
int sam_segment_stat(const char *path, struct sam_stat *buf,
	size_t bufsize);
int sam_segment_lstat(const char *path, struct sam_stat *buf,
	size_t bufsize);
int sam_restore_file(const char *path, struct sam_stat *buf,
	size_t bufsize);
int sam_restore_copy(const char *path, int copy, struct sam_stat *buf,
	size_t bufsize, struct sam_section *vbuf, size_t vbufsize);

/*
 * macro NUM_SEGS, takes in, fsbuff,  a ptr to a sam_stat struct, returns the
 * number of segments of the file associated with fsbuff.
 */

#define	NUM_SEGS(fsbuff) (int)(((fsbuff) == NULL || (fsbuff)->st_size <= 0 || \
				(fsbuff)->segment_size <= 0 || \
				!SS_ISSEGMENT_F((fsbuff)->attr)) ? 0 : \
				((fsbuff)->st_size + \
				(offset_t)(fsbuff)->segment_size * (SAM_MIN_SEGMENT_SIZE) - 1LL) / \
				((offset_t)(fsbuff)->segment_size * (SAM_MIN_SEGMENT_SIZE)))

#ifdef  __cplusplus
}
#endif

#endif /* SAM_STAT_H */
