code:
/****************************************************************************
 * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc.              *
 *                                                                          *
 * Permission is hereby granted, free of charge, to any person obtaining a  *
 * copy of this software and associated documentation files (the            *
 * "Software"), to deal in the Software without restriction, including      *
 * without limitation the rights to use, copy, modify, merge, publish,      *
 * distribute, distribute with modifications, sublicense, and/or sell       *
 * copies of the Software, and to permit persons to whom the Software is    *
 * furnished to do so, subject to the following conditions:                 *
 *                                                                          *
 * The above copyright notice and this permission notice shall be included  *
 * in all copies or substantial portions of the Software.                   *
 *                                                                          *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
 *                                                                          *
 * Except as contained in this notice, the name(s) of the above copyright   *
 * holders shall not be used in advertising or otherwise to promote the     *
 * sale, use or other dealings in this Software without prior written       *
 * authorization.                                                           *
 ****************************************************************************/

/****************************************************************************
 *   Author:  Juergen Pfeifer, 1995,1997                                    *
 ****************************************************************************/

/* $Id: form.h,v 0.20 2004/12/04 22:22:10 tom Exp $ */

#ifndef FORM_H
#define FORM_H

#include <curses.h>
#include <eti.h>

#ifdef __cplusplus
  extern "C" {
#endif

#ifndef FORM_PRIV_H
typedef void *FIELD_CELL;
#endif

#ifndef NCURSES_FIELD_INTERNALS
#define NCURSES_FIELD_INTERNALS /* nothing */
#endif

typedef int Form_Options;
typedef int Field_Options;

	/**********
	*  _PAGE  *
	**********/

typedef struct {
  short pmin;		/* index of first field on page			*/
  short pmax;		/* index of last field on page			*/
  short smin;		/* index of top leftmost field on page		*/
  short smax;		/* index of bottom rightmost field on page	*/
} _PAGE;

	/**********
	*  FIELD  *
	**********/

typedef struct fieldnode {
  unsigned short	status;		/* flags			*/
  short			rows;		/* size in rows			*/
  short			cols;		/* size in cols			*/
  short			frow;		/* first row			*/
  short			fcol;		/* first col			*/
  int			drows;		/* dynamic rows			*/
  int			dcols;		/* dynamic cols			*/
  int			maxgrow;	/* maximum field growth		*/
  int			nrow;		/* off-screen rows		*/
  short			nbuf;		/* additional buffers		*/
  short			just;		/* justification		*/
  short			page;		/* page on form			*/
  short			index;		/* into form -> field		*/
  int			pad;		/* pad character		*/
  chtype		fore;		/* foreground attribute		*/
  chtype		back;		/* background attribute		*/
  Field_Options		opts;		/* options			*/
  struct fieldnode *	snext;		/* sorted order pointer		*/
  struct fieldnode *	sprev;		/* sorted order pointer		*/
  struct fieldnode *	link;		/* linked field chain		*/
  struct formnode *	form;		/* containing form		*/
  struct typenode *	type;		/* field type			*/
  void *		arg;		/* argument for type		*/
  FIELD_CELL *		buf;		/* field buffers		*/
  void *		usrptr;		/* user pointer			*/
  /*
   * The wide-character configuration requires extra information.  Because
   * there are existing applications that manipulate the members of FIELD
   * directly, we cannot make the struct opaque.  Offsets of members up to
   * this point are the same in the narrow- and wide-character configuration.
   * But note that the type of buf depends on the configuration, and is made
   * opaque for that reason.
   */
  NCURSES_FIELD_INTERNALS
} FIELD;

	/**************
	*  FIELDTYPE  *
	**************/

typedef struct typenode {
  unsigned short	status;			/* flags		*/
  long			ref;			/* reference count	*/
  struct typenode *	left;			/* ptr to operand for | */
  struct typenode *	right;			/* ptr to operand for | */

  void* (*makearg)(va_list *);			/* make fieldtype arg	*/
  void* (*copyarg)(const void *);		/* copy fieldtype arg	*/
  void	(*freearg)(void *);			/* free fieldtype arg	*/

  bool	(*fcheck)(FIELD *,const void *);	/* field validation	*/
  bool	(*ccheck)(int,const void *);		/* character validation */

  bool	(*next)(FIELD *,const void *);		/* enumerate next value */
  bool	(*prev)(FIELD *,const void *);		/* enumerate prev value */

} FIELDTYPE;

	/*********
	*  FORM  *
	*********/

typedef struct formnode {
  unsigned short	status;		/* flags			*/
  short			rows;		/* size in rows			*/
  short			cols;		/* size in cols			*/
  int			currow;		/* current row in field window	*/
  int			curcol;		/* current col in field window	*/
  int			toprow;		/* in scrollable field window	*/
  int			begincol;	/* in horiz. scrollable field	*/
  short			maxfield;	/* number of fields		*/
  short			maxpage;	/* number of pages		*/
  short			curpage;	/* index into page		*/
  Form_Options		opts;		/* options			*/
  WINDOW *		win;		/* window			*/
  WINDOW *		sub;		/* subwindow			*/
  WINDOW *		w;		/* window for current field	*/
  FIELD **		field;		/* field [maxfield]		*/
  FIELD *		current;	/* current field		*/
  _PAGE *		page;		/* page [maxpage]		*/
  void *		usrptr;		/* user pointer			*/

  void			(*forminit)(struct formnode *);
  void			(*formterm)(struct formnode *);
  void			(*fieldinit)(struct formnode *);
  void			(*fieldterm)(struct formnode *);

} FORM;

typedef void (*Form_Hook)(FORM *);

	/***************************
	*  miscellaneous #defines  *
	***************************/

/* field justification */
#define NO_JUSTIFICATION	(0)
#define JUSTIFY_LEFT		(1)
#define JUSTIFY_CENTER		(2)
#define JUSTIFY_RIGHT		(3)

/* field options */
#define O_VISIBLE		(0x0001U)
#define O_ACTIVE		(0x0002U)
#define O_PUBLIC		(0x0004U)
#define O_EDIT			(0x0008U)
#define O_WRAP			(0x0010U)
#define O_BLANK			(0x0020U)
#define O_AUTOSKIP		(0x0040U)
#define O_NULLOK		(0x0080U)
#define O_PASSOK		(0x0100U)
#define O_STATIC		(0x0200U)

/* form options */
#define O_NL_OVERLOAD		(0x0001U)
#define O_BS_OVERLOAD		(0x0002U)

/* form driver commands */
#define REQ_NEXT_PAGE	 (KEY_MAX + 1)	/* move to next page		*/
#define REQ_PREV_PAGE	 (KEY_MAX + 2)	/* move to previous page	*/
#define REQ_FIRST_PAGE	 (KEY_MAX + 3)	/* move to first page		*/
#define REQ_LAST_PAGE	 (KEY_MAX + 4)	/* move to last page		*/

#define REQ_NEXT_FIELD	 (KEY_MAX + 5)	/* move to next field		*/
#define REQ_PREV_FIELD	 (KEY_MAX + 6)	/* move to previous field	*/
#define REQ_FIRST_FIELD	 (KEY_MAX + 7)	/* move to first field		*/
#define REQ_LAST_FIELD	 (KEY_MAX + 8)	/* move to last field		*/
#define REQ_SNEXT_FIELD	 (KEY_MAX + 9)	/* move to sorted next field	*/
#define REQ_SPREV_FIELD	 (KEY_MAX + 10)	/* move to sorted prev field	*/
#define REQ_SFIRST_FIELD (KEY_MAX + 11)	/* move to sorted first field	*/
#define REQ_SLAST_FIELD	 (KEY_MAX + 12)	/* move to sorted last field	*/
#define REQ_LEFT_FIELD	 (KEY_MAX + 13)	/* move to left to field	*/
#define REQ_RIGHT_FIELD	 (KEY_MAX + 14)	/* move to right to field	*/
#define REQ_UP_FIELD	 (KEY_MAX + 15)	/* move to up to field		*/
#define REQ_DOWN_FIELD	 (KEY_MAX + 16)	/* move to down to field	*/

#define REQ_NEXT_CHAR	 (KEY_MAX + 17)	/* move to next char in field	*/
#define REQ_PREV_CHAR	 (KEY_MAX + 18)	/* move to prev char in field	*/
#define REQ_NEXT_LINE	 (KEY_MAX + 19)	/* move to next line in field	*/
#define REQ_PREV_LINE	 (KEY_MAX + 20)	/* move to prev line in field	*/
#define REQ_NEXT_WORD	 (KEY_MAX + 21)	/* move to next word in field	*/
#define REQ_PREV_WORD	 (KEY_MAX + 22)	/* move to prev word in field	*/
#define REQ_BEG_FIELD	 (KEY_MAX + 23)	/* move to first char in field	*/
#define REQ_END_FIELD	 (KEY_MAX + 24)	/* move after last char in fld	*/
#define REQ_BEG_LINE	 (KEY_MAX + 25)	/* move to beginning of line	*/
#define REQ_END_LINE	 (KEY_MAX + 26)	/* move after last char in line	*/
#define REQ_LEFT_CHAR	 (KEY_MAX + 27)	/* move left in field		*/
#define REQ_RIGHT_CHAR	 (KEY_MAX + 28)	/* move right in field		*/
#define REQ_UP_CHAR	 (KEY_MAX + 29)	/* move up in field		*/
#define REQ_DOWN_CHAR	 (KEY_MAX + 30)	/* move down in field		*/

#define REQ_NEW_LINE	 (KEY_MAX + 31)	/* insert/overlay new line	*/
#define REQ_INS_CHAR	 (KEY_MAX + 32)	/* insert blank char at cursor	*/
#define REQ_INS_LINE	 (KEY_MAX + 33)	/* insert blank line at cursor	*/
#define REQ_DEL_CHAR	 (KEY_MAX + 34)	/* delete char at cursor	*/
#define REQ_DEL_PREV	 (KEY_MAX + 35)	/* delete char before cursor	*/
#define REQ_DEL_LINE	 (KEY_MAX + 36)	/* delete line at cursor	*/
#define REQ_DEL_WORD	 (KEY_MAX + 37)	/* delete word at cursor	*/
#define REQ_CLR_EOL	 (KEY_MAX + 38)	/* clear to end of line		*/
#define REQ_CLR_EOF	 (KEY_MAX + 39)	/* clear to end of field	*/
#define REQ_CLR_FIELD	 (KEY_MAX + 40)	/* clear entire field		*/
#define REQ_OVL_MODE	 (KEY_MAX + 41)	/* begin overlay mode		*/
#define REQ_INS_MODE	 (KEY_MAX + 42)	/* begin insert mode		*/
#define REQ_SCR_FLINE	 (KEY_MAX + 43)	/* scroll field forward a line	*/
#define REQ_SCR_BLINE	 (KEY_MAX + 44)	/* scroll field backward a line	*/
#define REQ_SCR_FPAGE	 (KEY_MAX + 45)	/* scroll field forward a page	*/
#define REQ_SCR_BPAGE	 (KEY_MAX + 46)	/* scroll field backward a page	*/
#define REQ_SCR_FHPAGE	 (KEY_MAX + 47) /* scroll field forward	 half page */
#define REQ_SCR_BHPAGE	 (KEY_MAX + 48) /* scroll field backward half page */
#define REQ_SCR_FCHAR	 (KEY_MAX + 49) /* horizontal scroll char	*/
#define REQ_SCR_BCHAR	 (KEY_MAX + 50) /* horizontal scroll char	*/
#define REQ_SCR_HFLINE	 (KEY_MAX + 51) /* horizontal scroll line	*/
#define REQ_SCR_HBLINE	 (KEY_MAX + 52) /* horizontal scroll line	*/
#define REQ_SCR_HFHALF	 (KEY_MAX + 53) /* horizontal scroll half line	*/
#define REQ_SCR_HBHALF	 (KEY_MAX + 54) /* horizontal scroll half line	*/

#define REQ_VALIDATION	 (KEY_MAX + 55)	/* validate field		*/
#define REQ_NEXT_CHOICE	 (KEY_MAX + 56)	/* display next field choice	*/
#define REQ_PREV_CHOICE	 (KEY_MAX + 57)	/* display prev field choice	*/

#define MIN_FORM_COMMAND (KEY_MAX + 1)	/* used by form_driver		*/
#define MAX_FORM_COMMAND (KEY_MAX + 57)	/* used by form_driver		*/

#if defined(MAX_COMMAND)
#  if (MAX_FORM_COMMAND > MAX_COMMAND)
#    error Something is wrong -- MAX_FORM_COMMAND is greater than MAX_COMMAND
#  elif (MAX_COMMAND != (KEY_MAX + 128))
#    error Something is wrong -- MAX_COMMAND is already inconsistently defined.
#  endif
#else
#  define MAX_COMMAND (KEY_MAX + 128)
#endif

	/*************************
	*  standard field types  *
	*************************/
extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ALPHA;
extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ALNUM;
extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ENUM;
extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_INTEGER;
extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_NUMERIC;
extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_REGEXP;

	/************************************
	*  built-in additional field types  *
	*  They are not defined in SVr4     *
	************************************/
extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_IPV4;      /* Internet IP Version 4 address */

	/***********************
	*   Default objects    *
	***********************/
extern NCURSES_EXPORT_VAR(FORM *)	_nc_Default_Form;
extern NCURSES_EXPORT_VAR(FIELD *)	_nc_Default_Field;

	/***********************
	*  FIELDTYPE routines  *
	***********************/
extern NCURSES_EXPORT(FIELDTYPE *) new_fieldtype (
		    bool (* const field_check)(FIELD *,const void *),
		    bool (* const char_check)(int,const void *));
extern NCURSES_EXPORT(FIELDTYPE *) link_fieldtype(
		    FIELDTYPE *, FIELDTYPE *);

extern NCURSES_EXPORT(int)	free_fieldtype (FIELDTYPE *);
extern NCURSES_EXPORT(int)	set_fieldtype_arg (FIELDTYPE *,
		    void * (* const make_arg)(va_list *),
		    void * (* const copy_arg)(const void *),
		    void (* const free_arg)(void *));
extern NCURSES_EXPORT(int)	 set_fieldtype_choice (FIELDTYPE *,
		    bool (* const next_choice)(FIELD *,const void *),
	      	    bool (* const prev_choice)(FIELD *,const void *));

	/*******************
	*  FIELD routines  *
	*******************/
extern NCURSES_EXPORT(FIELD *)	new_field (int,int,int,int,int,int);
extern NCURSES_EXPORT(FIELD *)	dup_field (FIELD *,int,int);
extern NCURSES_EXPORT(FIELD *)	link_field (FIELD *,int,int);

extern NCURSES_EXPORT(int)	free_field (FIELD *);
extern NCURSES_EXPORT(int)	field_info (const FIELD *,int *,int *,int *,int *,int *,int *);
extern NCURSES_EXPORT(int)	dynamic_field_info (const FIELD *,int *,int *,int *);
extern NCURSES_EXPORT(int)	set_max_field ( FIELD *,int);
extern NCURSES_EXPORT(int)	move_field (FIELD *,int,int);
extern NCURSES_EXPORT(int)	set_field_type (FIELD *,FIELDTYPE *,...);
extern NCURSES_EXPORT(int)	set_new_page (FIELD *,bool);
extern NCURSES_EXPORT(int)	set_field_just (FIELD *,int);
extern NCURSES_EXPORT(int)	field_just (const FIELD *);
extern NCURSES_EXPORT(int)	set_field_fore (FIELD *,chtype);
extern NCURSES_EXPORT(int)	set_field_back (FIELD *,chtype);
extern NCURSES_EXPORT(int)	set_field_pad (FIELD *,int);
extern NCURSES_EXPORT(int)	field_pad (const FIELD *);
extern NCURSES_EXPORT(int)	set_field_buffer (FIELD *,int,const char *);
extern NCURSES_EXPORT(int)	set_field_status (FIELD *,bool);
extern NCURSES_EXPORT(int)	set_field_userptr (FIELD *, void *);
extern NCURSES_EXPORT(int)	set_field_opts (FIELD *,Field_Options);
extern NCURSES_EXPORT(int)	field_opts_on (FIELD *,Field_Options);
extern NCURSES_EXPORT(int)	field_opts_off (FIELD *,Field_Options);

extern NCURSES_EXPORT(chtype)	field_fore (const FIELD *);
extern NCURSES_EXPORT(chtype)	field_back (const FIELD *);

extern NCURSES_EXPORT(bool)	new_page (const FIELD *);
extern NCURSES_EXPORT(bool)	field_status (const FIELD *);

extern NCURSES_EXPORT(void *)	field_arg (const FIELD *);

extern NCURSES_EXPORT(void *)	field_userptr (const FIELD *);

extern NCURSES_EXPORT(FIELDTYPE *)	field_type (const FIELD *);

extern NCURSES_EXPORT(char *)	field_buffer (const FIELD *,int);

extern NCURSES_EXPORT(Field_Options)	field_opts (const FIELD *);

	/******************
	*  FORM routines  *
	******************/

extern NCURSES_EXPORT(FORM *)	new_form (FIELD **);

extern NCURSES_EXPORT(FIELD **)	form_fields (const FORM *);
extern NCURSES_EXPORT(FIELD *)	current_field (const FORM *);

extern NCURSES_EXPORT(WINDOW *)	form_win (const FORM *);
extern NCURSES_EXPORT(WINDOW *)	form_sub (const FORM *);

extern NCURSES_EXPORT(Form_Hook)	form_init (const FORM *);
extern NCURSES_EXPORT(Form_Hook)	form_term (const FORM *);
extern NCURSES_EXPORT(Form_Hook)	field_init (const FORM *);
extern NCURSES_EXPORT(Form_Hook)	field_term (const FORM *);

extern NCURSES_EXPORT(int)	free_form (FORM *);
extern NCURSES_EXPORT(int)	set_form_fields (FORM *,FIELD **);
extern NCURSES_EXPORT(int)	field_count (const FORM *);
extern NCURSES_EXPORT(int)	set_form_win (FORM *,WINDOW *);
extern NCURSES_EXPORT(int)	set_form_sub (FORM *,WINDOW *);
extern NCURSES_EXPORT(int)	set_current_field (FORM *,FIELD *);
extern NCURSES_EXPORT(int)	field_index (const FIELD *);
extern NCURSES_EXPORT(int)	set_form_page (FORM *,int);
extern NCURSES_EXPORT(int)	form_page (const FORM *);
extern NCURSES_EXPORT(int)	scale_form (const FORM *,int *,int *);
extern NCURSES_EXPORT(int)	set_form_init (FORM *,Form_Hook);
extern NCURSES_EXPORT(int)	set_form_term (FORM *,Form_Hook);
extern NCURSES_EXPORT(int)	set_field_init (FORM *,Form_Hook);
extern NCURSES_EXPORT(int)	set_field_term (FORM *,Form_Hook);
extern NCURSES_EXPORT(int)	post_form (FORM *);
extern NCURSES_EXPORT(int)	unpost_form (FORM *);
extern NCURSES_EXPORT(int)	pos_form_cursor (FORM *);
extern NCURSES_EXPORT(int)	form_driver (FORM *,int);
extern NCURSES_EXPORT(int)	set_form_userptr (FORM *,void *);
extern NCURSES_EXPORT(int)	set_form_opts (FORM *,Form_Options);
extern NCURSES_EXPORT(int)	form_opts_on (FORM *,Form_Options);
extern NCURSES_EXPORT(int)	form_opts_off (FORM *,Form_Options);
extern NCURSES_EXPORT(int)	form_request_by_name (const char *);

extern NCURSES_EXPORT(const char *)	form_request_name (int);

extern NCURSES_EXPORT(void *)	form_userptr (const FORM *);

extern NCURSES_EXPORT(Form_Options)	form_opts (const FORM *);

extern NCURSES_EXPORT(bool)	data_ahead (const FORM *);
extern NCURSES_EXPORT(bool)	data_behind (const FORM *);

#ifdef __cplusplus
  }
