11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/fs/adfs/dir_fplus.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997-1999 Russell King 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/buffer_head.h> 112f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales#include <linux/slab.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "adfs.h" 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dir_fplus.h" 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsadfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct adfs_dir *dir) 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adfs_bigdirheader *h; 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adfs_bigdirtail *t; 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long block; 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int blk, size; 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret = -EIO; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir->nr_buffers = 0; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 262f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales /* start off using fixed bh set - only alloc for big dirs */ 272f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus = &dir->bh[0]; 282f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds block = __adfs_block_map(sb, id, 0); 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!block) { 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adfs_error(sb, "dir object %X has a hole at offset 0", id); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 352f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus[0] = sb_bread(sb, block); 362f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales if (!dir->bh_fplus[0]) 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir->nr_buffers += 1; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 402f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales h = (struct adfs_bigdirheader *)dir->bh_fplus[0]->b_data; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = le32_to_cpu(h->bigdirsize); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (size != sz) { 432f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales printk(KERN_WARNING "adfs: adfs_fplus_read:" 442f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales " directory header size %X\n" 452f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales " does not match directory size %X\n", 462f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales size, sz); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (h->bigdirversion[0] != 0 || h->bigdirversion[1] != 0 || 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->bigdirversion[2] != 0 || size & 2047 || 512f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales h->bigdirstartname != cpu_to_le32(BIGDIRSTARTNAME)) { 522f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales printk(KERN_WARNING "adfs: dir object %X has" 532f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales " malformed dir header\n", id); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 552f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales } 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size >>= sb->s_blocksize_bits; 58e2ffcf5c7ee7eb979b1f2375404668a2f5076c1bFabian Frederick if (size > ARRAY_SIZE(dir->bh)) { 592f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales /* this directory is too big for fixed bh set, must allocate */ 602f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales struct buffer_head **bh_fplus = 61b16214d43d9060722360360f741416660b54c4f5Fabian Frederick kcalloc(size, sizeof(struct buffer_head *), 622f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales GFP_KERNEL); 632f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales if (!bh_fplus) { 642f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales adfs_error(sb, "not enough memory for" 652f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales " dir object %X (%d blocks)", id, size); 662f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales goto out; 672f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales } 682f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus = bh_fplus; 692f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales /* copy over the pointer to the block that we've already read */ 702f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus[0] = dir->bh[0]; 712f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales } 722f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (blk = 1; blk < size; blk++) { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds block = __adfs_block_map(sb, id, blk); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!block) { 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adfs_error(sb, "dir object %X has a hole at offset %d", id, blk); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 802f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus[blk] = sb_bread(sb, block); 812f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales if (!dir->bh_fplus[blk]) { 8219bdd41a57e1418b8661148125e9b6d99f468c1bJoe Perches adfs_error(sb, "dir object %x failed read for offset %d, mapped block %lX", 8319bdd41a57e1418b8661148125e9b6d99f468c1bJoe Perches id, blk, block); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 852f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales } 862f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 872f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->nr_buffers += 1; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 902f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales t = (struct adfs_bigdirtail *) 912f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales (dir->bh_fplus[size - 1]->b_data + (sb->s_blocksize - 8)); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t->bigdirendname != cpu_to_le32(BIGDIRENDNAME) || 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->bigdirendmasseq != h->startmasseq || 952f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales t->reserved[0] != 0 || t->reserved[1] != 0) { 962f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales printk(KERN_WARNING "adfs: dir object %X has " 972f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales "malformed dir end\n", id); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 992f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales } 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir->parent_id = le32_to_cpu(h->bigdirparent); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir->sb = sb; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1042f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 1062f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales if (dir->bh_fplus) { 1072f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales for (i = 0; i < dir->nr_buffers; i++) 1082f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales brelse(dir->bh_fplus[i]); 1092f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 1102f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales if (&dir->bh[0] != dir->bh_fplus) 1112f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales kfree(dir->bh_fplus); 1122f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 1132f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus = NULL; 1142f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales } 1152f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 1162f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->nr_buffers = 0; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir->sb = NULL; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsadfs_fplus_setpos(struct adfs_dir *dir, unsigned int fpos) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1242f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales struct adfs_bigdirheader *h = 1252f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales (struct adfs_bigdirheader *) dir->bh_fplus[0]->b_data; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -ENOENT; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fpos <= le32_to_cpu(h->bigdirentries)) { 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir->pos = fpos; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdir_memcpy(struct adfs_dir *dir, unsigned int offset, void *to, int len) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct super_block *sb = dir->sb; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int buffer, partial, remainder; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer = offset >> sb->s_blocksize_bits; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset &= sb->s_blocksize - 1; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds partial = sb->s_blocksize - offset; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (partial >= len) 1482f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales memcpy(to, dir->bh_fplus[buffer]->b_data + offset, len); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *c = (char *)to; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remainder = len - partial; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1542f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales memcpy(c, 1552f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus[buffer]->b_data + offset, 1562f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales partial); 1572f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 1582f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales memcpy(c + partial, 1592f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus[buffer + 1]->b_data, 1602f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales remainder); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsadfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1672f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales struct adfs_bigdirheader *h = 1682f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales (struct adfs_bigdirheader *) dir->bh_fplus[0]->b_data; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adfs_bigdirentry bde; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int offset; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret = -ENOENT; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dir->pos >= le32_to_cpu(h->bigdirentries)) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = offsetof(struct adfs_bigdirheader, bigdirname); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += ((le32_to_cpu(h->bigdirnamelen) + 4) & ~3); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += dir->pos * sizeof(struct adfs_bigdirentry); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir_memcpy(dir, offset, &bde, sizeof(struct adfs_bigdirentry)); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds obj->loadaddr = le32_to_cpu(bde.bigdirload); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds obj->execaddr = le32_to_cpu(bde.bigdirexec); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds obj->size = le32_to_cpu(bde.bigdirlen); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds obj->file_id = le32_to_cpu(bde.bigdirindaddr); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds obj->attr = le32_to_cpu(bde.bigdirattr); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds obj->name_len = le32_to_cpu(bde.bigdirobnamelen); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = offsetof(struct adfs_bigdirheader, bigdirname); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += ((le32_to_cpu(h->bigdirnamelen) + 4) & ~3); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += le32_to_cpu(h->bigdirentries) * sizeof(struct adfs_bigdirentry); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += le32_to_cpu(bde.bigdirobnameptr); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir_memcpy(dir, offset, obj->name, obj->name_len); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < obj->name_len; i++) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (obj->name[i] == '/') 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds obj->name[i] = '.'; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 199da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales obj->filetype = -1; 200da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales 201da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales /* 202da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales * object is a file and is filetyped and timestamped? 203da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales * RISC OS 12-bit filetype is stored in load_address[19:8] 204da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales */ 205da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) && 206da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales (0xfff00000 == (0xfff00000 & obj->loadaddr))) { 207da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8); 208da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales 209da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales /* optionally append the ,xyz hex filetype suffix */ 210da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales if (ADFS_SB(dir->sb)->s_ftsuffix) 211da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales obj->name_len += 212da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales append_filetype_suffix( 213da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales &obj->name[obj->name_len], 214da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales obj->filetype); 215da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales } 216da23ef0549d4205ca9b576cf6cce9a80d0c3e43aStuart Swales 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir->pos += 1; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 223ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Virostatic int 224ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viroadfs_fplus_sync(struct adfs_dir *dir) 225ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro{ 226ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro int err = 0; 227ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro int i; 228ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro 229ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro for (i = dir->nr_buffers - 1; i >= 0; i--) { 2302f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales struct buffer_head *bh = dir->bh_fplus[i]; 231ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro sync_dirty_buffer(bh); 232ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro if (buffer_req(bh) && !buffer_uptodate(bh)) 233ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro err = -EIO; 234ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro } 235ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro 236ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro return err; 237ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro} 238ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsadfs_fplus_free(struct adfs_dir *dir) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2442f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales if (dir->bh_fplus) { 2452f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales for (i = 0; i < dir->nr_buffers; i++) 2462f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales brelse(dir->bh_fplus[i]); 2472f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 2482f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales if (&dir->bh[0] != dir->bh_fplus) 2492f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales kfree(dir->bh_fplus); 2502f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 2512f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->bh_fplus = NULL; 2522f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales } 2532f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales 2542f09719af705db56032ae480a2d9c32c2a3fcbd3Stuart Swales dir->nr_buffers = 0; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dir->sb = NULL; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct adfs_dir_ops adfs_fplus_dir_ops = { 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = adfs_fplus_read, 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .setpos = adfs_fplus_setpos, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getnext = adfs_fplus_getnext, 262ffdc9064f8b4fa9db37a7d5180f41cce2ea2b7adAl Viro .sync = adfs_fplus_sync, 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .free = adfs_fplus_free 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 265