1 | /* $NetBSD: dir.h,v 1.25 2015/09/01 06:16:03 dholland Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1982, 1986, 1989, 1993 |
5 | * The Regents of the University of California. All rights reserved. |
6 | * (c) UNIX System Laboratories, Inc. |
7 | * All or some portions of this file are derived from material licensed |
8 | * to the University of California by American Telephone and Telegraph |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with |
10 | * the permission of UNIX System Laboratories, Inc. |
11 | * |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions |
14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions and the following disclaimer. |
17 | * 2. Redistributions in binary form must reproduce the above copyright |
18 | * notice, this list of conditions and the following disclaimer in the |
19 | * documentation and/or other materials provided with the distribution. |
20 | * 3. Neither the name of the University nor the names of its contributors |
21 | * may be used to endorse or promote products derived from this software |
22 | * without specific prior written permission. |
23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 | * SUCH DAMAGE. |
35 | * |
36 | * @(#)dir.h 8.5 (Berkeley) 4/27/95 |
37 | */ |
38 | |
39 | #ifndef _UFS_UFS_DIR_H_ |
40 | #define _UFS_UFS_DIR_H_ |
41 | |
42 | /* |
43 | * Theoretically, directories can be more than 2Gb in length; however, in |
44 | * practice this seems unlikely. So, we define the type doff_t as a 32-bit |
45 | * quantity to keep down the cost of doing lookup on a 32-bit machine. |
46 | */ |
47 | #define doff_t int32_t |
48 | #define UFS_MAXDIRSIZE (0x7fffffff) |
49 | |
50 | /* |
51 | * A directory consists of some number of blocks of UFS_DIRBLKSIZ |
52 | * bytes, where UFS_DIRBLKSIZ is chosen such that it can be transferred |
53 | * to disk in a single atomic operation (e.g. 512 bytes on most machines). |
54 | * |
55 | * Each UFS_DIRBLKSIZ byte block contains some number of directory entry |
56 | * structures, which are of variable length. Each directory entry has |
57 | * a struct direct at the front of it, containing its inode number, |
58 | * the length of the entry, and the length of the name contained in |
59 | * the entry. These are followed by the name padded to a 4 byte boundary. |
60 | * All names are guaranteed null terminated. |
61 | * The maximum length of a name in a directory is FFS_MAXNAMLEN. |
62 | * |
63 | * The macro UFS_DIRSIZ(fmt, dp) gives the amount of space required to represent |
64 | * a directory entry. Free space in a directory is represented by |
65 | * entries which have dp->d_reclen > DIRSIZ(fmt, dp). All UFS_DIRBLKSIZ bytes |
66 | * in a directory block are claimed by the directory entries. This |
67 | * usually results in the last entry in a directory having a large |
68 | * dp->d_reclen. When entries are deleted from a directory, the |
69 | * space is returned to the previous entry in the same directory |
70 | * block by increasing its dp->d_reclen. If the first entry of |
71 | * a directory block is free, then its dp->d_ino is set to 0. |
72 | * Entries other than the first in a directory do not normally have |
73 | * dp->d_ino set to 0. |
74 | */ |
75 | #undef UFS_DIRBLKSIZ |
76 | #define UFS_DIRBLKSIZ DEV_BSIZE |
77 | #define FFS_MAXNAMLEN 255 |
78 | #define APPLEUFS_DIRBLKSIZ 1024 |
79 | |
80 | #define d_ino d_fileno |
81 | struct direct { |
82 | u_int32_t d_fileno; /* inode number of entry */ |
83 | u_int16_t d_reclen; /* length of this record */ |
84 | u_int8_t d_type; /* file type, see below */ |
85 | u_int8_t d_namlen; /* length of string in d_name */ |
86 | char d_name[FFS_MAXNAMLEN + 1];/* name with length <= FFS_MAXNAMLEN */ |
87 | }; |
88 | |
89 | /* |
90 | * File types |
91 | */ |
92 | #define DT_UNKNOWN 0 |
93 | #define DT_FIFO 1 |
94 | #define DT_CHR 2 |
95 | #define DT_DIR 4 |
96 | #define DT_BLK 6 |
97 | #define DT_REG 8 |
98 | #define DT_LNK 10 |
99 | #define DT_SOCK 12 |
100 | #define DT_WHT 14 |
101 | |
102 | /* |
103 | * Convert between stat structure types and directory types. |
104 | */ |
105 | #define IFTODT(mode) (((mode) & 0170000) >> 12) |
106 | #define DTTOIF(dirtype) ((dirtype) << 12) |
107 | |
108 | /* |
109 | * The UFS_DIRSIZ macro gives the minimum record length which will hold |
110 | * the directory entry. This requires the amount of space in struct direct |
111 | * without the d_name field, plus enough space for the name with a terminating |
112 | * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. |
113 | */ |
114 | #define UFS_DIRECTSIZ(namlen) \ |
115 | ((sizeof(struct direct) - (FFS_MAXNAMLEN+1)) + (((namlen)+1 + 3) &~ 3)) |
116 | |
117 | #if (BYTE_ORDER == LITTLE_ENDIAN) |
118 | #define UFS_DIRSIZ(oldfmt, dp, needswap) \ |
119 | (((oldfmt) && !(needswap)) ? \ |
120 | UFS_DIRECTSIZ((dp)->d_type) : UFS_DIRECTSIZ((dp)->d_namlen)) |
121 | #else |
122 | #define UFS_DIRSIZ(oldfmt, dp, needswap) \ |
123 | (((oldfmt) && (needswap)) ? \ |
124 | UFS_DIRECTSIZ((dp)->d_type) : UFS_DIRECTSIZ((dp)->d_namlen)) |
125 | #endif |
126 | |
127 | /* |
128 | * UFS_OLDDIRFMT and UFS_NEWDIRFMT are code numbers for a directory |
129 | * format change that happened in ffs a long time ago. (Back in the |
130 | * 80s, if I'm not mistaken.) |
131 | * |
132 | * These code numbers do not appear on disk. They're generated from |
133 | * runtime logic that is cued by other things, which is why |
134 | * UFS_OLDDIRFMT is confusingly 1 and UFS_NEWDIRFMT is confusingly 0. |
135 | * |
136 | * Relatedly, the FFS_EI byte swapping logic for directories is a |
137 | * horrible mess. For example, to access the namlen field, one |
138 | * currently does the following: |
139 | * |
140 | * #if (BYTE_ORDER == LITTLE_ENDIAN) |
141 | * swap = (UFS_IPNEEDSWAP(VTOI(vp)) == 0); |
142 | * #else |
143 | * swap = (UFS_IPNEEDSWAP(VTOI(vp)) != 0); |
144 | * #endif |
145 | * return ((FSFMT(vp) && swap) ? dp->d_type : dp->d_namlen); |
146 | * |
147 | * UFS_IPNEEDSWAP() returns true if the volume is opposite-endian. This |
148 | * horrible "swap" logic is cutpasted all over everywhere but amounts |
149 | * to the following: |
150 | * |
151 | * running code volume lfs_dobyteswap "swap" |
152 | * ---------------------------------------------------------- |
153 | * LITTLE_ENDIAN LITTLE_ENDIAN false true |
154 | * LITTLE_ENDIAN BIG_ENDIAN true false |
155 | * BIG_ENDIAN LITTLE_ENDIAN true true |
156 | * BIG_ENDIAN BIG_ENDIAN false false |
157 | * |
158 | * which you'll note boils down to "volume is little-endian". |
159 | * |
160 | * Meanwhile, FSFMT(vp) yields UFS_OLDDIRFMT or UFS_NEWDIRFMT via |
161 | * perverted logic of its own. Since UFS_OLDDIRFMT is 1 (contrary to |
162 | * what one might expect approaching this cold) what this mess means |
163 | * is: on OLDDIRFMT volumes that are little-endian, we read the |
164 | * namlen value out of the type field. This is because on OLDDIRFMT |
165 | * volumes there is no d_type field, just a 16-bit d_namlen; so if |
166 | * the 16-bit d_namlen is little-endian, the useful part of it is |
167 | * in the first byte, which in the NEWDIRFMT structure is the d_type |
168 | * field. |
169 | */ |
170 | |
171 | #define UFS_OLDDIRFMT 1 |
172 | #define UFS_NEWDIRFMT 0 |
173 | |
174 | /* |
175 | * Template for manipulating directories. Should use struct direct's, |
176 | * but the name field is FFS_MAXNAMLEN - 1, and this just won't do. |
177 | */ |
178 | struct dirtemplate { |
179 | u_int32_t dot_ino; |
180 | int16_t dot_reclen; |
181 | u_int8_t dot_type; |
182 | u_int8_t dot_namlen; |
183 | char dot_name[4]; /* must be multiple of 4 */ |
184 | u_int32_t dotdot_ino; |
185 | int16_t dotdot_reclen; |
186 | u_int8_t dotdot_type; |
187 | u_int8_t dotdot_namlen; |
188 | char dotdot_name[4]; /* ditto */ |
189 | }; |
190 | |
191 | /* |
192 | * This is the old format of directories, sans type element. |
193 | */ |
194 | struct odirtemplate { |
195 | u_int32_t dot_ino; |
196 | int16_t dot_reclen; |
197 | u_int16_t dot_namlen; |
198 | char dot_name[4]; /* must be multiple of 4 */ |
199 | u_int32_t dotdot_ino; |
200 | int16_t dotdot_reclen; |
201 | u_int16_t dotdot_namlen; |
202 | char dotdot_name[4]; /* ditto */ |
203 | }; |
204 | #endif /* !_UFS_UFS_DIR_H_ */ |
205 | |