#endif

#endif	/* FORM_H */


code:
/*-
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 * Copyright (c) 2000
 *	Poul-Henning Kamp.  All rights reserved.
 * Copyright (c) 2002
 *	Dima Dorfman.  All rights reserved.
 *
 * This code is derived from software donated to Berkeley by
 * Jan-Simon Pendry.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)kernfs.h	8.6 (Berkeley) 3/29/95
 * From: FreeBSD: src/sys/miscfs/kernfs/kernfs.h 1.14
 *
 * $FreeBSD: release/9.0.0/sys/fs/devfs/devfs.h 213725 2010-10-12 15:58:52Z jh $
 */

#ifndef _FS_DEVFS_DEVFS_H_
#define	_FS_DEVFS_DEVFS_H_

#define	DEVFS_MAGIC	0xdb0a087a

/*
 * Identifiers.  The ruleset and rule numbers are 16-bit values.  The
 * "rule ID" is a combination of the ruleset and rule number; it
 * should be able to univocally describe a rule in the system.  In
 * this implementation, the upper 16 bits of the rule ID is the
 * ruleset number; the lower 16 bits, the rule number within the
 * aforementioned ruleset.
 */
typedef uint16_t devfs_rnum;
typedef uint16_t devfs_rsnum;
typedef uint32_t devfs_rid;

/*
 * Identifier manipulators.
 */
#define	rid2rsn(rid)	((rid) >> 16)
#define	rid2rn(rid)	((rid) & 0xffff)
#define	mkrid(rsn, rn)	((rn) | ((rsn) << 16))

/*
 * Plain DEVFS rule.  This gets shared between kernel and userland
 * verbatim, so it shouldn't contain any pointers or other kernel- or
 * userland-specific values.
 */
struct devfs_rule {
	uint32_t dr_magic;			/* Magic number. */
	devfs_rid dr_id;			/* Identifier. */

	/*
	 * Conditions under which this rule should be applied.  These
	 * are ANDed together since OR can be simulated by using
	 * multiple rules.  dr_icond determines which of the other
	 * variables we should process.
	 */
	int	dr_icond;
#define	DRC_DSWFLAGS	0x001
#define	DRC_PATHPTRN	0x002
	int	dr_dswflags;			/* cdevsw flags to match. */
#define	DEVFS_MAXPTRNLEN	200
	char	dr_pathptrn[DEVFS_MAXPTRNLEN];	/* Pattern to match path. */

	/*
	 * Things to change.  dr_iacts determines which of the other
	 * variables we should process.
	 */
	int	dr_iacts;
#define	DRA_BACTS	0x001
#define	DRA_UID		0x002
#define	DRA_GID		0x004
#define	DRA_MODE	0x008
#define	DRA_INCSET	0x010
	int	dr_bacts;			/* Boolean (on/off) action. */
#define	DRB_HIDE	0x001			/* Hide entry (DE_WHITEOUT). */
#define	DRB_UNHIDE	0x002			/* Unhide entry. */
	uid_t	dr_uid;
	gid_t	dr_gid;
	mode_t	dr_mode;
	devfs_rsnum dr_incset;			/* Included ruleset. */
};

/*
 * Rule-related ioctls.
 */
#define	DEVFSIO_RADD		_IOWR('D', 0, struct devfs_rule)
#define	DEVFSIO_RDEL		_IOW('D', 1, devfs_rid)
#define	DEVFSIO_RAPPLY		_IOW('D', 2, struct devfs_rule)
#define	DEVFSIO_RAPPLYID	_IOW('D', 3, devfs_rid)
#define	DEVFSIO_RGETNEXT       	_IOWR('D', 4, struct devfs_rule)

#define	DEVFSIO_SUSE		_IOW('D', 10, devfs_rsnum)
#define	DEVFSIO_SAPPLY		_IOW('D', 11, devfs_rsnum)
#define	DEVFSIO_SGETNEXT	_IOWR('D', 12, devfs_rsnum)

/* XXX: DEVFSIO_RS_GET_INFO for refcount, active if any, etc. */

#ifdef _KERNEL

#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_DEVFS);
#endif

struct componentname;

TAILQ_HEAD(devfs_dlist_head, devfs_dirent);

struct devfs_dirent {
	struct cdev_priv	*de_cdp;
	int			de_inode;
	int			de_flags;
#define	DE_WHITEOUT	0x01
#define	DE_DOT		0x02
#define	DE_DOTDOT	0x04
#define	DE_DOOMED	0x08
#define	DE_COVERED	0x10
#define	DE_USER		0x20
	int			de_holdcnt;
	struct dirent 		*de_dirent;
	TAILQ_ENTRY(devfs_dirent) de_list;
	struct devfs_dlist_head	de_dlist;
	struct devfs_dirent	*de_dir;
	int			de_links;
	mode_t			de_mode;
	uid_t			de_uid;
	gid_t			de_gid;
	struct label		*de_label;
	struct timespec 	de_atime;
	struct timespec 	de_mtime;
	struct timespec 	de_ctime;
	struct vnode 		*de_vnode;
	char 			*de_symlink;
};

struct devfs_mount {
	u_int			dm_idx;
	struct mount		*dm_mount;
	struct devfs_dirent	*dm_rootdir;
	unsigned		dm_generation;
	int			dm_holdcnt;
	struct sx		dm_lock;
	devfs_rsnum		dm_ruleset;
};

#define DEVFS_ROOTINO 2

extern unsigned devfs_rule_depth;

#define VFSTODEVFS(mp)	((struct devfs_mount *)((mp)->mnt_data))

#define DEVFS_DE_HOLD(de)	((de)->de_holdcnt++)
#define DEVFS_DE_DROP(de)	(--(de)->de_holdcnt == 0)

#define DEVFS_DMP_HOLD(dmp)	((dmp)->dm_holdcnt++)
#define DEVFS_DMP_DROP(dmp)	(--(dmp)->dm_holdcnt == 0)

#define	DEVFS_DEL_VNLOCKED	0x01
#define	DEVFS_DEL_NORECURSE	0x02

