^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/fs/isofs/namei.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (C) 1991 Linus Torvalds - minix filesystem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "isofs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * ok, we cannot use strncmp, as the name is not in our data space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Thus we'll have to use isofs_match. No big problem. Match also makes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * some sanity tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct qstr qstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) qstr.name = compare;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) qstr.len = dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (likely(!dentry->d_op))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return dentry->d_name.len != dlen || memcmp(dentry->d_name.name, compare, dlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return dentry->d_op->d_compare(NULL, dentry->d_name.len, dentry->d_name.name, &qstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * isofs_find_entry()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * finds an entry in the specified directory with the wanted name. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * returns the inode number of the found entry, or 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) isofs_find_entry(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long *block_rv, unsigned long *offset_rv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) char *tmpname, struct iso_directory_record *tmpde)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) unsigned long block, f_pos, offset, block_saved, offset_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (!ISOFS_I(dir)->i_first_extent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) f_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) block = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) while (f_pos < dir->i_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct iso_directory_record *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int de_len, match, i, dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) char *dpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) bh = isofs_bread(dir, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (!bh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) de = (struct iso_directory_record *) (bh->b_data + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) de_len = *(unsigned char *) de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (!de_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) block = f_pos >> bufbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) block_saved = bh->b_blocknr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) offset_saved = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) offset += de_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) f_pos += de_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Make sure we have a full directory entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (offset >= bufsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int slop = bufsize - offset + de_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) memcpy(tmpde, de, slop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) offset &= bufsize - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) block++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) bh = isofs_bread(dir, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!bh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) memcpy((void *) tmpde + slop, bh->b_data, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) de = tmpde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dlen = de->name_len[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dpnt = de->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* Basic sanity check, whether name doesn't exceed dir entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (de_len < dlen + sizeof(struct iso_directory_record)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) printk(KERN_NOTICE "iso9660: Corrupted directory entry"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) " in block %lu of inode %lu\n", block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) dir->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (sbi->s_rock &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) dlen = i; /* possibly -1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dpnt = tmpname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #ifdef CONFIG_JOLIET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } else if (sbi->s_joliet_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dlen = get_joliet_filename(de, tmpname, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dpnt = tmpname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) } else if (sbi->s_mapping == 'a') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) dlen = get_acorn_filename(de, tmpname, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dpnt = tmpname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) } else if (sbi->s_mapping == 'n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dlen = isofs_name_translate(de, tmpname, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dpnt = tmpname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * Skip hidden or associated files unless hide or showassoc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * respectively, is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) match = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (dlen > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) (!sbi->s_hide ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) (!(de->flags[-sbi->s_high_sierra] & 1))) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) (sbi->s_showassoc ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) (!(de->flags[-sbi->s_high_sierra] & 4)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (dpnt && (dlen > 1 || dpnt[0] > 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) match = (isofs_cmp(dentry, dpnt, dlen) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) isofs_normalize_block_and_offset(de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) &block_saved,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) &offset_saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *block_rv = block_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *offset_rv = offset_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) unsigned long block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) page = alloc_page(GFP_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) found = isofs_find_entry(dir, dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) &block, &offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) page_address(page),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 1024 + page_address(page));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) __free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) inode = found ? isofs_iget(dir->i_sb, block, offset) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return d_splice_alias(inode, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }