1 /* 2 * directory.c 3 * 4 * PURPOSE 5 * Directory related functions 6 * 7 * COPYRIGHT 8 * This file is distributed under the terms of the GNU General Public 9 * License (GPL). Copies of the GPL can be obtained from: 10 * ftp://prep.ai.mit.edu/pub/gnu/GPL 11 * Each contributing author retains all rights to their own work. 12 */ 13 14 #include "udfdecl.h" 15 #include "udf_i.h" 16 17 #include <linux/fs.h> 18 #include <linux/string.h> 19 #include <linux/buffer_head.h> 20 21 #if 0 22 static uint8_t *udf_filead_read(struct inode *dir, uint8_t *tmpad, 23 uint8_t ad_size, kernel_lb_addr fe_loc, 24 int *pos, int *offset, struct buffer_head **bh, 25 int *error) 26 { 27 int loffset = *offset; 28 int block; 29 uint8_t *ad; 30 int remainder; 31 32 *error = 0; 33 34 ad = (uint8_t *)(*bh)->b_data + *offset; 35 *offset += ad_size; 36 37 if (!ad) { 38 brelse(*bh); 39 *error = 1; 40 return NULL; 41 } 42 43 if (*offset == dir->i_sb->s_blocksize) { 44 brelse(*bh); 45 block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos); 46 if (!block) 47 return NULL; 48 *bh = udf_tread(dir->i_sb, block); 49 if (!*bh) 50 return NULL; 51 } else if (*offset > dir->i_sb->s_blocksize) { 52 ad = tmpad; 53 54 remainder = dir->i_sb->s_blocksize - loffset; 55 memcpy((uint8_t *)ad, (*bh)->b_data + loffset, remainder); 56 57 brelse(*bh); 58 block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos); 59 if (!block) 60 return NULL; 61 (*bh) = udf_tread(dir->i_sb, block); 62 if (!*bh) 63 return NULL; 64 65 memcpy((uint8_t *)ad + remainder, (*bh)->b_data, 66 ad_size - remainder); 67 *offset = ad_size - remainder; 68 } 69 70 return ad; 71 } 72 #endif 73 74 struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, 75 struct udf_fileident_bh *fibh, 76 struct fileIdentDesc *cfi, 77 struct extent_position *epos, 78 kernel_lb_addr *eloc, uint32_t *elen, 79 sector_t *offset) 80 { 81 struct fileIdentDesc *fi; 82 int i, num, block; 83 struct buffer_head *tmp, *bha[16]; 84 struct udf_inode_info *iinfo = UDF_I(dir); 85 86 fibh->soffset = fibh->eoffset; 87 88 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { 89 fi = udf_get_fileident(iinfo->i_ext.i_data - 90 (iinfo->i_efe ? 91 sizeof(struct extendedFileEntry) : 92 sizeof(struct fileEntry)), 93 dir->i_sb->s_blocksize, 94 &(fibh->eoffset)); 95 if (!fi) 96 return NULL; 97 98 *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2); 99 100 memcpy((uint8_t *)cfi, (uint8_t *)fi, 101 sizeof(struct fileIdentDesc)); 102 103 return fi; 104 } 105 106 if (fibh->eoffset == dir->i_sb->s_blocksize) { 107 int lextoffset = epos->offset; 108 unsigned char blocksize_bits = dir->i_sb->s_blocksize_bits; 109 110 if (udf_next_aext(dir, epos, eloc, elen, 1) != 111 (EXT_RECORDED_ALLOCATED >> 30)) 112 return NULL; 113 114 block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset); 115 116 (*offset)++; 117 118 if ((*offset << blocksize_bits) >= *elen) 119 *offset = 0; 120 else 121 epos->offset = lextoffset; 122 123 brelse(fibh->sbh); 124 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); 125 if (!fibh->sbh) 126 return NULL; 127 fibh->soffset = fibh->eoffset = 0; 128 129 if (!(*offset & ((16 >> (blocksize_bits - 9)) - 1))) { 130 i = 16 >> (blocksize_bits - 9); 131 if (i + *offset > (*elen >> blocksize_bits)) 132 i = (*elen >> blocksize_bits)-*offset; 133 for (num = 0; i > 0; i--) { 134 block = udf_get_lb_pblock(dir->i_sb, *eloc, 135 *offset + i); 136 tmp = udf_tgetblk(dir->i_sb, block); 137 if (tmp && !buffer_uptodate(tmp) && 138 !buffer_locked(tmp)) 139 bha[num++] = tmp; 140 else 141 brelse(tmp); 142 } 143 if (num) { 144 ll_rw_block(READA, num, bha); 145 for (i = 0; i < num; i++) 146 brelse(bha[i]); 147 } 148 } 149 } else if (fibh->sbh != fibh->ebh) { 150 brelse(fibh->sbh); 151 fibh->sbh = fibh->ebh; 152 } 153 154 fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize, 155 &(fibh->eoffset)); 156 157 if (!fi) 158 return NULL; 159 160 *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2); 161 162 if (fibh->eoffset <= dir->i_sb->s_blocksize) { 163 memcpy((uint8_t *)cfi, (uint8_t *)fi, 164 sizeof(struct fileIdentDesc)); 165 } else if (fibh->eoffset > dir->i_sb->s_blocksize) { 166 int lextoffset = epos->offset; 167 168 if (udf_next_aext(dir, epos, eloc, elen, 1) != 169 (EXT_RECORDED_ALLOCATED >> 30)) 170 return NULL; 171 172 block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset); 173 174 (*offset)++; 175 176 if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen) 177 *offset = 0; 178 else 179 epos->offset = lextoffset; 180 181 fibh->soffset -= dir->i_sb->s_blocksize; 182 fibh->eoffset -= dir->i_sb->s_blocksize; 183 184 fibh->ebh = udf_tread(dir->i_sb, block); 185 if (!fibh->ebh) 186 return NULL; 187 188 if (sizeof(struct fileIdentDesc) > -fibh->soffset) { 189 int fi_len; 190 191 memcpy((uint8_t *)cfi, (uint8_t *)fi, -fibh->soffset); 192 memcpy((uint8_t *)cfi - fibh->soffset, 193 fibh->ebh->b_data, 194 sizeof(struct fileIdentDesc) + fibh->soffset); 195 196 fi_len = (sizeof(struct fileIdentDesc) + 197 cfi->lengthFileIdent + 198 le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3; 199 200 *nf_pos += (fi_len - (fibh->eoffset - fibh->soffset)) 201 >> 2; 202 fibh->eoffset = fibh->soffset + fi_len; 203 } else { 204 memcpy((uint8_t *)cfi, (uint8_t *)fi, 205 sizeof(struct fileIdentDesc)); 206 } 207 } 208 return fi; 209 } 210 211 struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, int *offset) 212 { 213 struct fileIdentDesc *fi; 214 int lengthThisIdent; 215 uint8_t *ptr; 216 int padlen; 217 218 if ((!buffer) || (!offset)) { 219 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, 220 offset); 221 return NULL; 222 } 223 224 ptr = buffer; 225 226 if ((*offset > 0) && (*offset < bufsize)) 227 ptr += *offset; 228 fi = (struct fileIdentDesc *)ptr; 229 if (fi->descTag.tagIdent != cpu_to_le16(TAG_IDENT_FID)) { 230 udf_debug("0x%x != TAG_IDENT_FID\n", 231 le16_to_cpu(fi->descTag.tagIdent)); 232 udf_debug("offset: %u sizeof: %lu bufsize: %u\n", 233 *offset, (unsigned long)sizeof(struct fileIdentDesc), 234 bufsize); 235 return NULL; 236 } 237 if ((*offset + sizeof(struct fileIdentDesc)) > bufsize) 238 lengthThisIdent = sizeof(struct fileIdentDesc); 239 else 240 lengthThisIdent = sizeof(struct fileIdentDesc) + 241 fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse); 242 243 /* we need to figure padding, too! */ 244 padlen = lengthThisIdent % UDF_NAME_PAD; 245 if (padlen) 246 lengthThisIdent += (UDF_NAME_PAD - padlen); 247 *offset = *offset + lengthThisIdent; 248 249 return fi; 250 } 251 252 #if 0 253 static extent_ad *udf_get_fileextent(void *buffer, int bufsize, int *offset) 254 { 255 extent_ad *ext; 256 struct fileEntry *fe; 257 uint8_t *ptr; 258 259 if ((!buffer) || (!offset)) { 260 printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n"); 261 return NULL; 262 } 263 264 fe = (struct fileEntry *)buffer; 265 266 if (fe->descTag.tagIdent != cpu_to_le16(TAG_IDENT_FE)) { 267 udf_debug("0x%x != TAG_IDENT_FE\n", 268 le16_to_cpu(fe->descTag.tagIdent)); 269 return NULL; 270 } 271 272 ptr = (uint8_t *)(fe->extendedAttr) + 273 le32_to_cpu(fe->lengthExtendedAttr); 274 275 if ((*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs))) 276 ptr += *offset; 277 278 ext = (extent_ad *)ptr; 279 280 *offset = *offset + sizeof(extent_ad); 281 return ext; 282 } 283 #endif 284 285 short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset, 286 int inc) 287 { 288 short_ad *sa; 289 290 if ((!ptr) || (!offset)) { 291 printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n"); 292 return NULL; 293 } 294 295 if ((*offset + sizeof(short_ad)) > maxoffset) 296 return NULL; 297 else { 298 sa = (short_ad *)ptr; 299 if (sa->extLength == 0) 300 return NULL; 301 } 302 303 if (inc) 304 *offset += sizeof(short_ad); 305 return sa; 306 } 307 308 long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc) 309 { 310 long_ad *la; 311 312 if ((!ptr) || (!offset)) { 313 printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n"); 314 return NULL; 315 } 316 317 if ((*offset + sizeof(long_ad)) > maxoffset) 318 return NULL; 319 else { 320 la = (long_ad *)ptr; 321 if (la->extLength == 0) 322 return NULL; 323 } 324 325 if (inc) 326 *offset += sizeof(long_ad); 327 return la; 328 } 329