void	devfs_rules_apply(struct devfs_mount *, struct devfs_dirent *);
void	devfs_rules_cleanup(struct devfs_mount *);
int	devfs_rules_ioctl(struct devfs_mount *, u_long, caddr_t,
	    struct thread *);
int	devfs_allocv(struct devfs_dirent *, struct mount *, int,
	    struct vnode **);
char	*devfs_fqpn(char *, struct devfs_mount *, struct devfs_dirent *,
	    struct componentname *);
void	devfs_delete(struct devfs_mount *, struct devfs_dirent *, int);
void	devfs_dirent_free(struct devfs_dirent *);
void	devfs_populate(struct devfs_mount *);
void	devfs_cleanup(struct devfs_mount *);
void	devfs_unmount_final(struct devfs_mount *);
struct devfs_dirent	*devfs_newdirent(char *, int);
struct devfs_dirent	*devfs_parent_dirent(struct devfs_dirent *);
struct devfs_dirent	*devfs_vmkdir(struct devfs_mount *, char *, int,
			    struct devfs_dirent *, u_int);
struct devfs_dirent	*devfs_find(struct devfs_dirent *, const char *, int,
			    int);

#endif /* _KERNEL */

#endif /* !_FS_DEVFS_DEVFS_H_ */

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (c) 2005 Poul-Henning Kamp.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/fs/devfs/devfs_int.h 213725 2010-10-12 15:58:52Z jh $
 */

/*
 * This file documents a private interface and it SHALL only be used
 * by kern/kern_conf.c and fs/devfs/...
 */

#ifndef _FS_DEVFS_DEVFS_INT_H_
#define	_FS_DEVFS_DEVFS_INT_H_

#include <sys/queue.h>

#ifdef _KERNEL

struct devfs_dirent;
struct devfs_mount;

struct cdev_privdata {
	struct file		*cdpd_fp;
	void			*cdpd_data;
	void			(*cdpd_dtr)(void *);
	LIST_ENTRY(cdev_privdata) cdpd_list;
};

struct cdev_priv {
	struct cdev		cdp_c;
	TAILQ_ENTRY(cdev_priv)	cdp_list;

	u_int			cdp_inode;

	u_int			cdp_flags;
#define CDP_ACTIVE		(1 << 0)
#define CDP_SCHED_DTR		(1 << 1)

	u_int			cdp_inuse;
	u_int			cdp_maxdirent;
	struct devfs_dirent	**cdp_dirents;
	struct devfs_dirent	*cdp_dirent0;

	TAILQ_ENTRY(cdev_priv)	cdp_dtr_list;
	void			(*cdp_dtr_cb)(void *);
	void			*cdp_dtr_cb_arg;

	LIST_HEAD(, cdev_privdata) cdp_fdpriv;
};

#define	cdev2priv(c)	member2struct(cdev_priv, cdp_c, c)

struct cdev	*devfs_alloc(int);
int	devfs_dev_exists(const char *);
void	devfs_free(struct cdev *);
void	devfs_create(struct cdev *);
void	devfs_destroy(struct cdev *);
void	devfs_destroy_cdevpriv(struct cdev_privdata *);

int	devfs_dir_find(const char *);
void	devfs_dir_ref_de(struct devfs_mount *, struct devfs_dirent *);
void	devfs_dir_unref_de(struct devfs_mount *, struct devfs_dirent *);
int	devfs_pathpath(const char *, const char *);

extern struct unrhdr *devfs_inos;
extern struct mtx devmtx;
extern struct mtx devfs_de_interlock;
extern struct sx clone_drain_lock;
extern struct mtx cdevpriv_mtx;
extern TAILQ_HEAD(cdev_priv_list, cdev_priv) cdevp_list;

#endif /* _KERNEL */

#endif /* !_FS_DEVFS_DEVFS_INT_H_ */


code:
/*-
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software donated to Berkeley by
 * Jan-Simon Pendry.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)fdesc.h	8.5 (Berkeley) 1/21/94
 *
 * $FreeBSD: release/9.0.0/sys/fs/fdescfs/fdesc.h 191990 2009-05-11 15:33:26Z attilio $
 */

#ifdef _KERNEL
/* Private mount flags for fdescfs. */
#define FMNT_UNMOUNTF 0x01
struct fdescmount {
	struct vnode	*f_root;	/* Root node */
	int flags;
};

#define FD_ROOT		1
#define FD_DESC		3

typedef enum {
	Froot,
	Fdesc
} fdntype;

struct fdescnode {
	LIST_ENTRY(fdescnode) fd_hash;	/* Hash list */
	struct vnode	*fd_vnode;	/* Back ptr to vnode */
	fdntype		fd_type;	/* Type of this node */
	unsigned	fd_fd;		/* Fd to be dup'ed */
	int		fd_ix;		/* filesystem index */
};

extern struct mtx fdesc_hashmtx;
#define VFSTOFDESC(mp)	((struct fdescmount *)((mp)->mnt_data))
#define	VTOFDESC(vp) ((struct fdescnode *)(vp)->v_data)

extern vfs_init_t fdesc_init;
extern vfs_uninit_t fdesc_uninit;
extern int fdesc_allocvp(fdntype, unsigned, int, struct mount *,
    struct vnode **);
#endif /* _KERNEL */


code:
/*-
 * Copyright (c) 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)fifo.h	8.6 (Berkeley) 5/21/95
 * $FreeBSD: release/9.0.0/sys/fs/fifofs/fifo.h 139776 2005-01-06 18:10:42Z imp $
 */

/*
 * Prototypes for fifo operations on vnodes.
 */
int	fifo_vnoperate(struct vop_generic_args *);
int	fifo_printinfo(struct vnode *);


code:
/* $FreeBSD: release/9.0.0/sys/fs/msdosfs/bootsect.h 203827 2010-02-13 12:41:07Z kib $ */
/*	$NetBSD: bootsect.h,v 1.9 1997/11/17 15:36:17 ws Exp $	*/

/*-
 * Written by Paul Popelka (paulp@uts.amdahl.com)
 *
 * You can do anything you want with this software, just don't say you wrote
 * it, and don't remove this notice.
 *
 * This software is provided "as is".
 *
 * The author supplies this software to be publicly redistributed on the
 * understanding that the author is not responsible for the correct
 * functioning of this software in any circumstances and is not liable for
 * any damages caused by this software.
 *
 * October 1992
 */
#ifndef _FS_MSDOSFS_BOOTSECT_H_
#define	_FS_MSDOSFS_BOOTSECT_H_

/*
 * Format of a boot sector.  This is the first sector on a DOS floppy disk
 * or the fist sector of a partition on a hard disk.  But, it is not the
 * first sector of a partitioned hard disk.
 */
struct bootsector33 {
	u_int8_t	bsJump[3];		/* jump inst E9xxxx or EBxx90 */
	int8_t		bsOemName[8];		/* OEM name and version */
	int8_t		bsBPB[19];		/* BIOS parameter block */
	int8_t		bsDriveNumber;		/* drive number (0x80) */
	int8_t		bsBootCode[479];	/* pad so struct is 512b */
	u_int8_t	bsBootSectSig0;
	u_int8_t	bsBootSectSig1;
#define	BOOTSIG0	0x55
#define	BOOTSIG1	0xaa
};

struct extboot {
	int8_t		exDriveNumber;		/* drive number (0x80) */
	int8_t		exReserved1;		/* reserved */
	int8_t		exBootSignature;	/* ext. boot signature (0x29) */
#define	EXBOOTSIG	0x29
	int8_t		exVolumeID[4];		/* volume ID number */
	int8_t		exVolumeLabel[11];	/* volume label */
	int8_t		exFileSysType[8];	/* fs type (FAT12 or FAT16) */
};

struct bootsector50 {
	u_int8_t	bsJump[3];		/* jump inst E9xxxx or EBxx90 */
	int8_t		bsOemName[8];		/* OEM name and version */
	int8_t		bsBPB[25];		/* BIOS parameter block */
	int8_t		bsExt[26];		/* Bootsector Extension */
	int8_t		bsBootCode[448];	/* pad so structure is 512b */
	u_int8_t	bsBootSectSig0;
	u_int8_t	bsBootSectSig1;
#define	BOOTSIG0	0x55
#define	BOOTSIG1	0xaa
};

struct bootsector710 {
	u_int8_t	bsJump[3];		/* jump inst E9xxxx or EBxx90 */
	int8_t		bsOEMName[8];		/* OEM name and version */
	int8_t		bsBPB[53];		/* BIOS parameter block */
	int8_t		bsExt[26];		/* Bootsector Extension */
	int8_t		bsBootCode[420];	/* pad so structure is 512b */
	u_int8_t	bsBootSectSig0;
	u_int8_t	bsBootSectSig1;
#define	BOOTSIG0	0x55
#define	BOOTSIG1	0xaa
};

union bootsector {
	struct bootsector33 bs33;
	struct bootsector50 bs50;
	struct bootsector710 bs710;
};

#if 0
/*
 * Shorthand for fields in the bpb.
 */
#define	bsBytesPerSec	bsBPB.bpbBytesPerSec
#define	bsSectPerClust	bsBPB.bpbSectPerClust
#define	bsResSectors	bsBPB.bpbResSectors
#define	bsFATS		bsBPB.bpbFATS
#define	bsRootDirEnts	bsBPB.bpbRootDirEnts
#define	bsSectors	bsBPB.bpbSectors
#define	bsMedia		bsBPB.bpbMedia
#define	bsFATsecs	bsBPB.bpbFATsecs
#define	bsSectPerTrack	bsBPB.bpbSectPerTrack
#define	bsHeads		bsBPB.bpbHeads
#define	bsHiddenSecs	bsBPB.bpbHiddenSecs
#define	bsHugeSectors	bsBPB.bpbHugeSectors
#endif

#endif /* !_FS_MSDOSFS_BOOTSECT_H_ */


code:
/* $FreeBSD: release/9.0.0/sys/fs/msdosfs/bpb.h 203827 2010-02-13 12:41:07Z kib $ */
/*	$NetBSD: bpb.h,v 1.7 1997/11/17 15:36:24 ws Exp $	*/

/*-
 * Written by Paul Popelka (paulp@uts.amdahl.com)
 *
 * You can do anything you want with this software, just don't say you wrote
 * it, and don't remove this notice.
 *
 * This software is provided "as is".
 *
 * The author supplies this software to be publicly redistributed on the
 * understanding that the author is not responsible for the correct
 * functioning of this software in any circumstances and is not liable for
 * any damages caused by this software.
 *
 * October 1992
 */

#ifndef _FS_MSDOSFS_BPB_H_
#define	_FS_MSDOSFS_BPB_H_

/*
 * BIOS Parameter Block (BPB) for DOS 3.3
 */
struct bpb33 {
	u_int16_t	bpbBytesPerSec;	/* bytes per sector */
	u_int8_t	bpbSecPerClust;	/* sectors per cluster */
	u_int16_t	bpbResSectors;	/* number of reserved sectors */
	u_int8_t	bpbFATs;	/* number of FATs */
	u_int16_t	bpbRootDirEnts;	/* number of root directory entries */
	u_int16_t	bpbSectors;	/* total number of sectors */
	u_int8_t	bpbMedia;	/* media descriptor */
	u_int16_t	bpbFATsecs;	/* number of sectors per FAT */
	u_int16_t	bpbSecPerTrack;	/* sectors per track */
	u_int16_t	bpbHeads;	/* number of heads */
	u_int16_t	bpbHiddenSecs;	/* number of hidden sectors */
};

/*
 * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3,
 * and bpbHugeSectors is not in the 3.3 bpb.
 */
struct bpb50 {
	u_int16_t	bpbBytesPerSec;	/* bytes per sector */
	u_int8_t	bpbSecPerClust;	/* sectors per cluster */
	u_int16_t	bpbResSectors;	/* number of reserved sectors */
	u_int8_t	bpbFATs;	/* number of FATs */
	u_int16_t	bpbRootDirEnts;	/* number of root directory entries */
	u_int16_t	bpbSectors;	/* total number of sectors */
	u_int8_t	bpbMedia;	/* media descriptor */
	u_int16_t	bpbFATsecs;	/* number of sectors per FAT */
	u_int16_t	bpbSecPerTrack;	/* sectors per track */
	u_int16_t	bpbHeads;	/* number of heads */
	u_int32_t	bpbHiddenSecs;	/* # of hidden sectors */
	u_int32_t	bpbHugeSectors;	/* # of sectors if bpbSectors == 0 */
};

/*
 * BPB for DOS 7.10 (FAT32).  This one has a few extensions to bpb50.
 */
