| 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 | |