/*
 * (C) Copyright Fuji Xerox Co., Ltd. All rights are reserved.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * 2017/12/15	nobuo.iwata@fujixerox.co.jp
 */

#ifndef __FXLSM_LIST_INTERNAL_H
#define	__FXLSM_LIST_INTERNAL_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include "fxlsm_list.h"
#ifdef FXLSM_LIST_USER
#include "fxlsm_list_user.h"
#else /* FXLSM_LIST_USER */
#include <linux/sched.h>
#endif /* !FXLSM_LIST_USER */

#define FXLSM_LIST_ID_VOID	-1
#define FXLSM_LIST_ID_SEQ	0
#define FXLSM_LIST_ID_SEQ2	1
#define FXLSM_LIST_ID_NSEQ	2
#define FXLSM_LIST_ID_NSEQ2	3
#define FXLSM_LIST_ID_CAPF	4
#define FXLSM_LIST_ID_COMM	5
#define FXLSM_LIST_ID_COMM2	6
#define FXLSM_LIST_ID_CAPC	7
#define FXLSM_LIST_ID_LD	8
#define FXLSM_LIST_ID_LD2	9
#define FXLSM_LIST_NUM		10

#define FXLSM_LIST_GROUP_FILES	0
#define FXLSM_LIST_GROUP_COMMS	1
#define FXLSM_LIST_GROUP_LDS	2

#define FXLSM_LIST_TYPE_SECONDARY	0x1
#define FXLSM_LIST_TYPE_CAPTURE		0x2

#define FXLSM_LIST_BIT_ARRAYS_VALID	0
#define FXLSM_LIST_BIT_IN_CAPTURE	1

#if defined(FXLSM_USE_PROF_TIME) && defined(FXLSM_USE_PROF_MEM)
#define FXLSM_LIST_DEF(s, id, g) \
		.name = s, \
		.group = FXLSM_LIST_GROUP_ ## g, \
		.prof_time_hit = FXLSM_PROF_TIME_ID_ ## id ## _HIT, \
		.prof_time_mis = FXLSM_PROF_TIME_ID_ ## id ## _MIS, \
		.prof_mem_id = FXLSM_PROF_MEM_ID_ ## id
#elif defined(FXLSM_USE_PROF_TIME)
#define FXLSM_LIST_DEF(s, id, g) \
		.name = s, \
		.group = FXLSM_LIST_GROUP_ ## g, \
		.prof_time_hit = FXLSM_PROF_TIME_ID_ ## id ## _HIT, \
		.prof_time_mis = FXLSM_PROF_TIME_ID_ ## id ## _MIS
#elif defined(FXLSM_USE_PROF_MEM)
#define FXLSM_LIST_DEF(s, id, g) \
		.name = s, \
		.group = FXLSM_LIST_GROUP_ ## g, \
		.prof_mem_id = FXLSM_PROF_MEM_ID_ ## id
#else
#define FXLSM_LIST_DEF(s, id, g) \
		.name = s, \
		.group = FXLSM_LIST_GROUP_ ## g
#endif /* !FXLSM_USE_PROF_MEM */

struct fxlsm_list {
	struct list_head list;
	unsigned int num;
	void *arrays;
	const char *name;
	rwlock_t lock;
	unsigned long flags;
	unsigned char group;
	unsigned char type;
	unsigned char only;
#ifdef FXLSM_USE_PROF_TIME
	unsigned char prof_time_hit;
	unsigned char prof_time_mis;
#endif /* FXLSM_USE_PROF_TIME */
#ifdef FXLSM_USE_PROF_MEM
	unsigned char prof_mem_id;
#endif /* FXLSM_USE_PROF_MEM */
};

#ifdef FXLSM_USE_PROF_TIME
#define FXLSM_LIST_GROUP_DEF(s, __ids, __id, cap) \
		.name = s, \
		.ids = __ids, \
		.id = FXLSM_LIST_GROUP_ ## __id, \
		.capture = FXLSM_LIST_ID_ ## cap, \
		.prof_time_hit = FXLSM_PROF_TIME_ID_ ## __id ## _HIT, \
		.prof_time_mis = FXLSM_PROF_TIME_ID_ ## __id ## _MIS