struct bpb710 {
	u_int16_t	bpbBytesPerSec;	/* bytes per sector */
	u_int8_t	bpbSecPerClust;	/* sectors per cluster */
	u_int16_t	bpbResSectors;	/* number of reserved sectors */
	u_int8_t	bpbFATs;	/* number of FATs */
	u_int16_t	bpbRootDirEnts;	/* number of root directory entries */
	u_int16_t	bpbSectors;	/* total number of sectors */
	u_int8_t	bpbMedia;	/* media descriptor */
	u_int16_t	bpbFATsecs;	/* number of sectors per FAT */
	u_int16_t	bpbSecPerTrack;	/* sectors per track */
	u_int16_t	bpbHeads;	/* number of heads */
	u_int32_t	bpbHiddenSecs;	/* # of hidden sectors */
	u_int32_t	bpbHugeSectors;	/* # of sectors if bpbSectors == 0 */
	u_int32_t	bpbBigFATsecs;	/* like bpbFATsecs for FAT32 */
	u_int16_t	bpbExtFlags;	/* extended flags: */
#define	FATNUM		0xf		/* mask for numbering active FAT */
#define	FATMIRROR	0x80		/* FAT is mirrored (like it always was) */
	u_int16_t	bpbFSVers;	/* filesystem version */
#define	FSVERS		0		/* currently only 0 is understood */
	u_int32_t	bpbRootClust;	/* start cluster for root directory */
	u_int16_t	bpbFSInfo;	/* filesystem info structure sector */
	u_int16_t	bpbBackup;	/* backup boot sector */
	u_int8_t	bpbReserved[12]; /* reserved for future expansion */
};

/*
 * The following structures represent how the bpb's look on disk.  shorts
 * and longs are just character arrays of the appropriate length.  This is
 * because the compiler forces shorts and longs to align on word or
 * halfword boundaries.
 */

#include <sys/endian.h>

#define	getushort(x)	le16dec(x)
#define	getulong(x)	le32dec(x)
#define	putushort(p, v)	le16enc(p, v)
#define	putulong(p, v)	le32enc(p, v)

/*
 * BIOS Parameter Block (BPB) for DOS 3.3
 */
struct byte_bpb33 {
	int8_t bpbBytesPerSec[2];	/* bytes per sector */
	int8_t bpbSecPerClust;		/* sectors per cluster */
	int8_t bpbResSectors[2];	/* number of reserved sectors */
	int8_t bpbFATs;			/* number of FATs */
	int8_t bpbRootDirEnts[2];	/* number of root directory entries */
	int8_t bpbSectors[2];		/* total number of sectors */
	int8_t bpbMedia;		/* media descriptor */
	int8_t bpbFATsecs[2];		/* number of sectors per FAT */
	int8_t bpbSecPerTrack[2];	/* sectors per track */
	int8_t bpbHeads[2];		/* number of heads */
	int8_t bpbHiddenSecs[2];	/* number of hidden sectors */
};

/*
 * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3,
 * and bpbHugeSectors is not in the 3.3 bpb.
 */
struct byte_bpb50 {
	int8_t bpbBytesPerSec[2];	/* bytes per sector */
	int8_t bpbSecPerClust;		/* sectors per cluster */
	int8_t bpbResSectors[2];	/* number of reserved sectors */
	int8_t bpbFATs;			/* number of FATs */
	int8_t bpbRootDirEnts[2];	/* number of root directory entries */
	int8_t bpbSectors[2];		/* total number of sectors */
	int8_t bpbMedia;		/* media descriptor */
	int8_t bpbFATsecs[2];		/* number of sectors per FAT */
	int8_t bpbSecPerTrack[2];	/* sectors per track */
	int8_t bpbHeads[2];		/* number of heads */
	int8_t bpbHiddenSecs[4];	/* number of hidden sectors */
	int8_t bpbHugeSectors[4];	/* # of sectors if bpbSectors == 0 */
};

/*
 * BPB for DOS 7.10 (FAT32).  This one has a few extensions to bpb50.
 */
struct byte_bpb710 {
	u_int8_t bpbBytesPerSec[2];	/* bytes per sector */
	u_int8_t bpbSecPerClust;	/* sectors per cluster */
	u_int8_t bpbResSectors[2];	/* number of reserved sectors */
	u_int8_t bpbFATs;		/* number of FATs */
	u_int8_t bpbRootDirEnts[2];	/* number of root directory entries */
	u_int8_t bpbSectors[2];		/* total number of sectors */
	u_int8_t bpbMedia;		/* media descriptor */
	u_int8_t bpbFATsecs[2];		/* number of sectors per FAT */
	u_int8_t bpbSecPerTrack[2];	/* sectors per track */
	u_int8_t bpbHeads[2];		/* number of heads */
	u_int8_t bpbHiddenSecs[4];	/* # of hidden sectors */
	u_int8_t bpbHugeSectors[4];	/* # of sectors if bpbSectors == 0 */
	u_int8_t bpbBigFATsecs[4];	/* like bpbFATsecs for FAT32 */
	u_int8_t bpbExtFlags[2];	/* extended flags: */
	u_int8_t bpbFSVers[2];		/* filesystem version */
	u_int8_t bpbRootClust[4];	/* start cluster for root directory */
	u_int8_t bpbFSInfo[2];		/* filesystem info structure sector */
	u_int8_t bpbBackup[2];		/* backup boot sector */
	u_int8_t bpbReserved[12];	/* reserved for future expansion */
};

/*
 * FAT32 FSInfo block.
 */
struct fsinfo {
	u_int8_t fsisig1[4];
	u_int8_t fsifill1[480];
	u_int8_t fsisig2[4];
	u_int8_t fsinfree[4];
	u_int8_t fsinxtfree[4];
	u_int8_t fsifill2[12];
	u_int8_t fsisig3[4];
};
#endif /* !_FS_MSDOSFS_BPB_H_ */


code:
/* $FreeBSD: release/9.0.0/sys/fs/msdosfs/denode.h 203822 2010-02-13 11:34:25Z kib $ */
/*	$NetBSD: denode.h,v 1.25 1997/11/17 15:36:28 ws Exp $	*/

/*-
 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
 * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
 * All rights reserved.
 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*-
 * Written by Paul Popelka (paulp@uts.amdahl.com)
 *
 * You can do anything you want with this software, just don't say you wrote
 * it, and don't remove this notice.
 *
 * This software is provided "as is".
 *
 * The author supplies this software to be publicly redistributed on the
 * understanding that the author is not responsible for the correct
 * functioning of this software in any circumstances and is not liable for
 * any damages caused by this software.
 *
 * October 1992
 */

/*
 * This is the pc filesystem specific portion of the vnode structure.
 *
 * To describe a file uniquely the de_dirclust, de_diroffset, and
 * de_StartCluster fields are used.
 *
 * de_dirclust contains the cluster number of the directory cluster
 *	containing the entry for a file or directory.
 * de_diroffset is the index into the cluster for the entry describing
 *	a file or directory.
 * de_StartCluster is the number of the first cluster of the file or directory.
 *
 * Now to describe the quirks of the pc filesystem.
 * - Clusters 0 and 1 are reserved.
 * - The first allocatable cluster is 2.
 * - The root directory is of fixed size and all blocks that make it up
 *   are contiguous.
 * - Cluster 0 refers to the root directory when it is found in the
 *   startcluster field of a directory entry that points to another directory.
 * - Cluster 0 implies a 0 length file when found in the start cluster field
 *   of a directory entry that points to a file.
 * - You can't use the cluster number 0 to derive the address of the root
 *   directory.
 * - Multiple directory entries can point to a directory. The entry in the
 *   parent directory points to a child directory.  Any directories in the
 *   child directory contain a ".." entry that points back to the parent.
 *   The child directory itself contains a "." entry that points to itself.
 * - The root directory does not contain a "." or ".." entry.
 * - Directory entries for directories are never changed once they are created
 *   (except when removed).  The size stays 0, and the last modification time
 *   is never changed.  This is because so many directory entries can point to
 *   the physical clusters that make up a directory.  It would lead to an
 *   update nightmare.
 * - The length field in a directory entry pointing to a directory contains 0
 *   (always).  The only way to find the end of a directory is to follow the
 *   cluster chain until the "last cluster" marker is found.
 *
 * My extensions to make this house of cards work.  These apply only to the in
 * memory copy of the directory entry.
 * - A reference count for each denode will be kept since dos doesn't keep such
 *   things.
 */

/*
 * Internal pseudo-offset for (nonexistent) directory entry for the root
 * dir in the root dir
 */
#define	MSDOSFSROOT_OFS	0x1fffffff

/*
 * The fat cache structure. fc_fsrcn is the filesystem relative cluster
 * number that corresponds to the file relative cluster number in this
 * structure (fc_frcn).
 */
struct fatcache {
	u_long fc_frcn;		/* file relative cluster number */
	u_long fc_fsrcn;	/* filesystem relative cluster number */
};

/*
 * The fat entry cache as it stands helps make extending files a "quick"
 * operation by avoiding having to scan the fat to discover the last
 * cluster of the file. The cache also helps sequential reads by
 * remembering the last cluster read from the file.  This also prevents us
 * from having to rescan the fat to find the next cluster to read.  This
 * cache is probably pretty worthless if a file is opened by multiple
 * processes.
 */
#define	FC_SIZE		3	/* number of entries in the cache */
#define	FC_LASTMAP	0	/* entry the last call to pcbmap() resolved
				 * to */
#define	FC_LASTFC	1	/* entry for the last cluster in the file */
#define	FC_NEXTTOLASTFC	2	/* entry for a close to the last cluster in
				 * the file */

#define	FCE_EMPTY	0xffffffff	/* doesn't represent an actual cluster # */

/*
 * Set a slot in the fat cache.
 */
#define	fc_setcache(dep, slot, frcn, fsrcn) \
	(dep)->de_fc[(slot)].fc_frcn = (frcn); \
	(dep)->de_fc[(slot)].fc_fsrcn = (fsrcn);

/*
 * This is the in memory variant of a dos directory entry.  It is usually
 * contained within a vnode.
 */
struct denode {
	struct vnode *de_vnode;	/* addr of vnode we are part of */
	u_long de_flag;		/* flag bits */
	u_long de_dirclust;	/* cluster of the directory file containing this entry */
	u_long de_diroffset;	/* offset of this entry in the directory cluster */
	u_long de_fndoffset;	/* offset of found dir entry */
	int de_fndcnt;		/* number of slots before de_fndoffset */
	long de_refcnt;		/* reference count */
	struct msdosfsmount *de_pmp;	/* addr of our mount struct */
	u_char de_Name[12];	/* name, from DOS directory entry */
	u_char de_Attributes;	/* attributes, from directory entry */
	u_char de_LowerCase;	/* NT VFAT lower case flags */
	u_char de_CHun;		/* Hundredth of second of CTime*/
	u_short de_CTime;	/* creation time */
	u_short de_CDate;	/* creation date */
	u_short de_ADate;	/* access date */
	u_short de_MTime;	/* modification time */
	u_short de_MDate;	/* modification date */
	u_long de_StartCluster; /* starting cluster of file */
	u_long de_FileSize;	/* size of file in bytes */
	struct fatcache de_fc[FC_SIZE];	/* fat cache */
	u_quad_t de_modrev;	/* Revision level for lease. */
	u_int64_t de_inode;	/* Inode number (really byte offset of direntry) */
};

/*
 * Values for the de_flag field of the denode.
 */
#define	DE_UPDATE	0x0004	/* Modification time update request */
#define	DE_CREATE	0x0008	/* Creation time update */
#define	DE_ACCESS	0x0010	/* Access time update */
#define	DE_MODIFIED	0x0020	/* Denode has been modified */
#define	DE_RENAME	0x0040	/* Denode is in the process of being renamed */

/*
 * Transfer directory entries between internal and external form.
 * dep is a struct denode * (internal form),
 * dp is a struct direntry * (external form).
 */
#define DE_INTERNALIZE32(dep, dp)			\
	 ((dep)->de_StartCluster |= getushort((dp)->deHighClust) << 16)
#define DE_INTERNALIZE(dep, dp)				\
	(bcopy((dp)->deName, (dep)->de_Name, 11),	\
	 (dep)->de_Attributes = (dp)->deAttributes,	\
	 (dep)->de_LowerCase = (dp)->deLowerCase,	\
	 (dep)->de_CHun = (dp)->deCHundredth,		\
	 (dep)->de_CTime = getushort((dp)->deCTime),	\
	 (dep)->de_CDate = getushort((dp)->deCDate),	\
	 (dep)->de_ADate = getushort((dp)->deADate),	\
	 (dep)->de_MTime = getushort((dp)->deMTime),	\
	 (dep)->de_MDate = getushort((dp)->deMDate),	\
	 (dep)->de_StartCluster = getushort((dp)->deStartCluster), \
	 (dep)->de_FileSize = getulong((dp)->deFileSize), \
	 (FAT32((dep)->de_pmp) ? DE_INTERNALIZE32((dep), (dp)) : 0))

