| Guide to Porting lsof 4 to Unix OS Dialects | |
| ********************************************************************** | |
| | The latest release of lsof is always available via anonymous ftp | | |
| | from lsof.itap.purdue.edu. Look in pub/lsof.README for its | | |
| | location. | | |
| ********************************************************************** | |
| Contents | |
| How Lsof Works | |
| /proc-based Linux Lsof -- a Different Approach | |
| General Guidelines | |
| Organization | |
| Source File Naming Conventions | |
| Coding Philosophies | |
| Data Requirements | |
| Dlsof.h and #include's | |
| Definitions That Affect Compilation | |
| Options: Common and Special | |
| Defining Dialect-Specific Symbols and Global Storage | |
| Coding Dialect-specific Functions | |
| Function Prototype Definitions and the _PROTOTYPE Macro | |
| The Makefile | |
| The Mksrc Shell Script | |
| The MkKernOpts Shell Script | |
| Testing and the lsof Test Suite | |
| Where Next? | |
| How Lsof Works | |
| -------------- | |
| Before getting on with porting guidelines, just a word or two about | |
| how lsof works. | |
| Lsof obtains data about open UNIX dialect files by reading the | |
| kernel's proc structure information, following it to the related | |
| user structure, then reading the open file structures stored | |
| (usually) in the user structure. Typically lsof uses the kernel | |
| memory devices, /dev/kmem, /dev/mem, etc. to read kernel data. | |
| Lsof stores information from the proc and user structures in an | |
| internal, local proc structure table. It then processes the open | |
| file structures by reading the file system nodes that lie behind | |
| them, extracting and storing relevant data in internal local file | |
| structures that are linked to the internal local process structure. | |
| Once all data has been gathered, lsof reports it from its internal, | |
| local tables. | |
| There are a few variants on this subject. Some systems don't have | |
| just proc structures, but have task structures, too, (e.g., NeXTSTEP | |
| and OSF/1 derivatives). For some dialects lsof gets proc structures | |
| or process information (See "/proc-based Linux Lsof -- a Different | |
| Approach) from files of the /proc file system. It's not necessary | |
| for lsof to read user structures on some systems (recent versions | |
| of HP-UX), because the data lsof needs can be found in the task or | |
| proc structures. In the end lsof gathers the same data, just from | |
| slightly different sources. | |
| /proc-based Linux Lsof -- a Different Approach | |
| ============================================== | |
| For a completely different approach to lsof construction, take a | |
| look at the /proc-based Linux sources in .../dialects/linux/proc. | |
| (The sources in .../dialects/linux/kmem are for a traditional lsof | |
| that uses /dev/kmem to read information from kernel structures.) | |
| The /proc-based lsof obtains all its information from the Linux | |
| /proc file system. Consequently, it is relatively immune to changes | |
| in Linux kernel structures and doesn't need to be re-compiled each | |
| time the Linux kernel version changes. | |
| There are some down-sides to the Linux /proc-based lsof: | |
| * It must run setuid-root in order to be able to read the | |
| /proc file system branches for all processes. In contrast, | |
| the /dev/kmem-based Linux lsof usually needs only setgid | |
| permission. | |
| * It depends on the exact character format of /proc files, so | |
| it is sensitive to changes in /proc file composition. | |
| * It is limited to the information a /proc file system | |
| implementor decides to provide. For example, if a | |
| /proc/net/<protocol> file lacks an inode number, the | |
| /proc-based lsof can't connect open socket files to that | |
| protocol. Another deficiency is that the /proc-based may | |
| not be able to report file offset (position) information, | |
| when it isn't available in the /proc/<PID>/fd/ entry for a | |
| file. | |
| In contrast the /dev/kmem-based lsof has full access to | |
| kernel structures and "sees" new data as soon as it appears. | |
| Of course, that new data requires that lsof be recompiled | |
| and usually also requires changes to lsof. | |
| Overall the switch from a /dev/kmem base to a /proc one is an | |
| advantage to Linux lsof. The switch was made at lsof revision 4.23 | |
| for Linux kernel versions 2.1.72 (approximately) and higher. The | |
| reason I'm not certain at which Linux kernel version a /proc-based | |
| lsof becomes possible is that the /proc additions needed to implement | |
| it have been added gradually to Linux 2.1.x in ways that I cannot | |
| measure. | |
| /proc-based lsof functions in many ways the same as /dev/kmem-based | |
| lsof. It scans the /proc directory, looking for <PID>/ subdirectories. | |
| Inside each one it collects process-related data from the cwd, exe, | |
| maps, root, and stat information files. | |
| It collects open file information from the fd/ subdirectory of each | |
| <PID>/ subdirectory. The lstat(2), readlink(2), and stat(2) system | |
| calls gather information about the files from the kernel. | |
| Lock information comes from /proc/locks. It is matched to open | |
| files by inode number. Mount information comes from /proc/mounts. | |
| Per domain protocol information comes from the files of /proc/net; | |
| it's matched to open socket files by inode number. | |
| The Linux /proc file system implementors have done an amazing job | |
| of providing the information lsof needs. The /proc-based lsof | |
| project has so far generated only two kernel modification: | |
| * A modification to /usr/src/linux/net/ipx/af_ipx.c adds the | |
| inode number to the entries of /proc/net/ipx. | |
| Jonathan Sergent did this kernel modification. | |
| It may be found in the .../dialects/linux/proc/patches | |
| subdirectory of the lsof distribution. | |
| * An experimental modification to /usr/src/linux/fs/stat.c | |
| allows lstat(2) to return file position information for | |
| /proc/<PID>/fd/<FD> files. | |
| Contact me for this modification. | |
| One final note about the /proc-based Linux lsof: it doesn't need | |
| any functions from the lsof library in the lib/ subdirectory. | |
| General Guidelines | |
| ------------------ | |
| These are the general guidelines for porting lsof 4 to a new Unix | |
| dialect: | |
| * Understand the organization of the lsof sources and the | |
| philosophies that guide their coding. | |
| * Understand the data requirements and determine the methods | |
| of locating the necessary data in the new dialect's kernel. | |
| * Pick a name for the subdirectory in lsof4/dialects for your | |
| dialect. Generally I use a vendor operating system name | |
| abbreviation. | |
| * Locate the necessary header files and #include them in the | |
| dialect's dlsof.h file. (You may not be able to complete | |
| this step until you have coded all dialect-specific functions.) | |
| * Determine the optional library functions of lsof to be used | |
| and set their definitions in the dialect's machine.h file. | |
| * Define the dialect's specific symbols and global storage | |
| in the dialect's dlsof.h and dstore.c files. | |
| * Code the dialect-specific functions in the appropriate | |
| source files of the dialect's subdirectory. | |
| Include the necessary prototype definitions of the dialect- | |
| specific functions in the dproto.h file in the dialect's | |
| subdirectory. | |
| * Define the dialect's Makefile and source construction shell | |
| script, Mksrc. | |
| * If there are #define's that affect how kernel structures | |
| are organized, and those #define's are needed when compiling | |
| lsof, build a MkKernOpts shell script to locate the #define's | |
| and supply them to the Configure shell script. | |
| Organization | |
| ------------ | |
| The code in a dialect-specific version of lsof comes from three | |
| sources: | |
| 1) functions common to all versions, located in the top level | |
| directory, lsof4; | |
| 2) functions specific to the dialect, located in the dialect's | |
| subdirectory -- e.g., lsof4/dialects/sun; | |
| 3) functions that are common to several dialects, although | |
| not to all, organized in a library, liblsof.a. The functions | |
| in the library source can be selected and customized with | |
| definitions in the dialect machine.h header files. | |
| The tree looks like this: | |
| lsof4 ----------------------+ 3) library -- | |
| | \ lsof4/lib | |
| 1) fully common functions + \ | |
| e.g., lsof4/main.c + lsof4/dialects/ | |
| / / / / \ | |
| + + + + + | |
| 2) dialect-specific subdirectories -- e.g., lsof4/dialects/sun | |
| The code for a dialect-specific version is constructed from these | |
| three sources by the Configure shell script in the top level lsof4 | |
| directory and definitions in the dialect machine.h header files. | |
| Configure uses the Mksrc shell script in each dialect's subdirectory, | |
| and may use an optional MkKernOpts shell script in selected dialect | |
| subdirectories. | |
| Configure calls the Mksrc shell script in each dialect's subdirectory | |
| to assemble the dialect-specific sources in the main lsof directory. | |
| Configure may call MkKernOpts to determine kernel compile-time | |
| options that are needed for compiling kernel structures correctly | |
| for use by lsof. Configure puts the options in a dialect-specific | |
| Makefile it build, using a template in the dialect subdirectory. | |
| The assembly of dialect-specific sources in the main lsof directory | |
| is usually done by creating symbolic links from the top level to | |
| the dialect's subdirectory. The LSOF_MKC environment variable may | |
| be defined prior to using Configure to change the technique used | |
| to assemble the sources -- most commonly to use cp instead of ln -s. | |
| The Configure script completes the dialect's Makefile by adding | |
| string definitions, including the necessary kernel compile-time | |
| options, to a dialect skeleton Makefile while copying it from the | |
| dialect subdirectory to the top level lsof4 directory. Optionally | |
| Makefile may call the dialect's MkKernOpts script to add string | |
| definitions. | |
| When the lsof library, lsof4/lib/liblsof.a, is compiled its | |
| functions are selected and customized by #define's in the dialect | |
| machine.h header file. | |
| Source File Naming Conventions | |
| ------------------------------ | |
| With one exception, dialect-specific source files begin with a | |
| lower case `d' character -- ddev.c, dfile.c, dlsof.h. The one | |
| exception is the header file that contains dialect-specific | |
| definitions for the optional features of the common functions. | |
| It's called machine.h for historical reasons. | |
| Currently all dialects use almost the same source file names. One | |
| exception to the rule happens in dialects where there must be | |
| different source files -- e.g., dnode[123].c -- to eliminate node | |
| header file structure element name conflicts. The source modules | |
| in a few subdirectories are organized that way. | |
| Unusual situations occur for NetBSD and OpenBSD, and for NEXTSTEP | |
| and OPENSTEP. Each pair of dialects is so close in design that | |
| the same dialect sources from the n+obsd subdirectory serves NetBSD | |
| and OpenBSD; from n+os, NEXTSTEP and OPENSTEP. | |
| These are common files in lsof4/: | |
| Configure the configuration script | |
| Customize does some customization of the selected lsof | |
| dialect | |
| Inventory takes an inventory of the files in an lsof | |
| distribution | |
| version the version number | |
| dialects/ the dialects subdirectory | |
| These are the common function source files in lsof4/: | |
| arg.c common argument processing functions | |
| lsof.h common header file that #include's the dialect-specific | |
| header files | |
| main.c common main function for lsof 4 | |
| misc.c common miscellaneous functions -- e.g., special versions | |
| of stat() and readlink() | |
| node.c common node reading functions -- readinode(), readvnode() | |
| print.c common print support functions | |
| proc.c common process and file structure functions | |
| proto.h common prototype definitions, including the definition of | |
| the _PROTOTYPE() macro | |
| store.c common global storage version.h the current lsof version | |
| number, derived from the file version by the Makefile | |
| usage.c functions to display lsof usage panel | |
| These are the dialect-specific files: | |
| Makefile the Makefile skeleton | |
| Mksrc a shell script that assists the Configure script | |
| in configuring dialect sources | |
| MkKernOpts an optional shell script that identifies kernel | |
| compile-time options for selected dialects -- e.g., | |
| Pyramid DC/OSx and Reliant UNIX | |
| ddev.c device support functions -- readdev() -- may be | |
| eliminated by functions from lsof4/lib/ | |
| dfile.c file processing functions -- may be eliminated by | |
| functions from lsof4/lib/ | |
| dlsof.h dialect-specific header file -- contains #include's | |
| for system header files and dialect-specific global | |
| storage declarations | |
| dmnt.c mount support functions -- may be eliminated by | |
| functions from lsof4/lib/ | |
| dnode.c node processing functions -- e.g., for gnode or vnode | |
| dnode?.c additional node processing functions, used when node | |
| header files have duplicate and conflicting element | |
| names. | |
| dproc.c functions to access, read, examine and cache data about | |
| dialect-specific process structures -- this file contains | |
| the dialect-specific "main" function, gather_proc_info() | |
| dproto.h dialect-specific prototype declarations | |
| dsock.c dialect-specific socket processing functions | |
| dstore.c dialect-specific global storage -- e.g., the nlist() | |
| structure | |
| machine.h dialect specific definitions of common function options -- | |
| e.g., a HASINODE definition to activate the readinode() | |
| function in lsof4/node.c | |
| The machine.h header file also selects and customizes | |
| the functions of lsof4/lib/. | |
| These are the lib/ files. Definitions in the dialect machine.h | |
| header files select and customize the contained functions that are | |
| to be compiled and archived to liblsof.a. | |
| Makefile.skel is a skeleton Makefile, used by Configure | |
| to construct the Makefile for the lsof | |
| library. | |
| cvfs.c completevfs() function | |
| USE_LIB_COMPLETEVFS selects it. | |
| CVFS_DEVSAVE, CVFS_NLKSAVE, CVFS_SZSAVE, | |
| and HASFSINO customize it. | |
| dvch.c device cache functions | |
| HASDCACHE selects them. | |
| DCACHE_CLONE, DCACHE_CLR, DCACHE_PSEUDO, | |
| DVCH_CHOWN, DVCH_DEVPATH, DVCH_EXPDEV, | |
| HASBLKDEV, HASENVDC, HASSYSDC, HASPERSDC, | |
| HASPERSDCPATH, and NOWARNBLKDEV customize | |
| them. | |
| fino.c find block and character device inode functions | |
| HASBLKDEV and USE_LIB_FIND_CH_INO select them. | |
| isfn.c hashSfile() and is_file_named() functions | |
| USE_LIB_IS_FILE_NAMED selects it. | |
| lkud.c device lookup functions | |
| HASBLKDEV and USE_LIB_LKUPDEV select them. | |
| pdvn.c print device name functions | |
| HASBLKDEV and USE_LIB_PRINTDEVNAME select them. | |
| prfp.c process_file() function | |
| USE_LIB_PROCESS_FILE selects it. | |
| FILEPTR, DTYPE_PIPE, HASPIPEFN, DTYPE_GNODE, | |
| DTYPE_INODE, DTYPE_PORT, DTYPE_VNODE, | |
| HASF_VNODE, HASKQUEUE, HASPRIVFILETYPE, | |
| HASPSXSHM and HASPSXSEM customize it. | |
| ptti.c print_tcptpi() function | |
| USE_LIB_PRINT_TCPTPI selects it. | |
| HASSOOPT, HASSBSTATE, HASSOSTATE, AHSTCPOPT, | |
| HASTCPTPIQ and HASTCPTPIW customize it. | |
| rdev.c readdev() function | |
| USE_LIB_READDEV selects it. | |
| DIRTYPE, HASBLKDEV, HASDCACHE, HASDNAMLEN, | |
| RDEV_EXPDEV, RDEV_STATFN, USE_STAT, and | |
| WARNDEVACCESS customize it. | |
| rmnt.c readmnt() function | |
| USE_LIB_READMNT selects it. | |
| HASFSTYPE, MNTSKIP, RMNT_EXPDEV, RMNT_FSTYPE, | |
| and MOUNTS_FSTYPE customize it. | |
| rnam.c BSD format name cache functions | |
| HASNCACHE and USE_LIB_RNAM select them. | |
| HASFSINO, NCACHE, NCACHE_NC_CAST, NCACHE_NM, | |
| NCACHE_NMLEN, NCACHE_NODEADDR, NCACHE_NODEID, | |
| NCACHE_NO_ROOT, NCACHE_NXT, NCACHE_PARADDR, | |
| NCACHE_PARID, NCACHE_SZ_CAST, NCHNAMLEN, | |
| X_NCACHE, and X_NCSIZE, customize them. | |
| rnch.c Sun format name cache functions | |
| HASNCACHE and USE_LIB_RNCH select them. | |
| ADDR_NCACHE, HASDNLCPTR, HASFSINO, NCACHE_DP, | |
| NCACHE_NAME, NCACHE_NAMLEN, NCACHE_NEGVN, | |
| NCACHE_NODEID, NCACHE_NXT, NCACHE_PARID, | |
| NCACHE_VP, X_NCACHE, and X_NCSIZE, customize | |
| them. | |
| snpf.c Source for the snprintf() family of functions | |
| USE_LIB_SNPF selects it. | |
| The comments and the source code in these library files give more | |
| information on customization. | |
| Coding Philosophies | |
| ------------------- | |
| A few basic philosophies govern the coding of lsof 4 functions: | |
| * Use as few #if/#else/#endif constructs as possible, even at | |
| the cost of nearly-duplicate code. | |
| When #if/#else/#endif constructs are necessary: | |
| o Use the form | |
| #if defined(s<symbol>) | |
| in preference to | |
| #ifdef <symbol> | |
| to allow easier addition of tests to the #if. | |
| o Indent them to signify their level -- e.g., | |
| #if /* level one */ | |
| # if /* level two */ | |
| # endif /* level two */ | |
| #else /* level one */ | |
| #endif /* level one */ | |
| o Use ANSI standard comments on #else and #endif statements. | |
| * Document copiously. | |
| * Aim for ANSI-C compatibility: | |
| o Use function prototypes for all functions, hiding them | |
| from compilers that cannot handle them with the _PROTOTYPE() | |
| macro. | |
| o Use the compiler's ANSI conformance checking wherever | |
| possible -- e.g., gcc's -ansi option. | |
| Data Requirements | |
| ----------------- | |
| Lsof's strategy in obtaining open file information is to access | |
| the process table via its proc structures, then obtain the associated | |
| user area and open file structures. The open file structures then | |
| lead lsof to file type specific structures -- cdrnodes, fifonodes, | |
| inodes, gnodes, hsfsnodes, pipenodes, pcnodes, rnodes, snodes, | |
| sockets, tmpnodes, and vnodes. | |
| The specific node structures must yield data about the open files. The | |
| most important items and device number (raw and cooked) and node | |
| number. (Lsof uses them to identify files and file systems named as | |
| arguments.) Link counts and file sizes are important, too, as are the | |
| special characteristics of sockets, pipes, FIFOs, etc. | |
| This means that to begin an lsof port to a new Unix dialect you | |
| must understand how to obtain these structures from the dialect's | |
| kernel. Look for kernel access functions -- e.g., the AIX readx() | |
| function, Sun and Sun-like kvm_*() functions, or SGI's syssgi() | |
| function. Look for clues in header files -- e.g. external declarations | |
| and macros. | |
| If you have access to them, look at sources to programs like ps(1), | |
| or the freely available monitor and top programs. They may give | |
| you important clues on reading proc and user area structures. An | |
| appeal to readers of dialect-specific news groups may uncover | |
| correspondents who can help. | |
| Careful reading of system header files -- e.g., <sys/proc.h> -- | |
| may give hints about how kernel storage is organized. Look for | |
| global variables declared under a KERNEL or _KERNEL #if. Run nm(1) | |
| across the kernel image (/vmunix, /unix, etc.) and look for references | |
| to structures of interest. | |
| Even if there are support functions for reading structures, like the | |
| kvm_*() functions, you must still understand how to read data from | |
| kernel memory. Typically this requires an understanding of the | |
| nlist() function, and how to use /dev/kmem, /dev/mem, and /dev/swap. | |
| Don't overlook the possibility that you may have to use the process | |
| file system -- e.g., /proc. I try to avoid using /proc when I can, | |
| since it usually requires that lsof have setuid(root) permission | |
| to read the individual /proc "files". | |
| Once you can access kernel structures, you must understand how | |
| they're connected. You must answer questions like: | |
| * How big are kernel addresses? How are they type cast? | |
| * How are kernel variable names converted to addresses? | |
| Nlist()? | |
| * How are the proc structures organized? Is it a static | |
| table? Are the proc structures linked? Is there a | |
| kernel pointer to the first proc structure? Is there a | |
| proc structure count? | |
| * How does one obtain copies of the proc structures? Via | |
| /dev/kmem? Via a vendor API? | |
| * If this is a Mach derivative, is it necessary to obtain the | |
| task and thread structures? How? | |
| * How does one obtain the user area (or the utask area in Mach | |
| systems) that corresponds to a process? | |
| * Where are the file structures located for open file | |
| descriptors and how are they located? Are all file | |
| structures in the user area? Is the file structure space | |
| extensible? | |
| * Where do the private data pointers in file structures lead? | |
| To gnodes? To inodes? To sockets? To vnodes? Hint: look | |
| in <sys/file.h> for DTYPE_* instances and further pointers. | |
| * How are the nodes organized? To what other nodes do they | |
| lead and how? Where are the common bits of information in | |
| nodes -- device, node number, size -- stored? Hint: look | |
| in the header files for nodes for macros that may be used | |
| to obtain the address of one node from another -- e.g., the | |
| VTOI() macro that leads from a vnode to an inode. | |
| * Are text reference nodes identified and how? Is it | |
| necessary to examine the virtual memory map of a process or | |
| a task to locate text references? Some kernels have text | |
| node pointers in the proc structures; some, in the user | |
| area; Mach kernels may have text information in the task | |
| structure, reached in various ways from the proc, user area, | |
| or user task structure. | |
| * How is the device table -- e.g., /dev or /devices -- | |
| organized? How is it read? Using direct or dirent structures? | |
| How are major/minor device numbers represented? How are | |
| device numbers assembled and disassembled? | |
| Are there clone devices? How are they identified? | |
| * How is mount information obtained? Getmntinfo()? Getmntent()? | |
| Some special kernel call? | |
| * How are sockets identified and organized? BSD-style? As | |
| streams? Are there streams? | |
| * Are there special nodes -- CD-ROM nodes, FIFO nodes, etc.? | |
| * How is the kernel's name cache organized? Can lsof access | |
| it to get partial name components? | |
| Dlsof.h and #include's | |
| ---------------------- | |
| Once you have identified the kernel's data organization and know | |
| what structures it provides, you must add #include's to dlsof.h to | |
| access their definitions. Sometimes it is difficult to locate the | |
| header files -- you may need to introduce -I specifications in the | |
| Makefile via the DINC shell variable in the Configure script. | |
| Sometimes it is necessary to define special symbols -- e.g., KERNEL, | |
| _KERNEL, _KMEMUSER -- to induce system header files to yield kernel | |
| structure definitions. Sometimes making those symbol definitions | |
| cause other header file and definition conflicts. There's no good | |
| general rule on how to proceed when conflicts occur. | |
| Rarely it may be necessary to extract structure definitions from | |
| system header files and move them to dlsof.h, create special versions | |
| of system header files, or obtain special copies of system header | |
| files from "friendly" (e.g., vendor) sources. The dlsof.h header | |
| file in lsof4/dialects/sun shows examples of the first case; the | |
| second, no examples; the third, the irix5hdr subdirectory in | |
| lsof4/dialects/irix (a mixture of the first and third). | |
| Building up the necessary #includes in dlsof.h is an iterative | |
| process that requires attention as you build the dialect-specific | |
| functions that references kernel structures. Be prepared to revisit | |
| dlsof.h frequently. | |
| Definitions That Affect Compilation | |
| ----------------------------------- | |
| The source files at the top level and in the lib/ subdirectory | |
| contain optional functions that may be activated with definitions | |
| in a dialect's machine.h header file. Some are functions for | |
| reading node structures that may not apply to all dialects -- e.g. | |
| CD-ROM nodes (cdrnode), or `G' nodes (gnode) -- and others are | |
| common functions that may occasionally be replaced by dialect-specific | |
| ones. Once you understand your kernel's data organization, you'll | |
| be able to decide the optional common node functions to activate. | |
| Definitions in machine.h and dlsof.h also enable or disable other | |
| optional common features. The following is an attempt to list all | |
| the definitions that affect lsof code, but CAUTION, it is only | |
| attempt and may be incomplete. Always check lsof4 source code in | |
| lib/ and dialects/, and dialect machine.h header files for other | |
| possibilities | |
| AFS_VICE See 00XCONFIG. | |
| AIX_KERNBITS specifies the kernel bit size, 32 or 64, of the Power | |
| architecture AIX 5.x kernel for which lsof was built. | |
| CAN_USE_CLNT_CREATE is defined for dialects where the more modern | |
| RPC function clnt_create() can be used in | |
| place of the deprecated clnttcp_create(). | |
| CLONEMAJ defines the name of the variable that | |
| contains the clone major device number. | |
| (Also see HAS_STD_CLONE and HAVECLONEMAJ.) | |
| DEVDEV_PATH defines the path to the directory where device | |
| nodes are stored, usually /dev. Solaris 10 | |
| uses /devices. | |
| DIALECT_WARNING may be defined by a dialect to provide a | |
| warning message that will be displayed with | |
| help (-h) and version (-v) output. | |
| FSV_DEFAULT defines the default file structure values to | |
| list. It may be composed of or'd FSV_* | |
| (See lsof.h) values. The default is none (0). | |
| GET_MAJ_DEV is a macro to get major portion from device | |
| number instead of via the standard major() | |
| macro. | |
| GET_MIN_DEV is a macro to get minor portion from device | |
| number instead of via the standard minor() | |
| macro. | |
| GET_MAX_FD the name of the function that returns an | |
| int for the maximum open file descriptor | |
| plus one. If not defined, defaults to | |
| getdtablesize. | |
| HAS9660FS enables CD9660 file system support in a | |
| BSD dialect. | |
| HAS_ADVLOCK_ARGS is defined for NetBSD and OpenBSD dialects | |
| whose <sys/lockf.h> references vop_advlock_args. | |
| HAS_AFS enables AFS support code for the dialect. | |
| HAS_ATOMIC_T indicates the Linux version has an | |
| <asm/atomic.h> header file and it contains | |
| "typedef struct .* atomic_t;" | |
| HASAOPT indicates the dialect supports the AFS -A | |
| option when HAS_AFS is also defined. | |
| HAS_ASM_TERMIOBITS indicates for Linux Alpha that the | |
| <asm/termiobits.h> header file exists. | |
| HASAX25CBPTR indicates that the Linux sock struct has an | |
| ax25_db pointer. | |
| HASBLKDEV indicates the dialect has block device support. | |
| HASBUFQ_H indicates the *NSD dialect has the <sys/bufq.h> | |
| header file. | |
| HASCACHEFS enables cache file system support for the | |
| dialect. | |
| HAS_CDFS enables CDFS file system support for the | |
| dialect. | |
| HASCDRNODE enables/disables readcdrnode() in node.c. | |
| HAS_CONN_NEW indicates the Solaris version has the new form | |
| of the conn_s structure, introduced in b134 of | |
| Solaris 11. This will always accompany the | |
| HAS_IPCLASSIFIER_H definition. | |
| HAS_CONST indicates that the compiler supports the | |
| const keyword. | |
| HASCPUMASK_T indicates the FreeBSD 5.2 or higher dialect | |
| has cpumask_t typedef's. | |
| HAS_CRED_IMPL_H indicates the Solaris 10 dialect has the | |
| <sys/cred_impl.h> header file available. | |
| HASCWDINFO indicates the cwdinfo structure is defined | |
| in the NetBSD <sys/filedesc.h>. | |
| HASDCACHE enables device file cache file support. | |
| The device cache file contains information | |
| about the names, device numbers and inode | |
| numbers of entries in the /dev (or /device) | |
| node subtree that lsof saves from call to | |
| call. See the 00DCACHE file of the lsof | |
| distribution for more information on this | |
| feature. | |
| HASDENTRY indicates the Linux version has a dentry | |
| struct defined in <linux/dcache.h>. | |
| HASDEVKNC indicates the Linux version has a kernel | |
| name cached keyed on device number. | |
| HAS_DINODE_U indicates the OpenBSD version has a dinode_u | |
| union in its inode structure. | |
| HASDNLCPTR is defined when the name cache entry of | |
| <sys/dnlc.h> has a name character pointer | |
| rather than a name character array. | |
| HASEFFNLINK indicates the *BSD system has the i_effnlink | |
| member in the inode structure. | |
| HASENVDC enables the use of an environment-defined | |
| device cache file path and defines the name | |
| of the environment variable from which lsof | |
| may take it. (See the 00DCACHE file of | |
| the lsof distribution for information on | |
| when HASENVDC is used or ignored.) | |
| HASEOPT indicates the dialect supports the -e option to | |
| eliminate kernel blocks on a named file system. | |
| HASEXT2FS is defined for BSD dialects for which ext2fs | |
| file system support can be provided. A value | |
| of 1 indicates that the i_e2din member does not | |
| exist; 2, it exists. | |
| HASF_VNODE indicates the dialect's file structure has an | |
| f_vnode member in it. | |
| HASFDESCFS enables file descriptor file system support | |
| for the dialect. A value of 1 indicates | |
| <miscfs/fdesc.h> has a Fctty definition; 2, | |
| it does not. | |
| HASFDLINK indicates the file descriptor file system | |
| node has the fd_link member. | |
| HASFIFONODE enables/disables readfifonode() in node.c. | |
| HAS_FL_FD indicates the Linux version has an fl_fd | |
| element in the lock structure of <linux/fs.h>. | |
| HAS_FL_FILE indicates the Linux version has an fl_file | |
| element in the lock structure of <linux/fs.h>. | |
| HAS_FL_WHENCE indicates the Linux version has an fl_whence | |
| element in the lock structure of <linux/fs.h>. | |
| HAS_F_OPEN indicates the UnixWare 7.x dialect has the | |
| f_open member in its file struct. | |
| HASFSINO enables the inclusion of the fs_ino element | |
| in the lfile structure definition in lsof.h. | |
| This contains the file system's inode number | |
| and may be needed when searching the kernel | |
| name cache. See dialects/osr/dproc.c for | |
| an example. | |
| HAS_JFS2 The AIX >= 5.0 dialect has jfs2 support. | |
| HASFSTRUCT indicates the dialect has a file structure | |
| the listing of whose element values can be | |
| enabled with +f[cfn]. FSV_DEFAULT defines | |
| the default listing values. | |
| HASFSTYPE enables/disables the use of the file system's | |
| stat(2) st_fstype member. | |
| If the HASFSTYPE value is 1, st_fstype is | |
| treated as a character array; 2, it is | |
| treated as an integer. | |
| See also the RMNT_EXPDEV and RMNT_FSTYPE | |
| documentation in lib/rmnt.c | |
| HASGETBOOTFILE indicates the NetBSD or OpenBSD dialect has | |
| a getbootfile() function. | |
| HASGNODE enables/disables readgnode() in node.c. | |
| HASHASHPID is defined when the Linux version (probably | |
| above 2.1.35) has a pidhash_next member in | |
| its task structure. | |
| HASHSNODE enables/disables readhsnode() in node.c. | |
| HASI_E2FS_PTR indicates the BSD dialect has a pointer in | |
| its inode to the EXTFS dinode. | |
| HASI_FFS indicates the BSD dialect has i_ffs_size | |
| in <ufs/ufs/inode.h>. | |
| HASI_FFS1 indicates the BSD dialect supports the fast | |
| UFS1 and UFS2 file systems. | |
| HAS_INKERNEL indicates the SCO OSR 6.0.0 or higher, or | |
| UnixWare 7.1.4 or higher system uses the | |
| INKERNEL symbol in <netinet/in_pcb.h> or | |
| <netinet/tcp_var.h>. | |
| HASINODE enables/disables readinode() in node.c. | |
| HASINOKNC indicates the Linux version has a kernel | |
| name cache keyed on inode address. | |
| HASINADDRSTR is defined when the inp_[fl]addr members | |
| of the inpcb structure are structures. | |
| HASINRIAIPv6 is defined if the dialect has the INRIA IPv6 | |
| support. (HASIPv6 will also be defined.) | |
| HASINT16TYPE is defined when the dialect has a typedef | |
| for int16 that may conflict with some other | |
| header file's redefinition (e.g., <afs/std.h>). | |
| HASINT32TYPE is defined when the dialect has a typedef | |
| for int32 that may conflict with some other | |
| header file's redefinition (e.g., <afs/std.h>). | |
| HASINTSIGNAL is defined when signal() returns an int. | |
| HAS_IPCLASSIFIER_H is defined for Solaris dialects that have the | |
| <inet/ipclassifier.h> header file. | |
| HAS_IPC_S_PATCH is defined when the HP-UX 11 dialect has the | |
| ipc_s patch installed. It has a value of | |
| 1 if the ipc_s structure has an ipc_ipis | |
| member, but the ipis_s structure lacks the | |
| ipis_msgsqueued member; 2, if ipc_s has | |
| ipc_ipis, but ipis_s lacks ipis_msgsqueued. | |
| HASIPv6 indicates the dialect supports the IPv6 | |
| Internet address family. | |
| HASKERNELKEYT indicates the Linux version has a | |
| __kernel_key_t typedef in <linux/types.h>. | |
| HASKERNFS is defined for BSD dialects for which | |
| /kern file system support can be provided. | |
| HASKERNFS_KFS_KT indicates *kfs_kt is in the BSD dialect's | |
| <miscfs/kernfs/kernfs.h>. | |
| HASKOPT enables/disables the ability to read the | |
| kernel's name list from a file -- e.g., from | |
| a crash dump file. | |
| HASKQUEUE indicates the dialect supports the kqueue | |
| file type. | |
| HASKVMGETPROC2 The *BSD dialect has the kvm_gettproc2() | |
| function. | |
| HAS_KVM_VNODE indicates the FreeBSD 5.3 or higher dialect has | |
| "defined(_KVM_VNODE)" in <sys/vnode.h>. | |
| HASLFILEADD defines additional, dialect-specific elements | |
| SETLFILEADD in the lfile structure (defined in lsof.h). | |
| HASLFILEADD is a macro. The accompanying SETFILEADD | |
| macro is used in the alloc_lfile() function of | |
| proc.c to preset the additional elements. | |
| HAS_LF_LWP is defined for BSD dialects where the lockf | |
| structure has an lf_lwp member. | |
| HASLFS indicates the *BSD dialect has log-structured | |
| file system support. | |
| HAS_LGRP_ROOT_CONFLICT | |
| indicates the Solaris 9 or Solaris 10 system has | |
| a conflict over the lgrp_root symbol in the | |
| <sys/lgrp.h> and <sys/lgrp_user.h> header files. | |
| HAS_LIBCTF indicates the Solaris 10 and above system has | |
| the CTF library. | |
| HAS_LOCKF_ENTRY indicates the FreeBSD version has a lockf_entry | |
| structure in its <sys/lockf.h> header file. | |
| HAS_LWP_H is defined for BSD dialects that have the | |
| <sys/lwp.h> header file. | |
| HASMOPT enables/disables the ability to read kernel | |
| memory from a file -- e.g., from a crash | |
| dump file. | |
| HASMSDOSFS enables MS-DOS file system support in a | |
| BSD dialect. | |
| HASMNTSTAT indicates the dialect has a stat(2) status | |
| element in its mounts structure. | |
| HASMNTSUP indicates the dialect supports the mount supplement | |
| option. | |
| HASNAMECACHE indicates the FreeBSD dialect has a namecache | |
| structure definition in <sys/namei.h>. | |
| HASNCACHE enables the probing of the kernel's name cache | |
| to obtain path name components. A value | |
| of 1 directs printname() to prefix the | |
| cache value with the file system directory | |
| name; 2, avoid the prefix. | |
| HASNCVPID The *BSD dialect namecache struct has an | |
| nc_vpid member. | |
| HASNETDEVICE_H indicates the Linux version has a netdevice.h | |
| header file. | |
| HAS_NFS enables NFS support for the dialect. | |
| HASNFSKNC indicates the LINUX version has a separate | |
| NFS name cache. | |
| HASNFSPROTO indicates the NetBSD or OpenBSD version | |
| has the nfsproto.h header file. | |
| HASNFSVATTRP indicates the n_vattr member of the nfsnode of | |
| the *BSD dialect is a pointer. | |
| HASNLIST enables/disables nlist() function support. | |
| (See NLIST_TYPE.) | |
| HASNOFSADDR is defined if the dialect has no file structure | |
| addresses. (HASFSTRUCT must be defined.) | |
| HASNOFSCOUNT is defined if the dialect has no file structure counts. | |
| (HASFSTRUCT must be defined.) | |
| HASNOFSFLAGS is defined if the dialect has no file structure flags. | |
| (HASFSTRUCT must be defined.) | |
| HASNOFSNADDR is defined if the dialect has no file structure node | |
| addresses. (HASFSTRUCT must be defined.) | |
| HAS_NO_6PORT is defined if the FreeBSD in_pcb.h has no in6p_.port | |
| definitions. | |
| HAS_NO_6PPCB is defined if the FreeBSD in_pcb.h has no in6p_ppcb | |
| definition. | |
| HAS_NO_ISO_DEV indicates the FreeBSD 6 and higher system has | |
| no i_dev member in its iso_node structure. | |
| HAS_NO_LONG_LONG indicates the dialect has no support for the C | |
| long long type. This definition is used by | |
| the built-in snprintf() support of lib/snpf.c. | |
| HASNORPC_H indicates the dialect has no /usr/include/rpc/rpc.h | |
| header file. | |
| HAS_NO_SI_UDEV indicates the FreeBSD 6 and higher system has | |
| no si_udev member in its cdev structure. | |
| HASNOSOCKSECURITY enables the listing of open socket files, | |
| even when HASSECURITY restricts listing of | |
| open files to the UID of the user who is | |
| running lsof, provided socket file listing | |
| is selected with the "-i" option. This | |
| definition is only effective when HASSECURITY | |
| is also defined. | |
| HASNULLFS indicates the dialect (usually *BSD) has a | |
| null file system. | |
| HASOBJFS indicates the Pyramid version has OBJFS | |
| support. | |
| HASONLINEJFS indicates the HP-UX 11 dialect has the optional | |
| OnlineJFS package installed. | |
| HAS_PC_DIRENTPERSEC | |
| indicates the Solaris 10 system's <sys/fs/pc_node.h> | |
| header file has the pc_direntpersec() macro. | |
| HAS_PAD_MUTEX indicates the Solaris 11 system has the pad_mutex_t | |
| typedef in its <sys/mutex.h> header file. | |
| HASPERSDC enables the use of a personal device cache | |
| file path and specifies a format by which | |
| it is constructed. See the 00DCACHE file | |
| of the lsof distribution for more information | |
| on the format. | |
| HASPERSDCPATH enables the use of a modified personal | |
| device cache file path and specifies the | |
| name of the environment variable from which | |
| its component may be taken. See the 00DCACHE | |
| file of the lsof distribution for more | |
| information on the modified personal device | |
| cache file path. | |
| HASPINODEN declares that the inode number of a /proc file | |
| should be stored in its procfsid structure. | |
| HASPIPEFN defines the function that processes DTYPE_PIPE | |
| file structures. It's used in the prfp.c | |
| library source file. See the FreeBSD | |
| dialect source for an example. | |
| HASPIPENODE enables/disables readpipenode() in node.c. | |
| HASPMAPENABLED enables the automatic reporting of portmapper | |
| registration information for TCP and UDP | |
| ports that have been registered. | |
| HASPPID indicates the dialect has parent PID support. | |
| HASPR_LDT indicates the Solaris dialect has a pr_ldt | |
| member in the pronodetype enum. | |
| HASPR_GWINDOWS indicates the Solaris dialect has a pr_windows | |
| member in the pronodetype enum. | |
| HASPRINTDEV this value defines a private function for | |
| printing the dialect's device number. Used | |
| by print.c/print_file(). Takes one argument: | |
| char *HASPRINTDEV(struct lfile *) | |
| HASPRINTINO this value names a private function for | |
| printing the dialect's inode number. Used | |
| by print.c/print_file(). Takes one argument: | |
| char *HASPRINTINO(struct lfile *) | |
| HASPRINTNM this value names a private function for | |
| printing the dialect's file name. Used by | |
| print.c/print_file(). Takes one argument: | |
| void HASPRINTNM(struct lfile *) | |
| HASPRINTOFF this value names a private function for | |
| printing the dialect's file offset. Used | |
| by print.c/print_file(). Takes two arguments: | |
| char *HASPRINTOFF(struct lfile *, int ty) | |
| Where ty == 0 if the offset is to be printed | |
| in 0t<decimal> format; 1, 0x<hexadecimal>. | |
| HASPRINTSZ this value names a private function for | |
| printing the dialect's file size. Used | |
| by print.c/print_file(). Takes one argument: | |
| char *HASPRINTSZ(struct lfile *) | |
| void HASPRINTNM(struct lfile *) | |
| HASPRIVFILETYPE enables processing of the private file | |
| type, whose number (from f_type of the file | |
| struct) is defined by PRIVFILETYPE. | |
| HASPRIVFILETYPE defines the function that | |
| processes the file struct's f_data member. | |
| Processing is initiated from the process_file() | |
| function of the prfp.c library source file | |
| or from the dialect's own process_file() | |
| function. | |
| HASPRIVNMCACHE enables printing of a file path from a | |
| private name cache. HASPRIVNMCACHE defines | |
| the name of the printing function. The | |
| function takes one argument, a struct lfile | |
| pointer to the file, and returns non-zero | |
| if it prints a cached name to stdout. | |
| HASPRIVPRIPP is defined for dialects that have a private | |
| function for printing the IP protocol name. | |
| When this is not defined, the function to | |
| do that defaults to printiproto(). | |
| HASPROCFS defines the name (if any) of the process file | |
| system -- e.g., /proc. | |
| HASPROCFS_PFSROOT indicates PFSroot is in the BSD dialect's | |
| <miscfs/procfs/procfs.h>. | |
| HASPSEUDOFS indicates the FreeBSD dialect has pseudofs | |
| file system support. | |
| HASPSXSEM indicates the dialect has support for the POSIX | |
| semaphore file type. | |
| HASPSXSHM indicates the dialect has support for the POSIX | |
| shared memory file type. | |
| HASPTYFS indicates the *BSD dialect has a ptyfs file system. | |
| HASRNODE enables/disables readrnode() in node.c. | |
| HASRNODE3 indicates the HPUX 10.20 or lower dialect has NFS3 | |
| support with a modified rnode structure. | |
| HASRPCV2H The FreeBSD dialect has <nfs/rpcv2.h>. | |
| HAS_SANFS indicates the AIX system has SANFS file system | |
| support. | |
| HASSBSTATE indicates the dialect has socket buffer state | |
| information (e.g., SBS_* symbols) available. | |
| HASSECURITY enables/disables restricting open file | |
| information access. (Also see HASNOSOCKSECURITY.) | |
| HASSELINUX indicates the Linux dialect has SELinux security | |
| context support available. | |
| HASSETLOCALE is defined if the dialect has <locale.h> and | |
| setlocale(). | |
| HAS_SI_PRIV indicates the FreeBSD 6.0 and higher cdev | |
| structure has an si_priv member. | |
| HAS_SOCKET_PROTO_H indicates the Solaris 10 system has the header file | |
| <sys/socket_proto.h>. | |
| HASSOUXSOUA indicates that the Solaris <sys/socketvar.h> has | |
| soua_* members in its so_ux_addr structure. | |
| HASSPECDEVD indicates the dialect has a special device | |
| directory and defines the name of a function | |
| that processes the results of a successful | |
| stat(2) of a file in that directory. | |
| HASSPECNODE indicates the DEC OSF/1, or Digital UNIX, | |
| or Tru64 UNIX <sys/specdev.h> has a spec_node | |
| structure definition. | |
| HASSNODE indicates the dialect has snode support. | |
| HAS_SOCKET_SK indicates that the Linux socket structure | |
| has the ``struct sock *sk'' member. | |
| HASSOOPT indicates the dialect has socket option | |
| information (e.g., SO_* symbols) available. | |
| HASSOSTATE indicates the dialect has socket state | |
| information (e.g., SS_* symbols) available. | |
| HASSTATVFS indicates the NetBSD dialect has a statvfs | |
| struct definition. | |
| HASSTAT64 indicates the dialect's <sys/stat.h> contains | |
| stat64. | |
| HAS_STD_CLONE indicates the dialect uses a standard clone | |
| device structure that can be used in common | |
| library function clone processing. If the | |
| value is 1, the clone table will be built | |
| by readdev() and cached when HASDCACHE is | |
| defined; if the value is 2, it is assumed | |
| the clone table is built independently. | |
| (Also see CLONEMAJ and HAVECLONEMAJ.) | |
| HASSTREAMS enables/disables streams. CAUTION, requires | |
| specific support code in the dialect sources. | |
| HAS_STRFTIME indicates the dialect has the gmtime() and | |
| strftime() C library functions that support | |
| the -r marker format option. Configure tests | |
| for the functions and defines this symbol. | |
| HASSYSDC enables the use of a system-wide device | |
| cache file and defines its path. See the | |
| 00DCACHE file of the lsof distribution for | |
| more information on the system-wide device | |
| cache file path option. | |
| HAS_SYS_PIPEH indicates the dialect has a <sys/pipe.h> | |
| header file. | |
| HAS_SYS_SX_H indicates the FreeBSD 7.0 and higher system has | |
| a <sys/sx.h> header file. | |
| HASTAGTOPATH indicates the DEC OSF/1, Digital UNIX, or | |
| Tru64 UNIX dialect has a libmsfs.so, | |
| containing tag_to_path(). | |
| HASTMPNODE enables/disables readtnode() in node.c. | |
| HASTCPOPT indicates the dialect has TCP option | |
| information (i.e., from TF_* symbols) | |
| available. | |
| HASTCPTPIQ is defined when the dialect can duplicate | |
| the receive and send queue sizes reported | |
| by netstat. | |
| HASTCPTPIW is defined when the dialect can duplicate | |
| the receive and send window sizes reported | |
| by netstat. | |
| HASTCPUDPSTATE is defined when the dialect has support for | |
| TCP and UDP state, including the "-s p:s" | |
| option and associated speed ehancements. | |
| HASTFS indicates that the Pyramid dialect has TFS | |
| file system support. | |
| HAS_UFS1_2 indicates the FreeBSD 6 and higher system has | |
| UFS1 and UFS2 members in its inode structure. | |
| HAS_UM_UFS indicates the OpenBSD version has UM_UFS[12] | |
| definitions. | |
| HASUNMINSOCK indicates the Linux version has a user name | |
| element in the socket structure; a value of | |
| 0 says there is no unix_address member; 1, | |
| there is. | |
| HASUINT16TYPE is defined when the dialect has a typedef | |
| for u_int16 that may conflict with some other | |
| header file's redefinition (e.g., <afs/std.h>). | |
| HASUTMPX indicates the dialect has a <utmpx.h> header | |
| file. | |
| HAS_UVM_INCL indicates the NetBSD or OpenBSD dialect has | |
| a <uvm> include directory. | |
| HAS_UW_CFS indicates the UnixWare 7.1.1 or above dialect | |
| has CFS file system support. | |
| HAS_UW_NSC indicates the UnixWare 7.1.1 or above dialect | |
| has a NonStop Cluster (NSC) kernel. | |
| HAS_V_LOCKF indicates the FreeBSD version has a v_lockf | |
| member in the vode structure, defined in | |
| <sys/vnode.h>. | |
| HAS_VM_MEMATTR_T indicates the FreeBSD <sys/conf.h> uses the | |
| vm_memattr_t typedef. | |
| HASVMLOCKH indicates the FreeBSD dialect has <vm/lock.h>. | |
| HASVNODE enables/disables readvnode() function in node.c. | |
| HAS_V_PATH indicates the dialect's vnode structure has a | |
| v_path member. | |
| HAS_VSOCK indicates that the Solaris version has a VSOCK | |
| member in the vtype enum | |
| HASVXFS enables Veritas VxFS file system support for | |
| the dialect. CAUTION, the dialect sources | |
| must have the necessary support code. | |
| HASVXFSDNLC indicates the VxFS file system has its own | |
| name cache. | |
| HASVXFS_FS_H indicates <sys/fs/vx_fs.h> exists. | |
| HASVXFS_MACHDEP_H indicates <sys/fs/vx_machdep.h> exists. | |
| HASVXFS_OFF64_T indicates <sys/fs/vx_solaris.h> exists and | |
| has an off64_t typedef. | |
| HASXVFSRNL indicates the dialect has VxFS Reverse Name | |
| Lookup (RNL) support. | |
| HASVXFS_SOL_H indicates <sys/fs/vx_sol.h> exists. | |
| HASVXFS_SOLARIS_H indicates <sys/fs/vx_solaris.h> exists. | |
| HASVXFS_U64_T if HASVXFS_SOLARIS_H is defined, this | |
| variable indicates that <sys/fs/vx_solaris.h> | |
| has a vx_u64_t typedef. | |
| HASVXFSUTIL indicates the Solaris dialect has VxFS 3.4 | |
| or higher and has the utility libraries, | |
| libvxfsutil.a (32 bit) and libvxfsutil64.a | |
| (64 bit). | |
| HASVXFS_VX_INODE indicates that <sys/fs/vx_inode.h> contains | |
| a vx_inode structure. | |
| HASWIDECHAR indicates the dialect has the wide-character | |
| support functions iswprint(), mblen() and mbtowc(). | |
| HASXNAMNODE indicates the OSR dialect has <sys/fs/xnamnode.h>. | |
| HASXOPT defines help text for dialect-specific X option | |
| and enables X option processing in usage.c and | |
| main.c. | |
| HASXOPT_ROOT when defined, restricts the dialect-specific | |
| X option to processes whose real user ID | |
| is root. | |
| HAS_ZFS indicates the dialect has support for the ZFS file | |
| system. | |
| HASXOPT_VALUE defines the default binary value for the X option | |
| in store.c. | |
| HASZONES the Solaris dialect has zones. | |
| HAVECLONEMAJ defines the name of the status variable | |
| that indicates a clone major device number | |
| is available in CLONEMAJ. (Also see CLONEMAJ | |
| and HAS_STD_CLONE.) | |
| HPUX_KERNBITS defines the number of bits in the HP-UX 10.30 | |
| and above kernel "basic" word: 32 or 64. | |
| KA_T defines the type cast required to assign | |
| space to kernel pointers. When not defined | |
| by a dialect header file, KA_T defaults to | |
| unsigned long. | |
| KA_T_FMT_X defines the printf format for printing a | |
| KA_T -- the default is "%#lx" for the | |
| default unsigned long KA_T cast. | |
| LSOF_ARCH See 00XCONFIG. | |
| LSOF_BLDCMT See 00XCONFIG. | |
| LSOF_CC See 00XCONFIG. | |
| LSOF_CCV See 00XCONFIG. | |
| LSOF_HOST See 00XCONFIG. | |
| LSOF_INCLUDE See 00XCONFIG. | |
| LSOF_LOGNAME See 00XCONFIG. | |
| LSOF_MKC See the "The Mksrc Shell Script" section of | |
| this file. | |
| LSOF_SYSINFO See 00XCONFIG. | |
| LSOF_USER See 00XCONFIG. | |
| LSOF_VERS See 00XCONFIG. | |
| LSOF_VSTR See 00XCONFIG. | |
| MACH defines a MACH system. | |
| N_UNIXV defines an alternate value for the N_UNIV symbol. | |
| NCACHELDPFX defines C code to be executed before calling | |
| ncache_load(). | |
| NCACHELDSFX defines C code to be executed after calling | |
| ncache_load(). | |
| NEEDS_BOOLEAN_T indicates the FreeBSD 9 and above system needs a | |
| boolean_t definition for <sys/conf.h>. | |
| NEVER_HASDCACHE keeps the Customize script from offering to | |
| change HASDCACHE by its presence anywhere | |
| in a dialect's machine.h header file -- | |
| e.g., in a comment. See the Customize | |
| script or machine.h in dialects/linux/proc. | |
| NEVER_WARNDEVACCESS keeps the Customize script from offering to | |
| change WARNDEVACCESS by its presence anywhere | |
| in a dialect's machine.h header file -- | |
| including in a comment. See the Customize | |
| script or machine.h in dialects/linux/proc. | |
| NLIST_TYPE is the type of the nlist table, Nl[], if it is | |
| not nlist. HASNLIST must be set for this | |
| definition to be effective. | |
| NOWARNBLKDEV specifies that no warning is to be issued | |
| when no block devices are found. This | |
| definiton is used only when HASBLKDEV is | |
| also defined. | |
| OFFDECDIG specifies how many decimal digits will be | |
| printed for the file offset in a 0t form | |
| before switching to a 0x form. The count | |
| includes the "0t". A count of zero means | |
| the size is unlimited. | |
| PRIVFILETYPE is the number of a private file type, found | |
| in the f_type member of the file struct, to | |
| be processed by the HASPRIVFILETYPE function. | |
| See the AIX dialect sources for an example. | |
| _PSTAT_STREAM_GET_XPORT | |
| indicates the HP-UX PSTAT header files require | |
| this symbol to be defined for proper handling of | |
| stream export data. | |
| TIMEVAL_LSOF defines the name of the timeval structure. | |
| The default is timeval. /dev/kmem-based | |
| Linux lsof redefines timeval with this | |
| symbol to avoid conflicts between glibc | |
| and kernel definitions. | |
| TYPELOGSECSHIFT defines the type of the cdfs_LogSecShift | |
| member of the cdfs structure for UnixWare | |
| 7 and higher. | |
| UID_ARG_T defines the cast on a User ID when passed | |
| as a function argument. | |
| USE_LIB_COMPLETEVFS | |
| selects the use of the completevfs() function | |
| in lsof4/lib/cvfs.c. | |
| USE_LIB_FIND_CH_INO | |
| selects the use of the find_ch_ino() inode | |
| function in lsof4/lib/fino.c. | |
| Note: HASBLKDEV selects the has_bl_ino() | |
| function. | |
| USE_LIB_IS_FILE_NAMED | |
| selects the use of the is_file_named() function | |
| in lsof4/lib/isfn.c. | |
| USE_LIB_LKUPDEV selects the use of the lkupdev() function | |
| in lsof4/lib/lkud.c. | |
| Note: HASBLKDEV selects the lkupbdev() function. | |
| USE_LIB_PRINTDEVNAME | |
| selects the use of the printdevname() function | |
| in lsof4/lib/pdvn.c. | |
| Note: HASBLKDEV selects the printbdevname() | |
| function. | |
| USE_LIB_PRINT_TCPTPI | |
| selects the use of the print_tcptpi() function | |
| in lsof4/lib/ptti.c. | |
| USE_LIB_PROCESS_FILE | |
| selects the use of the process_file() function | |
| in lsof4/lib/prfp.c. | |
| USE_LIB_READDEV selects the use of the readdev() and stkdir() | |
| functions in lsof4/lib/rdev.c. | |
| USE_LIB_READMNT selects the use of the readmnt() function | |
| in lsof4/lib/rmnt.c. | |
| USE_LIB_RNAM selects the use of the device cache functions | |
| in lsof4/lib/rnam.c. | |
| Note: HASNCACHE must also be defined. | |
| USE_LIB_RNCH selects the use of the device cache functions | |
| in lsof4/lib/rnch.c. | |
| Note: HASNCACHE must also be defined. | |
| USE_STAT is defined for those dialects that must | |
| use the stat(2) function instead of lstat(2) | |
| to scan /dev -- i.e., in the readdev() | |
| function. | |
| VNODE_VFLAG is an alternate name for the vnode structure's | |
| v_flag member. | |
| WARNDEVACCESS enables the issuing of a warning message when | |
| lsof is unable to access /dev (or /device) | |
| or one of its subdirectories, or stat(2) | |
| a file in them. Some dialects (e.g., HP-UX) | |
| have many inaccessible subdirectories and | |
| it is appropriate to inhibit the warning | |
| for them with WARNDEVACCESS. The -w option | |
| will also inhibit these warnings. | |
| WARNINGSTATE when defined, disables the default issuing | |
| of warning messages. WARNINGSTATE is | |
| undefined by default for all dialects in | |
| the lsof distribution. | |
| WIDECHARINCL defines the header file to be included (if any) | |
| when wide-character support is enabled with | |
| HASWIDECHAR. | |
| zeromem() defines a macro to zero memory -- e.g., using | |
| bzero() or memset(). | |
| Any dialect's machine.h file and Configure stanza can serve as a | |
| template for building your own. All machine.h files usually have | |
| all definitions, disabling some (with comment prefix and suffix) | |
| and enabling others. | |
| Options: Common and Special | |
| --------------------------- | |
| All but one lsof option is common; the specific option is ``-X''. | |
| If a dialect does not support a common option, the related #define | |
| in machine.h -- e.g., HASCOPT -- should be deselected. | |
| The specific option, ``-X'', may be used by any dialect for its | |
| own purpose. Right now (May 30, 1995) the ``-X'' option is binary | |
| (i.e., it's not allowed arguments of its own, and its value must | |
| be 0 or 1) but that could be changed should the need arise. The | |
| option is enabled with the HASXOPT definition in machine.h; its | |
| default value is defined by HASXOPT_VALUE. | |
| The value of HASXOPT should be the text displayed for ``-X'' by | |
| the usage() function in usage.c. HASXOPT_VALUE should be the | |
| default value, 0 or 1. | |
| AIX for the IBM RICS System/6000 defines the ``-X'' option to | |
| control readx() usage, since there is a bug in AIX kernels that | |
| readx() can expose for other processes. | |
| Defining Dialect-Specific Symbols and Global Storage | |
| ---------------------------------------------------- | |
| A dialect's dlsof.h and dstore.c files contain dialect-specific | |
| symbol and global storage definitions. There are symbol definitions, | |
| for example, for function and data casts, and for file paths. | |
| Dslof.h defines lookup names the nlist() table -- X_* symbols -- | |
| when nlist() is being used. | |
| Global storage definitions include such things as structures for | |
| local Virtual File System (vfs) information; mount information; | |
| search file information; and kernel memory file descriptors -- | |
| e.g., Kmem for /dev/kmem, Mem for /dev/mem, Swap for /dev/drum. | |
| Coding Dialect-specific Functions | |
| --------------------------------- | |
| Each supported dialect must have some basic functions that the | |
| common functions of the top level may call. Some of them may be | |
| obtained from the library in lsof4/lib, selected and customized by | |
| #define's in the dialect machine.h header file. Others may have | |
| to be coded specifically for the dialect. | |
| Each supported dialect usually has private functions, too. Those | |
| are wholly determined by the needs of the dialect's data organization | |
| and access. | |
| These are some of the basic functions that each dialect must supply | |
| -- they're all defined in proto.h: | |
| initialize() function to initialize the dialect | |
| is_file_named() function to check if a file was named | |
| by an optional file name argument | |
| (lsof4/lib/isfn.c) | |
| gather_proc_info() function to gather process table | |
| and related information and cache it | |
| printchdevname() function to locate and optionally | |
| print the name of a character device | |
| (lsof4/lib/pdvn.c) | |
| print_tcptpistate() function to print the TCP or TPI | |
| state for a TCP or UDP socket file, | |
| if the one in lib/ptti.c isn't | |
| suitable (define USE_LIB_PRINT_TCPTPI | |
| to activate lib/ptti.c) | |
| process_file() function to process an open file | |
| structure (lsof4/lib/prfp.c) | |
| process_node() function to process a primary node | |
| process_socket() function to process a socket | |
| readdev() and stkdir() functions to read and cache device | |
| information (lsof4/lib/rdev.c) | |
| readmnt() function to read mount table information | |
| (lsof4/lib/rmnt.c) | |
| Other common functions may be needed, and might be obtained from | |
| lsof4/lib, depending on the needs of the dialect's node and socket | |
| file processing functions. | |
| Check the functions in lsof4/lib and specific lsof4/dialects/* | |
| files for examples. | |
| As you build these functions you will probably have to add #include's | |
| to dlsof.h. | |
| Function Prototype Definitions and the _PROTOTYPE Macro | |
| ------------------------------------------------------- | |
| Once you've defined your dialect-specific definitions, you should | |
| define their prototypes in dproto.h or locally in the file where | |
| they occur and are used. Do this even if your compiler is not ANSI | |
| compliant -- the _PROTOTYPE macro knows how to cope with that and | |
| will avoid creating prototypes that will confuse your compiler. | |
| The Makefile | |
| ------------ | |
| Here are some general rules for constructing the dialect Makefile. | |
| * Use an existing dialect's Makefile as a template. | |
| * Make sure the echo actions of the install rule are appropriate. | |
| * Use the DEBUG string to set debugging options, like ``-g''. | |
| You may also need to use the -O option when forking and | |
| SIGCHLD signals defeat your debugger. | |
| * Don't put ``\"'' in a compiler flags -D<symbol>=<string> | |
| clause in your Makefile. Leave off the ``\"'' even though | |
| you want <string> to be a string literal and instead adapt | |
| the N_UNIX* macros you'll find in Makefiles for FreeBSD | |
| and Linux. That will allow the Makefile's version.h rule | |
| to put CFLAGS into version.h without having to worry about | |
| the ``\"'' sequences. | |
| * Finally, remember that strings can be passed from the top | |
| level's Configure shell script. That's an appropriate way | |
| to handle options, especially if there are multiple versions | |
| of the Unix dialect to which you are porting lsof 4. | |
| The Mksrc Shell Script | |
| ---------------------- | |
| Pattern your Mksrc shell script after an existing one from another | |
| dialect. Change the D shell variable to the name of your dialect's | |
| subdirectory in lsof4/dialects. Adjust any other shell variable | |
| to your local conditions. (Probably that won't be necessary.) | |
| Note that, if using symbolic links from the top level to your | |
| dialect subdirectory is impossible or impractical, you can set the | |
| LSOF_MKC shell variable in Configure to something other than | |
| "ln -s" -- e.g., "cp," and Configure will pass it to the Mksrc | |
| shell script in the M environment variable. | |
| The MkKernOpts Shell Script | |
| --------------------------- | |
| The MkKernOptrs shell script is used by some dialects -- e.g., | |
| Pyramid DC/OSx and Reliant UNIX -- to determine the compile-time | |
| options used to build the current kernel that affect kernel structure | |
| definitions, so those same options can be used to build lsof. | |
| Configure calls MkKernOpts for the selected dialects. | |
| If your kernel is built with options that affect structure definitions. | |
| -- most commonly affected are the proc structure from <sys/proc.h> | |
| and the user structure from <sys/user.h> -- check the MkKernOpts | |
| in lsof4/dialects/irix for a comprehensive example. | |
| Testing and the Lsof Test Suite | |
| ------------------------------- | |
| Once you have managed to create a port, here are some tips for | |
| testing it. | |
| * First look at the test suite in the tests/ sub-directory of the | |
| lsof distribution. While it will need to be customized to be | |
| usable with a new port, it should provide ideas on things to | |
| test. Look for more information about the test suite in the | |
| 00TEST file. | |
| * Pick a simple process whose open files you are likely to | |
| know and see if the lsof output agrees with what you know. | |
| (Hint: select the process with `lsof -p <process_PID>`.) | |
| Are the device numbers and device names correct? | |
| Are the file system names and mount points correct? | |
| Are inode numbers and sizes correct? | |
| Are command names, file descriptor numbers, UIDs, PIDs, PGIDs, | |
| and PPIDs correct? | |
| A simple tool that does a stat(2) of the files being examined | |
| and reports the stat struct contents can provide a reference for | |
| some values; so can `ls -l /dev/<device>`. | |
| * Let lsof list information about all open files and ask the | |
| same questions. Look also for error messages about not being | |
| able to read a node or structure. | |
| * Pick a file that you know is open -- open it and hold it | |
| that way with a C program (not vi), if you must. Ask lsof to | |
| find the file's open instance by specifying its path to lsof. | |
| * Create a C program that opens a large number of files and holds | |
| them open. Background the test process and ask lsof to list | |
| its files. | |
| * Generate some locks -- you may need to write a C program to | |
| do this, hold the locked file open, and see if lsof can identify | |
| the lock properly. You may need to write several C programs | |
| if your dialect supports different lock functions -- fnctl(), | |
| flock(), lockf(), locking(). | |
| * Identify a process with known Internet file usage -- inetd | |
| is a good one -- and ask lsof to list its open files. See if | |
| protocols and service names are listed properly. | |
| See if your lsof identifies Internet socket files properly for | |
| rlogind or telnetd processes. | |
| * Create a UNIX domain socket file, if your dialect allows it, | |
| hold it open by backgrounding the process, and see if lsof can | |
| identify the open UNIX domain socket file properly. | |
| * Create a FIFO file and see what lsof says about it. | |
| * Watch an open pipe -- `lsof -u <your_login> | less` is a | |
| good way to do this. | |
| * See if lsof can identify NFS files and their devices properly. | |
| Open and hold open an NFS file and see if lsof can find the open | |
| instance by path. | |
| * If your test system has CD-ROM and floppy disk devices, open | |
| files on them and see if lsof reports their information correctly. | |
| Such devices often have special kernel structures associated | |
| with them and need special attention from lsof for their | |
| identification. Pay particular attention to the inode numbers | |
| lsof reports for CD-ROM and floppy disk files -- often they are | |
| calculated dynamically, rather than stored in a kernel node | |
| structure. | |
| * If your implementation can probe the kernel name cache, look | |
| at some processes with open files whose paths you know to see | |
| if lsof identifies any name components. If it doesn't, make | |
| sure the name components are in the name cache by accessing | |
| the files yourself with ls or a similar tool. | |
| * If your dialect supports the /proc file system, use a C program | |
| to open files there, background a test process, and ask lsof to | |
| report its open files. | |
| * If your dialect supports fattach(), create a small test program | |
| to use it, background a test process, and ask lsof to report | |
| its open files. | |
| I can supply some quick-and-dirty tools for reporting stat buffer | |
| contents, holding files open, creating UNIX domain files, creating | |
| FIFOs, etc., if you need them. | |
| Where Next? | |
| ----------- | |
| Is this document complete? Certainly not! One might wish that it | |
| were accompanied by man pages for all lsof functions, by free beer | |
| or chocolates, by ... (You get the idea.) | |
| But those things are not likely to happen as long as lsof is a | |
| privately supported, one man operation. | |
| So, if you need more information on how lsof is constructed or | |
| works in order to do a port of your own, you'll have to read the | |
| lsof source code. You can also ask me questions via email, but | |
| keep in mind the private, one-man nature of current lsof support. | |
| Vic Abell <abe@purdue.edu> | |
| September 27, 2011 |