1 // SPDX-License-Identifier: GPL-2.0
3 * QNX6 file system, Linux implementation.
9 * 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
10 * 16-02-2012 pagemap extension by Al Viro
16 static unsigned qnx6_lfile_checksum(char *name
, unsigned size
)
19 char *end
= name
+ size
;
21 crc
= ((crc
>> 1) + *(name
++)) ^
22 ((crc
& 0x00000001) ? 0x80000000 : 0);
27 static void *qnx6_get_folio(struct inode
*dir
, unsigned long n
,
28 struct folio
**foliop
)
30 struct folio
*folio
= read_mapping_folio(dir
->i_mapping
, n
, NULL
);
35 return kmap_local_folio(folio
, 0);
38 static unsigned last_entry(struct inode
*inode
, unsigned long page_nr
)
40 unsigned long last_byte
= inode
->i_size
;
41 last_byte
-= page_nr
<< PAGE_SHIFT
;
42 if (last_byte
> PAGE_SIZE
)
43 last_byte
= PAGE_SIZE
;
44 return last_byte
/ QNX6_DIR_ENTRY_SIZE
;
47 static struct qnx6_long_filename
*qnx6_longname(struct super_block
*sb
,
48 struct qnx6_long_dir_entry
*de
,
49 struct folio
**foliop
)
51 struct qnx6_sb_info
*sbi
= QNX6_SB(sb
);
52 u32 s
= fs32_to_cpu(sbi
, de
->de_long_inode
); /* in block units */
53 u32 n
= s
>> (PAGE_SHIFT
- sb
->s_blocksize_bits
); /* in pages */
55 struct address_space
*mapping
= sbi
->longfile
->i_mapping
;
56 struct folio
*folio
= read_mapping_folio(mapping
, n
, NULL
);
59 return ERR_CAST(folio
);
60 offs
= offset_in_folio(folio
, s
<< sb
->s_blocksize_bits
);
62 return kmap_local_folio(folio
, offs
);
65 static int qnx6_dir_longfilename(struct inode
*inode
,
66 struct qnx6_long_dir_entry
*de
,
67 struct dir_context
*ctx
,
70 struct qnx6_long_filename
*lf
;
71 struct super_block
*s
= inode
->i_sb
;
72 struct qnx6_sb_info
*sbi
= QNX6_SB(s
);
76 if (de
->de_size
!= 0xff) {
77 /* error - long filename entries always have size 0xff
79 pr_err("invalid direntry size (%i).\n", de
->de_size
);
82 lf
= qnx6_longname(s
, de
, &folio
);
84 pr_err("Error reading longname\n");
88 lf_size
= fs16_to_cpu(sbi
, lf
->lf_size
);
90 if (lf_size
> QNX6_LONG_NAME_MAX
) {
91 pr_debug("file %s\n", lf
->lf_fname
);
92 pr_err("Filename too long (%i)\n", lf_size
);
93 folio_release_kmap(folio
, lf
);
97 /* calc & validate longfilename checksum
98 mmi 3g filesystem does not have that checksum */
99 if (!test_opt(s
, MMI_FS
) && fs32_to_cpu(sbi
, de
->de_checksum
) !=
100 qnx6_lfile_checksum(lf
->lf_fname
, lf_size
))
101 pr_info("long filename checksum error.\n");
103 pr_debug("qnx6_readdir:%.*s inode:%u\n",
104 lf_size
, lf
->lf_fname
, de_inode
);
105 if (!dir_emit(ctx
, lf
->lf_fname
, lf_size
, de_inode
, DT_UNKNOWN
)) {
106 folio_release_kmap(folio
, lf
);
110 folio_release_kmap(folio
, lf
);
115 static int qnx6_readdir(struct file
*file
, struct dir_context
*ctx
)
117 struct inode
*inode
= file_inode(file
);
118 struct super_block
*s
= inode
->i_sb
;
119 struct qnx6_sb_info
*sbi
= QNX6_SB(s
);
120 loff_t pos
= ctx
->pos
& ~(QNX6_DIR_ENTRY_SIZE
- 1);
121 unsigned long npages
= dir_pages(inode
);
122 unsigned long n
= pos
>> PAGE_SHIFT
;
123 unsigned offset
= (pos
& ~PAGE_MASK
) / QNX6_DIR_ENTRY_SIZE
;
127 if (ctx
->pos
>= inode
->i_size
)
130 for ( ; !done
&& n
< npages
; n
++, offset
= 0) {
131 struct qnx6_dir_entry
*de
;
133 char *kaddr
= qnx6_get_folio(inode
, n
, &folio
);
137 pr_err("%s(): read failed\n", __func__
);
138 ctx
->pos
= (n
+ 1) << PAGE_SHIFT
;
139 return PTR_ERR(kaddr
);
141 de
= (struct qnx6_dir_entry
*)(kaddr
+ offset
);
142 limit
= kaddr
+ last_entry(inode
, n
);
143 for (; (char *)de
< limit
; de
++, ctx
->pos
+= QNX6_DIR_ENTRY_SIZE
) {
144 int size
= de
->de_size
;
145 u32 no_inode
= fs32_to_cpu(sbi
, de
->de_inode
);
147 if (!no_inode
|| !size
)
150 if (size
> QNX6_SHORT_NAME_MAX
) {
151 /* long filename detected
152 get the filename from long filename
154 if (!qnx6_dir_longfilename(inode
,
155 (struct qnx6_long_dir_entry
*)de
,
161 pr_debug("%s():%.*s inode:%u\n",
162 __func__
, size
, de
->de_fname
,
164 if (!dir_emit(ctx
, de
->de_fname
, size
,
165 no_inode
, DT_UNKNOWN
)) {
171 folio_release_kmap(folio
, kaddr
);
177 * check if the long filename is correct.
179 static unsigned qnx6_long_match(int len
, const char *name
,
180 struct qnx6_long_dir_entry
*de
, struct inode
*dir
)
182 struct super_block
*s
= dir
->i_sb
;
183 struct qnx6_sb_info
*sbi
= QNX6_SB(s
);
186 struct qnx6_long_filename
*lf
= qnx6_longname(s
, de
, &folio
);
191 thislen
= fs16_to_cpu(sbi
, lf
->lf_size
);
192 if (len
!= thislen
) {
193 folio_release_kmap(folio
, lf
);
196 if (memcmp(name
, lf
->lf_fname
, len
) == 0) {
197 folio_release_kmap(folio
, lf
);
198 return fs32_to_cpu(sbi
, de
->de_inode
);
200 folio_release_kmap(folio
, lf
);
205 * check if the filename is correct.
207 static unsigned qnx6_match(struct super_block
*s
, int len
, const char *name
,
208 struct qnx6_dir_entry
*de
)
210 struct qnx6_sb_info
*sbi
= QNX6_SB(s
);
211 if (memcmp(name
, de
->de_fname
, len
) == 0)
212 return fs32_to_cpu(sbi
, de
->de_inode
);
217 unsigned qnx6_find_ino(int len
, struct inode
*dir
, const char *name
)
219 struct super_block
*s
= dir
->i_sb
;
220 struct qnx6_inode_info
*ei
= QNX6_I(dir
);
222 unsigned long start
, n
;
223 unsigned long npages
= dir_pages(dir
);
225 struct qnx6_dir_entry
*de
;
226 struct qnx6_long_dir_entry
*lde
;
230 start
= ei
->i_dir_start_lookup
;
236 de
= qnx6_get_folio(dir
, n
, &folio
);
238 int limit
= last_entry(dir
, n
);
241 for (i
= 0; i
< limit
; i
++, de
++) {
242 if (len
<= QNX6_SHORT_NAME_MAX
) {
244 if (len
!= de
->de_size
)
246 ino
= qnx6_match(s
, len
, name
, de
);
249 } else if (de
->de_size
== 0xff) {
250 /* deal with long filename */
251 lde
= (struct qnx6_long_dir_entry
*)de
;
252 ino
= qnx6_long_match(len
,
257 pr_err("undefined filename size in inode.\n");
259 folio_release_kmap(folio
, de
- i
);
264 } while (n
!= start
);
268 ei
->i_dir_start_lookup
= n
;
269 folio_release_kmap(folio
, de
);
273 const struct file_operations qnx6_dir_operations
= {
274 .llseek
= generic_file_llseek
,
275 .read
= generic_read_dir
,
276 .iterate_shared
= qnx6_readdir
,
277 .fsync
= generic_file_fsync
,
280 const struct inode_operations qnx6_dir_inode_operations
= {
281 .lookup
= qnx6_lookup
,