#define DE_EXTERNALIZE(dp, dep)				\
	(bcopy((dep)->de_Name, (dp)->deName, 11),	\
	 (dp)->deAttributes = (dep)->de_Attributes,	\
	 (dp)->deLowerCase = (dep)->de_LowerCase,	\
	 (dp)->deCHundredth = (dep)->de_CHun,		\
	 putushort((dp)->deCTime, (dep)->de_CTime),	\
	 putushort((dp)->deCDate, (dep)->de_CDate),	\
	 putushort((dp)->deADate, (dep)->de_ADate),	\
	 putushort((dp)->deMTime, (dep)->de_MTime),	\
	 putushort((dp)->deMDate, (dep)->de_MDate),	\
	 putushort((dp)->deStartCluster, (dep)->de_StartCluster), \
	 putulong((dp)->deFileSize,			\
	     ((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize), \
	 putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16))

#ifdef _KERNEL

#define	VTODE(vp)	((struct denode *)(vp)->v_data)
#define	DETOV(de)	((de)->de_vnode)

#define	DETIMES(dep, acc, mod, cre) do {				\
	if ((dep)->de_flag & DE_UPDATE) {				\
		(dep)->de_flag |= DE_MODIFIED;				\
		timespec2fattime((mod), 0, &(dep)->de_MDate,		\
		    &(dep)->de_MTime, NULL);				\
		(dep)->de_Attributes |= ATTR_ARCHIVE;			\
	}								\
	if ((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95) {		\
		(dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS);	\
		break;							\
	}								\
	if ((dep)->de_flag & DE_ACCESS) {				\
		u_int16_t adate;					\
									\
		timespec2fattime((acc), 0, &adate, NULL, NULL);		\
		if (adate != (dep)->de_ADate) {				\
			(dep)->de_flag |= DE_MODIFIED;			\
			(dep)->de_ADate = adate;			\
		}							\
	}								\
	if ((dep)->de_flag & DE_CREATE) {				\
		timespec2fattime((cre), 0, &(dep)->de_CDate,		\
		    &(dep)->de_CTime, &(dep)->de_CHun);			\
		(dep)->de_flag |= DE_MODIFIED;				\
	}								\
	(dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS);		\
} while (0)

/*
 * This overlays the fid structure (see mount.h)
 */
struct defid {
	u_short defid_len;	/* length of structure */
	u_short defid_pad;	/* force long alignment */

	u_int32_t defid_dirclust; /* cluster this dir entry came from */
	u_int32_t defid_dirofs;	/* offset of entry within the cluster */
#if 0
	u_int32_t defid_gen;	/* generation number */
#endif
};

extern struct vop_vector msdosfs_vnodeops;

int msdosfs_lookup(struct vop_cachedlookup_args *);
int msdosfs_inactive(struct vop_inactive_args *);
int msdosfs_reclaim(struct vop_reclaim_args *);

/*
 * Internal service routine prototypes.
 */
int deget(struct msdosfsmount *, u_long, u_long, struct denode **);
int uniqdosname(struct denode *, struct componentname *, u_char *);
int findwin95(struct denode *);

int readep(struct msdosfsmount *pmp, u_long dirclu, u_long dirofs,  struct buf **bpp, struct direntry **epp);
int readde(struct denode *dep, struct buf **bpp, struct direntry **epp);
int deextend(struct denode *dep, u_long length, struct ucred *cred);
int fillinusemap(struct msdosfsmount *pmp);
void reinsert(struct denode *dep);
int dosdirempty(struct denode *dep);
int createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct componentname *cnp);
int deupdat(struct denode *dep, int waitfor);
int removede(struct denode *pdep, struct denode *dep);
int detrunc(struct denode *dep, u_long length, int flags, struct ucred *cred, struct thread *td);
int doscheckpath( struct denode *source, struct denode *target);
#endif	/* _KERNEL */


code:
/* $FreeBSD: release/9.0.0/sys/fs/msdosfs/direntry.h 203827 2010-02-13 12:41:07Z kib $ */
/*	$NetBSD: direntry.h,v 1.14 1997/11/17 15:36:32 ws Exp $	*/

/*-
 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
 * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
 * All rights reserved.
 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*-
 * Written by Paul Popelka (paulp@uts.amdahl.com)
 *
 * You can do anything you want with this software, just don't say you wrote
 * it, and don't remove this notice.
 *
 * This software is provided "as is".
 *
 * The author supplies this software to be publicly redistributed on the
 * understanding that the author is not responsible for the correct
 * functioning of this software in any circumstances and is not liable for
 * any damages caused by this software.
 *
 * October 1992
 */
#ifndef _FS_MSDOSFS_DIRENTRY_H_
#define	_FS_MSDOSFS_DIRENTRY_H_

/*
 * Structure of a dos directory entry.
 */
struct direntry {
	u_int8_t	deName[11];	/* filename, blank filled */
#define	SLOT_EMPTY	0x00		/* slot has never been used */
#define	SLOT_E5		0x05		/* the real value is 0xe5 */
#define	SLOT_DELETED	0xe5		/* file in this slot deleted */
	u_int8_t	deAttributes;	/* file attributes */
#define	ATTR_NORMAL	0x00		/* normal file */
#define	ATTR_READONLY	0x01		/* file is readonly */
#define	ATTR_HIDDEN	0x02		/* file is hidden */
#define	ATTR_SYSTEM	0x04		/* file is a system file */
#define	ATTR_VOLUME	0x08		/* entry is a volume label */
#define	ATTR_DIRECTORY	0x10		/* entry is a directory name */
#define	ATTR_ARCHIVE	0x20		/* file is new or modified */
	u_int8_t	deLowerCase;	/* NT VFAT lower case flags */
#define	LCASE_BASE	0x08		/* filename base in lower case */
#define	LCASE_EXT	0x10		/* filename extension in lower case */
	u_int8_t	deCHundredth;	/* hundredth of seconds in CTime */
	u_int8_t	deCTime[2];	/* create time */
	u_int8_t	deCDate[2];	/* create date */
	u_int8_t	deADate[2];	/* access date */
	u_int8_t	deHighClust[2];	/* high bytes of cluster number */
	u_int8_t	deMTime[2];	/* last update time */
	u_int8_t	deMDate[2];	/* last update date */
	u_int8_t	deStartCluster[2]; /* starting cluster of file */
	u_int8_t	deFileSize[4];	/* size of file in bytes */
};

/*
 * Structure of a Win95 long name directory entry
 */
struct winentry {
	u_int8_t	weCnt;
#define	WIN_LAST	0x40
#define	WIN_CNT		0x3f
	u_int8_t	wePart1[10];
	u_int8_t	weAttributes;
#define	ATTR_WIN95	0x0f
	u_int8_t	weReserved1;
	u_int8_t	weChksum;
	u_int8_t	wePart2[12];
	u_int16_t	weReserved2;
	u_int8_t	wePart3[4];
};
#define	WIN_CHARS	13	/* Number of chars per winentry */

/*
 * Maximum number of winentries for a filename.
 */
#define	WIN_MAXSUBENTRIES 20

/*
 * Maximum filename length in Win95
 * Note: Must be < sizeof(dirent.d_name)
 */
#define	WIN_MAXLEN	255

/*
 * This is the format of the contents of the deTime field in the direntry
 * structure.
 * We don't use bitfields because we don't know how compilers for
 * arbitrary machines will lay them out.
 */
#define DT_2SECONDS_MASK	0x1F	/* seconds divided by 2 */
#define DT_2SECONDS_SHIFT	0
#define DT_MINUTES_MASK		0x7E0	/* minutes */
#define DT_MINUTES_SHIFT	5
#define DT_HOURS_MASK		0xF800	/* hours */
#define DT_HOURS_SHIFT		11

/*
 * This is the format of the contents of the deDate field in the direntry
 * structure.
 */
#define DD_DAY_MASK		0x1F	/* day of month */
#define DD_DAY_SHIFT		0
#define DD_MONTH_MASK		0x1E0	/* month */
#define DD_MONTH_SHIFT		5
#define DD_YEAR_MASK		0xFE00	/* year - 1980 */
#define DD_YEAR_SHIFT		9

#ifdef _KERNEL
struct mbnambuf {
	size_t	nb_len;
	int	nb_last_id;
	char	nb_buf[WIN_MAXLEN + 1];
};

struct dirent;
struct msdosfsmount;

char	*mbnambuf_flush(struct mbnambuf *nbp, struct dirent *dp);
void	mbnambuf_init(struct mbnambuf *nbp);
void	mbnambuf_write(struct mbnambuf *nbp, char *name, int id);
int	dos2unixfn(u_char dn[11], u_char *un, int lower,
	    struct msdosfsmount *pmp);
int	unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen,
	    struct msdosfsmount *pmp);
int	unix2winfn(const u_char *un, size_t unlen, struct winentry *wep, int cnt,
	    int chksum, struct msdosfsmount *pmp);
int	winChkName(struct mbnambuf *nbp, const u_char *un, size_t unlen,
	    int chksum, struct msdosfsmount *pmp);
int	win2unixfn(struct mbnambuf *nbp, struct winentry *wep, int chksum,
	    struct msdosfsmount *pmp);
u_int8_t winChksum(u_int8_t *name);
int	winSlotCnt(const u_char *un, size_t unlen, struct msdosfsmount *pmp);
size_t	winLenFixup(const u_char *un, size_t unlen);
#endif	/* _KERNEL */
#endif	/* !_FS_MSDOSFS_DIRENTRY_H_ */


code:
/* $FreeBSD: release/9.0.0/sys/fs/msdosfs/fat.h 139776 2005-01-06 18:10:42Z imp $ */
/*	$NetBSD: fat.h,v 1.12 1997/11/17 15:36:36 ws Exp $	*/

/*-
 * Copyright (C) 1994, 1997 Wolfgang Solfrank.
 * Copyright (C) 1994, 1997 TooLs GmbH.
 * All rights reserved.
 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*-
 * Written by Paul Popelka (paulp@uts.amdahl.com)
 *
 * You can do anything you want with this software, just don't say you wrote
 * it, and don't remove this notice.
 *
 * This software is provided "as is".
 *
 * The author supplies this software to be publicly redistributed on the
 * understanding that the author is not responsible for the correct
 * functioning of this software in any circumstances and is not liable for
 * any damages caused by this software.
 *
 * October 1992
 */

/*
 * Some useful cluster numbers.
 */
#define	MSDOSFSROOT	0		/* cluster 0 means the root dir */
#define	CLUST_FREE	0		/* cluster 0 also means a free cluster */
#define	MSDOSFSFREE	CLUST_FREE
#define	CLUST_FIRST	2		/* first legal cluster number */
#define	CLUST_RSRVD	0xfffffff6	/* reserved cluster range */
#define	CLUST_BAD	0xfffffff7	/* a cluster with a defect */
#define	CLUST_EOFS	0xfffffff8	/* start of eof cluster range */
#define	CLUST_EOFE	0xffffffff	/* end of eof cluster range */

#define	FAT12_MASK	0x00000fff	/* mask for 12 bit cluster numbers */
#define	FAT16_MASK	0x0000ffff	/* mask for 16 bit cluster numbers */
#define	FAT32_MASK	0x0fffffff	/* mask for FAT32 cluster numbers */

/*
 * MSDOSFS:
 * Return true if filesystem uses 12 bit fats. Microsoft Programmer's
 * Reference says if the maximum cluster number in a filesystem is greater
 * than 4078 ((CLUST_RSRVS - CLUST_FIRST) & FAT12_MASK) then we've got a
 * 16 bit fat filesystem. While mounting, the result of this test is stored
 * in pm_fatentrysize.
 */
#define	FAT12(pmp)	(pmp->pm_fatmask == FAT12_MASK)
#define	FAT16(pmp)	(pmp->pm_fatmask == FAT16_MASK)
#define	FAT32(pmp)	(pmp->pm_fatmask == FAT32_MASK)

#define	MSDOSFSEOF(pmp, cn)	((((cn) | ~(pmp)->pm_fatmask) & CLUST_EOFS) == CLUST_EOFS)

#ifdef _KERNEL
/*
 * These are the values for the function argument to the function
 * fatentry().
 */
#define	FAT_GET		0x0001	/* get a fat entry */
#define	FAT_SET		0x0002	/* set a fat entry */
#define	FAT_GET_AND_SET	(FAT_GET | FAT_SET)

/*
 * Flags to extendfile:
 */
#define	DE_CLEAR	1	/* Zero out the blocks allocated */

int pcbmap(struct denode *dep, u_long findcn, daddr_t *bnp, u_long *cnp, int* sp);
int clusterfree(struct msdosfsmount *pmp, u_long cn, u_long *oldcnp);
int clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count, u_long fillwith, u_long *retcluster, u_long *got);
int fatentry(int function, struct msdosfsmount *pmp, u_long cluster, u_long *oldcontents, u_long newcontents);
int freeclusterchain(struct msdosfsmount *pmp, u_long startchain);
int extendfile(struct denode *dep, u_long count, struct buf **bpp, u_long *ncp, int flags);
void fc_purge(struct denode *dep, u_int frcn);
int markvoldirty(struct msdosfsmount *pmp, int dirty);

#endif	/* _KERNEL */


code:
/* $FreeBSD: release/9.0.0/sys/fs/msdosfs/msdosfsmount.h 224290 2011-07-24 17:43:09Z mckusick $ */
/*	$NetBSD: msdosfsmount.h,v 1.17 1997/11/17 15:37:07 ws Exp $	*/

