1 /**
2 * libf2fs.c
3 *
4 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * Dual licensed under the GPL or LGPL version 2 licenses.
8 */
9 #define _LARGEFILE64_SOURCE
10 #define _FILE_OFFSET_BITS 64
11
12 #include <f2fs_fs.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <libgen.h>
20 #ifdef HAVE_MNTENT_H
21 #include <mntent.h>
22 #endif
23 #include <time.h>
24 #include <sys/stat.h>
25 #ifndef ANDROID_WINDOWS_HOST
26 #include <sys/mount.h>
27 #include <sys/ioctl.h>
28 #endif
29 #ifdef HAVE_SYS_SYSMACROS_H
30 #include <sys/sysmacros.h>
31 #endif
32 #ifdef HAVE_SYS_UTSNAME_H
33 #include <sys/utsname.h>
34 #endif
35 #ifndef WITH_ANDROID
36 #ifdef HAVE_SCSI_SG_H
37 #include <scsi/sg.h>
38 #endif
39 #endif
40 #ifdef HAVE_LINUX_HDREG_H
41 #include <linux/hdreg.h>
42 #endif
43 #ifdef HAVE_LINUX_LIMITS_H
44 #include <linux/limits.h>
45 #endif
46
47 #ifndef WITH_ANDROID
48 /* SCSI command for standard inquiry*/
49 #define MODELINQUIRY 0x12,0x00,0x00,0x00,0x4A,0x00
50 #endif
51
52 #ifndef ANDROID_WINDOWS_HOST /* O_BINARY is windows-specific flag */
53 #define O_BINARY 0
54 #else
55 /* On Windows, wchar_t is 8 bit sized and it causes compilation errors. */
56 #define wchar_t int
57 #endif
58
59 /*
60 * UTF conversion codes are Copied from exfat tools.
61 */
utf8_to_wchar(const char * input,wchar_t * wc,size_t insize)62 static const char *utf8_to_wchar(const char *input, wchar_t *wc,
63 size_t insize)
64 {
65 if ((input[0] & 0x80) == 0 && insize >= 1) {
66 *wc = (wchar_t) input[0];
67 return input + 1;
68 }
69 if ((input[0] & 0xe0) == 0xc0 && insize >= 2) {
70 *wc = (((wchar_t) input[0] & 0x1f) << 6) |
71 ((wchar_t) input[1] & 0x3f);
72 return input + 2;
73 }
74 if ((input[0] & 0xf0) == 0xe0 && insize >= 3) {
75 *wc = (((wchar_t) input[0] & 0x0f) << 12) |
76 (((wchar_t) input[1] & 0x3f) << 6) |
77 ((wchar_t) input[2] & 0x3f);
78 return input + 3;
79 }
80 if ((input[0] & 0xf8) == 0xf0 && insize >= 4) {
81 *wc = (((wchar_t) input[0] & 0x07) << 18) |
82 (((wchar_t) input[1] & 0x3f) << 12) |
83 (((wchar_t) input[2] & 0x3f) << 6) |
84 ((wchar_t) input[3] & 0x3f);
85 return input + 4;
86 }
87 if ((input[0] & 0xfc) == 0xf8 && insize >= 5) {
88 *wc = (((wchar_t) input[0] & 0x03) << 24) |
89 (((wchar_t) input[1] & 0x3f) << 18) |
90 (((wchar_t) input[2] & 0x3f) << 12) |
91 (((wchar_t) input[3] & 0x3f) << 6) |
92 ((wchar_t) input[4] & 0x3f);
93 return input + 5;
94 }
95 if ((input[0] & 0xfe) == 0xfc && insize >= 6) {
96 *wc = (((wchar_t) input[0] & 0x01) << 30) |
97 (((wchar_t) input[1] & 0x3f) << 24) |
98 (((wchar_t) input[2] & 0x3f) << 18) |
99 (((wchar_t) input[3] & 0x3f) << 12) |
100 (((wchar_t) input[4] & 0x3f) << 6) |
101 ((wchar_t) input[5] & 0x3f);
102 return input + 6;
103 }
104 return NULL;
105 }
106
wchar_to_utf16(u_int16_t * output,wchar_t wc,size_t outsize)107 static u_int16_t *wchar_to_utf16(u_int16_t *output, wchar_t wc, size_t outsize)
108 {
109 if (wc <= 0xffff) {
110 if (outsize == 0)
111 return NULL;
112 output[0] = cpu_to_le16(wc);
113 return output + 1;
114 }
115 if (outsize < 2)
116 return NULL;
117 wc -= 0x10000;
118 output[0] = cpu_to_le16(0xd800 | ((wc >> 10) & 0x3ff));
119 output[1] = cpu_to_le16(0xdc00 | (wc & 0x3ff));
120 return output + 2;
121 }
122
utf8_to_utf16(u_int16_t * output,const char * input,size_t outsize,size_t insize)123 int utf8_to_utf16(u_int16_t *output, const char *input, size_t outsize,
124 size_t insize)
125 {
126 const char *inp = input;
127 u_int16_t *outp = output;
128 wchar_t wc;
129
130 while ((size_t)(inp - input) < insize && *inp) {
131 inp = utf8_to_wchar(inp, &wc, insize - (inp - input));
132 if (inp == NULL) {
133 DBG(0, "illegal UTF-8 sequence\n");
134 return -EILSEQ;
135 }
136 outp = wchar_to_utf16(outp, wc, outsize - (outp - output));
137 if (outp == NULL) {
138 DBG(0, "name is too long\n");
139 return -ENAMETOOLONG;
140 }
141 }
142 *outp = cpu_to_le16(0);
143 return 0;
144 }
145
utf16_to_wchar(const u_int16_t * input,wchar_t * wc,size_t insize)146 static const u_int16_t *utf16_to_wchar(const u_int16_t *input, wchar_t *wc,
147 size_t insize)
148 {
149 if ((le16_to_cpu(input[0]) & 0xfc00) == 0xd800) {
150 if (insize < 2 || (le16_to_cpu(input[1]) & 0xfc00) != 0xdc00)
151 return NULL;
152 *wc = ((wchar_t) (le16_to_cpu(input[0]) & 0x3ff) << 10);
153 *wc |= (le16_to_cpu(input[1]) & 0x3ff);
154 *wc += 0x10000;
155 return input + 2;
156 } else {
157 *wc = le16_to_cpu(*input);
158 return input + 1;
159 }
160 }
161
wchar_to_utf8(char * output,wchar_t wc,size_t outsize)162 static char *wchar_to_utf8(char *output, wchar_t wc, size_t outsize)
163 {
164 if (wc <= 0x7f) {
165 if (outsize < 1)
166 return NULL;
167 *output++ = (char) wc;
168 } else if (wc <= 0x7ff) {
169 if (outsize < 2)
170 return NULL;
171 *output++ = 0xc0 | (wc >> 6);
172 *output++ = 0x80 | (wc & 0x3f);
173 } else if (wc <= 0xffff) {
174 if (outsize < 3)
175 return NULL;
176 *output++ = 0xe0 | (wc >> 12);
177 *output++ = 0x80 | ((wc >> 6) & 0x3f);
178 *output++ = 0x80 | (wc & 0x3f);
179 } else if (wc <= 0x1fffff) {
180 if (outsize < 4)
181 return NULL;
182 *output++ = 0xf0 | (wc >> 18);
183 *output++ = 0x80 | ((wc >> 12) & 0x3f);
184 *output++ = 0x80 | ((wc >> 6) & 0x3f);
185 *output++ = 0x80 | (wc & 0x3f);
186 } else if (wc <= 0x3ffffff) {
187 if (outsize < 5)
188 return NULL;
189 *output++ = 0xf8 | (wc >> 24);
190 *output++ = 0x80 | ((wc >> 18) & 0x3f);
191 *output++ = 0x80 | ((wc >> 12) & 0x3f);
192 *output++ = 0x80 | ((wc >> 6) & 0x3f);
193 *output++ = 0x80 | (wc & 0x3f);
194 } else if (wc <= 0x7fffffff) {
195 if (outsize < 6)
196 return NULL;
197 *output++ = 0xfc | (wc >> 30);
198 *output++ = 0x80 | ((wc >> 24) & 0x3f);
199 *output++ = 0x80 | ((wc >> 18) & 0x3f);
200 *output++ = 0x80 | ((wc >> 12) & 0x3f);
201 *output++ = 0x80 | ((wc >> 6) & 0x3f);
202 *output++ = 0x80 | (wc & 0x3f);
203 } else
204 return NULL;
205
206 return output;
207 }
208
utf16_to_utf8(char * output,const u_int16_t * input,size_t outsize,size_t insize)209 int utf16_to_utf8(char *output, const u_int16_t *input, size_t outsize,
210 size_t insize)
211 {
212 const u_int16_t *inp = input;
213 char *outp = output;
214 wchar_t wc;
215
216 while ((size_t)(inp - input) < insize && le16_to_cpu(*inp)) {
217 inp = utf16_to_wchar(inp, &wc, insize - (inp - input));
218 if (inp == NULL) {
219 DBG(0, "illegal UTF-16 sequence\n");
220 return -EILSEQ;
221 }
222 outp = wchar_to_utf8(outp, wc, outsize - (outp - output));
223 if (outp == NULL) {
224 DBG(0, "name is too long\n");
225 return -ENAMETOOLONG;
226 }
227 }
228 *outp = '\0';
229 return 0;
230 }
231
log_base_2(u_int32_t num)232 int log_base_2(u_int32_t num)
233 {
234 int ret = 0;
235 if (num <= 0 || (num & (num - 1)) != 0)
236 return -1;
237
238 while (num >>= 1)
239 ret++;
240 return ret;
241 }
242
243 /*
244 * f2fs bit operations
245 */
246 static const int bits_in_byte[256] = {
247 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
248 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
249 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
250 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
251 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
252 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
253 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
254 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
255 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
256 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
257 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
258 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
259 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
260 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
261 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
262 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
263 };
264
get_bits_in_byte(unsigned char n)265 int get_bits_in_byte(unsigned char n)
266 {
267 return bits_in_byte[n];
268 }
269
test_and_set_bit_le(u32 nr,u8 * addr)270 int test_and_set_bit_le(u32 nr, u8 *addr)
271 {
272 int mask, retval;
273
274 addr += nr >> 3;
275 mask = 1 << ((nr & 0x07));
276 retval = mask & *addr;
277 *addr |= mask;
278 return retval;
279 }
280
test_and_clear_bit_le(u32 nr,u8 * addr)281 int test_and_clear_bit_le(u32 nr, u8 *addr)
282 {
283 int mask, retval;
284
285 addr += nr >> 3;
286 mask = 1 << ((nr & 0x07));
287 retval = mask & *addr;
288 *addr &= ~mask;
289 return retval;
290 }
291
test_bit_le(u32 nr,const u8 * addr)292 int test_bit_le(u32 nr, const u8 *addr)
293 {
294 return ((1 << (nr & 7)) & (addr[nr >> 3]));
295 }
296
f2fs_test_bit(unsigned int nr,const char * p)297 int f2fs_test_bit(unsigned int nr, const char *p)
298 {
299 int mask;
300 char *addr = (char *)p;
301
302 addr += (nr >> 3);
303 mask = 1 << (7 - (nr & 0x07));
304 return (mask & *addr) != 0;
305 }
306
f2fs_set_bit(unsigned int nr,char * addr)307 int f2fs_set_bit(unsigned int nr, char *addr)
308 {
309 int mask;
310 int ret;
311
312 addr += (nr >> 3);
313 mask = 1 << (7 - (nr & 0x07));
314 ret = mask & *addr;
315 *addr |= mask;
316 return ret;
317 }
318
f2fs_clear_bit(unsigned int nr,char * addr)319 int f2fs_clear_bit(unsigned int nr, char *addr)
320 {
321 int mask;
322 int ret;
323
324 addr += (nr >> 3);
325 mask = 1 << (7 - (nr & 0x07));
326 ret = mask & *addr;
327 *addr &= ~mask;
328 return ret;
329 }
330
__ffs(u8 word)331 static inline u64 __ffs(u8 word)
332 {
333 int num = 0;
334
335 if ((word & 0xf) == 0) {
336 num += 4;
337 word >>= 4;
338 }
339 if ((word & 0x3) == 0) {
340 num += 2;
341 word >>= 2;
342 }
343 if ((word & 0x1) == 0)
344 num += 1;
345 return num;
346 }
347
348 /* Copied from linux/lib/find_bit.c */
349 #define BITMAP_FIRST_BYTE_MASK(start) (0xff << ((start) & (BITS_PER_BYTE - 1)))
350
_find_next_bit_le(const u8 * addr,u64 nbits,u64 start,char invert)351 static u64 _find_next_bit_le(const u8 *addr, u64 nbits, u64 start, char invert)
352 {
353 u8 tmp;
354
355 if (!nbits || start >= nbits)
356 return nbits;
357
358 tmp = addr[start / BITS_PER_BYTE] ^ invert;
359
360 /* Handle 1st word. */
361 tmp &= BITMAP_FIRST_BYTE_MASK(start);
362 start = round_down(start, BITS_PER_BYTE);
363
364 while (!tmp) {
365 start += BITS_PER_BYTE;
366 if (start >= nbits)
367 return nbits;
368
369 tmp = addr[start / BITS_PER_BYTE] ^ invert;
370 }
371
372 return min(start + __ffs(tmp), nbits);
373 }
374
find_next_bit_le(const u8 * addr,u64 size,u64 offset)375 u64 find_next_bit_le(const u8 *addr, u64 size, u64 offset)
376 {
377 return _find_next_bit_le(addr, size, offset, 0);
378 }
379
380
find_next_zero_bit_le(const u8 * addr,u64 size,u64 offset)381 u64 find_next_zero_bit_le(const u8 *addr, u64 size, u64 offset)
382 {
383 return _find_next_bit_le(addr, size, offset, 0xff);
384 }
385
386 /*
387 * Hashing code adapted from ext3
388 */
389 #define DELTA 0x9E3779B9
390
TEA_transform(unsigned int buf[4],unsigned int const in[])391 static void TEA_transform(unsigned int buf[4], unsigned int const in[])
392 {
393 __u32 sum = 0;
394 __u32 b0 = buf[0], b1 = buf[1];
395 __u32 a = in[0], b = in[1], c = in[2], d = in[3];
396 int n = 16;
397
398 do {
399 sum += DELTA;
400 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
401 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
402 } while (--n);
403
404 buf[0] += b0;
405 buf[1] += b1;
406
407 }
408
str2hashbuf(const unsigned char * msg,int len,unsigned int * buf,int num)409 static void str2hashbuf(const unsigned char *msg, int len,
410 unsigned int *buf, int num)
411 {
412 unsigned pad, val;
413 int i;
414
415 pad = (__u32)len | ((__u32)len << 8);
416 pad |= pad << 16;
417
418 val = pad;
419 if (len > num * 4)
420 len = num * 4;
421 for (i = 0; i < len; i++) {
422 if ((i % 4) == 0)
423 val = pad;
424 val = msg[i] + (val << 8);
425 if ((i % 4) == 3) {
426 *buf++ = val;
427 val = pad;
428 num--;
429 }
430 }
431 if (--num >= 0)
432 *buf++ = val;
433 while (--num >= 0)
434 *buf++ = pad;
435
436 }
437
438 /**
439 * Return hash value of directory entry
440 * @param name dentry name
441 * @param len name lenth
442 * @return return on success hash value, errno on failure
443 */
__f2fs_dentry_hash(const unsigned char * name,int len)444 static f2fs_hash_t __f2fs_dentry_hash(const unsigned char *name, int len)/* Need update */
445 {
446 __u32 hash;
447 f2fs_hash_t f2fs_hash;
448 const unsigned char *p;
449 __u32 in[8], buf[4];
450
451 /* special hash codes for special dentries */
452 if ((len <= 2) && (name[0] == '.') &&
453 (name[1] == '.' || name[1] == '\0'))
454 return 0;
455
456 /* Initialize the default seed for the hash checksum functions */
457 buf[0] = 0x67452301;
458 buf[1] = 0xefcdab89;
459 buf[2] = 0x98badcfe;
460 buf[3] = 0x10325476;
461
462 p = name;
463 while (1) {
464 str2hashbuf(p, len, in, 4);
465 TEA_transform(buf, in);
466 p += 16;
467 if (len <= 16)
468 break;
469 len -= 16;
470 }
471 hash = buf[0];
472
473 f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
474 return f2fs_hash;
475 }
476
f2fs_dentry_hash(int encoding,int casefolded,const unsigned char * name,int len)477 f2fs_hash_t f2fs_dentry_hash(int encoding, int casefolded,
478 const unsigned char *name, int len)
479 {
480 const struct f2fs_nls_table *table = f2fs_load_nls_table(encoding);
481 int r, dlen;
482 unsigned char *buff;
483
484 if (len && casefolded) {
485 buff = malloc(sizeof(char) * PATH_MAX);
486 if (!buff)
487 return -ENOMEM;
488 dlen = table->ops->casefold(table, name, len, buff, PATH_MAX);
489 if (dlen < 0) {
490 free(buff);
491 goto opaque_seq;
492 }
493 r = __f2fs_dentry_hash(buff, dlen);
494
495 free(buff);
496 return r;
497 }
498 opaque_seq:
499 return __f2fs_dentry_hash(name, len);
500 }
501
addrs_per_inode(struct f2fs_inode * i)502 unsigned int addrs_per_inode(struct f2fs_inode *i)
503 {
504 unsigned int addrs = CUR_ADDRS_PER_INODE(i) - get_inline_xattr_addrs(i);
505
506 if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
507 !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
508 return addrs;
509 return ALIGN_DOWN(addrs, 1 << i->i_log_cluster_size);
510 }
511
addrs_per_block(struct f2fs_inode * i)512 unsigned int addrs_per_block(struct f2fs_inode *i)
513 {
514 if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
515 !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
516 return DEF_ADDRS_PER_BLOCK;
517 return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, 1 << i->i_log_cluster_size);
518 }
519
f2fs_max_file_offset(struct f2fs_inode * i)520 unsigned int f2fs_max_file_offset(struct f2fs_inode *i)
521 {
522 if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
523 !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
524 return le64_to_cpu(i->i_size);
525 return ALIGN_UP(le64_to_cpu(i->i_size), 1 << i->i_log_cluster_size);
526 }
527
528 /*
529 * CRC32
530 */
531 #define CRCPOLY_LE 0xedb88320
532
f2fs_cal_crc32(u_int32_t crc,void * buf,int len)533 u_int32_t f2fs_cal_crc32(u_int32_t crc, void *buf, int len)
534 {
535 int i;
536 unsigned char *p = (unsigned char *)buf;
537 while (len--) {
538 crc ^= *p++;
539 for (i = 0; i < 8; i++)
540 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
541 }
542 return crc;
543 }
544
f2fs_crc_valid(u_int32_t blk_crc,void * buf,int len)545 int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len)
546 {
547 u_int32_t cal_crc = 0;
548
549 cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len);
550
551 if (cal_crc != blk_crc) {
552 DBG(0,"CRC validation failed: cal_crc = %u, "
553 "blk_crc = %u buff_size = 0x%x\n",
554 cal_crc, blk_crc, len);
555 return -1;
556 }
557 return 0;
558 }
559
f2fs_inode_chksum(struct f2fs_node * node)560 __u32 f2fs_inode_chksum(struct f2fs_node *node)
561 {
562 struct f2fs_inode *ri = &node->i;
563 __le32 ino = node->footer.ino;
564 __le32 gen = ri->i_generation;
565 __u32 chksum, chksum_seed;
566 __u32 dummy_cs = 0;
567 unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum);
568 unsigned int cs_size = sizeof(dummy_cs);
569
570 chksum = f2fs_cal_crc32(c.chksum_seed, (__u8 *)&ino,
571 sizeof(ino));
572 chksum_seed = f2fs_cal_crc32(chksum, (__u8 *)&gen, sizeof(gen));
573
574 chksum = f2fs_cal_crc32(chksum_seed, (__u8 *)ri, offset);
575 chksum = f2fs_cal_crc32(chksum, (__u8 *)&dummy_cs, cs_size);
576 offset += cs_size;
577 chksum = f2fs_cal_crc32(chksum, (__u8 *)ri + offset,
578 F2FS_BLKSIZE - offset);
579 return chksum;
580 }
581
f2fs_checkpoint_chksum(struct f2fs_checkpoint * cp)582 __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *cp)
583 {
584 unsigned int chksum_ofs = le32_to_cpu(cp->checksum_offset);
585 __u32 chksum;
586
587 chksum = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, chksum_ofs);
588 if (chksum_ofs < CP_CHKSUM_OFFSET) {
589 chksum_ofs += sizeof(chksum);
590 chksum = f2fs_cal_crc32(chksum, (__u8 *)cp + chksum_ofs,
591 F2FS_BLKSIZE - chksum_ofs);
592 }
593 return chksum;
594 }
595
write_inode(struct f2fs_node * inode,u64 blkaddr)596 int write_inode(struct f2fs_node *inode, u64 blkaddr)
597 {
598 if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
599 inode->i.i_inode_checksum =
600 cpu_to_le32(f2fs_inode_chksum(inode));
601 return dev_write_block(inode, blkaddr);
602 }
603
604 /*
605 * try to identify the root device
606 */
get_rootdev()607 char *get_rootdev()
608 {
609 #if defined(ANDROID_WINDOWS_HOST) || defined(WITH_ANDROID)
610 return NULL;
611 #else
612 struct stat sb;
613 int fd, ret;
614 char buf[PATH_MAX + 1];
615 char *uevent, *ptr;
616 char *rootdev;
617
618 if (stat("/", &sb) == -1)
619 return NULL;
620
621 snprintf(buf, PATH_MAX, "/sys/dev/block/%u:%u/uevent",
622 major(sb.st_dev), minor(sb.st_dev));
623
624 fd = open(buf, O_RDONLY);
625
626 if (fd < 0)
627 return NULL;
628
629 ret = lseek(fd, (off_t)0, SEEK_END);
630 (void)lseek(fd, (off_t)0, SEEK_SET);
631
632 if (ret == -1) {
633 close(fd);
634 return NULL;
635 }
636
637 uevent = malloc(ret + 1);
638 ASSERT(uevent);
639
640 uevent[ret] = '\0';
641
642 ret = read(fd, uevent, ret);
643 close(fd);
644
645 ptr = strstr(uevent, "DEVNAME");
646 if (!ptr)
647 goto out_free;
648
649 ret = sscanf(ptr, "DEVNAME=%s\n", buf);
650 if (strlen(buf) == 0)
651 goto out_free;
652
653 ret = strlen(buf) + 5;
654 rootdev = malloc(ret + 1);
655 if (!rootdev)
656 goto out_free;
657 rootdev[ret] = '\0';
658
659 snprintf(rootdev, ret + 1, "/dev/%s", buf);
660 free(uevent);
661 return rootdev;
662
663 out_free:
664 free(uevent);
665 return NULL;
666 #endif
667 }
668
669 /*
670 * device information
671 */
f2fs_init_configuration(void)672 void f2fs_init_configuration(void)
673 {
674 int i;
675
676 memset(&c, 0, sizeof(struct f2fs_configuration));
677 c.ndevs = 1;
678 c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
679 c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
680 c.wanted_total_sectors = -1;
681 c.wanted_sector_size = -1;
682 #ifndef WITH_ANDROID
683 c.preserve_limits = 1;
684 c.no_kernel_check = 1;
685 #else
686 c.no_kernel_check = 0;
687 #endif
688
689 for (i = 0; i < MAX_DEVICES; i++) {
690 c.devices[i].fd = -1;
691 c.devices[i].sector_size = DEFAULT_SECTOR_SIZE;
692 c.devices[i].end_blkaddr = -1;
693 c.devices[i].zoned_model = F2FS_ZONED_NONE;
694 }
695
696 /* calculated by overprovision ratio */
697 c.segs_per_sec = 1;
698 c.secs_per_zone = 1;
699 c.segs_per_zone = 1;
700 c.vol_label = "";
701 c.trim = 1;
702 c.kd = -1;
703 c.fixed_time = -1;
704 c.s_encoding = 0;
705 c.s_encoding_flags = 0;
706
707 /* default root owner */
708 c.root_uid = getuid();
709 c.root_gid = getgid();
710 }
711
f2fs_dev_is_writable(void)712 int f2fs_dev_is_writable(void)
713 {
714 return !c.ro || c.force;
715 }
716
717 #ifdef HAVE_SETMNTENT
is_mounted(const char * mpt,const char * device)718 static int is_mounted(const char *mpt, const char *device)
719 {
720 FILE *file = NULL;
721 struct mntent *mnt = NULL;
722
723 file = setmntent(mpt, "r");
724 if (file == NULL)
725 return 0;
726
727 while ((mnt = getmntent(file)) != NULL) {
728 if (!strcmp(device, mnt->mnt_fsname)) {
729 #ifdef MNTOPT_RO
730 if (hasmntopt(mnt, MNTOPT_RO))
731 c.ro = 1;
732 #endif
733 break;
734 }
735 }
736 endmntent(file);
737 return mnt ? 1 : 0;
738 }
739 #endif
740
f2fs_dev_is_umounted(char * path)741 int f2fs_dev_is_umounted(char *path)
742 {
743 #ifdef ANDROID_WINDOWS_HOST
744 return 0;
745 #else
746 struct stat *st_buf;
747 int is_rootdev = 0;
748 int ret = 0;
749 char *rootdev_name = get_rootdev();
750
751 if (rootdev_name) {
752 if (!strcmp(path, rootdev_name))
753 is_rootdev = 1;
754 free(rootdev_name);
755 }
756
757 /*
758 * try with /proc/mounts fist to detect RDONLY.
759 * f2fs_stop_checkpoint makes RO in /proc/mounts while RW in /etc/mtab.
760 */
761 #ifdef __linux__
762 ret = is_mounted("/proc/mounts", path);
763 if (ret) {
764 MSG(0, "Info: Mounted device!\n");
765 return -1;
766 }
767 #endif
768 #if defined(MOUNTED) || defined(_PATH_MOUNTED)
769 #ifndef MOUNTED
770 #define MOUNTED _PATH_MOUNTED
771 #endif
772 ret = is_mounted(MOUNTED, path);
773 if (ret) {
774 MSG(0, "Info: Mounted device!\n");
775 return -1;
776 }
777 #endif
778 /*
779 * If we are supposed to operate on the root device, then
780 * also check the mounts for '/dev/root', which sometimes
781 * functions as an alias for the root device.
782 */
783 if (is_rootdev) {
784 #ifdef __linux__
785 ret = is_mounted("/proc/mounts", "/dev/root");
786 if (ret) {
787 MSG(0, "Info: Mounted device!\n");
788 return -1;
789 }
790 #endif
791 }
792
793 /*
794 * If f2fs is umounted with -l, the process can still use
795 * the file system. In this case, we should not format.
796 */
797 st_buf = malloc(sizeof(struct stat));
798 ASSERT(st_buf);
799
800 if (stat(path, st_buf) == 0 && S_ISBLK(st_buf->st_mode)) {
801 int fd = open(path, O_RDONLY | O_EXCL);
802
803 if (fd >= 0) {
804 close(fd);
805 } else if (errno == EBUSY) {
806 MSG(0, "\tError: In use by the system!\n");
807 free(st_buf);
808 return -1;
809 }
810 }
811 free(st_buf);
812 return ret;
813 #endif
814 }
815
f2fs_devs_are_umounted(void)816 int f2fs_devs_are_umounted(void)
817 {
818 int i;
819
820 for (i = 0; i < c.ndevs; i++)
821 if (f2fs_dev_is_umounted((char *)c.devices[i].path))
822 return -1;
823 return 0;
824 }
825
get_kernel_version(__u8 * version)826 void get_kernel_version(__u8 *version)
827 {
828 int i;
829 for (i = 0; i < VERSION_NAME_LEN; i++) {
830 if (version[i] == '\n')
831 break;
832 }
833 memset(version + i, 0, VERSION_LEN + 1 - i);
834 }
835
get_kernel_uname_version(__u8 * version)836 void get_kernel_uname_version(__u8 *version)
837 {
838 #ifdef HAVE_SYS_UTSNAME_H
839 struct utsname buf;
840
841 memset(version, 0, VERSION_LEN);
842 if (uname(&buf))
843 return;
844
845 #if defined(WITH_KERNEL_VERSION)
846 snprintf((char *)version,
847 VERSION_NAME_LEN, "%s %s", buf.release, buf.version);
848 #else
849 snprintf((char *)version,
850 VERSION_NAME_LEN, "%s", buf.release);
851 #endif
852 #else
853 memset(version, 0, VERSION_LEN);
854 #endif
855 }
856
857 #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
858 #define BLKGETSIZE _IO(0x12,96)
859 #endif
860
861 #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
862 #define BLKGETSIZE64 _IOR(0x12,114, size_t)
863 #endif
864
865 #if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
866 #define BLKSSZGET _IO(0x12,104)
867 #endif
868
869 #if defined(__APPLE__)
870 #include <sys/disk.h>
871 #define BLKGETSIZE DKIOCGETBLOCKCOUNT
872 #define BLKSSZGET DKIOCGETBLOCKCOUNT
873 #endif /* APPLE_DARWIN */
874
875 #ifndef ANDROID_WINDOWS_HOST
open_check_fs(char * path,int flag)876 static int open_check_fs(char *path, int flag)
877 {
878 if (c.func != DUMP && (c.func != FSCK || c.fix_on || c.auto_fix))
879 return -1;
880
881 /* allow to open ro */
882 return open(path, O_RDONLY | flag);
883 }
884
get_device_info(int i)885 int get_device_info(int i)
886 {
887 int32_t fd = 0;
888 uint32_t sector_size;
889 #ifndef BLKGETSIZE64
890 uint32_t total_sectors;
891 #endif
892 struct stat *stat_buf;
893 #ifdef HDIO_GETGIO
894 struct hd_geometry geom;
895 #endif
896 #if !defined(WITH_ANDROID) && defined(__linux__)
897 sg_io_hdr_t io_hdr;
898 unsigned char reply_buffer[96] = {0};
899 unsigned char model_inq[6] = {MODELINQUIRY};
900 #endif
901 struct device_info *dev = c.devices + i;
902
903 if (c.sparse_mode) {
904 fd = open(dev->path, O_RDWR | O_CREAT | O_BINARY, 0644);
905 if (fd < 0) {
906 fd = open_check_fs(dev->path, O_BINARY);
907 if (fd < 0) {
908 MSG(0, "\tError: Failed to open a sparse file!\n");
909 return -1;
910 }
911 }
912 }
913
914 stat_buf = malloc(sizeof(struct stat));
915 ASSERT(stat_buf);
916
917 if (!c.sparse_mode) {
918 if (stat(dev->path, stat_buf) < 0 ) {
919 MSG(0, "\tError: Failed to get the device stat!\n");
920 free(stat_buf);
921 return -1;
922 }
923
924 if (S_ISBLK(stat_buf->st_mode) &&
925 !c.force && c.func != DUMP && !c.dry_run) {
926 fd = open(dev->path, O_RDWR | O_EXCL);
927 if (fd < 0)
928 fd = open_check_fs(dev->path, O_EXCL);
929 } else {
930 fd = open(dev->path, O_RDWR);
931 if (fd < 0)
932 fd = open_check_fs(dev->path, 0);
933 }
934 }
935 if (fd < 0) {
936 MSG(0, "\tError: Failed to open the device!\n");
937 free(stat_buf);
938 return -1;
939 }
940
941 dev->fd = fd;
942
943 if (c.sparse_mode) {
944 if (f2fs_init_sparse_file()) {
945 free(stat_buf);
946 return -1;
947 }
948 }
949
950 if (c.kd == -1) {
951 #if !defined(WITH_ANDROID) && defined(__linux__)
952 c.kd = open("/proc/version", O_RDONLY);
953 #endif
954 if (c.kd < 0) {
955 MSG(0, "Info: not exist /proc/version!\n");
956 c.kd = -2;
957 }
958 }
959
960 if (c.sparse_mode) {
961 dev->total_sectors = c.device_size / dev->sector_size;
962 } else if (S_ISREG(stat_buf->st_mode)) {
963 dev->total_sectors = stat_buf->st_size / dev->sector_size;
964 } else if (S_ISBLK(stat_buf->st_mode)) {
965 #ifdef BLKSSZGET
966 if (ioctl(fd, BLKSSZGET, §or_size) < 0)
967 MSG(0, "\tError: Using the default sector size\n");
968 else if (dev->sector_size < sector_size)
969 dev->sector_size = sector_size;
970 #endif
971 #ifdef BLKGETSIZE64
972 if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
973 MSG(0, "\tError: Cannot get the device size\n");
974 free(stat_buf);
975 return -1;
976 }
977 #else
978 if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
979 MSG(0, "\tError: Cannot get the device size\n");
980 free(stat_buf);
981 return -1;
982 }
983 dev->total_sectors = total_sectors;
984 #endif
985 dev->total_sectors /= dev->sector_size;
986
987 if (i == 0) {
988 #ifdef HDIO_GETGIO
989 if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
990 c.start_sector = 0;
991 else
992 c.start_sector = geom.start;
993 #else
994 c.start_sector = 0;
995 #endif
996 }
997
998 #if !defined(WITH_ANDROID) && defined(__linux__)
999 /* Send INQUIRY command */
1000 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
1001 io_hdr.interface_id = 'S';
1002 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
1003 io_hdr.dxfer_len = sizeof(reply_buffer);
1004 io_hdr.dxferp = reply_buffer;
1005 io_hdr.cmd_len = sizeof(model_inq);
1006 io_hdr.cmdp = model_inq;
1007 io_hdr.timeout = 1000;
1008
1009 if (!ioctl(fd, SG_IO, &io_hdr)) {
1010 MSG(0, "Info: [%s] Disk Model: %.16s\n",
1011 dev->path, reply_buffer+16);
1012 }
1013 #endif
1014 } else {
1015 MSG(0, "\tError: Volume type is not supported!!!\n");
1016 free(stat_buf);
1017 return -1;
1018 }
1019
1020 if (!c.sector_size) {
1021 c.sector_size = dev->sector_size;
1022 c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1023 } else if (c.sector_size != c.devices[i].sector_size) {
1024 MSG(0, "\tError: Different sector sizes!!!\n");
1025 free(stat_buf);
1026 return -1;
1027 }
1028
1029 #if !defined(WITH_ANDROID) && defined(__linux__)
1030 if (S_ISBLK(stat_buf->st_mode)) {
1031 if (f2fs_get_zoned_model(i) < 0) {
1032 free(stat_buf);
1033 return -1;
1034 }
1035 }
1036
1037 if (dev->zoned_model != F2FS_ZONED_NONE) {
1038
1039 /* Get the number of blocks per zones */
1040 if (f2fs_get_zone_blocks(i)) {
1041 MSG(0, "\tError: Failed to get number of blocks per zone\n");
1042 free(stat_buf);
1043 return -1;
1044 }
1045
1046 /*
1047 * Check zone configuration: for the first disk of a
1048 * multi-device volume, conventional zones are needed.
1049 */
1050 if (f2fs_check_zones(i)) {
1051 MSG(0, "\tError: Failed to check zone configuration\n");
1052 free(stat_buf);
1053 return -1;
1054 }
1055 MSG(0, "Info: Host-%s zoned block device:\n",
1056 (dev->zoned_model == F2FS_ZONED_HA) ?
1057 "aware" : "managed");
1058 MSG(0, " %u zones, %u randomly writeable zones\n",
1059 dev->nr_zones, dev->nr_rnd_zones);
1060 MSG(0, " %lu blocks per zone\n",
1061 dev->zone_blocks);
1062 }
1063 #endif
1064 /* adjust wanted_total_sectors */
1065 if (c.wanted_total_sectors != -1) {
1066 MSG(0, "Info: wanted sectors = %"PRIu64" (in %"PRIu64" bytes)\n",
1067 c.wanted_total_sectors, c.wanted_sector_size);
1068 if (c.wanted_sector_size == -1) {
1069 c.wanted_sector_size = dev->sector_size;
1070 } else if (dev->sector_size != c.wanted_sector_size) {
1071 c.wanted_total_sectors *= c.wanted_sector_size;
1072 c.wanted_total_sectors /= dev->sector_size;
1073 }
1074 }
1075
1076 c.total_sectors += dev->total_sectors;
1077 free(stat_buf);
1078 return 0;
1079 }
1080
1081 #else
1082
1083 #include "windows.h"
1084 #include "winioctl.h"
1085
1086 #if (_WIN32_WINNT >= 0x0500)
1087 #define HAVE_GET_FILE_SIZE_EX 1
1088 #endif
1089
win_get_device_size(const char * file,uint64_t * device_size)1090 static int win_get_device_size(const char *file, uint64_t *device_size)
1091 {
1092 HANDLE dev;
1093 PARTITION_INFORMATION pi;
1094 DISK_GEOMETRY gi;
1095 DWORD retbytes;
1096 #ifdef HAVE_GET_FILE_SIZE_EX
1097 LARGE_INTEGER filesize;
1098 #else
1099 DWORD filesize;
1100 #endif /* HAVE_GET_FILE_SIZE_EX */
1101
1102 dev = CreateFile(file, GENERIC_READ,
1103 FILE_SHARE_READ | FILE_SHARE_WRITE ,
1104 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1105
1106 if (dev == INVALID_HANDLE_VALUE)
1107 return EBADF;
1108 if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
1109 &pi, sizeof(PARTITION_INFORMATION),
1110 &pi, sizeof(PARTITION_INFORMATION),
1111 &retbytes, NULL)) {
1112
1113 *device_size = pi.PartitionLength.QuadPart;
1114
1115 } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
1116 &gi, sizeof(DISK_GEOMETRY),
1117 &gi, sizeof(DISK_GEOMETRY),
1118 &retbytes, NULL)) {
1119
1120 *device_size = gi.BytesPerSector *
1121 gi.SectorsPerTrack *
1122 gi.TracksPerCylinder *
1123 gi.Cylinders.QuadPart;
1124
1125 #ifdef HAVE_GET_FILE_SIZE_EX
1126 } else if (GetFileSizeEx(dev, &filesize)) {
1127 *device_size = filesize.QuadPart;
1128 }
1129 #else
1130 } else {
1131 filesize = GetFileSize(dev, NULL);
1132 if (INVALID_FILE_SIZE != filesize)
1133 return -1;
1134 *device_size = filesize;
1135 }
1136 #endif /* HAVE_GET_FILE_SIZE_EX */
1137
1138 CloseHandle(dev);
1139 return 0;
1140 }
1141
get_device_info(int i)1142 int get_device_info(int i)
1143 {
1144 struct device_info *dev = c.devices + i;
1145 uint64_t device_size = 0;
1146 int32_t fd = 0;
1147
1148 /* Block device target is not supported on Windows. */
1149 if (!c.sparse_mode) {
1150 if (win_get_device_size(dev->path, &device_size)) {
1151 MSG(0, "\tError: Failed to get device size!\n");
1152 return -1;
1153 }
1154 } else {
1155 device_size = c.device_size;
1156 }
1157 if (c.sparse_mode) {
1158 fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1159 } else {
1160 fd = open((char *)dev->path, O_RDWR | O_BINARY);
1161 }
1162 if (fd < 0) {
1163 MSG(0, "\tError: Failed to open the device!\n");
1164 return -1;
1165 }
1166 dev->fd = fd;
1167 dev->total_sectors = device_size / dev->sector_size;
1168 c.start_sector = 0;
1169 c.sector_size = dev->sector_size;
1170 c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1171 c.total_sectors += dev->total_sectors;
1172
1173 if (c.sparse_mode && f2fs_init_sparse_file())
1174 return -1;
1175 return 0;
1176 }
1177 #endif
1178
f2fs_get_device_info(void)1179 int f2fs_get_device_info(void)
1180 {
1181 int i;
1182
1183 for (i = 0; i < c.ndevs; i++)
1184 if (get_device_info(i))
1185 return -1;
1186 return 0;
1187 }
1188
f2fs_get_f2fs_info(void)1189 int f2fs_get_f2fs_info(void)
1190 {
1191 int i;
1192
1193 if (c.wanted_total_sectors < c.total_sectors) {
1194 MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
1195 c.total_sectors, c.sector_size);
1196 c.total_sectors = c.wanted_total_sectors;
1197 c.devices[0].total_sectors = c.total_sectors;
1198 }
1199 if (c.total_sectors * c.sector_size >
1200 (u_int64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) {
1201 MSG(0, "\tError: F2FS can support 16TB at most!!!\n");
1202 return -1;
1203 }
1204
1205 /*
1206 * Check device types and determine the final volume operation mode:
1207 * - If all devices are regular block devices, default operation.
1208 * - If at least one HM device is found, operate in HM mode (BLKZONED
1209 * feature will be enabled by mkfs).
1210 * - If an HA device is found, let mkfs decide based on the -m option
1211 * setting by the user.
1212 */
1213 c.zoned_model = F2FS_ZONED_NONE;
1214 for (i = 0; i < c.ndevs; i++) {
1215 switch (c.devices[i].zoned_model) {
1216 case F2FS_ZONED_NONE:
1217 continue;
1218 case F2FS_ZONED_HM:
1219 c.zoned_model = F2FS_ZONED_HM;
1220 break;
1221 case F2FS_ZONED_HA:
1222 if (c.zoned_model != F2FS_ZONED_HM)
1223 c.zoned_model = F2FS_ZONED_HA;
1224 break;
1225 }
1226 }
1227
1228 if (c.zoned_model != F2FS_ZONED_NONE) {
1229
1230 /*
1231 * For zoned model, the zones sizes of all zoned devices must
1232 * be equal.
1233 */
1234 for (i = 0; i < c.ndevs; i++) {
1235 if (c.devices[i].zoned_model == F2FS_ZONED_NONE)
1236 continue;
1237 if (c.zone_blocks &&
1238 c.zone_blocks != c.devices[i].zone_blocks) {
1239 MSG(0, "\tError: zones of different size are "
1240 "not supported\n");
1241 return -1;
1242 }
1243 c.zone_blocks = c.devices[i].zone_blocks;
1244 }
1245
1246 /*
1247 * Align sections to the device zone size and align F2FS zones
1248 * to the device zones. For F2FS_ZONED_HA model without the
1249 * BLKZONED feature set at format time, this is only an
1250 * optimization as sequential writes will not be enforced.
1251 */
1252 c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT;
1253 c.secs_per_zone = 1;
1254 } else {
1255 if(c.zoned_mode != 0) {
1256 MSG(0, "\n Error: %s may not be a zoned block device \n",
1257 c.devices[0].path);
1258 return -1;
1259 }
1260 }
1261
1262 c.segs_per_zone = c.segs_per_sec * c.secs_per_zone;
1263
1264 MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec);
1265 MSG(0, "Info: Sections per zone = %d\n", c.secs_per_zone);
1266 MSG(0, "Info: sector size = %u\n", c.sector_size);
1267 MSG(0, "Info: total sectors = %"PRIu64" (%"PRIu64" MB)\n",
1268 c.total_sectors, (c.total_sectors *
1269 (c.sector_size >> 9)) >> 11);
1270 return 0;
1271 }
1272
calc_extra_isize(void)1273 unsigned int calc_extra_isize(void)
1274 {
1275 unsigned int size = offsetof(struct f2fs_inode, i_projid);
1276
1277 if (c.feature & cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR))
1278 size = offsetof(struct f2fs_inode, i_projid);
1279 if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA))
1280 size = offsetof(struct f2fs_inode, i_inode_checksum);
1281 if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
1282 size = offsetof(struct f2fs_inode, i_crtime);
1283 if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME))
1284 size = offsetof(struct f2fs_inode, i_compr_blocks);
1285 if (c.feature & cpu_to_le32(F2FS_FEATURE_COMPRESSION))
1286 size = offsetof(struct f2fs_inode, i_extra_end);
1287
1288 return size - F2FS_EXTRA_ISIZE_OFFSET;
1289 }
1290
1291 #define ARRAY_SIZE(array) \
1292 (sizeof(array) / sizeof(array[0]))
1293
1294 static const struct {
1295 char *name;
1296 __u16 encoding_magic;
1297 __u16 default_flags;
1298
1299 } f2fs_encoding_map[] = {
1300 {
1301 .encoding_magic = F2FS_ENC_UTF8_12_1,
1302 .name = "utf8",
1303 .default_flags = 0,
1304 },
1305 };
1306
1307 static const struct enc_flags {
1308 __u16 flag;
1309 char *param;
1310 } encoding_flags[] = {
1311 { F2FS_ENC_STRICT_MODE_FL, "strict" },
1312 };
1313
1314 /* Return a positive number < 0xff indicating the encoding magic number
1315 * or a negative value indicating error. */
f2fs_str2encoding(const char * string)1316 int f2fs_str2encoding(const char *string)
1317 {
1318 int i;
1319
1320 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1321 if (!strcmp(string, f2fs_encoding_map[i].name))
1322 return f2fs_encoding_map[i].encoding_magic;
1323
1324 return -EINVAL;
1325 }
1326
f2fs_encoding2str(const int encoding)1327 char *f2fs_encoding2str(const int encoding)
1328 {
1329 int i;
1330
1331 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1332 if (f2fs_encoding_map[i].encoding_magic == encoding)
1333 return f2fs_encoding_map[i].name;
1334
1335 return NULL;
1336 }
1337
f2fs_get_encoding_flags(int encoding)1338 int f2fs_get_encoding_flags(int encoding)
1339 {
1340 int i;
1341
1342 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1343 if (f2fs_encoding_map[i].encoding_magic == encoding)
1344 return f2fs_encoding_map[encoding].default_flags;
1345
1346 return 0;
1347 }
1348
f2fs_str2encoding_flags(char ** param,__u16 * flags)1349 int f2fs_str2encoding_flags(char **param, __u16 *flags)
1350 {
1351 char *f = strtok(*param, ",");
1352 const struct enc_flags *fl;
1353 int i, neg = 0;
1354
1355 while (f) {
1356 neg = 0;
1357 if (!strncmp("no", f, 2)) {
1358 neg = 1;
1359 f += 2;
1360 }
1361
1362 for (i = 0; i < ARRAY_SIZE(encoding_flags); i++) {
1363 fl = &encoding_flags[i];
1364 if (!strcmp(fl->param, f)) {
1365 if (neg) {
1366 MSG(0, "Sub %s\n", fl->param);
1367 *flags &= ~fl->flag;
1368 } else {
1369 MSG(0, "Add %s\n", fl->param);
1370 *flags |= fl->flag;
1371 }
1372
1373 goto next_flag;
1374 }
1375 }
1376 *param = f;
1377 return -EINVAL;
1378 next_flag:
1379 f = strtok(NULL, ":");
1380 }
1381 return 0;
1382 }
1383