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