/*-
 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
 * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
 * All rights reserved.
 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*-
 * Written by Paul Popelka (paulp@uts.amdahl.com)
 *
 * You can do anything you want with this software, just don't say you wrote
 * it, and don't remove this notice.
 *
 * This software is provided "as is".
 *
 * The author supplies this software to be publicly redistributed on the
 * understanding that the author is not responsible for the correct
 * functioning of this software in any circumstances and is not liable for
 * any damages caused by this software.
 *
 * October 1992
 */

#ifndef _MSDOSFS_MSDOSFSMOUNT_H_
#define	_MSDOSFS_MSDOSFSMOUNT_H_

#ifdef _KERNEL

#include <sys/types.h>
#include <sys/lock.h>
#include <sys/lockmgr.h>
#include <sys/tree.h>

#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_MSDOSFSMNT);
#endif

struct msdosfs_fileno;

/*
 * Layout of the mount control block for a msdos filesystem.
 */
struct msdosfsmount {
	struct mount *pm_mountp;/* vfs mount struct for this fs */
	struct g_consumer *pm_cp;
	struct bufobj *pm_bo;
	uid_t pm_uid;		/* uid to set as owner of the files */
	gid_t pm_gid;		/* gid to set as owner of the files */
	mode_t pm_mask;		/* mask to and with file protection bits
				   for files */
	mode_t pm_dirmask;	/* mask to and with file protection bits
				   for directories */
	struct vnode *pm_devvp;	/* vnode for character device mounted */
	struct cdev *pm_dev;	/* character device mounted */
	struct bpb50 pm_bpb;	/* BIOS parameter blk for this fs */
	u_long pm_BlkPerSec;	/* How many DEV_BSIZE blocks fit inside a physical sector */
	u_long pm_FATsecs;	/* actual number of fat sectors */
	u_long pm_fatblk;	/* block # of first FAT */
	u_long pm_rootdirblk;	/* block # (cluster # for FAT32) of root directory number */
	u_long pm_rootdirsize;	/* size in blocks (not clusters) */
	u_long pm_firstcluster;	/* block number of first cluster */
	u_long pm_maxcluster;	/* maximum cluster number */
	u_long pm_freeclustercount;	/* number of free clusters */
	u_long pm_cnshift;	/* shift file offset right this amount to get a cluster number */
	u_long pm_crbomask;	/* and a file offset with this mask to get cluster rel offset */
	u_long pm_bnshift;	/* shift file offset right this amount to get a block number */
	u_long pm_bpcluster;	/* bytes per cluster */
	u_long pm_fmod;		/* ~0 if fs is modified, this can rollover to 0	*/
	u_long pm_fatblocksize;	/* size of fat blocks in bytes */
	u_long pm_fatblocksec;	/* size of fat blocks in sectors */
	u_long pm_fatsize;	/* size of fat in bytes */
	u_int32_t pm_fatmask;	/* mask to use for fat numbers */
	u_long pm_fsinfo;	/* fsinfo block number */
	u_long pm_nxtfree;	/* next place to search for a free cluster */
	u_int pm_fatmult;	/* these 2 values are used in fat */
	u_int pm_fatdiv;	/*	offset computation */
	u_int pm_curfat;	/* current fat for FAT32 (0 otherwise) */
	u_int *pm_inusemap;	/* ptr to bitmap of in-use clusters */
	uint64_t pm_flags;	/* see below */
	void *pm_u2w;	/* Local->Unicode iconv handle */
	void *pm_w2u;	/* Unicode->Local iconv handle */
	void *pm_u2d;	/* Unicode->DOS iconv handle */
	void *pm_d2u;	/* DOS->Local iconv handle */
	u_int32_t pm_nfileno;	/* next 32-bit fileno */
	RB_HEAD(msdosfs_filenotree, msdosfs_fileno)
	    pm_filenos; /* 64<->32-bit fileno mapping */
	struct lock pm_fatlock;	/* lockmgr protecting allocations and rb tree */
};

/*
 * A 64-bit file number and the 32-bit file number to which it is mapped,
 * in a red-black tree node.
 */
struct msdosfs_fileno {
	RB_ENTRY(msdosfs_fileno)	mf_tree;
	uint32_t			mf_fileno32;
	uint64_t			mf_fileno64;
};

/* Byte offset in FAT on filesystem pmp, cluster cn */
#define	FATOFS(pmp, cn)	((cn) * (pmp)->pm_fatmult / (pmp)->pm_fatdiv)

#define	VFSTOMSDOSFS(mp)	((struct msdosfsmount *)mp->mnt_data)

/* Number of bits in one pm_inusemap item: */
#define	N_INUSEBITS	(8 * sizeof(u_int))

/*
 * Shorthand for fields in the bpb contained in the msdosfsmount structure.
 */
#define	pm_BytesPerSec	pm_bpb.bpbBytesPerSec
#define	pm_ResSectors	pm_bpb.bpbResSectors
#define	pm_FATs		pm_bpb.bpbFATs
#define	pm_RootDirEnts	pm_bpb.bpbRootDirEnts
#define	pm_Sectors	pm_bpb.bpbSectors
#define	pm_Media	pm_bpb.bpbMedia
#define	pm_SecPerTrack	pm_bpb.bpbSecPerTrack
#define	pm_Heads	pm_bpb.bpbHeads
#define	pm_HiddenSects	pm_bpb.bpbHiddenSecs
#define	pm_HugeSectors	pm_bpb.bpbHugeSectors

/*
 * Convert pointer to buffer -> pointer to direntry
 */
#define	bptoep(pmp, bp, dirofs) \
	((struct direntry *)(((bp)->b_data)	\
	 + ((dirofs) & (pmp)->pm_crbomask)))

/*
 * Convert block number to cluster number
 */
#define	de_bn2cn(pmp, bn) \
	((bn) >> ((pmp)->pm_cnshift - (pmp)->pm_bnshift))

/*
 * Convert cluster number to block number
 */
#define	de_cn2bn(pmp, cn) \
	((cn) << ((pmp)->pm_cnshift - (pmp)->pm_bnshift))

/*
 * Convert file offset to cluster number
 */
#define de_cluster(pmp, off) \
	((off) >> (pmp)->pm_cnshift)

/*
 * Clusters required to hold size bytes
 */
#define	de_clcount(pmp, size) \
	(((size) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift)

/*
 * Convert file offset to block number
 */
#define de_blk(pmp, off) \
	(de_cn2bn(pmp, de_cluster((pmp), (off))))

/*
 * Convert cluster number to file offset
 */
#define	de_cn2off(pmp, cn) \
	((cn) << (pmp)->pm_cnshift)

/*
 * Convert block number to file offset
 */
#define	de_bn2off(pmp, bn) \
	((bn) << (pmp)->pm_bnshift)
/*
 * Map a cluster number into a filesystem relative block number.
 */
#define	cntobn(pmp, cn) \
	(de_cn2bn((pmp), (cn)-CLUST_FIRST) + (pmp)->pm_firstcluster)

/*
 * Calculate block number for directory entry in root dir, offset dirofs
 */
#define	roottobn(pmp, dirofs) \
	(de_blk((pmp), (dirofs)) + (pmp)->pm_rootdirblk)

/*
 * Calculate block number for directory entry at cluster dirclu, offset
 * dirofs
 */
#define	detobn(pmp, dirclu, dirofs) \
	((dirclu) == MSDOSFSROOT \
	 ? roottobn((pmp), (dirofs)) \
	 : cntobn((pmp), (dirclu)))

void msdosfs_fileno_init(struct mount *);
void msdosfs_fileno_free(struct mount *);
uint32_t msdosfs_fileno_map(struct mount *, uint64_t);

#define	MSDOSFS_LOCK_MP(pmp) \
	lockmgr(&(pmp)->pm_fatlock, LK_EXCLUSIVE, NULL)
#define	MSDOSFS_UNLOCK_MP(pmp) \
	lockmgr(&(pmp)->pm_fatlock, LK_RELEASE, NULL)
#define	MSDOSFS_ASSERT_MP_LOCKED(pmp) \
	lockmgr_assert(&(pmp)->pm_fatlock, KA_XLOCKED)

#endif /* _KERNEL */

/*
 *  Arguments to mount MSDOS filesystems.
 */
struct msdosfs_args {
	char	*fspec;		/* blocks special holding the fs to mount */
	struct	oexport_args export;	/* network export information */
	uid_t	uid;		/* uid that owns msdosfs files */
	gid_t	gid;		/* gid that owns msdosfs files */
	mode_t	mask;		/* file mask to be applied for msdosfs perms */
	int	flags;		/* see below */
	int magic;		/* version number */
	u_int16_t u2w[128];     /* Local->Unicode table */
	char	*cs_win;	/* Windows(Unicode) Charset */
	char	*cs_dos;	/* DOS Charset */
	char	*cs_local;	/* Local Charset */
	mode_t	dirmask;	/* dir  mask to be applied for msdosfs perms */
};

/*
 * Msdosfs mount options:
 */
#define	MSDOSFSMNT_SHORTNAME	1	/* Force old DOS short names only */
#define	MSDOSFSMNT_LONGNAME	2	/* Force Win'95 long names */
#define	MSDOSFSMNT_NOWIN95	4	/* Completely ignore Win95 entries */
#define	MSDOSFSMNT_KICONV	0x10    /* Use libiconv to convert chars */
/* All flags above: */
#define	MSDOSFSMNT_MNTOPT \
	(MSDOSFSMNT_SHORTNAME|MSDOSFSMNT_LONGNAME|MSDOSFSMNT_NOWIN95 \
	 |MSDOSFSMNT_KICONV)
#define	MSDOSFSMNT_RONLY	0x80000000	/* mounted read-only	*/
#define	MSDOSFSMNT_WAITONFAT	0x40000000	/* mounted synchronous	*/
#define	MSDOSFS_FATMIRROR	0x20000000	/* FAT is mirrored */
#define	MSDOSFS_LARGEFS		0x10000000	/* perform fileno mapping */

#define MSDOSFS_ARGSMAGIC	0xe4eff300

#endif /* !_MSDOSFS_MSDOSFSMOUNT_H_ */


code:
/*-
 * Copyright (c) 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Rick Macklem at The University of Guelph.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/fs/nfs/nfs.h 221523 2011-05-06 13:11:50Z mav $
 */

#ifndef _NFS_NFS_H_
#define	_NFS_NFS_H_
/*
 * Tunable constants for nfs
 */

#define	NFS_MAXIOVEC	34
#define	NFS_TICKINTVL	500		/* Desired time for a tick (msec) */
#define	NFS_HZ		(hz / nfscl_ticks) /* Ticks/sec */
#define	NFS_TIMEO	(1 * NFS_HZ)	/* Default timeout = 1 second */
#define	NFS_MINTIMEO	(1 * NFS_HZ)	/* Min timeout to use */
#define	NFS_MAXTIMEO	(60 * NFS_HZ)	/* Max timeout to backoff to */
#define	NFS_TCPTIMEO	300		/* TCP timeout */
#define	NFS_MAXRCVTIMEO	60		/* 1 minute in seconds */
#define	NFS_MINIDEMTIMEO (5 * NFS_HZ)	/* Min timeout for non-idempotent ops*/
#define	NFS_MAXREXMIT	100		/* Stop counting after this many */
#define	NFSV4_CALLBACKTIMEO (2 * NFS_HZ) /* Timeout in ticks */
#define	NFSV4_CALLBACKRETRY 5		/* Number of retries before failure */
#define	NFSV4_CBRETRYCNT 4		/* # of CBRecall retries upon err */
#define	NFSV4_UPCALLTIMEO (15 * NFS_HZ)	/* Timeout in ticks for upcalls */
					/* to gssd or nfsuserd */
#define	NFSV4_UPCALLRETRY 4		/* Number of retries before failure */
#define	NFS_MAXWINDOW	1024		/* Max number of outstanding requests */
#define	NFS_RETRANS	10		/* Num of retrans for soft mounts */
#define	NFS_RETRANS_TCP	2		/* Num of retrans for TCP soft mounts */
#define	NFS_MAXGRPS	16		/* Max. size of groups list */
#define	NFS_TRYLATERDEL	15		/* Maximum delay timeout (sec) */
#ifndef NFS_REMOVETIMEO
#define	NFS_REMOVETIMEO 15  /* # sec to wait for delegret in local syscall */
#endif
#ifndef NFS_MINATTRTIMO
#define	NFS_MINATTRTIMO 5		/* Attribute cache timeout in sec */
#endif
#ifndef NFS_MAXATTRTIMO
#define	NFS_MAXATTRTIMO 60
#endif
#define	NFS_WSIZE	8192		/* Def. write data size <= 8192 */
#define	NFS_RSIZE	8192		/* Def. read data size <= 8192 */
#define	NFS_READDIRSIZE	8192		/* Def. readdir size */
#define	NFS_DEFRAHEAD	1		/* Def. read ahead # blocks */
#define	NFS_MAXRAHEAD	16		/* Max. read ahead # blocks */
#define	NFS_MAXASYNCDAEMON 	64	/* Max. number async_daemons runnable */
#define	NFS_MAXUIDHASH	64		/* Max. # of hashed uid entries/mp */
#ifndef	NFSRV_LEASE
#define	NFSRV_LEASE		120	/* Lease time in seconds for V4 */
#endif					/* assigned to nfsrv_lease */
#ifndef NFSRV_STALELEASE
#define	NFSRV_STALELEASE	(5 * nfsrv_lease)
#endif
#ifndef NFSRV_MOULDYLEASE
#define	NFSRV_MOULDYLEASE	604800	/* One week (in sec) */
#endif
#ifndef NFSCLIENTHASHSIZE
#define	NFSCLIENTHASHSIZE	20	/* Size of server client hash table */
#endif
#ifndef NFSLOCKHASHSIZE
#define	NFSLOCKHASHSIZE		20	/* Size of server nfslock hash table */
#endif
#define	NFSSTATEHASHSIZE	10	/* Size of server stateid hash table */
#ifndef NFSUSERHASHSIZE
#define	NFSUSERHASHSIZE		30	/* Size of user id hash table */
#endif
#ifndef NFSGROUPHASHSIZE
#define	NFSGROUPHASHSIZE	5	/* Size of group id hash table */
#endif
#ifndef	NFSCLDELEGHIGHWATER
#define	NFSCLDELEGHIGHWATER	10000	/* limit for client delegations */
#endif
#ifndef NFSNOOPEN			/* Inactive open owner (sec) */
#define	NFSNOOPEN		120
#endif
#define	NFSRV_LEASEDELTA	15	/* # of seconds to delay beyond lease */
#define	NFS_IDMAXSIZE		4	/* max sizeof (in_addr_t) */
#ifndef NFSRVCACHE_UDPTIMEOUT
#define	NFSRVCACHE_UDPTIMEOUT	30	/* # of sec to hold cached rpcs(udp) */
#endif
#ifndef NFSRVCACHE_UDPHIGHWATER
#define	NFSRVCACHE_UDPHIGHWATER	500	/* Max # of udp cache entries */
#endif
#ifndef NFSRVCACHE_TCPTIMEOUT
#define	NFSRVCACHE_TCPTIMEOUT	(3600*12) /*#of sec to hold cached rpcs(tcp) */
#endif
#ifndef	NFSRVCACHE_FLOODLEVEL
#define	NFSRVCACHE_FLOODLEVEL	16384	/* Very high water mark for cache */
#endif
#ifndef	NFSRV_CLIENTHIGHWATER
#define	NFSRV_CLIENTHIGHWATER	1000
#endif
#ifndef	NFSRV_MAXDUMPLIST
#define	NFSRV_MAXDUMPLIST	10000
#endif
#ifndef NFS_ACCESSCACHESIZE
#define	NFS_ACCESSCACHESIZE	8
#endif
#define	NFSV4_CBPORT	7745		/* Callback port for testing */

/*
 * This macro defines the high water mark for issuing V4 delegations.
 * (It is currently set at a conservative 20% of NFSRV_V4STATELIMIT. This
 *  may want to increase when clients can make more effective use of
 *  delegations.)
 */
#define	NFSRV_V4DELEGLIMIT(c) (((c) * 5) > NFSRV_V4STATELIMIT)

#define	NFS_READDIRBLKSIZ	DIRBLKSIZ	/* Minimal nm_readdirsize */

/*
 * Oddballs
 */
#define	NFS_CMPFH(n, f, s) 						\
    ((n)->n_fhp->nfh_len == (s) && !NFSBCMP((n)->n_fhp->nfh_fh, (caddr_t)(f), (s)))
#define	NFSRV_CMPFH(nf, ns, f, s) 					\
	((ns) == (s) && !NFSBCMP((caddr_t)(nf), (caddr_t)(f), (s)))
#define	NFS_CMPTIME(t1, t2) 						\
	((t1).tv_sec == (t2).tv_sec && (t1).tv_nsec == (t2).tv_nsec)
#define	NFS_SETTIME(t) do { 						\
	(t).tv_sec = time.tv_sec; (t).tv_nsec = 1000 * time.tv_usec; } while (0)
