dir.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * linux/fs/adfs/dir.c
  4. *
  5. * Copyright (C) 1999-2000 Russell King
  6. *
  7. * Common directory handling for ADFS
  8. */
  9. #include <linux/hex.h>
  10. #include <linux/slab.h>
  11. #include "adfs.h"
  12. /*
  13. * For future. This should probably be per-directory.
  14. */
  15. static DECLARE_RWSEM(adfs_dir_rwsem);
  16. int adfs_dir_copyfrom(void *dst, struct adfs_dir *dir, unsigned int offset,
  17. size_t len)
  18. {
  19. struct super_block *sb = dir->sb;
  20. unsigned int index, remain;
  21. index = offset >> sb->s_blocksize_bits;
  22. offset &= sb->s_blocksize - 1;
  23. remain = sb->s_blocksize - offset;
  24. if (index + (remain < len) >= dir->nr_buffers)
  25. return -EINVAL;
  26. if (remain < len) {
  27. memcpy(dst, dir->bhs[index]->b_data + offset, remain);
  28. dst += remain;
  29. len -= remain;
  30. index += 1;
  31. offset = 0;
  32. }
  33. memcpy(dst, dir->bhs[index]->b_data + offset, len);
  34. return 0;
  35. }
  36. int adfs_dir_copyto(struct adfs_dir *dir, unsigned int offset, const void *src,
  37. size_t len)
  38. {
  39. struct super_block *sb = dir->sb;
  40. unsigned int index, remain;
  41. index = offset >> sb->s_blocksize_bits;
  42. offset &= sb->s_blocksize - 1;
  43. remain = sb->s_blocksize - offset;
  44. if (index + (remain < len) >= dir->nr_buffers)
  45. return -EINVAL;
  46. if (remain < len) {
  47. memcpy(dir->bhs[index]->b_data + offset, src, remain);
  48. src += remain;
  49. len -= remain;
  50. index += 1;
  51. offset = 0;
  52. }
  53. memcpy(dir->bhs[index]->b_data + offset, src, len);
  54. return 0;
  55. }
  56. static void __adfs_dir_cleanup(struct adfs_dir *dir)
  57. {
  58. dir->nr_buffers = 0;
  59. if (dir->bhs != dir->bh)
  60. kfree(dir->bhs);
  61. dir->bhs = NULL;
  62. dir->sb = NULL;
  63. }
  64. void adfs_dir_relse(struct adfs_dir *dir)
  65. {
  66. unsigned int i;
  67. for (i = 0; i < dir->nr_buffers; i++)
  68. brelse(dir->bhs[i]);
  69. __adfs_dir_cleanup(dir);
  70. }
  71. static void adfs_dir_forget(struct adfs_dir *dir)
  72. {
  73. unsigned int i;
  74. for (i = 0; i < dir->nr_buffers; i++)
  75. bforget(dir->bhs[i]);
  76. __adfs_dir_cleanup(dir);
  77. }
  78. int adfs_dir_read_buffers(struct super_block *sb, u32 indaddr,
  79. unsigned int size, struct adfs_dir *dir)
  80. {
  81. struct buffer_head **bhs;
  82. unsigned int i, num;
  83. int block;
  84. num = ALIGN(size, sb->s_blocksize) >> sb->s_blocksize_bits;
  85. if (num > ARRAY_SIZE(dir->bh)) {
  86. /* We only allow one extension */
  87. if (dir->bhs != dir->bh)
  88. return -EINVAL;
  89. bhs = kzalloc_objs(*bhs, num);
  90. if (!bhs)
  91. return -ENOMEM;
  92. if (dir->nr_buffers)
  93. memcpy(bhs, dir->bhs, dir->nr_buffers * sizeof(*bhs));
  94. dir->bhs = bhs;
  95. }
  96. for (i = dir->nr_buffers; i < num; i++) {
  97. block = __adfs_block_map(sb, indaddr, i);
  98. if (!block) {
  99. adfs_error(sb, "dir %06x has a hole at offset %u",
  100. indaddr, i);
  101. goto error;
  102. }
  103. dir->bhs[i] = sb_bread(sb, block);
  104. if (!dir->bhs[i]) {
  105. adfs_error(sb,
  106. "dir %06x failed read at offset %u, mapped block 0x%08x",
  107. indaddr, i, block);
  108. goto error;
  109. }
  110. dir->nr_buffers++;
  111. }
  112. return 0;
  113. error:
  114. adfs_dir_relse(dir);
  115. return -EIO;
  116. }
  117. static int adfs_dir_read(struct super_block *sb, u32 indaddr,
  118. unsigned int size, struct adfs_dir *dir)
  119. {
  120. dir->sb = sb;
  121. dir->bhs = dir->bh;
  122. dir->nr_buffers = 0;
  123. return ADFS_SB(sb)->s_dir->read(sb, indaddr, size, dir);
  124. }
  125. static int adfs_dir_read_inode(struct super_block *sb, struct inode *inode,
  126. struct adfs_dir *dir)
  127. {
  128. int ret;
  129. ret = adfs_dir_read(sb, ADFS_I(inode)->indaddr, inode->i_size, dir);
  130. if (ret)
  131. return ret;
  132. if (ADFS_I(inode)->parent_id != dir->parent_id) {
  133. adfs_error(sb,
  134. "parent directory id changed under me! (%06x but got %06x)\n",
  135. ADFS_I(inode)->parent_id, dir->parent_id);
  136. adfs_dir_relse(dir);
  137. ret = -EIO;
  138. }
  139. return ret;
  140. }
  141. static void adfs_dir_mark_dirty(struct adfs_dir *dir)
  142. {
  143. unsigned int i;
  144. /* Mark the buffers dirty */
  145. for (i = 0; i < dir->nr_buffers; i++)
  146. mark_buffer_dirty(dir->bhs[i]);
  147. }
  148. static int adfs_dir_sync(struct adfs_dir *dir)
  149. {
  150. int err = 0;
  151. int i;
  152. for (i = dir->nr_buffers - 1; i >= 0; i--) {
  153. struct buffer_head *bh = dir->bhs[i];
  154. sync_dirty_buffer(bh);
  155. if (buffer_req(bh) && !buffer_uptodate(bh))
  156. err = -EIO;
  157. }
  158. return err;
  159. }
  160. void adfs_object_fixup(struct adfs_dir *dir, struct object_info *obj)
  161. {
  162. unsigned int dots, i;
  163. /*
  164. * RISC OS allows the use of '/' in directory entry names, so we need
  165. * to fix these up. '/' is typically used for FAT compatibility to
  166. * represent '.', so do the same conversion here. In any case, '.'
  167. * will never be in a RISC OS name since it is used as the pathname
  168. * separator. Handle the case where we may generate a '.' or '..'
  169. * name, replacing the first character with '^' (the RISC OS "parent
  170. * directory" character.)
  171. */
  172. for (i = dots = 0; i < obj->name_len; i++)
  173. if (obj->name[i] == '/') {
  174. obj->name[i] = '.';
  175. dots++;
  176. }
  177. if (obj->name_len <= 2 && dots == obj->name_len)
  178. obj->name[0] = '^';
  179. /*
  180. * If the object is a file, and the user requested the ,xyz hex
  181. * filetype suffix to the name, check the filetype and append.
  182. */
  183. if (!(obj->attr & ADFS_NDA_DIRECTORY) && ADFS_SB(dir->sb)->s_ftsuffix) {
  184. u16 filetype = adfs_filetype(obj->loadaddr);
  185. if (filetype != ADFS_FILETYPE_NONE) {
  186. obj->name[obj->name_len++] = ',';
  187. obj->name[obj->name_len++] = hex_asc_lo(filetype >> 8);
  188. obj->name[obj->name_len++] = hex_asc_lo(filetype >> 4);
  189. obj->name[obj->name_len++] = hex_asc_lo(filetype >> 0);
  190. }
  191. }
  192. }
  193. static int adfs_iterate(struct file *file, struct dir_context *ctx)
  194. {
  195. struct inode *inode = file_inode(file);
  196. struct super_block *sb = inode->i_sb;
  197. const struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
  198. struct adfs_dir dir;
  199. int ret;
  200. down_read(&adfs_dir_rwsem);
  201. ret = adfs_dir_read_inode(sb, inode, &dir);
  202. if (ret)
  203. goto unlock;
  204. if (ctx->pos == 0) {
  205. if (!dir_emit_dot(file, ctx))
  206. goto unlock_relse;
  207. ctx->pos = 1;
  208. }
  209. if (ctx->pos == 1) {
  210. if (!dir_emit(ctx, "..", 2, dir.parent_id, DT_DIR))
  211. goto unlock_relse;
  212. ctx->pos = 2;
  213. }
  214. ret = ops->iterate(&dir, ctx);
  215. unlock_relse:
  216. up_read(&adfs_dir_rwsem);
  217. adfs_dir_relse(&dir);
  218. return ret;
  219. unlock:
  220. up_read(&adfs_dir_rwsem);
  221. return ret;
  222. }
  223. int
  224. adfs_dir_update(struct super_block *sb, struct object_info *obj, int wait)
  225. {
  226. const struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
  227. struct adfs_dir dir;
  228. int ret;
  229. if (!IS_ENABLED(CONFIG_ADFS_FS_RW))
  230. return -EINVAL;
  231. if (!ops->update)
  232. return -EINVAL;
  233. down_write(&adfs_dir_rwsem);
  234. ret = adfs_dir_read(sb, obj->parent_id, 0, &dir);
  235. if (ret)
  236. goto unlock;
  237. ret = ops->update(&dir, obj);
  238. if (ret)
  239. goto forget;
  240. ret = ops->commit(&dir);
  241. if (ret)
  242. goto forget;
  243. up_write(&adfs_dir_rwsem);
  244. adfs_dir_mark_dirty(&dir);
  245. if (wait)
  246. ret = adfs_dir_sync(&dir);
  247. adfs_dir_relse(&dir);
  248. return ret;
  249. /*
  250. * If the updated failed because the entry wasn't found, we can
  251. * just release the buffers. If it was any other error, forget
  252. * the dirtied buffers so they aren't written back to the media.
  253. */
  254. forget:
  255. if (ret == -ENOENT)
  256. adfs_dir_relse(&dir);
  257. else
  258. adfs_dir_forget(&dir);
  259. unlock:
  260. up_write(&adfs_dir_rwsem);
  261. return ret;
  262. }
  263. static unsigned char adfs_tolower(unsigned char c)
  264. {
  265. if (c >= 'A' && c <= 'Z')
  266. c += 'a' - 'A';
  267. return c;
  268. }
  269. static int __adfs_compare(const unsigned char *qstr, u32 qlen,
  270. const char *str, u32 len)
  271. {
  272. u32 i;
  273. if (qlen != len)
  274. return 1;
  275. for (i = 0; i < qlen; i++)
  276. if (adfs_tolower(qstr[i]) != adfs_tolower(str[i]))
  277. return 1;
  278. return 0;
  279. }
  280. static int adfs_dir_lookup_byname(struct inode *inode, const struct qstr *qstr,
  281. struct object_info *obj)
  282. {
  283. struct super_block *sb = inode->i_sb;
  284. const struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
  285. const unsigned char *name;
  286. struct adfs_dir dir;
  287. u32 name_len;
  288. int ret;
  289. down_read(&adfs_dir_rwsem);
  290. ret = adfs_dir_read_inode(sb, inode, &dir);
  291. if (ret)
  292. goto unlock;
  293. ret = ops->setpos(&dir, 0);
  294. if (ret)
  295. goto unlock_relse;
  296. ret = -ENOENT;
  297. name = qstr->name;
  298. name_len = qstr->len;
  299. while (ops->getnext(&dir, obj) == 0) {
  300. if (!__adfs_compare(name, name_len, obj->name, obj->name_len)) {
  301. ret = 0;
  302. break;
  303. }
  304. }
  305. obj->parent_id = ADFS_I(inode)->indaddr;
  306. unlock_relse:
  307. up_read(&adfs_dir_rwsem);
  308. adfs_dir_relse(&dir);
  309. return ret;
  310. unlock:
  311. up_read(&adfs_dir_rwsem);
  312. return ret;
  313. }
  314. const struct file_operations adfs_dir_operations = {
  315. .read = generic_read_dir,
  316. .llseek = generic_file_llseek,
  317. .iterate_shared = adfs_iterate,
  318. .fsync = generic_file_fsync,
  319. };
  320. static int
  321. adfs_hash(const struct dentry *parent, struct qstr *qstr)
  322. {
  323. const unsigned char *name;
  324. unsigned long hash;
  325. u32 len;
  326. if (qstr->len > ADFS_SB(parent->d_sb)->s_namelen)
  327. return -ENAMETOOLONG;
  328. len = qstr->len;
  329. name = qstr->name;
  330. hash = init_name_hash(parent);
  331. while (len--)
  332. hash = partial_name_hash(adfs_tolower(*name++), hash);
  333. qstr->hash = end_name_hash(hash);
  334. return 0;
  335. }
  336. /*
  337. * Compare two names, taking note of the name length
  338. * requirements of the underlying filesystem.
  339. */
  340. static int adfs_compare(const struct dentry *dentry, unsigned int len,
  341. const char *str, const struct qstr *qstr)
  342. {
  343. return __adfs_compare(qstr->name, qstr->len, str, len);
  344. }
  345. const struct dentry_operations adfs_dentry_operations = {
  346. .d_hash = adfs_hash,
  347. .d_compare = adfs_compare,
  348. };
  349. static struct dentry *
  350. adfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
  351. {
  352. struct inode *inode = NULL;
  353. struct object_info obj;
  354. int error;
  355. error = adfs_dir_lookup_byname(dir, &dentry->d_name, &obj);
  356. if (error == 0) {
  357. /*
  358. * This only returns NULL if get_empty_inode
  359. * fails.
  360. */
  361. inode = adfs_iget(dir->i_sb, &obj);
  362. if (!inode)
  363. inode = ERR_PTR(-EACCES);
  364. } else if (error != -ENOENT) {
  365. inode = ERR_PTR(error);
  366. }
  367. return d_splice_alias(inode, dentry);
  368. }
  369. /*
  370. * directories can handle most operations...
  371. */
  372. const struct inode_operations adfs_dir_inode_operations = {
  373. .lookup = adfs_lookup,
  374. .setattr = adfs_notify_change,
  375. };