#else /* FXLSM_USE_PROF_TIME */
#define FXLSM_LIST_GROUP_DEF(s, __ids, __id, cap) \
		.name = s, \
		.ids = __ids, \
		.id = FXLSM_LIST_GROUP_ ## __id, \
		.capture = FXLSM_LIST_ID_ ## cap
#endif /* !FXLSM_USE_PROF_TIME */

struct fxlsm_list_group {
	const char *name;
	int *ids;
	int id;
	int capture;
#ifdef FXLSM_USE_PROF_TIME
	unsigned char prof_time_hit;
	unsigned char prof_time_mis;
#endif /* FXLSM_USE_PROF_TIME */
};

struct fxlsm_entry {
	struct list_head node;
	unsigned int nr;
	unsigned char mode_type;
	unsigned char acc;
	unsigned char ns;
	unsigned char flags;
	unsigned int len;
#ifdef FXLSM_USE_PROF_ENTRY
	unsigned int count;
#endif /* FXLSM_USE_PROF_ENTRY */
	char string[0] __attribute__ ((aligned(sizeof(void *))));
};

#define FXLSM_MODE_WHITE	0x40
#define FXLSM_MODE_BLACK	0x80
#define FXLSM_MODE_MASK		0xc0

static inline unsigned char fxlsm_get_mode(struct fxlsm_entry *e)
{
	return e->mode_type & FXLSM_MODE_MASK;
}

static inline int __fxlsm_is_white(unsigned char mode)
{
	return mode != FXLSM_MODE_BLACK;
}

static inline int fxlsm_is_white(struct fxlsm_entry *e)
{
	return __fxlsm_is_white(fxlsm_get_mode(e));
}

#define FXLSM_TYPE_PATH		1
#define FXLSM_TYPE_DPATH	2
#define FXLSM_TYPE_DIR		3
#define FXLSM_TYPE_FILE		4
#define FXLSM_TYPE_SFILE	5
#define FXLSM_TYPE_NS		6
#define FXLSM_TYPE_MASK		0xf

static inline unsigned char fxlsm_get_type(struct fxlsm_entry *e)
{
	return e->mode_type & FXLSM_TYPE_MASK;
}

static inline unsigned int fxlsm_get_len(struct fxlsm_entry *e)
{
	return (fxlsm_get_type(e) == FXLSM_TYPE_DPATH) ? e->len - 1 : e->len;
}

static inline void fxlsm_set_mode_type(struct fxlsm_entry *e,
		unsigned char mode, unsigned char type)
{
	e->mode_type = mode | type;
}

#define FXLSM_NS_NET	0x01
#define FXLSM_NS_UTS	0x02
#define FXLSM_NS_IPC	0x04
#define FXLSM_NS_PID	0x08
#define FXLSM_NS_USER	0x10
#define FXLSM_NS_MNT	0x20
#define FXLSM_NS_CGROUP	0x40

#define FXLSM_ENTRY_FLAG_DUP		0x01

void fxlsm_entry_print(const char *label, struct fxlsm_entry *e);
#ifdef DEBUG
#define DEBUG_ENTRY_PRINT(label, e) fxlsm_entry_print(label, e)
#else
#define DEBUG_ENTRY_PRINT(label, e) do {} while (0)
#endif

struct fxlsm_list_paths {
	const char *paths[FXLSM_LIST_NUM];
};

struct fxlsm_string {
	const char *s;
	unsigned int len;
};

static inline int fxlsm_is_valid_string(struct fxlsm_string *s)
{
	return (s->s && s->len) ? 1 : 0;
}

static inline int fxlsm_is_valid_path(struct fxlsm_string *s)
{
	return (s->s && s->len && (*(s->s) == '/')) ? 1 : 0;
}

struct fxlsm_find_params {
	struct fxlsm_string path;
	struct fxlsm_string file;
	const char *comm;
	unsigned char ns;
	unsigned int inum;
};

#define FXLSM_THIRD_LEN 80

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* !__FXLSM_LIST_INTERNAL_H */