#define	NFS_SRVMAXDATA(n) 						\
		(((n)->nd_flag & (ND_NFSV3 | ND_NFSV4)) ? 		\
		 NFS_MAXDATA : NFS_V2MAXDATA)
#define	NFS64BITSSET	0xffffffffffffffffull
#define	NFS64BITSMINUS1	0xfffffffffffffffeull

/*
 * Structures for the nfssvc(2) syscall. Not that anyone but nfsd, mount_nfs
 * and nfsloaduser should ever try and use it.
 */
struct nfsd_addsock_args {
	int	sock;		/* Socket to serve */
	caddr_t	name;		/* Client addr for connection based sockets */
	int	namelen;	/* Length of name */
};

/*
 * nfsd argument for new krpc.
 */
struct nfsd_nfsd_args {
	const char *principal;	/* GSS-API service principal name */
	int	minthreads;	/* minimum service thread count */
	int	maxthreads;	/* maximum service thread count */
};

/*
 * Arguments for use by the callback daemon.
 */
struct nfsd_nfscbd_args {
	const char *principal;	/* GSS-API service principal name */
};

struct nfscbd_args {
	int	sock;		/* Socket to serve */
	caddr_t	name;		/* Client addr for connection based sockets */
	int	namelen;	/* Length of name */
	u_short	port;		/* Port# for callbacks */
};

struct nfsd_idargs {
	int		nid_flag;	/* Flags (see below) */
	uid_t		nid_uid;	/* user/group id */
	gid_t		nid_gid;
	int		nid_usermax;	/* Upper bound on user name cache */
	int		nid_usertimeout;/* User name timeout (minutes) */
	u_char		*nid_name;	/* Name */
	int		nid_namelen;	/* and its length */
};

struct nfsd_clid {
	int		nclid_idlen;	/* Length of client id */
	u_char		nclid_id[NFSV4_OPAQUELIMIT]; /* and name */
};

struct nfsd_dumplist {
	int		ndl_size;	/* Number of elements */
	void		*ndl_list;	/* and the list of elements */
};

struct nfsd_dumpclients {
	u_int32_t	ndcl_flags;		/* LCL_xxx flags */
	u_int32_t	ndcl_nopenowners;	/* Number of openowners */
	u_int32_t	ndcl_nopens;		/* and opens */
	u_int32_t	ndcl_nlockowners;	/* and of lockowners */
	u_int32_t	ndcl_nlocks;		/* and of locks */
	u_int32_t	ndcl_ndelegs;		/* and of delegations */
	u_int32_t	ndcl_nolddelegs;	/* and old delegations */
	sa_family_t	ndcl_addrfam;		/* Callback address */
	union {
		struct in_addr sin_addr;
		struct in6_addr sin6_addr;
	} ndcl_cbaddr;
	struct nfsd_clid ndcl_clid;	/* and client id */
};

struct nfsd_dumplocklist {
	char		*ndllck_fname;	/* File Name */
	int		ndllck_size;	/* Number of elements */
	void		*ndllck_list;	/* and the list of elements */
};

struct nfsd_dumplocks {
	u_int32_t	ndlck_flags;		/* state flags NFSLCK_xxx */
	nfsv4stateid_t	ndlck_stateid;		/* stateid */
	u_int64_t	ndlck_first;		/* lock byte range */
	u_int64_t	ndlck_end;
	struct nfsd_clid ndlck_owner;		/* Owner of open/lock */
	sa_family_t	ndlck_addrfam;		/* Callback address */
	union {
		struct in_addr sin_addr;
		struct in6_addr sin6_addr;
	} ndlck_cbaddr;
	struct nfsd_clid ndlck_clid;	/* and client id */
};

/*
 * Structure for referral information.
 */
struct nfsreferral {
	u_char		*nfr_srvlist;	/* List of servers */
	int		nfr_srvcnt;	/* number of servers */
	vnode_t		nfr_vp;	/* vnode for referral */
	u_int32_t	nfr_dfileno;	/* assigned dir inode# */
};

/*
 * Flags for lc_flags and opsflags for nfsrv_getclient().
 */
#define	LCL_NEEDSCONFIRM	0x00000001
#define	LCL_DONTCLEAN		0x00000002
#define	LCL_WAKEUPWANTED	0x00000004
#define	LCL_TCPCALLBACK		0x00000008
#define	LCL_CALLBACKSON		0x00000010
#define	LCL_INDEXNOTOK		0x00000020
#define	LCL_STAMPEDSTABLE	0x00000040
#define	LCL_EXPIREIT		0x00000080
#define	LCL_CBDOWN		0x00000100
#define	LCL_KERBV		0x00000400
#define	LCL_NAME		0x00000800
#define	LCL_NEEDSCBNULL		0x00001000
#define	LCL_GSSINTEGRITY	0x00002000
#define	LCL_GSSPRIVACY		0x00004000
#define	LCL_ADMINREVOKED	0x00008000

#define	LCL_GSS		LCL_KERBV	/* Or of all mechs */

/*
 * Bits for flags in nfslock and nfsstate.
 * The access, deny, NFSLCK_READ and NFSLCK_WRITE bits must be defined as
 * below, in the correct order, so the shifts work for tests.
 */
#define	NFSLCK_READACCESS	0x00000001
#define	NFSLCK_WRITEACCESS	0x00000002
#define	NFSLCK_ACCESSBITS	(NFSLCK_READACCESS | NFSLCK_WRITEACCESS)
#define	NFSLCK_SHIFT		2
#define	NFSLCK_READDENY		0x00000004
#define	NFSLCK_WRITEDENY	0x00000008
#define	NFSLCK_DENYBITS		(NFSLCK_READDENY | NFSLCK_WRITEDENY)
#define	NFSLCK_SHAREBITS 						\
    (NFSLCK_READACCESS|NFSLCK_WRITEACCESS|NFSLCK_READDENY|NFSLCK_WRITEDENY)
#define	NFSLCK_LOCKSHIFT	4
#define	NFSLCK_READ		0x00000010
#define	NFSLCK_WRITE		0x00000020
#define	NFSLCK_BLOCKING		0x00000040
#define	NFSLCK_RECLAIM		0x00000080
#define	NFSLCK_OPENTOLOCK	0x00000100
#define	NFSLCK_TEST		0x00000200
#define	NFSLCK_LOCK		0x00000400
#define	NFSLCK_UNLOCK		0x00000800
#define	NFSLCK_OPEN		0x00001000
#define	NFSLCK_CLOSE		0x00002000
#define	NFSLCK_CHECK		0x00004000
#define	NFSLCK_RELEASE		0x00008000
#define	NFSLCK_NEEDSCONFIRM	0x00010000
#define	NFSLCK_CONFIRM		0x00020000
#define	NFSLCK_DOWNGRADE	0x00040000
#define	NFSLCK_DELEGREAD	0x00080000
#define	NFSLCK_DELEGWRITE	0x00100000
#define	NFSLCK_DELEGCUR		0x00200000
#define	NFSLCK_DELEGPREV	0x00400000
#define	NFSLCK_OLDDELEG		0x00800000
#define	NFSLCK_DELEGRECALL	0x01000000
#define	NFSLCK_SETATTR		0x02000000
#define	NFSLCK_DELEGPURGE	0x04000000
#define	NFSLCK_DELEGRETURN	0x08000000

/* And bits for nid_flag */
#define	NFSID_INITIALIZE	0x0001
#define	NFSID_ADDUID		0x0002
#define	NFSID_DELUID		0x0004
#define	NFSID_ADDUSERNAME	0x0008
#define	NFSID_DELUSERNAME	0x0010
#define	NFSID_ADDGID		0x0020
#define	NFSID_DELGID		0x0040
#define	NFSID_ADDGROUPNAME	0x0080
#define	NFSID_DELGROUPNAME	0x0100

/*
 * fs.nfs sysctl(3) identifiers
 */
#define	NFS_NFSSTATS	1		/* struct: struct nfsstats */

#define	FS_NFS_NAMES { 							\
		       { 0, 0 }, 					\
		       { "nfsstats", CTLTYPE_STRUCT }, 			\
}

/*
 * Here is the definition of the attribute bits array and macros that
 * manipulate it.
 * THE MACROS MUST BE MANUALLY MODIFIED IF NFSATTRBIT_MAXWORDS CHANGES!!
 * It is (NFSATTRBIT_MAX + 31) / 32.
 */
#define	NFSATTRBIT_MAXWORDS	2

typedef struct {
	u_int32_t bits[NFSATTRBIT_MAXWORDS];
} nfsattrbit_t;

#define	NFSZERO_ATTRBIT(b) do { (b)->bits[0] = 0; (b)->bits[1] = 0; } while (0)
#define	NFSSET_ATTRBIT(t, f) do { (t)->bits[0] = (f)->bits[0]; 		\
				  (t)->bits[1] = (f)->bits[1]; } while (0)
