/* * Copyright 1997,1998 Julian Elischer. All rights reserved. * julian@freebsd.org * * 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. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``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 HOLDER 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$ */ #ifdef DEVFS_DEBUG #define DBPRINT(A) printf(A) #else #define DBPRINT(A) #endif /* first a couple of defines for compatibility with inodes */ #define ISUID 04000 /* set user identifier when exec'ing */ #define ISGID 02000 /* set group identifier when exec'ing */ #define ISVTX 01000 /* save execution information on exit */ #define IREAD 0400 /* read permission */ #define IWRITE 0200 /* write permission */ #define IEXEC 0100 /* execute permission */ #define ILOCKED 0x0001 /* inode is locked */ #define IWANT 0x0002 /* some process waiting on lock */ #define IRENAME 0x0004 /* inode is being renamed */ #define IUPD 0x0010 /* file has been modified */ #define IACC 0x0020 /* inode access time to be updated */ #define ICHG 0x0040 /* inode has been changed */ #define IMOD 0x0080 /* inode has been modified */ #define ISHLOCK 0x0100 /* file has shared lock */ #define IEXLOCK 0x0200 /* file has exclusive lock */ #define ILWAIT 0x0400 /* someone waiting on file lock */ /* * Lock and unlock inodes. */ #ifdef notdef #define DNLOCK(ip) { \ while ((ip)->i_flag & ILOCKED) { \ (ip)->i_flag |= IWANT; \ (void) sleep((caddr_t)(ip), PINOD); \ } \ (ip)->i_flag |= ILOCKED; \ } #define DNUNLOCK(ip) { \ (ip)->i_flag &= ~ILOCKED; \ if ((ip)->i_flag&IWANT) { \ (ip)->i_flag &= ~IWANT; \ wakeup((caddr_t)(ip)); \ } \ } #else #define DNLOCK(ip) #define DNUNLOCK(ip) #endif #define DEVMAXNAMESIZE 32 #define DEVMAXPATHSIZE 128 #define DEV_DIR 1 #define DEV_BDEV 2 #define DEV_CDEV 3 #define DEV_DDEV 4 #define DEV_ALIAS 5 #define DEV_SLNK 6 #define DEV_PIPE 7 extern vop_t **devfs_vnodeop_p; /* our own vector array for dirs */ extern vop_t **devfs_spec_vnodeop_p; /* our own vector array for devs */ typedef struct dev_name *devnm_p; typedef struct devnode *dn_p; struct devnode /* the equivalent of an INODE */ { u_short type; int flags; /* more inode compatible for now *//*XXXkill*/ #define IN_ACCESS 0x0001 u_short mode; /* basically inode compatible (drwxrwxrwx) */ u_short uid; /* basically inode compatible */ u_short gid; /* basically inode compatible */ struct timespec atime; /* time of last access */ struct timespec mtime; /* time of last modification */ struct timespec ctime; /* time file changed */ int links; /* how many file links does this node have? */ struct devfsmount *dvm; /* the mount structure for this 'plane' */ struct vnode *vn; /* address of last vnode that represented us */ u_long vn_id; /* make sure we have the right vnode */ int (***ops)(void *); /* yuk... pointer to pointer(s) to funcs */ int len; /* of any associated info (e.g. dir data) */ devnm_p linklist; /* circular list of hardlinks to this node */ devnm_p last_lookup; /* name I was last looked up from */ dn_p nextsibling; /* the list of equivelent nodes */ dn_p *prevsiblingp; /* backpointer for the above */ union typeinfo { struct { dev_t dev; }dev; struct { int (***ops)(void *); /* duplicate, used in dev_add_node */ int arg; }Ddev; struct { devnm_p dirlist; devnm_p *dirlast; dn_p parent; devnm_p myname; /* my entry in .. */ int entrycount; }Dir; struct { char *name; /* must be allocated separately */ int namelen; }Slnk; struct { devnm_p realthing; devnm_p next; }Alias; struct { struct socket *sock; }Pipe; }by; }; typedef struct devnode devnode_t; struct dev_name { /*-----------------------directory entry fields-------------*/ char name[DEVMAXNAMESIZE]; dn_p dnp; /* the "inode" (devnode) pointer */ dn_p parent; /* backpointer to the directory itself */ devnm_p next; /* next object in this directory */ devnm_p *prevp; /* previous pointer in directory linked list */ devnm_p nextlink; /* next hardlink to this node */ devnm_p *prevlinkp; /* previous hardlink pointer for this node */ /*-----------------------aliases or backing nodes----------*/ union { struct { devnm_p aliases; /* aliase chain (kill with us)*/ } back; struct { devnm_p realthing; /* ptr to the backing node */ } front; } as; }; typedef struct dev_name devnm_t; extern int devfs_up_and_going; extern devnm_p dev_root; /* * Rules for front nodes: * Dirs hava a strict 1:1 relationship with their OWN devnode * Symlinks similarly * Device Nodes ALWAYS point to the devnode that is linked * to the Backing node. (with a ref count) */ /* * DEVFS specific per/mount information, used to link a monted fs to a * particular 'plane' of front nodes. */ struct devfsmount { struct mount *mount; /* vfs mount struct for this fs */ devnm_p plane_root; /* the root of this 'plane' */ int flags; /* usefule some day 8-) */ }; struct dev_vn_data { char magic[6]; /* = "devfs" if correct */ devnm_p front; devnm_p back; }; /* * Prototypes for DEVFS virtual filesystem operations */ #include