^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) * QNX6 file system, Linux implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Version : 1.0.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * History :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * 16-02-2012 pagemap extension by Al Viro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^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) #include "qnx6.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static unsigned qnx6_lfile_checksum(char *name, unsigned size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) char *end = name + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) while (name < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) crc = ((crc >> 1) + *(name++)) ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) ((crc & 0x00000001) ? 0x80000000 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static struct page *qnx6_get_page(struct inode *dir, unsigned long n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct address_space *mapping = dir->i_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct page *page = read_mapping_page(mapping, n, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (!IS_ERR(page))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) kmap(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static unsigned last_entry(struct inode *inode, unsigned long page_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned long last_byte = inode->i_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) last_byte -= page_nr << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (last_byte > PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) last_byte = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return last_byte / QNX6_DIR_ENTRY_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static struct qnx6_long_filename *qnx6_longname(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct qnx6_long_dir_entry *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct page **p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct qnx6_sb_info *sbi = QNX6_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u32 s = fs32_to_cpu(sbi, de->de_long_inode); /* in block units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 n = s >> (PAGE_SHIFT - sb->s_blocksize_bits); /* in pages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* within page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u32 offs = (s << sb->s_blocksize_bits) & ~PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct address_space *mapping = sbi->longfile->i_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct page *page = read_mapping_page(mapping, n, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (IS_ERR(page))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return ERR_CAST(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) kmap(*p = page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return (struct qnx6_long_filename *)(page_address(page) + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static int qnx6_dir_longfilename(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct qnx6_long_dir_entry *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct dir_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned de_inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct qnx6_long_filename *lf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct super_block *s = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct qnx6_sb_info *sbi = QNX6_SB(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int lf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (de->de_size != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* error - long filename entries always have size 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) in direntry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pr_err("invalid direntry size (%i).\n", de->de_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) lf = qnx6_longname(s, de, &page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (IS_ERR(lf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pr_err("Error reading longname\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) lf_size = fs16_to_cpu(sbi, lf->lf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (lf_size > QNX6_LONG_NAME_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) pr_debug("file %s\n", lf->lf_fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) pr_err("Filename too long (%i)\n", lf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) qnx6_put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* calc & validate longfilename checksum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) mmi 3g filesystem does not have that checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!test_opt(s, MMI_FS) && fs32_to_cpu(sbi, de->de_checksum) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) qnx6_lfile_checksum(lf->lf_fname, lf_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) pr_info("long filename checksum error.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) pr_debug("qnx6_readdir:%.*s inode:%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) lf_size, lf->lf_fname, de_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!dir_emit(ctx, lf->lf_fname, lf_size, de_inode, DT_UNKNOWN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) qnx6_put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) qnx6_put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int qnx6_readdir(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct super_block *s = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct qnx6_sb_info *sbi = QNX6_SB(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) loff_t pos = ctx->pos & ~(QNX6_DIR_ENTRY_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned long npages = dir_pages(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned long n = pos >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned start = (pos & ~PAGE_MASK) / QNX6_DIR_ENTRY_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) bool done = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ctx->pos = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (ctx->pos >= inode->i_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) for ( ; !done && n < npages; n++, start = 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct page *page = qnx6_get_page(inode, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int limit = last_entry(inode, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct qnx6_dir_entry *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int i = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (IS_ERR(page)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) pr_err("%s(): read failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ctx->pos = (n + 1) << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return PTR_ERR(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) de = ((struct qnx6_dir_entry *)page_address(page)) + start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) for (; i < limit; i++, de++, ctx->pos += QNX6_DIR_ENTRY_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int size = de->de_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u32 no_inode = fs32_to_cpu(sbi, de->de_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (!no_inode || !size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (size > QNX6_SHORT_NAME_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* long filename detected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) get the filename from long filename
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) structure / block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (!qnx6_dir_longfilename(inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) (struct qnx6_long_dir_entry *)de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ctx, no_inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) pr_debug("%s():%.*s inode:%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) __func__, size, de->de_fname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) no_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (!dir_emit(ctx, de->de_fname, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) no_inode, DT_UNKNOWN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) qnx6_put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * check if the long filename is correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static unsigned qnx6_long_match(int len, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct qnx6_long_dir_entry *de, struct inode *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct super_block *s = dir->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct qnx6_sb_info *sbi = QNX6_SB(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int thislen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct qnx6_long_filename *lf = qnx6_longname(s, de, &page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (IS_ERR(lf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) thislen = fs16_to_cpu(sbi, lf->lf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (len != thislen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) qnx6_put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (memcmp(name, lf->lf_fname, len) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) qnx6_put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return fs32_to_cpu(sbi, de->de_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) qnx6_put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * check if the filename is correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static unsigned qnx6_match(struct super_block *s, int len, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct qnx6_dir_entry *de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct qnx6_sb_info *sbi = QNX6_SB(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (memcmp(name, de->de_fname, len) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return fs32_to_cpu(sbi, de->de_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned qnx6_find_entry(int len, struct inode *dir, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct page **res_page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct super_block *s = dir->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct qnx6_inode_info *ei = QNX6_I(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct page *page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) unsigned long start, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned long npages = dir_pages(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) unsigned ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct qnx6_dir_entry *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct qnx6_long_dir_entry *lde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *res_page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (npages == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) start = ei->i_dir_start_lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (start >= npages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) n = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) page = qnx6_get_page(dir, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!IS_ERR(page)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int limit = last_entry(dir, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) de = (struct qnx6_dir_entry *)page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) for (i = 0; i < limit; i++, de++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (len <= QNX6_SHORT_NAME_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* short filename */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (len != de->de_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ino = qnx6_match(s, len, name, de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) } else if (de->de_size == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* deal with long filename */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) lde = (struct qnx6_long_dir_entry *)de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ino = qnx6_long_match(len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) name, lde, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) pr_err("undefined filename size in inode.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) qnx6_put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (++n >= npages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) } while (n != start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) *res_page = page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ei->i_dir_start_lookup = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) const struct file_operations qnx6_dir_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .read = generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .iterate_shared = qnx6_readdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .fsync = generic_file_fsync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) const struct inode_operations qnx6_dir_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .lookup = qnx6_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) };