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 #ifndef _LARGEFILE64_SOURCE
10 #define _LARGEFILE64_SOURCE
11 #endif
12 #define _FILE_OFFSET_BITS 64
13
14 #include <f2fs_fs.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <libgen.h>
22 #ifdef HAVE_MNTENT_H
23 #include <mntent.h>
24 #endif
25 #include <time.h>
26 #include <sys/stat.h>
27 #ifdef HAVE_SYS_MOUNT_H
28 #include <sys/mount.h>
29 #endif
30 #ifdef HAVE_SYS_IOCTL_H
31 #include <sys/ioctl.h>
32 #endif
33 #ifdef HAVE_SYS_SYSMACROS_H
34 #include <sys/sysmacros.h>
35 #endif
36 #ifdef HAVE_SYS_UTSNAME_H
37 #include <sys/utsname.h>
38 #endif
39 #ifdef HAVE_SCSI_SG_H
40 #include <scsi/sg.h>
41 #endif
42 #ifdef HAVE_LINUX_HDREG_H
43 #include <linux/hdreg.h>
44 #endif
45 #ifdef HAVE_LINUX_LIMITS_H
46 #include <linux/limits.h>
47 #endif
48
49 /* SCSI command for standard inquiry*/
50 #define MODELINQUIRY 0x12,0x00,0x00,0x00,0x4A,0x00
51
52 #ifndef _WIN32 /* 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(uint16_t * output,wchar_t wc,size_t outsize)107 static uint16_t *wchar_to_utf16(uint16_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(uint16_t * output,const char * input,size_t outsize,size_t insize)123 int utf8_to_utf16(uint16_t *output, const char *input, size_t outsize,
124 size_t insize)
125 {
126 const char *inp = input;
127 uint16_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 uint16_t * input,wchar_t * wc,size_t insize)146 static const uint16_t *utf16_to_wchar(const uint16_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 uint16_t * input,size_t outsize,size_t insize)209 int utf16_to_utf8(char *output, const uint16_t *input, size_t outsize,
210 size_t insize)
211 {
212 const uint16_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(uint32_t num)232 int log_base_2(uint32_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(uint32_t crc,void * buf,int len)533 uint32_t f2fs_cal_crc32(uint32_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(uint32_t blk_crc,void * buf,int len)545 int f2fs_crc_valid(uint32_t blk_crc, void *buf, int len)
546 {
547 uint32_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(_WIN32) || 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 _WIN32
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 _WIN32
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
is_power_of_2(unsigned long n)885 static int is_power_of_2(unsigned long n)
886 {
887 return (n != 0 && ((n & (n - 1)) == 0));
888 }
889
get_device_info(int i)890 int get_device_info(int i)
891 {
892 int32_t fd = 0;
893 uint32_t sector_size;
894 #ifndef BLKGETSIZE64
895 uint32_t total_sectors;
896 #endif
897 struct stat *stat_buf;
898 #ifdef HDIO_GETGIO
899 struct hd_geometry geom;
900 #endif
901 #ifdef __linux__
902 sg_io_hdr_t io_hdr;
903 unsigned char reply_buffer[96] = {0};
904 unsigned char model_inq[6] = {MODELINQUIRY};
905 #endif
906 struct device_info *dev = c.devices + i;
907
908 if (c.sparse_mode) {
909 fd = open(dev->path, O_RDWR | O_CREAT | O_BINARY, 0644);
910 if (fd < 0) {
911 fd = open_check_fs(dev->path, O_BINARY);
912 if (fd < 0) {
913 MSG(0, "\tError: Failed to open a sparse file!\n");
914 return -1;
915 }
916 }
917 }
918
919 stat_buf = malloc(sizeof(struct stat));
920 ASSERT(stat_buf);
921
922 if (!c.sparse_mode) {
923 if (stat(dev->path, stat_buf) < 0 ) {
924 MSG(0, "\tError: Failed to get the device stat!\n");
925 free(stat_buf);
926 return -1;
927 }
928
929 if (S_ISBLK(stat_buf->st_mode) &&
930 !c.force && c.func != DUMP && !c.dry_run) {
931 fd = open(dev->path, O_RDWR | O_EXCL);
932 if (fd < 0)
933 fd = open_check_fs(dev->path, O_EXCL);
934 } else {
935 fd = open(dev->path, O_RDWR);
936 if (fd < 0)
937 fd = open_check_fs(dev->path, 0);
938 }
939 }
940 if (fd < 0) {
941 MSG(0, "\tError: Failed to open the device!\n");
942 free(stat_buf);
943 return -1;
944 }
945
946 dev->fd = fd;
947
948 if (c.sparse_mode) {
949 if (f2fs_init_sparse_file()) {
950 free(stat_buf);
951 return -1;
952 }
953 }
954
955 if (c.kd == -1) {
956 #if !defined(WITH_ANDROID) && defined(__linux__)
957 c.kd = open("/proc/version", O_RDONLY);
958 #endif
959 if (c.kd < 0) {
960 MSG(0, "Info: not exist /proc/version!\n");
961 c.kd = -2;
962 }
963 }
964
965 if (c.sparse_mode) {
966 dev->total_sectors = c.device_size / dev->sector_size;
967 } else if (S_ISREG(stat_buf->st_mode)) {
968 dev->total_sectors = stat_buf->st_size / dev->sector_size;
969 } else if (S_ISBLK(stat_buf->st_mode)) {
970 #ifdef BLKSSZGET
971 if (ioctl(fd, BLKSSZGET, §or_size) < 0)
972 MSG(0, "\tError: Using the default sector size\n");
973 else if (dev->sector_size < sector_size)
974 dev->sector_size = sector_size;
975 #endif
976 #ifdef BLKGETSIZE64
977 if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
978 MSG(0, "\tError: Cannot get the device size\n");
979 free(stat_buf);
980 return -1;
981 }
982 #else
983 if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
984 MSG(0, "\tError: Cannot get the device size\n");
985 free(stat_buf);
986 return -1;
987 }
988 dev->total_sectors = total_sectors;
989 #endif
990 dev->total_sectors /= dev->sector_size;
991
992 if (i == 0) {
993 #ifdef HDIO_GETGIO
994 if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
995 c.start_sector = 0;
996 else
997 c.start_sector = geom.start;
998 #else
999 c.start_sector = 0;
1000 #endif
1001 }
1002
1003 #ifdef __linux__
1004 /* Send INQUIRY command */
1005 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
1006 io_hdr.interface_id = 'S';
1007 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
1008 io_hdr.dxfer_len = sizeof(reply_buffer);
1009 io_hdr.dxferp = reply_buffer;
1010 io_hdr.cmd_len = sizeof(model_inq);
1011 io_hdr.cmdp = model_inq;
1012 io_hdr.timeout = 1000;
1013
1014 if (!ioctl(fd, SG_IO, &io_hdr)) {
1015 MSG(0, "Info: [%s] Disk Model: %.16s\n",
1016 dev->path, reply_buffer+16);
1017 }
1018 #endif
1019 } else {
1020 MSG(0, "\tError: Volume type is not supported!!!\n");
1021 free(stat_buf);
1022 return -1;
1023 }
1024
1025 if (!c.sector_size) {
1026 c.sector_size = dev->sector_size;
1027 c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1028 } else if (c.sector_size != c.devices[i].sector_size) {
1029 MSG(0, "\tError: Different sector sizes!!!\n");
1030 free(stat_buf);
1031 return -1;
1032 }
1033
1034 #ifdef __linux__
1035 if (S_ISBLK(stat_buf->st_mode)) {
1036 if (f2fs_get_zoned_model(i) < 0) {
1037 free(stat_buf);
1038 return -1;
1039 }
1040 }
1041
1042 if (dev->zoned_model != F2FS_ZONED_NONE) {
1043
1044 /* Get the number of blocks per zones */
1045 if (f2fs_get_zone_blocks(i)) {
1046 MSG(0, "\tError: Failed to get number of blocks per zone\n");
1047 free(stat_buf);
1048 return -1;
1049 }
1050
1051 if (!is_power_of_2(dev->zone_size)) {
1052 MSG(0, "\tError: zoned: illegal zone size %lu (not a power of 2)\n",
1053 dev->zone_size);
1054 free(stat_buf);
1055 return -1;
1056 }
1057
1058 /*
1059 * Check zone configuration: for the first disk of a
1060 * multi-device volume, conventional zones are needed.
1061 */
1062 if (f2fs_check_zones(i)) {
1063 MSG(0, "\tError: Failed to check zone configuration\n");
1064 free(stat_buf);
1065 return -1;
1066 }
1067 MSG(0, "Info: Host-%s zoned block device:\n",
1068 (dev->zoned_model == F2FS_ZONED_HA) ?
1069 "aware" : "managed");
1070 MSG(0, " %u zones, %lu zone size(bytes), %u randomly writeable zones\n",
1071 dev->nr_zones, dev->zone_size,
1072 dev->nr_rnd_zones);
1073 MSG(0, " %lu blocks per zone\n",
1074 dev->zone_blocks);
1075 }
1076 #endif
1077 /* adjust wanted_total_sectors */
1078 if (c.wanted_total_sectors != -1) {
1079 MSG(0, "Info: wanted sectors = %"PRIu64" (in %"PRIu64" bytes)\n",
1080 c.wanted_total_sectors, c.wanted_sector_size);
1081 if (c.wanted_sector_size == -1) {
1082 c.wanted_sector_size = dev->sector_size;
1083 } else if (dev->sector_size != c.wanted_sector_size) {
1084 c.wanted_total_sectors *= c.wanted_sector_size;
1085 c.wanted_total_sectors /= dev->sector_size;
1086 }
1087 }
1088
1089 c.total_sectors += dev->total_sectors;
1090 free(stat_buf);
1091 return 0;
1092 }
1093
1094 #else
1095
1096 #include "windows.h"
1097 #include "winioctl.h"
1098
1099 #if (_WIN32_WINNT >= 0x0500)
1100 #define HAVE_GET_FILE_SIZE_EX 1
1101 #endif
1102
win_get_device_size(const char * file,uint64_t * device_size)1103 static int win_get_device_size(const char *file, uint64_t *device_size)
1104 {
1105 HANDLE dev;
1106 PARTITION_INFORMATION pi;
1107 DISK_GEOMETRY gi;
1108 DWORD retbytes;
1109 #ifdef HAVE_GET_FILE_SIZE_EX
1110 LARGE_INTEGER filesize;
1111 #else
1112 DWORD filesize;
1113 #endif /* HAVE_GET_FILE_SIZE_EX */
1114
1115 dev = CreateFile(file, GENERIC_READ,
1116 FILE_SHARE_READ | FILE_SHARE_WRITE ,
1117 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1118
1119 if (dev == INVALID_HANDLE_VALUE)
1120 return EBADF;
1121 if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
1122 &pi, sizeof(PARTITION_INFORMATION),
1123 &pi, sizeof(PARTITION_INFORMATION),
1124 &retbytes, NULL)) {
1125
1126 *device_size = pi.PartitionLength.QuadPart;
1127
1128 } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
1129 &gi, sizeof(DISK_GEOMETRY),
1130 &gi, sizeof(DISK_GEOMETRY),
1131 &retbytes, NULL)) {
1132
1133 *device_size = gi.BytesPerSector *
1134 gi.SectorsPerTrack *
1135 gi.TracksPerCylinder *
1136 gi.Cylinders.QuadPart;
1137
1138 #ifdef HAVE_GET_FILE_SIZE_EX
1139 } else if (GetFileSizeEx(dev, &filesize)) {
1140 *device_size = filesize.QuadPart;
1141 }
1142 #else
1143 } else {
1144 filesize = GetFileSize(dev, NULL);
1145 if (INVALID_FILE_SIZE != filesize)
1146 return -1;
1147 *device_size = filesize;
1148 }
1149 #endif /* HAVE_GET_FILE_SIZE_EX */
1150
1151 CloseHandle(dev);
1152 return 0;
1153 }
1154
get_device_info(int i)1155 int get_device_info(int i)
1156 {
1157 struct device_info *dev = c.devices + i;
1158 uint64_t device_size = 0;
1159 int32_t fd = 0;
1160
1161 /* Block device target is not supported on Windows. */
1162 if (!c.sparse_mode) {
1163 if (win_get_device_size(dev->path, &device_size)) {
1164 MSG(0, "\tError: Failed to get device size!\n");
1165 return -1;
1166 }
1167 } else {
1168 device_size = c.device_size;
1169 }
1170 if (c.sparse_mode) {
1171 fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1172 } else {
1173 fd = open((char *)dev->path, O_RDWR | O_BINARY);
1174 }
1175 if (fd < 0) {
1176 MSG(0, "\tError: Failed to open the device!\n");
1177 return -1;
1178 }
1179 dev->fd = fd;
1180 dev->total_sectors = device_size / dev->sector_size;
1181 c.start_sector = 0;
1182 c.sector_size = dev->sector_size;
1183 c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1184 c.total_sectors += dev->total_sectors;
1185
1186 if (c.sparse_mode && f2fs_init_sparse_file())
1187 return -1;
1188 return 0;
1189 }
1190 #endif
1191
f2fs_get_device_info(void)1192 int f2fs_get_device_info(void)
1193 {
1194 int i;
1195
1196 for (i = 0; i < c.ndevs; i++)
1197 if (get_device_info(i))
1198 return -1;
1199 return 0;
1200 }
1201
f2fs_get_f2fs_info(void)1202 int f2fs_get_f2fs_info(void)
1203 {
1204 int i;
1205
1206 if (c.wanted_total_sectors < c.total_sectors) {
1207 MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
1208 c.total_sectors, c.sector_size);
1209 c.total_sectors = c.wanted_total_sectors;
1210 c.devices[0].total_sectors = c.total_sectors;
1211 }
1212 if (c.total_sectors * c.sector_size >
1213 (uint64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) {
1214 MSG(0, "\tError: F2FS can support 16TB at most!!!\n");
1215 return -1;
1216 }
1217
1218 /*
1219 * Check device types and determine the final volume operation mode:
1220 * - If all devices are regular block devices, default operation.
1221 * - If at least one HM device is found, operate in HM mode (BLKZONED
1222 * feature will be enabled by mkfs).
1223 * - If an HA device is found, let mkfs decide based on the -m option
1224 * setting by the user.
1225 */
1226 c.zoned_model = F2FS_ZONED_NONE;
1227 for (i = 0; i < c.ndevs; i++) {
1228 switch (c.devices[i].zoned_model) {
1229 case F2FS_ZONED_NONE:
1230 continue;
1231 case F2FS_ZONED_HM:
1232 c.zoned_model = F2FS_ZONED_HM;
1233 break;
1234 case F2FS_ZONED_HA:
1235 if (c.zoned_model != F2FS_ZONED_HM)
1236 c.zoned_model = F2FS_ZONED_HA;
1237 break;
1238 }
1239 }
1240
1241 if (c.zoned_model != F2FS_ZONED_NONE) {
1242
1243 /*
1244 * For zoned model, the zones sizes of all zoned devices must
1245 * be equal.
1246 */
1247 for (i = 0; i < c.ndevs; i++) {
1248 if (c.devices[i].zoned_model == F2FS_ZONED_NONE)
1249 continue;
1250 if (c.zone_blocks &&
1251 c.zone_blocks != c.devices[i].zone_blocks) {
1252 MSG(0, "\tError: zones of different size are "
1253 "not supported\n");
1254 return -1;
1255 }
1256 c.zone_blocks = c.devices[i].zone_blocks;
1257 }
1258
1259 /*
1260 * Align sections to the device zone size and align F2FS zones
1261 * to the device zones. For F2FS_ZONED_HA model without the
1262 * BLKZONED feature set at format time, this is only an
1263 * optimization as sequential writes will not be enforced.
1264 */
1265 c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT;
1266 c.secs_per_zone = 1;
1267 } else {
1268 if(c.zoned_mode != 0) {
1269 MSG(0, "\n Error: %s may not be a zoned block device \n",
1270 c.devices[0].path);
1271 return -1;
1272 }
1273 }
1274
1275 c.segs_per_zone = c.segs_per_sec * c.secs_per_zone;
1276
1277 if (c.func != MKFS)
1278 return 0;
1279
1280 MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec);
1281 MSG(0, "Info: Sections per zone = %d\n", c.secs_per_zone);
1282 MSG(0, "Info: sector size = %u\n", c.sector_size);
1283 MSG(0, "Info: total sectors = %"PRIu64" (%"PRIu64" MB)\n",
1284 c.total_sectors, (c.total_sectors *
1285 (c.sector_size >> 9)) >> 11);
1286 return 0;
1287 }
1288
calc_extra_isize(void)1289 unsigned int calc_extra_isize(void)
1290 {
1291 unsigned int size = offsetof(struct f2fs_inode, i_projid);
1292
1293 if (c.feature & cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR))
1294 size = offsetof(struct f2fs_inode, i_projid);
1295 if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA))
1296 size = offsetof(struct f2fs_inode, i_inode_checksum);
1297 if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
1298 size = offsetof(struct f2fs_inode, i_crtime);
1299 if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME))
1300 size = offsetof(struct f2fs_inode, i_compr_blocks);
1301 if (c.feature & cpu_to_le32(F2FS_FEATURE_COMPRESSION))
1302 size = offsetof(struct f2fs_inode, i_extra_end);
1303
1304 return size - F2FS_EXTRA_ISIZE_OFFSET;
1305 }
1306
1307 #define ARRAY_SIZE(array) \
1308 (sizeof(array) / sizeof(array[0]))
1309
1310 static const struct {
1311 char *name;
1312 __u16 encoding_magic;
1313 __u16 default_flags;
1314
1315 } f2fs_encoding_map[] = {
1316 {
1317 .encoding_magic = F2FS_ENC_UTF8_12_1,
1318 .name = "utf8",
1319 .default_flags = 0,
1320 },
1321 };
1322
1323 static const struct enc_flags {
1324 __u16 flag;
1325 char *param;
1326 } encoding_flags[] = {
1327 { F2FS_ENC_STRICT_MODE_FL, "strict" },
1328 };
1329
1330 /* Return a positive number < 0xff indicating the encoding magic number
1331 * or a negative value indicating error. */
f2fs_str2encoding(const char * string)1332 int f2fs_str2encoding(const char *string)
1333 {
1334 int i;
1335
1336 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1337 if (!strcmp(string, f2fs_encoding_map[i].name))
1338 return f2fs_encoding_map[i].encoding_magic;
1339
1340 return -EINVAL;
1341 }
1342
f2fs_encoding2str(const int encoding)1343 char *f2fs_encoding2str(const int encoding)
1344 {
1345 int i;
1346
1347 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1348 if (f2fs_encoding_map[i].encoding_magic == encoding)
1349 return f2fs_encoding_map[i].name;
1350
1351 return NULL;
1352 }
1353
f2fs_get_encoding_flags(int encoding)1354 int f2fs_get_encoding_flags(int encoding)
1355 {
1356 int i;
1357
1358 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1359 if (f2fs_encoding_map[i].encoding_magic == encoding)
1360 return f2fs_encoding_map[encoding].default_flags;
1361
1362 return 0;
1363 }
1364
f2fs_str2encoding_flags(char ** param,__u16 * flags)1365 int f2fs_str2encoding_flags(char **param, __u16 *flags)
1366 {
1367 char *f = strtok(*param, ",");
1368 const struct enc_flags *fl;
1369 int i, neg = 0;
1370
1371 while (f) {
1372 neg = 0;
1373 if (!strncmp("no", f, 2)) {
1374 neg = 1;
1375 f += 2;
1376 }
1377
1378 for (i = 0; i < ARRAY_SIZE(encoding_flags); i++) {
1379 fl = &encoding_flags[i];
1380 if (!strcmp(fl->param, f)) {
1381 if (neg) {
1382 MSG(0, "Sub %s\n", fl->param);
1383 *flags &= ~fl->flag;
1384 } else {
1385 MSG(0, "Add %s\n", fl->param);
1386 *flags |= fl->flag;
1387 }
1388
1389 goto next_flag;
1390 }
1391 }
1392 *param = f;
1393 return -EINVAL;
1394 next_flag:
1395 f = strtok(NULL, ":");
1396 }
1397 return 0;
1398 }
1399