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 
502 #define ALIGN_DOWN(addrs, size)		(((addrs) / (size)) * (size))
addrs_per_inode(struct f2fs_inode * i)503 unsigned int addrs_per_inode(struct f2fs_inode *i)
504 {
505 	unsigned int addrs = CUR_ADDRS_PER_INODE(i) - get_inline_xattr_addrs(i);
506 
507 	if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
508 			!(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
509 		return addrs;
510 	return ALIGN_DOWN(addrs, 1 << i->i_log_cluster_size);
511 }
512 
addrs_per_block(struct f2fs_inode * i)513 unsigned int addrs_per_block(struct f2fs_inode *i)
514 {
515 	if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
516 			!(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
517 		return DEF_ADDRS_PER_BLOCK;
518 	return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, 1 << i->i_log_cluster_size);
519 }
520 
521 /*
522  * CRC32
523  */
524 #define CRCPOLY_LE 0xedb88320
525 
f2fs_cal_crc32(u_int32_t crc,void * buf,int len)526 u_int32_t f2fs_cal_crc32(u_int32_t crc, void *buf, int len)
527 {
528 	int i;
529 	unsigned char *p = (unsigned char *)buf;
530 	while (len--) {
531 		crc ^= *p++;
532 		for (i = 0; i < 8; i++)
533 			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
534 	}
535 	return crc;
536 }
537 
f2fs_crc_valid(u_int32_t blk_crc,void * buf,int len)538 int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len)
539 {
540 	u_int32_t cal_crc = 0;
541 
542 	cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len);
543 
544 	if (cal_crc != blk_crc)	{
545 		DBG(0,"CRC validation failed: cal_crc = %u, "
546 			"blk_crc = %u buff_size = 0x%x\n",
547 			cal_crc, blk_crc, len);
548 		return -1;
549 	}
550 	return 0;
551 }
552 
f2fs_inode_chksum(struct f2fs_node * node)553 __u32 f2fs_inode_chksum(struct f2fs_node *node)
554 {
555 	struct f2fs_inode *ri = &node->i;
556 	__le32 ino = node->footer.ino;
557 	__le32 gen = ri->i_generation;
558 	__u32 chksum, chksum_seed;
559 	__u32 dummy_cs = 0;
560 	unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum);
561 	unsigned int cs_size = sizeof(dummy_cs);
562 
563 	chksum = f2fs_cal_crc32(c.chksum_seed, (__u8 *)&ino,
564 							sizeof(ino));
565 	chksum_seed = f2fs_cal_crc32(chksum, (__u8 *)&gen, sizeof(gen));
566 
567 	chksum = f2fs_cal_crc32(chksum_seed, (__u8 *)ri, offset);
568 	chksum = f2fs_cal_crc32(chksum, (__u8 *)&dummy_cs, cs_size);
569 	offset += cs_size;
570 	chksum = f2fs_cal_crc32(chksum, (__u8 *)ri + offset,
571 						F2FS_BLKSIZE - offset);
572 	return chksum;
573 }
574 
f2fs_checkpoint_chksum(struct f2fs_checkpoint * cp)575 __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *cp)
576 {
577 	unsigned int chksum_ofs = le32_to_cpu(cp->checksum_offset);
578 	__u32 chksum;
579 
580 	chksum = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, chksum_ofs);
581 	if (chksum_ofs < CP_CHKSUM_OFFSET) {
582 		chksum_ofs += sizeof(chksum);
583 		chksum = f2fs_cal_crc32(chksum, (__u8 *)cp + chksum_ofs,
584 						F2FS_BLKSIZE - chksum_ofs);
585 	}
586 	return chksum;
587 }
588 
write_inode(struct f2fs_node * inode,u64 blkaddr)589 int write_inode(struct f2fs_node *inode, u64 blkaddr)
590 {
591 	if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
592 		inode->i.i_inode_checksum =
593 			cpu_to_le32(f2fs_inode_chksum(inode));
594 	return dev_write_block(inode, blkaddr);
595 }
596 
597 /*
598  * try to identify the root device
599  */
get_rootdev()600 char *get_rootdev()
601 {
602 #if defined(ANDROID_WINDOWS_HOST) || defined(WITH_ANDROID)
603 	return NULL;
604 #else
605 	struct stat sb;
606 	int fd, ret;
607 	char buf[PATH_MAX + 1];
608 	char *uevent, *ptr;
609 	char *rootdev;
610 
611 	if (stat("/", &sb) == -1)
612 		return NULL;
613 
614 	snprintf(buf, PATH_MAX, "/sys/dev/block/%u:%u/uevent",
615 		major(sb.st_dev), minor(sb.st_dev));
616 
617 	fd = open(buf, O_RDONLY);
618 
619 	if (fd < 0)
620 		return NULL;
621 
622 	ret = lseek(fd, (off_t)0, SEEK_END);
623 	(void)lseek(fd, (off_t)0, SEEK_SET);
624 
625 	if (ret == -1) {
626 		close(fd);
627 		return NULL;
628 	}
629 
630 	uevent = malloc(ret + 1);
631 	ASSERT(uevent);
632 
633 	uevent[ret] = '\0';
634 
635 	ret = read(fd, uevent, ret);
636 	close(fd);
637 
638 	ptr = strstr(uevent, "DEVNAME");
639 	if (!ptr)
640 		goto out_free;
641 
642 	ret = sscanf(ptr, "DEVNAME=%s\n", buf);
643 	if (strlen(buf) == 0)
644 		goto out_free;
645 
646 	ret = strlen(buf) + 5;
647 	rootdev = malloc(ret + 1);
648 	if (!rootdev)
649 		goto out_free;
650 	rootdev[ret] = '\0';
651 
652 	snprintf(rootdev, ret + 1, "/dev/%s", buf);
653 	free(uevent);
654 	return rootdev;
655 
656 out_free:
657 	free(uevent);
658 	return NULL;
659 #endif
660 }
661 
662 /*
663  * device information
664  */
f2fs_init_configuration(void)665 void f2fs_init_configuration(void)
666 {
667 	int i;
668 
669 	memset(&c, 0, sizeof(struct f2fs_configuration));
670 	c.ndevs = 1;
671 	c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
672 	c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
673 	c.wanted_total_sectors = -1;
674 	c.wanted_sector_size = -1;
675 #ifndef WITH_ANDROID
676 	c.preserve_limits = 1;
677 	c.no_kernel_check = 1;
678 #else
679 	c.no_kernel_check = 0;
680 #endif
681 
682 	for (i = 0; i < MAX_DEVICES; i++) {
683 		c.devices[i].fd = -1;
684 		c.devices[i].sector_size = DEFAULT_SECTOR_SIZE;
685 		c.devices[i].end_blkaddr = -1;
686 		c.devices[i].zoned_model = F2FS_ZONED_NONE;
687 	}
688 
689 	/* calculated by overprovision ratio */
690 	c.segs_per_sec = 1;
691 	c.secs_per_zone = 1;
692 	c.segs_per_zone = 1;
693 	c.vol_label = "";
694 	c.trim = 1;
695 	c.kd = -1;
696 	c.fixed_time = -1;
697 	c.s_encoding = 0;
698 	c.s_encoding_flags = 0;
699 
700 	/* default root owner */
701 	c.root_uid = getuid();
702 	c.root_gid = getgid();
703 }
704 
f2fs_dev_is_writable(void)705 int f2fs_dev_is_writable(void)
706 {
707 	return !c.ro || c.force;
708 }
709 
710 #ifdef HAVE_SETMNTENT
is_mounted(const char * mpt,const char * device)711 static int is_mounted(const char *mpt, const char *device)
712 {
713 	FILE *file = NULL;
714 	struct mntent *mnt = NULL;
715 
716 	file = setmntent(mpt, "r");
717 	if (file == NULL)
718 		return 0;
719 
720 	while ((mnt = getmntent(file)) != NULL) {
721 		if (!strcmp(device, mnt->mnt_fsname)) {
722 #ifdef MNTOPT_RO
723 			if (hasmntopt(mnt, MNTOPT_RO))
724 				c.ro = 1;
725 #endif
726 			break;
727 		}
728 	}
729 	endmntent(file);
730 	return mnt ? 1 : 0;
731 }
732 #endif
733 
f2fs_dev_is_umounted(char * path)734 int f2fs_dev_is_umounted(char *path)
735 {
736 #ifdef ANDROID_WINDOWS_HOST
737 	return 0;
738 #else
739 	struct stat *st_buf;
740 	int is_rootdev = 0;
741 	int ret = 0;
742 	char *rootdev_name = get_rootdev();
743 
744 	if (rootdev_name) {
745 		if (!strcmp(path, rootdev_name))
746 			is_rootdev = 1;
747 		free(rootdev_name);
748 	}
749 
750 	/*
751 	 * try with /proc/mounts fist to detect RDONLY.
752 	 * f2fs_stop_checkpoint makes RO in /proc/mounts while RW in /etc/mtab.
753 	 */
754 #ifdef __linux__
755 	ret = is_mounted("/proc/mounts", path);
756 	if (ret) {
757 		MSG(0, "Info: Mounted device!\n");
758 		return -1;
759 	}
760 #endif
761 #if defined(MOUNTED) || defined(_PATH_MOUNTED)
762 #ifndef MOUNTED
763 #define MOUNTED _PATH_MOUNTED
764 #endif
765 	ret = is_mounted(MOUNTED, path);
766 	if (ret) {
767 		MSG(0, "Info: Mounted device!\n");
768 		return -1;
769 	}
770 #endif
771 	/*
772 	 * If we are supposed to operate on the root device, then
773 	 * also check the mounts for '/dev/root', which sometimes
774 	 * functions as an alias for the root device.
775 	 */
776 	if (is_rootdev) {
777 #ifdef __linux__
778 		ret = is_mounted("/proc/mounts", "/dev/root");
779 		if (ret) {
780 			MSG(0, "Info: Mounted device!\n");
781 			return -1;
782 		}
783 #endif
784 	}
785 
786 	/*
787 	 * If f2fs is umounted with -l, the process can still use
788 	 * the file system. In this case, we should not format.
789 	 */
790 	st_buf = malloc(sizeof(struct stat));
791 	ASSERT(st_buf);
792 
793 	if (stat(path, st_buf) == 0 && S_ISBLK(st_buf->st_mode)) {
794 		int fd = open(path, O_RDONLY | O_EXCL);
795 
796 		if (fd >= 0) {
797 			close(fd);
798 		} else if (errno == EBUSY) {
799 			MSG(0, "\tError: In use by the system!\n");
800 			free(st_buf);
801 			return -1;
802 		}
803 	}
804 	free(st_buf);
805 	return ret;
806 #endif
807 }
808 
f2fs_devs_are_umounted(void)809 int f2fs_devs_are_umounted(void)
810 {
811 	int i;
812 
813 	for (i = 0; i < c.ndevs; i++)
814 		if (f2fs_dev_is_umounted((char *)c.devices[i].path))
815 			return -1;
816 	return 0;
817 }
818 
get_kernel_version(__u8 * version)819 void get_kernel_version(__u8 *version)
820 {
821 	int i;
822 	for (i = 0; i < VERSION_LEN; i++) {
823 		if (version[i] == '\n')
824 			break;
825 	}
826 	memset(version + i, 0, VERSION_LEN + 1 - i);
827 }
828 
get_kernel_uname_version(__u8 * version)829 void get_kernel_uname_version(__u8 *version)
830 {
831 #ifdef HAVE_SYS_UTSNAME_H
832 	struct utsname buf;
833 
834 	memset(version, 0, VERSION_LEN);
835 	if (uname(&buf))
836 		return;
837 
838 #if defined(WITH_KERNEL_VERSION)
839 	snprintf((char *)version,
840 		VERSION_LEN, "%s %s", buf.release, buf.version);
841 #else
842 	snprintf((char *)version,
843 		VERSION_LEN, "%s", buf.release);
844 #endif
845 #else
846 	memset(version, 0, VERSION_LEN);
847 #endif
848 }
849 
850 #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
851 #define BLKGETSIZE	_IO(0x12,96)
852 #endif
853 
854 #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
855 #define BLKGETSIZE64	_IOR(0x12,114, size_t)
856 #endif
857 
858 #if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
859 #define BLKSSZGET	_IO(0x12,104)
860 #endif
861 
862 #if defined(__APPLE__)
863 #include <sys/disk.h>
864 #define BLKGETSIZE	DKIOCGETBLOCKCOUNT
865 #define BLKSSZGET	DKIOCGETBLOCKCOUNT
866 #endif /* APPLE_DARWIN */
867 
868 #ifndef ANDROID_WINDOWS_HOST
open_check_fs(char * path,int flag)869 static int open_check_fs(char *path, int flag)
870 {
871 	if (c.func != DUMP && (c.func != FSCK || c.fix_on || c.auto_fix))
872 		return -1;
873 
874 	/* allow to open ro */
875 	return open(path, O_RDONLY | flag);
876 }
877 
get_device_info(int i)878 int get_device_info(int i)
879 {
880 	int32_t fd = 0;
881 	uint32_t sector_size;
882 #ifndef BLKGETSIZE64
883 	uint32_t total_sectors;
884 #endif
885 	struct stat *stat_buf;
886 #ifdef HDIO_GETGIO
887 	struct hd_geometry geom;
888 #endif
889 #if !defined(WITH_ANDROID) && defined(__linux__)
890 	sg_io_hdr_t io_hdr;
891 	unsigned char reply_buffer[96] = {0};
892 	unsigned char model_inq[6] = {MODELINQUIRY};
893 #endif
894 	struct device_info *dev = c.devices + i;
895 
896 	if (c.sparse_mode) {
897 		fd = open(dev->path, O_RDWR | O_CREAT | O_BINARY, 0644);
898 		if (fd < 0) {
899 			fd = open_check_fs(dev->path, O_BINARY);
900 			if (fd < 0) {
901 				MSG(0, "\tError: Failed to open a sparse file!\n");
902 				return -1;
903 			}
904 		}
905 	}
906 
907 	stat_buf = malloc(sizeof(struct stat));
908 	ASSERT(stat_buf);
909 
910 	if (!c.sparse_mode) {
911 		if (stat(dev->path, stat_buf) < 0 ) {
912 			MSG(0, "\tError: Failed to get the device stat!\n");
913 			free(stat_buf);
914 			return -1;
915 		}
916 
917 		if (S_ISBLK(stat_buf->st_mode) &&
918 				!c.force && c.func != DUMP && !c.dry_run) {
919 			fd = open(dev->path, O_RDWR | O_EXCL);
920 			if (fd < 0)
921 				fd = open_check_fs(dev->path, O_EXCL);
922 		} else {
923 			fd = open(dev->path, O_RDWR);
924 			if (fd < 0)
925 				fd = open_check_fs(dev->path, 0);
926 		}
927 	}
928 	if (fd < 0) {
929 		MSG(0, "\tError: Failed to open the device!\n");
930 		free(stat_buf);
931 		return -1;
932 	}
933 
934 	dev->fd = fd;
935 
936 	if (c.sparse_mode) {
937 		if (f2fs_init_sparse_file()) {
938 			free(stat_buf);
939 			return -1;
940 		}
941 	}
942 
943 	if (c.kd == -1) {
944 #if !defined(WITH_ANDROID) && defined(__linux__)
945 		c.kd = open("/proc/version", O_RDONLY);
946 #endif
947 		if (c.kd < 0) {
948 			MSG(0, "\tInfo: No support kernel version!\n");
949 			c.kd = -2;
950 		}
951 	}
952 
953 	if (c.sparse_mode) {
954 		dev->total_sectors = c.device_size / dev->sector_size;
955 	} else if (S_ISREG(stat_buf->st_mode)) {
956 		dev->total_sectors = stat_buf->st_size / dev->sector_size;
957 	} else if (S_ISBLK(stat_buf->st_mode)) {
958 #ifdef BLKSSZGET
959 		if (ioctl(fd, BLKSSZGET, &sector_size) < 0)
960 			MSG(0, "\tError: Using the default sector size\n");
961 		else if (dev->sector_size < sector_size)
962 			dev->sector_size = sector_size;
963 #endif
964 #ifdef BLKGETSIZE64
965 		if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
966 			MSG(0, "\tError: Cannot get the device size\n");
967 			free(stat_buf);
968 			return -1;
969 		}
970 #else
971 		if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
972 			MSG(0, "\tError: Cannot get the device size\n");
973 			free(stat_buf);
974 			return -1;
975 		}
976 		dev->total_sectors = total_sectors;
977 #endif
978 		dev->total_sectors /= dev->sector_size;
979 
980 		if (i == 0) {
981 #ifdef HDIO_GETGIO
982 			if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
983 				c.start_sector = 0;
984 			else
985 				c.start_sector = geom.start;
986 #else
987 			c.start_sector = 0;
988 #endif
989 		}
990 
991 #if !defined(WITH_ANDROID) && defined(__linux__)
992 		/* Send INQUIRY command */
993 		memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
994 		io_hdr.interface_id = 'S';
995 		io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
996 		io_hdr.dxfer_len = sizeof(reply_buffer);
997 		io_hdr.dxferp = reply_buffer;
998 		io_hdr.cmd_len = sizeof(model_inq);
999 		io_hdr.cmdp = model_inq;
1000 		io_hdr.timeout = 1000;
1001 
1002 		if (!ioctl(fd, SG_IO, &io_hdr)) {
1003 			MSG(0, "Info: [%s] Disk Model: %.16s\n",
1004 					dev->path, reply_buffer+16);
1005 		}
1006 #endif
1007 	} else {
1008 		MSG(0, "\tError: Volume type is not supported!!!\n");
1009 		free(stat_buf);
1010 		return -1;
1011 	}
1012 
1013 	if (!c.sector_size) {
1014 		c.sector_size = dev->sector_size;
1015 		c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1016 	} else if (c.sector_size != c.devices[i].sector_size) {
1017 		MSG(0, "\tError: Different sector sizes!!!\n");
1018 		free(stat_buf);
1019 		return -1;
1020 	}
1021 
1022 #if !defined(WITH_ANDROID) && defined(__linux__)
1023 	if (S_ISBLK(stat_buf->st_mode)) {
1024 		if (f2fs_get_zoned_model(i) < 0) {
1025 			free(stat_buf);
1026 			return -1;
1027 		}
1028 	}
1029 
1030 	if (dev->zoned_model != F2FS_ZONED_NONE) {
1031 
1032 		/* Get the number of blocks per zones */
1033 		if (f2fs_get_zone_blocks(i)) {
1034 			MSG(0, "\tError: Failed to get number of blocks per zone\n");
1035 			free(stat_buf);
1036 			return -1;
1037 		}
1038 
1039 		/*
1040 		 * Check zone configuration: for the first disk of a
1041 		 * multi-device volume, conventional zones are needed.
1042 		 */
1043 		if (f2fs_check_zones(i)) {
1044 			MSG(0, "\tError: Failed to check zone configuration\n");
1045 			free(stat_buf);
1046 			return -1;
1047 		}
1048 		MSG(0, "Info: Host-%s zoned block device:\n",
1049 				(dev->zoned_model == F2FS_ZONED_HA) ?
1050 					"aware" : "managed");
1051 		MSG(0, "      %u zones, %u randomly writeable zones\n",
1052 				dev->nr_zones, dev->nr_rnd_zones);
1053 		MSG(0, "      %lu blocks per zone\n",
1054 				dev->zone_blocks);
1055 	}
1056 #endif
1057 	/* adjust wanted_total_sectors */
1058 	if (c.wanted_total_sectors != -1) {
1059 		MSG(0, "Info: wanted sectors = %"PRIu64" (in %"PRIu64" bytes)\n",
1060 				c.wanted_total_sectors, c.wanted_sector_size);
1061 		if (c.wanted_sector_size == -1) {
1062 			c.wanted_sector_size = dev->sector_size;
1063 		} else if (dev->sector_size != c.wanted_sector_size) {
1064 			c.wanted_total_sectors *= c.wanted_sector_size;
1065 			c.wanted_total_sectors /= dev->sector_size;
1066 		}
1067 	}
1068 
1069 	c.total_sectors += dev->total_sectors;
1070 	free(stat_buf);
1071 	return 0;
1072 }
1073 
1074 #else
1075 
1076 #include "windows.h"
1077 #include "winioctl.h"
1078 
1079 #if (_WIN32_WINNT >= 0x0500)
1080 #define HAVE_GET_FILE_SIZE_EX 1
1081 #endif
1082 
win_get_device_size(const char * file,uint64_t * device_size)1083 static int win_get_device_size(const char *file, uint64_t *device_size)
1084 {
1085 	HANDLE dev;
1086 	PARTITION_INFORMATION pi;
1087 	DISK_GEOMETRY gi;
1088 	DWORD retbytes;
1089 #ifdef HAVE_GET_FILE_SIZE_EX
1090 	LARGE_INTEGER filesize;
1091 #else
1092 	DWORD filesize;
1093 #endif /* HAVE_GET_FILE_SIZE_EX */
1094 
1095 	dev = CreateFile(file, GENERIC_READ,
1096 			FILE_SHARE_READ | FILE_SHARE_WRITE ,
1097 			NULL,  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,  NULL);
1098 
1099 	if (dev == INVALID_HANDLE_VALUE)
1100 		return EBADF;
1101 	if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
1102 				&pi, sizeof(PARTITION_INFORMATION),
1103 				&pi, sizeof(PARTITION_INFORMATION),
1104 				&retbytes, NULL)) {
1105 
1106 		*device_size = 	pi.PartitionLength.QuadPart;
1107 
1108 	} else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
1109 				&gi, sizeof(DISK_GEOMETRY),
1110 				&gi, sizeof(DISK_GEOMETRY),
1111 				&retbytes, NULL)) {
1112 
1113 		*device_size = gi.BytesPerSector *
1114 			gi.SectorsPerTrack *
1115 			gi.TracksPerCylinder *
1116 			gi.Cylinders.QuadPart;
1117 
1118 #ifdef HAVE_GET_FILE_SIZE_EX
1119 	} else if (GetFileSizeEx(dev, &filesize)) {
1120 		*device_size = filesize.QuadPart;
1121 	}
1122 #else
1123 	} else {
1124 		filesize = GetFileSize(dev, NULL);
1125 		if (INVALID_FILE_SIZE != filesize)
1126 			return -1;
1127 		*device_size = filesize;
1128 	}
1129 #endif /* HAVE_GET_FILE_SIZE_EX */
1130 
1131 	CloseHandle(dev);
1132 	return 0;
1133 }
1134 
get_device_info(int i)1135 int get_device_info(int i)
1136 {
1137 	struct device_info *dev = c.devices + i;
1138 	uint64_t device_size = 0;
1139 	int32_t fd = 0;
1140 
1141 	/* Block device target is not supported on Windows. */
1142 	if (!c.sparse_mode) {
1143 		if (win_get_device_size(dev->path, &device_size)) {
1144 			MSG(0, "\tError: Failed to get device size!\n");
1145 			return -1;
1146 		}
1147 	} else {
1148 		device_size = c.device_size;
1149 	}
1150 	if (c.sparse_mode) {
1151 		fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1152 	} else {
1153 		fd = open((char *)dev->path, O_RDWR | O_BINARY);
1154 	}
1155 	if (fd < 0) {
1156 		MSG(0, "\tError: Failed to open the device!\n");
1157 		return -1;
1158 	}
1159 	dev->fd = fd;
1160 	dev->total_sectors = device_size / dev->sector_size;
1161 	c.start_sector = 0;
1162 	c.sector_size = dev->sector_size;
1163 	c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1164 	c.total_sectors += dev->total_sectors;
1165 
1166 	if (c.sparse_mode && f2fs_init_sparse_file())
1167 		return -1;
1168 	return 0;
1169 }
1170 #endif
1171 
f2fs_get_device_info(void)1172 int f2fs_get_device_info(void)
1173 {
1174 	int i;
1175 
1176 	for (i = 0; i < c.ndevs; i++)
1177 		if (get_device_info(i))
1178 			return -1;
1179 
1180 	if (c.wanted_total_sectors < c.total_sectors) {
1181 		MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
1182 				c.total_sectors, c.sector_size);
1183 		c.total_sectors = c.wanted_total_sectors;
1184 		c.devices[0].total_sectors = c.total_sectors;
1185 	}
1186 	if (c.total_sectors * c.sector_size >
1187 		(u_int64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) {
1188 		MSG(0, "\tError: F2FS can support 16TB at most!!!\n");
1189 		return -1;
1190 	}
1191 
1192 	/*
1193 	 * Check device types and determine the final volume operation mode:
1194 	 *   - If all devices are regular block devices, default operation.
1195 	 *   - If at least one HM device is found, operate in HM mode (BLKZONED
1196 	 *     feature will be enabled by mkfs).
1197 	 *   - If an HA device is found, let mkfs decide based on the -m option
1198 	 *     setting by the user.
1199 	 */
1200 	c.zoned_model = F2FS_ZONED_NONE;
1201 	for (i = 0; i < c.ndevs; i++) {
1202 		switch (c.devices[i].zoned_model) {
1203 		case F2FS_ZONED_NONE:
1204 			continue;
1205 		case F2FS_ZONED_HM:
1206 			c.zoned_model = F2FS_ZONED_HM;
1207 			break;
1208 		case F2FS_ZONED_HA:
1209 			if (c.zoned_model != F2FS_ZONED_HM)
1210 				c.zoned_model = F2FS_ZONED_HA;
1211 			break;
1212 		}
1213 	}
1214 
1215 	if (c.zoned_model != F2FS_ZONED_NONE) {
1216 
1217 		/*
1218 		 * For zoned model, the zones sizes of all zoned devices must
1219 		 * be equal.
1220 		 */
1221 		for (i = 0; i < c.ndevs; i++) {
1222 			if (c.devices[i].zoned_model == F2FS_ZONED_NONE)
1223 				continue;
1224 			if (c.zone_blocks &&
1225 				c.zone_blocks != c.devices[i].zone_blocks) {
1226 				MSG(0, "\tError: zones of different size are "
1227 				       "not supported\n");
1228 				return -1;
1229 			}
1230 			c.zone_blocks = c.devices[i].zone_blocks;
1231 		}
1232 
1233 		/*
1234 		 * Align sections to the device zone size and align F2FS zones
1235 		 * to the device zones. For F2FS_ZONED_HA model without the
1236 		 * BLKZONED feature set at format time, this is only an
1237 		 * optimization as sequential writes will not be enforced.
1238 		 */
1239 		c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT;
1240 		c.secs_per_zone = 1;
1241 	} else {
1242 		if(c.zoned_mode != 0) {
1243 			MSG(0, "\n Error: %s may not be a zoned block device \n",
1244 					c.devices[0].path);
1245 			return -1;
1246 		}
1247 	}
1248 
1249 	c.segs_per_zone = c.segs_per_sec * c.secs_per_zone;
1250 
1251 	MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec);
1252 	MSG(0, "Info: Sections per zone = %d\n", c.secs_per_zone);
1253 	MSG(0, "Info: sector size = %u\n", c.sector_size);
1254 	MSG(0, "Info: total sectors = %"PRIu64" (%"PRIu64" MB)\n",
1255 				c.total_sectors, (c.total_sectors *
1256 					(c.sector_size >> 9)) >> 11);
1257 	return 0;
1258 }
1259 
calc_extra_isize(void)1260 unsigned int calc_extra_isize(void)
1261 {
1262 	unsigned int size = offsetof(struct f2fs_inode, i_projid);
1263 
1264 	if (c.feature & cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR))
1265 		size = offsetof(struct f2fs_inode, i_projid);
1266 	if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA))
1267 		size = offsetof(struct f2fs_inode, i_inode_checksum);
1268 	if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
1269 		size = offsetof(struct f2fs_inode, i_crtime);
1270 	if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME))
1271 		size = offsetof(struct f2fs_inode, i_compr_blocks);
1272 	if (c.feature & cpu_to_le32(F2FS_FEATURE_COMPRESSION))
1273 		size = offsetof(struct f2fs_inode, i_extra_end);
1274 
1275 	return size - F2FS_EXTRA_ISIZE_OFFSET;
1276 }
1277 
1278 #define ARRAY_SIZE(array)			\
1279 	(sizeof(array) / sizeof(array[0]))
1280 
1281 static const struct {
1282 	char *name;
1283 	__u16 encoding_magic;
1284 	__u16 default_flags;
1285 
1286 } f2fs_encoding_map[] = {
1287 	{
1288 		.encoding_magic = F2FS_ENC_UTF8_12_1,
1289 		.name = "utf8",
1290 		.default_flags = 0,
1291 	},
1292 };
1293 
1294 static const struct enc_flags {
1295 	__u16 flag;
1296 	char *param;
1297 } encoding_flags[] = {
1298 	{ F2FS_ENC_STRICT_MODE_FL, "strict" },
1299 };
1300 
1301 /* Return a positive number < 0xff indicating the encoding magic number
1302  * or a negative value indicating error. */
f2fs_str2encoding(const char * string)1303 int f2fs_str2encoding(const char *string)
1304 {
1305 	int i;
1306 
1307 	for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1308 		if (!strcmp(string, f2fs_encoding_map[i].name))
1309 			return f2fs_encoding_map[i].encoding_magic;
1310 
1311 	return -EINVAL;
1312 }
1313 
f2fs_encoding2str(const int encoding)1314 char *f2fs_encoding2str(const int encoding)
1315 {
1316 	int i;
1317 
1318 	for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1319 		if (f2fs_encoding_map[i].encoding_magic == encoding)
1320 			return f2fs_encoding_map[i].name;
1321 
1322 	return NULL;
1323 }
1324 
f2fs_get_encoding_flags(int encoding)1325 int f2fs_get_encoding_flags(int encoding)
1326 {
1327 	int i;
1328 
1329 	for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1330 		if (f2fs_encoding_map[i].encoding_magic == encoding)
1331 			return f2fs_encoding_map[encoding].default_flags;
1332 
1333 	return 0;
1334 }
1335 
f2fs_str2encoding_flags(char ** param,__u16 * flags)1336 int f2fs_str2encoding_flags(char **param, __u16 *flags)
1337 {
1338 	char *f = strtok(*param, ",");
1339 	const struct enc_flags *fl;
1340 	int i, neg = 0;
1341 
1342 	while (f) {
1343 		neg = 0;
1344 		if (!strncmp("no", f, 2)) {
1345 			neg = 1;
1346 			f += 2;
1347 		}
1348 
1349 		for (i = 0; i < ARRAY_SIZE(encoding_flags); i++) {
1350 			fl = &encoding_flags[i];
1351 			if (!strcmp(fl->param, f)) {
1352 				if (neg) {
1353 					MSG(0, "Sub %s\n", fl->param);
1354 					*flags &= ~fl->flag;
1355 				} else {
1356 					MSG(0, "Add %s\n", fl->param);
1357 					*flags |= fl->flag;
1358 				}
1359 
1360 				goto next_flag;
1361 			}
1362 		}
1363 		*param = f;
1364 		return -EINVAL;
1365 	next_flag:
1366 		f = strtok(NULL, ":");
1367 	}
1368 	return 0;
1369 }
1370