#define	NFSSETSUPP_ATTRBIT(b) do { 					\
	(b)->bits[0] = NFSATTRBIT_SUPP0; 				\
	(b)->bits[1] = (NFSATTRBIT_SUPP1 | NFSATTRBIT_SUPPSETONLY); } while (0)
#define	NFSISSET_ATTRBIT(b, p)	((b)->bits[(p) / 32] & (1 << ((p) % 32)))
#define	NFSSETBIT_ATTRBIT(b, p)	((b)->bits[(p) / 32] |= (1 << ((p) % 32)))
#define	NFSCLRBIT_ATTRBIT(b, p)	((b)->bits[(p) / 32] &= ~(1 << ((p) % 32)))
#define	NFSCLRALL_ATTRBIT(b, a)	do { 					\
		(b)->bits[0] &= ~((a)->bits[0]); 			\
		(b)->bits[1] &= ~((a)->bits[1]); 			\
		} while (0)
#define	NFSCLRNOT_ATTRBIT(b, a)	do { 					\
		(b)->bits[0] &= ((a)->bits[0]); 			\
		(b)->bits[1] &= ((a)->bits[1]); 			\
		} while (0)
#define	NFSCLRNOTFILLABLE_ATTRBIT(b) do { 				\
		(b)->bits[0] &= NFSATTRBIT_SUPP0; 			\
		(b)->bits[1] &= NFSATTRBIT_SUPP1; } while (0)
#define	NFSCLRNOTSETABLE_ATTRBIT(b) do { 				\
		(b)->bits[0] &= NFSATTRBIT_SETABLE0; 			\
		(b)->bits[1] &= NFSATTRBIT_SETABLE1; } while (0)
#define	NFSNONZERO_ATTRBIT(b)	((b)->bits[0] || (b)->bits[1])
#define	NFSEQUAL_ATTRBIT(b, p)						\
	((b)->bits[0] == (p)->bits[0] && (b)->bits[1] == (p)->bits[1])
#define	NFSGETATTR_ATTRBIT(b) do { 					\
		(b)->bits[0] = NFSATTRBIT_GETATTR0; 			\
		(b)->bits[1] = NFSATTRBIT_GETATTR1; } while (0)
#define	NFSWCCATTR_ATTRBIT(b) do { 					\
		(b)->bits[0] = NFSATTRBIT_WCCATTR0; 			\
		(b)->bits[1] = NFSATTRBIT_WCCATTR1; } while (0)
#define	NFSWRITEGETATTR_ATTRBIT(b) do { 				\
		(b)->bits[0] = NFSATTRBIT_WRITEGETATTR0;		\
		(b)->bits[1] = NFSATTRBIT_WRITEGETATTR1; } while (0)
#define	NFSCBGETATTR_ATTRBIT(b, c) do { 				\
	(c)->bits[0] = ((b)->bits[0] & NFSATTRBIT_CBGETATTR0); 		\
	(c)->bits[1] = ((b)->bits[1] & NFSATTRBIT_CBGETATTR1); } while (0)
#define	NFSPATHCONF_GETATTRBIT(b) do { 					\
		(b)->bits[0] = NFSGETATTRBIT_PATHCONF0; 		\
		(b)->bits[1] = NFSGETATTRBIT_PATHCONF1; } while (0)
#define	NFSSTATFS_GETATTRBIT(b)	do { 					\
		(b)->bits[0] = NFSGETATTRBIT_STATFS0; 			\
		(b)->bits[1] = NFSGETATTRBIT_STATFS1; } while (0)
#define	NFSISSETSTATFS_ATTRBIT(b) 					\
		(((b)->bits[0] & NFSATTRBIT_STATFS0) || 		\
		 ((b)->bits[1] & NFSATTRBIT_STATFS1))
#define	NFSCLRSTATFS_ATTRBIT(b)	do { 					\
		(b)->bits[0] &= ~NFSATTRBIT_STATFS0; 			\
		(b)->bits[1] &= ~NFSATTRBIT_STATFS1; } while (0)
#define	NFSREADDIRPLUS_ATTRBIT(b) do { 					\
		(b)->bits[0] = NFSATTRBIT_READDIRPLUS0; 		\
		(b)->bits[1] = NFSATTRBIT_READDIRPLUS1; } while (0)
#define	NFSREFERRAL_ATTRBIT(b) do { 					\
		(b)->bits[0] = NFSATTRBIT_REFERRAL0;	 		\
		(b)->bits[1] = NFSATTRBIT_REFERRAL1; } while (0)

/*
 * Store uid, gid creds that were used when the stateid was acquired.
 * The RPC layer allows NFS_MAXGRPS + 1 groups to go out on the wire,
 * so that's how many gets stored here.
 */
struct nfscred {
	uid_t 		nfsc_uid;
	gid_t		nfsc_groups[NFS_MAXGRPS + 1];
	int		nfsc_ngroups;
};

/*
 * Constants that define the file handle for the V4 root directory.
 * (The FSID must never be used by other file systems that are exported.)
 */
#define	NFSV4ROOT_FSID0		((int32_t) -1)
#define	NFSV4ROOT_FSID1		((int32_t) -1)
#define	NFSV4ROOT_REFERRAL	((int32_t) -2)
#define	NFSV4ROOT_INO		2	/* It's traditional */
#define	NFSV4ROOT_GEN		1

/*
 * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
 * What should be in this set is open to debate, but I believe that since
 * I/O system calls on ufs are never interrupted by signals the set should
 * be minimal. My reasoning is that many current programs that use signals
 * such as SIGALRM will not expect file I/O system calls to be interrupted
 * by them and break.
 */
#if defined(_KERNEL) || defined(KERNEL)

struct uio; struct buf; struct vattr; struct nameidata;	/* XXX */

/*
 * Socket errors ignored for connectionless sockets?
 * For now, ignore them all
 */
#define	NFSIGNORE_SOERROR(s, e) 					\
		((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
		((s) & PR_CONNREQUIRED) == 0)

/*
 * This structure holds socket information for a connection. Used by the
 * client and the server for callbacks.
 */
struct nfssockreq {
	NFSSOCKADDR_T	nr_nam;
	int		nr_sotype;
	int		nr_soproto;
	int		nr_soflags;
	struct ucred	*nr_cred;
	int		nr_lock;
	NFSMUTEX_T	nr_mtx;
	u_int32_t	nr_prog;
	u_int32_t	nr_vers;
	struct __rpc_client *nr_client;
};

/*
 * And associated nr_lock bits.
 */
#define	NFSR_SNDLOCK		0x01
#define	NFSR_WANTSND		0x02
#define	NFSR_RCVLOCK		0x04
#define	NFSR_WANTRCV		0x08
#define	NFSR_RESERVEDPORT	0x10
#define	NFSR_LOCALHOST		0x20

/*
 * Queue head for nfsreq's
 */
TAILQ_HEAD(nfsreqhead, nfsreq);

/* This is the only nfsreq R_xxx flag still used. */
#define	R_DONTRECOVER	0x00000100	/* don't initiate recovery when this
					   rpc gets a stale state reply */

/*
 * Network address hash list element
 */
union nethostaddr {
	struct in_addr	had_inet;
	struct in6_addr had_inet6;
};

/*
 * Structure of list of mechanisms.
 */
struct nfsgss_mechlist {
	int	len;
	const u_char	*str;
	int	totlen;
};
#define	KERBV_MECH	0	/* position in list */

/*
 * This structure is used by the server for describing each request.
 */
struct nfsrv_descript {
	mbuf_t			nd_mrep;	/* Request mbuf list */
	mbuf_t			nd_md;		/* Current dissect mbuf */
	mbuf_t			nd_mreq;	/* Reply mbuf list */
	mbuf_t			nd_mb;		/* Current build mbuf */
	NFSSOCKADDR_T		nd_nam;		/* and socket addr */
	NFSSOCKADDR_T		nd_nam2;	/* return socket addr */
	caddr_t			nd_dpos;	/* Current dissect pos */
	caddr_t			nd_bpos;	/* Current build pos */
	u_int16_t		nd_procnum;	/* RPC # */
	u_int32_t		nd_flag;	/* nd_flag */
	u_int32_t		nd_repstat;	/* Reply status */
	int			*nd_errp;	/* Pointer to ret status */
	u_int32_t		nd_retxid;	/* Reply xid */
	struct nfsrvcache	*nd_rp;		/* Assoc. cache entry */
	struct timeval		nd_starttime;	/* Time RPC initiated */
	fhandle_t		nd_fh;		/* File handle */
	struct ucred		*nd_cred;	/* Credentials */
	uid_t			nd_saveduid;	/* Saved uid */
	u_int64_t		nd_sockref;	/* Rcv socket ref# */
	u_int64_t		nd_compref;	/* Compound RPC ref# */
	time_t			nd_tcpconntime;	/* Time TCP connection est. */
	nfsquad_t		nd_clientid;	/* Implied clientid */
	int			nd_gssnamelen;	/* principal name length */
	char			*nd_gssname;	/* principal name */
};

#define	nd_princlen	nd_gssnamelen
#define	nd_principal	nd_gssname

/* Bits for "nd_flag" */
#define	ND_DONTSAVEREPLY 	0x00000001
#define	ND_SAVEREPLY		0x00000002
#define	ND_NFSV2		0x00000004
#define	ND_NFSV3		0x00000008
#define	ND_NFSV4		0x00000010
#define	ND_KERBV		0x00000020
#define	ND_GSSINTEGRITY		0x00000040
#define	ND_GSSPRIVACY		0x00000080
#define	ND_WINDOWVERF		0x00000100
#define	ND_GSSINITREPLY		0x00000200
#define	ND_STREAMSOCK		0x00000400
#define	ND_PUBLOOKUP		0x00000800
#define	ND_USEGSSNAME		0x00001000
#define	ND_SAMETCPCONN		0x00002000
#define	ND_IMPLIEDCLID		0x00004000
#define	ND_NOMOREDATA		0x00008000
#define	ND_V4WCCATTR		0x00010000
#define	ND_NFSCB		0x00020000
#define	ND_AUTHNONE		0x00040000
#define	ND_EXAUTHSYS		0x00080000
#define	ND_EXGSS		0x00100000
#define	ND_EXGSSINTEGRITY	0x00200000
#define	ND_EXGSSPRIVACY		0x00400000
#define	ND_INCRSEQID		0x00800000

/*
 * ND_GSS should be the "or" of all GSS type authentications.
 */
#define	ND_GSS		(ND_KERBV)

struct nfsv4_opflag {
	int	retfh;
	int	needscfh;
	int	savereply;
	int	modifyfs;
	int	lktype;
};

/*
 * Flags used to indicate what to do w.r.t. seqid checking.
 */
#define	NFSRVSEQID_FIRST	0x01
#define	NFSRVSEQID_LAST		0x02
#define	NFSRVSEQID_OPEN		0x04

/*
 * assign a doubly linked list to a new head
 * and prepend one list into another.
 */
#define	LIST_NEWHEAD(nhead, ohead, field) do { 				\
	if (((nhead)->lh_first = (ohead)->lh_first) != NULL) 		\
		(ohead)->lh_first->field.le_prev = &(nhead)->lh_first; 	\
	(ohead)->lh_first = NULL; 					\
    } while (0)

#define	LIST_PREPEND(head, phead, lelm, field) do {			\
	if ((head)->lh_first != NULL) {					\
		(lelm)->field.le_next = (head)->lh_first;		\
		(lelm)->field.le_next->field.le_prev =			\
		    &(lelm)->field.le_next;				\
	}								\
	(head)->lh_first = (phead)->lh_first;				\
	(head)->lh_first->field.le_prev = &(head)->lh_first;		\
    } while (0)

/*
 * File handle structure for client. Malloc'd to the correct length with
 * malloc type M_NFSFH.
 */
struct nfsfh {
	u_int16_t	nfh_len;	/* Length of file handle */
	u_int8_t	nfh_fh[1];	/* and the file handle */
};

/*
 * File handle structure for server. The NFSRV_MAXFH constant is
 * set in nfsdport.h. I use a 32bit length, so that alignment is
 * preserved.
 */
struct nfsrvfh {
	u_int32_t	nfsrvfh_len;
	u_int8_t	nfsrvfh_data[NFSRV_MAXFH];
};

/*
 * This structure is used for sleep locks on the NFSv4 nfsd threads and
 * NFSv4 client data structures.
 */
struct nfsv4lock {
	u_int32_t	nfslock_usecnt;
	u_int8_t	nfslock_lock;
};
#define	NFSV4LOCK_LOCK		0x01
#define	NFSV4LOCK_LOCKWANTED	0x02
#define	NFSV4LOCK_WANTED	0x04

/*
 * Values for the override argument for nfsvno_accchk().
 */
#define	NFSACCCHK_NOOVERRIDE		0
#define	NFSACCCHK_ALLOWROOT		1
#define	NFSACCCHK_ALLOWOWNER		2

/*
 * and values for the vpislocked argument for nfsvno_accchk().
 */
#define	NFSACCCHK_VPNOTLOCKED		0
#define	NFSACCCHK_VPISLOCKED		1

#endif	/* _KERNEL */

#endif	/* _NFS_NFS_H */