• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #include <f2fs_fs.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #ifdef HAVE_MNTENT_H
19 #include <mntent.h>
20 #endif
21 #include <time.h>
22 #include <sys/stat.h>
23 #ifndef ANDROID_WINDOWS_HOST
24 #include <sys/mount.h>
25 #include <sys/ioctl.h>
26 #endif
27 #ifdef HAVE_SYS_SYSMACROS_H
28 #include <sys/sysmacros.h>
29 #endif
30 #ifdef HAVE_SYS_UTSNAME_H
31 #include <sys/utsname.h>
32 #endif
33 #ifndef WITH_ANDROID
34 #ifdef HAVE_SCSI_SG_H
35 #include <scsi/sg.h>
36 #endif
37 #endif
38 #ifdef HAVE_LINUX_HDREG_H
39 #include <linux/hdreg.h>
40 #endif
41 #ifdef HAVE_LINUX_LIMITS_H
42 #include <linux/limits.h>
43 #endif
44 
45 #ifndef WITH_ANDROID
46 /* SCSI command for standard inquiry*/
47 #define MODELINQUIRY	0x12,0x00,0x00,0x00,0x4A,0x00
48 #endif
49 
50 #ifndef ANDROID_WINDOWS_HOST /* 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(u_int16_t * output,wchar_t wc,size_t outsize)105 static u_int16_t *wchar_to_utf16(u_int16_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(u_int16_t * output,const char * input,size_t outsize,size_t insize)121 int utf8_to_utf16(u_int16_t *output, const char *input, size_t outsize,
122 		size_t insize)
123 {
124 	const char *inp = input;
125 	u_int16_t *outp = output;
126 	wchar_t wc;
127 
128 	while ((size_t)(inp - input) < insize && *inp) {
129 		inp = utf8_to_wchar(inp, &wc, insize - (inp - input));
130 		if (inp == NULL) {
131 			DBG(0, "illegal UTF-8 sequence\n");
132 			return -EILSEQ;
133 		}
134 		outp = wchar_to_utf16(outp, wc, outsize - (outp - output));
135 		if (outp == NULL) {
136 			DBG(0, "name is too long\n");
137 			return -ENAMETOOLONG;
138 		}
139 	}
140 	*outp = cpu_to_le16(0);
141 	return 0;
142 }
143 
utf16_to_wchar(const u_int16_t * input,wchar_t * wc,size_t insize)144 static const u_int16_t *utf16_to_wchar(const u_int16_t *input, wchar_t *wc,
145 		size_t insize)
146 {
147 	if ((le16_to_cpu(input[0]) & 0xfc00) == 0xd800) {
148 		if (insize < 2 || (le16_to_cpu(input[1]) & 0xfc00) != 0xdc00)
149 			return NULL;
150 		*wc = ((wchar_t) (le16_to_cpu(input[0]) & 0x3ff) << 10);
151 		*wc |= (le16_to_cpu(input[1]) & 0x3ff);
152 		*wc += 0x10000;
153 		return input + 2;
154 	} else {
155 		*wc = le16_to_cpu(*input);
156 		return input + 1;
157 	}
158 }
159 
wchar_to_utf8(char * output,wchar_t wc,size_t outsize)160 static char *wchar_to_utf8(char *output, wchar_t wc, size_t outsize)
161 {
162 	if (wc <= 0x7f) {
163 		if (outsize < 1)
164 			return NULL;
165 		*output++ = (char) wc;
166 	} else if (wc <= 0x7ff) {
167 		if (outsize < 2)
168 			return NULL;
169 		*output++ = 0xc0 | (wc >> 6);
170 		*output++ = 0x80 | (wc & 0x3f);
171 	} else if (wc <= 0xffff) {
172 		if (outsize < 3)
173 			return NULL;
174 		*output++ = 0xe0 | (wc >> 12);
175 		*output++ = 0x80 | ((wc >> 6) & 0x3f);
176 		*output++ = 0x80 | (wc & 0x3f);
177 	} else if (wc <= 0x1fffff) {
178 		if (outsize < 4)
179 			return NULL;
180 		*output++ = 0xf0 | (wc >> 18);
181 		*output++ = 0x80 | ((wc >> 12) & 0x3f);
182 		*output++ = 0x80 | ((wc >> 6) & 0x3f);
183 		*output++ = 0x80 | (wc & 0x3f);
184 	} else if (wc <= 0x3ffffff) {
185 		if (outsize < 5)
186 			return NULL;
187 		*output++ = 0xf8 | (wc >> 24);
188 		*output++ = 0x80 | ((wc >> 18) & 0x3f);
189 		*output++ = 0x80 | ((wc >> 12) & 0x3f);
190 		*output++ = 0x80 | ((wc >> 6) & 0x3f);
191 		*output++ = 0x80 | (wc & 0x3f);
192 	} else if (wc <= 0x7fffffff) {
193 		if (outsize < 6)
194 			return NULL;
195 		*output++ = 0xfc | (wc >> 30);
196 		*output++ = 0x80 | ((wc >> 24) & 0x3f);
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
202 		return NULL;
203 
204 	return output;
205 }
206 
utf16_to_utf8(char * output,const u_int16_t * input,size_t outsize,size_t insize)207 int utf16_to_utf8(char *output, const u_int16_t *input, size_t outsize,
208 		size_t insize)
209 {
210 	const u_int16_t *inp = input;
211 	char *outp = output;
212 	wchar_t wc;
213 
214 	while ((size_t)(inp - input) < insize && le16_to_cpu(*inp)) {
215 		inp = utf16_to_wchar(inp, &wc, insize - (inp - input));
216 		if (inp == NULL) {
217 			DBG(0, "illegal UTF-16 sequence\n");
218 			return -EILSEQ;
219 		}
220 		outp = wchar_to_utf8(outp, wc, outsize - (outp - output));
221 		if (outp == NULL) {
222 			DBG(0, "name is too long\n");
223 			return -ENAMETOOLONG;
224 		}
225 	}
226 	*outp = '\0';
227 	return 0;
228 }
229 
log_base_2(u_int32_t num)230 int log_base_2(u_int32_t num)
231 {
232 	int ret = 0;
233 	if (num <= 0 || (num & (num - 1)) != 0)
234 		return -1;
235 
236 	while (num >>= 1)
237 		ret++;
238 	return ret;
239 }
240 
241 /*
242  * f2fs bit operations
243  */
244 static const int bits_in_byte[256] = {
245 	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
246 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
247 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
248 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
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 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
252 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
253 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
254 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
255 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
256 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
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 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
260 	4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
261 };
262 
get_bits_in_byte(unsigned char n)263 int get_bits_in_byte(unsigned char n)
264 {
265 	return bits_in_byte[n];
266 }
267 
test_and_set_bit_le(u32 nr,u8 * addr)268 int test_and_set_bit_le(u32 nr, u8 *addr)
269 {
270 	int mask, retval;
271 
272 	addr += nr >> 3;
273 	mask = 1 << ((nr & 0x07));
274 	retval = mask & *addr;
275 	*addr |= mask;
276 	return retval;
277 }
278 
test_and_clear_bit_le(u32 nr,u8 * addr)279 int test_and_clear_bit_le(u32 nr, u8 *addr)
280 {
281 	int mask, retval;
282 
283 	addr += nr >> 3;
284 	mask = 1 << ((nr & 0x07));
285 	retval = mask & *addr;
286 	*addr &= ~mask;
287 	return retval;
288 }
289 
test_bit_le(u32 nr,const u8 * addr)290 int test_bit_le(u32 nr, const u8 *addr)
291 {
292 	return ((1 << (nr & 7)) & (addr[nr >> 3]));
293 }
294 
f2fs_test_bit(unsigned int nr,const char * p)295 int f2fs_test_bit(unsigned int nr, const char *p)
296 {
297 	int mask;
298 	char *addr = (char *)p;
299 
300 	addr += (nr >> 3);
301 	mask = 1 << (7 - (nr & 0x07));
302 	return (mask & *addr) != 0;
303 }
304 
f2fs_set_bit(unsigned int nr,char * addr)305 int f2fs_set_bit(unsigned int nr, char *addr)
306 {
307 	int mask;
308 	int ret;
309 
310 	addr += (nr >> 3);
311 	mask = 1 << (7 - (nr & 0x07));
312 	ret = mask & *addr;
313 	*addr |= mask;
314 	return ret;
315 }
316 
f2fs_clear_bit(unsigned int nr,char * addr)317 int f2fs_clear_bit(unsigned int nr, char *addr)
318 {
319 	int mask;
320 	int ret;
321 
322 	addr += (nr >> 3);
323 	mask = 1 << (7 - (nr & 0x07));
324 	ret = mask & *addr;
325 	*addr &= ~mask;
326 	return ret;
327 }
328 
__ffs(u8 word)329 static inline u64 __ffs(u8 word)
330 {
331 	int num = 0;
332 
333 	if ((word & 0xf) == 0) {
334 		num += 4;
335 		word >>= 4;
336 	}
337 	if ((word & 0x3) == 0) {
338 		num += 2;
339 		word >>= 2;
340 	}
341 	if ((word & 0x1) == 0)
342 		num += 1;
343 	return num;
344 }
345 
346 /* Copied from linux/lib/find_bit.c */
347 #define BITMAP_FIRST_BYTE_MASK(start) (0xff << ((start) & (BITS_PER_BYTE - 1)))
348 
_find_next_bit_le(const u8 * addr,u64 nbits,u64 start,char invert)349 static u64 _find_next_bit_le(const u8 *addr, u64 nbits, u64 start, char invert)
350 {
351 	u8 tmp;
352 
353 	if (!nbits || start >= nbits)
354 		return nbits;
355 
356 	tmp = addr[start / BITS_PER_BYTE] ^ invert;
357 
358 	/* Handle 1st word. */
359 	tmp &= BITMAP_FIRST_BYTE_MASK(start);
360 	start = round_down(start, BITS_PER_BYTE);
361 
362 	while (!tmp) {
363 		start += BITS_PER_BYTE;
364 		if (start >= nbits)
365 			return nbits;
366 
367 		tmp = addr[start / BITS_PER_BYTE] ^ invert;
368 	}
369 
370 	return min(start + __ffs(tmp), nbits);
371 }
372 
find_next_bit_le(const u8 * addr,u64 size,u64 offset)373 u64 find_next_bit_le(const u8 *addr, u64 size, u64 offset)
374 {
375 	return _find_next_bit_le(addr, size, offset, 0);
376 }
377 
378 
find_next_zero_bit_le(const u8 * addr,u64 size,u64 offset)379 u64 find_next_zero_bit_le(const u8 *addr, u64 size, u64 offset)
380 {
381 	return _find_next_bit_le(addr, size, offset, 0xff);
382 }
383 
384 /*
385  * Hashing code adapted from ext3
386  */
387 #define DELTA 0x9E3779B9
388 
TEA_transform(unsigned int buf[4],unsigned int const in[])389 static void TEA_transform(unsigned int buf[4], unsigned int const in[])
390 {
391 	__u32 sum = 0;
392 	__u32 b0 = buf[0], b1 = buf[1];
393 	__u32 a = in[0], b = in[1], c = in[2], d = in[3];
394 	int     n = 16;
395 
396 	do {
397 		sum += DELTA;
398 		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
399 		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
400 	} while (--n);
401 
402 	buf[0] += b0;
403 	buf[1] += b1;
404 
405 }
406 
str2hashbuf(const unsigned char * msg,int len,unsigned int * buf,int num)407 static void str2hashbuf(const unsigned char *msg, int len,
408 					unsigned int *buf, int num)
409 {
410 	unsigned pad, val;
411 	int i;
412 
413 	pad = (__u32)len | ((__u32)len << 8);
414 	pad |= pad << 16;
415 
416 	val = pad;
417 	if (len > num * 4)
418 		len = num * 4;
419 	for (i = 0; i < len; i++) {
420 		if ((i % 4) == 0)
421 			val = pad;
422 		val = msg[i] + (val << 8);
423 		if ((i % 4) == 3) {
424 			*buf++ = val;
425 			val = pad;
426 			num--;
427 		}
428 	}
429 	if (--num >= 0)
430 		*buf++ = val;
431 	while (--num >= 0)
432 		*buf++ = pad;
433 
434 }
435 
436 /**
437  * Return hash value of directory entry
438  * @param name          dentry name
439  * @param len           name lenth
440  * @return              return on success hash value, errno on failure
441  */
f2fs_dentry_hash(const unsigned char * name,int len)442 f2fs_hash_t f2fs_dentry_hash(const unsigned char *name, int len)
443 {
444 	__u32 hash;
445 	f2fs_hash_t	f2fs_hash;
446 	const unsigned char	*p;
447 	__u32 in[8], buf[4];
448 
449 	/* special hash codes for special dentries */
450 	if ((len <= 2) && (name[0] == '.') &&
451 		(name[1] == '.' || name[1] == '\0'))
452 		return 0;
453 
454 	/* Initialize the default seed for the hash checksum functions */
455 	buf[0] = 0x67452301;
456 	buf[1] = 0xefcdab89;
457 	buf[2] = 0x98badcfe;
458 	buf[3] = 0x10325476;
459 
460 	p = name;
461 	while (1) {
462 		str2hashbuf(p, len, in, 4);
463 		TEA_transform(buf, in);
464 		p += 16;
465 		if (len <= 16)
466 			break;
467 		len -= 16;
468 	}
469 	hash = buf[0];
470 
471 	f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
472 	return f2fs_hash;
473 }
474 
addrs_per_inode(struct f2fs_inode * i)475 unsigned int addrs_per_inode(struct f2fs_inode *i)
476 {
477 	return CUR_ADDRS_PER_INODE(i) - get_inline_xattr_addrs(i);
478 }
479 
480 /*
481  * CRC32
482  */
483 #define CRCPOLY_LE 0xedb88320
484 
f2fs_cal_crc32(u_int32_t crc,void * buf,int len)485 u_int32_t f2fs_cal_crc32(u_int32_t crc, void *buf, int len)
486 {
487 	int i;
488 	unsigned char *p = (unsigned char *)buf;
489 	while (len--) {
490 		crc ^= *p++;
491 		for (i = 0; i < 8; i++)
492 			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
493 	}
494 	return crc;
495 }
496 
f2fs_crc_valid(u_int32_t blk_crc,void * buf,int len)497 int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len)
498 {
499 	u_int32_t cal_crc = 0;
500 
501 	cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len);
502 
503 	if (cal_crc != blk_crc)	{
504 		DBG(0,"CRC validation failed: cal_crc = %u, "
505 			"blk_crc = %u buff_size = 0x%x\n",
506 			cal_crc, blk_crc, len);
507 		return -1;
508 	}
509 	return 0;
510 }
511 
f2fs_inode_chksum(struct f2fs_node * node)512 __u32 f2fs_inode_chksum(struct f2fs_node *node)
513 {
514 	struct f2fs_inode *ri = &node->i;
515 	__le32 ino = node->footer.ino;
516 	__le32 gen = ri->i_generation;
517 	__u32 chksum, chksum_seed;
518 	__u32 dummy_cs = 0;
519 	unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum);
520 	unsigned int cs_size = sizeof(dummy_cs);
521 
522 	chksum = f2fs_cal_crc32(c.chksum_seed, (__u8 *)&ino,
523 							sizeof(ino));
524 	chksum_seed = f2fs_cal_crc32(chksum, (__u8 *)&gen, sizeof(gen));
525 
526 	chksum = f2fs_cal_crc32(chksum_seed, (__u8 *)ri, offset);
527 	chksum = f2fs_cal_crc32(chksum, (__u8 *)&dummy_cs, cs_size);
528 	offset += cs_size;
529 	chksum = f2fs_cal_crc32(chksum, (__u8 *)ri + offset,
530 						F2FS_BLKSIZE - offset);
531 	return chksum;
532 }
533 
534 /*
535  * try to identify the root device
536  */
get_rootdev()537 const char *get_rootdev()
538 {
539 #if defined(ANDROID_WINDOWS_HOST) || defined(WITH_ANDROID)
540 	return NULL;
541 #else
542 	struct stat sb;
543 	int fd, ret;
544 	char buf[32];
545 	char *uevent, *ptr;
546 
547 	static char rootdev[PATH_MAX + 1];
548 
549 	if (stat("/", &sb) == -1)
550 		return NULL;
551 
552 	snprintf(buf, 32, "/sys/dev/block/%u:%u/uevent",
553 		major(sb.st_dev), minor(sb.st_dev));
554 
555 	fd = open(buf, O_RDONLY);
556 
557 	if (fd < 0)
558 		return NULL;
559 
560 	ret = lseek(fd, (off_t)0, SEEK_END);
561 	(void)lseek(fd, (off_t)0, SEEK_SET);
562 
563 	if (ret == -1) {
564 		close(fd);
565 		return NULL;
566 	}
567 
568 	uevent = malloc(ret + 1);
569 	uevent[ret] = '\0';
570 
571 	ret = read(fd, uevent, ret);
572 	close(fd);
573 
574 	ptr = strstr(uevent, "DEVNAME");
575 	if (!ptr)
576 		return NULL;
577 
578 	ret = sscanf(ptr, "DEVNAME=%s\n", buf);
579 	snprintf(rootdev, PATH_MAX + 1, "/dev/%s", buf);
580 
581 	return rootdev;
582 #endif
583 }
584 
585 /*
586  * device information
587  */
f2fs_init_configuration(void)588 void f2fs_init_configuration(void)
589 {
590 	int i;
591 
592 	c.ndevs = 1;
593 	c.total_sectors = 0;
594 	c.sector_size = 0;
595 	c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
596 	c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
597 	c.rootdev_name = get_rootdev();
598 	c.wanted_total_sectors = -1;
599 	c.wanted_sector_size = -1;
600 	c.zoned_mode = 0;
601 	c.zoned_model = 0;
602 	c.zone_blocks = 0;
603 #ifdef WITH_ANDROID
604 	c.preserve_limits = 0;
605 #else
606 	c.preserve_limits = 1;
607 #endif
608 
609 	for (i = 0; i < MAX_DEVICES; i++) {
610 		memset(&c.devices[i], 0, sizeof(struct device_info));
611 		c.devices[i].fd = -1;
612 		c.devices[i].sector_size = DEFAULT_SECTOR_SIZE;
613 		c.devices[i].end_blkaddr = -1;
614 		c.devices[i].zoned_model = F2FS_ZONED_NONE;
615 	}
616 
617 	/* calculated by overprovision ratio */
618 	c.reserved_segments = 0;
619 	c.overprovision = 0;
620 	c.segs_per_sec = 1;
621 	c.secs_per_zone = 1;
622 	c.segs_per_zone = 1;
623 	c.heap = 0;
624 	c.vol_label = "";
625 	c.trim = 1;
626 	c.trimmed = 0;
627 	c.ro = 0;
628 	c.kd = -1;
629 	c.dry_run = 0;
630 	c.fixed_time = -1;
631 }
632 
633 #ifdef HAVE_SETMNTENT
is_mounted(const char * mpt,const char * device)634 static int is_mounted(const char *mpt, const char *device)
635 {
636 	FILE *file = NULL;
637 	struct mntent *mnt = NULL;
638 
639 	file = setmntent(mpt, "r");
640 	if (file == NULL)
641 		return 0;
642 
643 	while ((mnt = getmntent(file)) != NULL) {
644 		if (!strcmp(device, mnt->mnt_fsname)) {
645 #ifdef MNTOPT_RO
646 			if (hasmntopt(mnt, MNTOPT_RO))
647 				c.ro = 1;
648 #endif
649 			break;
650 		}
651 	}
652 	endmntent(file);
653 	return mnt ? 1 : 0;
654 }
655 #endif
656 
f2fs_dev_is_umounted(char * path)657 int f2fs_dev_is_umounted(char *path)
658 {
659 #ifdef ANDROID_WINDOWS_HOST
660 	return 0;
661 #else
662 	struct stat *st_buf;
663 	int is_rootdev = 0;
664 	int ret = 0;
665 
666 	if (c.rootdev_name && !strcmp(path, c.rootdev_name))
667 		is_rootdev = 1;
668 
669 	/*
670 	 * try with /proc/mounts fist to detect RDONLY.
671 	 * f2fs_stop_checkpoint makes RO in /proc/mounts while RW in /etc/mtab.
672 	 */
673 #ifdef __linux__
674 	ret = is_mounted("/proc/mounts", path);
675 	if (ret) {
676 		MSG(0, "Info: Mounted device!\n");
677 		return -1;
678 	}
679 #endif
680 #if defined(MOUNTED) || defined(_PATH_MOUNTED)
681 #ifndef MOUNTED
682 #define MOUNTED _PATH_MOUNTED
683 #endif
684 	ret = is_mounted(MOUNTED, path);
685 	if (ret) {
686 		MSG(0, "Info: Mounted device!\n");
687 		return -1;
688 	}
689 #endif
690 	/*
691 	 * If we are supposed to operate on the root device, then
692 	 * also check the mounts for '/dev/root', which sometimes
693 	 * functions as an alias for the root device.
694 	 */
695 	if (is_rootdev) {
696 #ifdef __linux__
697 		ret = is_mounted("/proc/mounts", "/dev/root");
698 		if (ret) {
699 			MSG(0, "Info: Mounted device!\n");
700 			return -1;
701 		}
702 #endif
703 	}
704 
705 	/*
706 	 * If f2fs is umounted with -l, the process can still use
707 	 * the file system. In this case, we should not format.
708 	 */
709 	st_buf = malloc(sizeof(struct stat));
710 	if (stat(path, st_buf) == 0 && S_ISBLK(st_buf->st_mode)) {
711 		int fd = open(path, O_RDONLY | O_EXCL);
712 
713 		if (fd >= 0) {
714 			close(fd);
715 		} else if (errno == EBUSY) {
716 			MSG(0, "\tError: In use by the system!\n");
717 			free(st_buf);
718 			return -1;
719 		}
720 	}
721 	free(st_buf);
722 	return ret;
723 #endif
724 }
725 
f2fs_devs_are_umounted(void)726 int f2fs_devs_are_umounted(void)
727 {
728 	int i;
729 
730 	for (i = 0; i < c.ndevs; i++)
731 		if (f2fs_dev_is_umounted((char *)c.devices[i].path))
732 			return -1;
733 	return 0;
734 }
735 
get_kernel_version(__u8 * version)736 void get_kernel_version(__u8 *version)
737 {
738 	int i;
739 	for (i = 0; i < VERSION_LEN; i++) {
740 		if (version[i] == '\n')
741 			break;
742 	}
743 	memset(version + i, 0, VERSION_LEN + 1 - i);
744 }
745 
get_kernel_uname_version(__u8 * version)746 void get_kernel_uname_version(__u8 *version)
747 {
748 #ifdef HAVE_SYS_UTSNAME_H
749 	struct utsname buf;
750 
751 	memset(version, 0, VERSION_LEN);
752 	if (uname(&buf))
753 		return;
754 
755 	snprintf((char *)version,
756 		VERSION_LEN, "%s %s", buf.release, buf.version);
757 #else
758 	memset(version, 0, VERSION_LEN);
759 #endif
760 }
761 
762 #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
763 #define BLKGETSIZE	_IO(0x12,96)
764 #endif
765 
766 #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
767 #define BLKGETSIZE64	_IOR(0x12,114, size_t)
768 #endif
769 
770 #if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
771 #define BLKSSZGET	_IO(0x12,104)
772 #endif
773 
774 #if defined(__APPLE__)
775 #include <sys/disk.h>
776 #define BLKGETSIZE	DKIOCGETBLOCKCOUNT
777 #define BLKSSZGET	DKIOCGETBLOCKCOUNT
778 #endif /* APPLE_DARWIN */
779 
780 #ifndef ANDROID_WINDOWS_HOST
get_device_info(int i)781 int get_device_info(int i)
782 {
783 	int32_t fd = 0;
784 	uint32_t sector_size;
785 #ifndef BLKGETSIZE64
786 	uint32_t total_sectors;
787 #endif
788 	struct stat *stat_buf;
789 #ifdef HDIO_GETGIO
790 	struct hd_geometry geom;
791 #endif
792 #if !defined(WITH_ANDROID) && defined(__linux__)
793 	sg_io_hdr_t io_hdr;
794 	unsigned char reply_buffer[96] = {0};
795 	unsigned char model_inq[6] = {MODELINQUIRY};
796 #endif
797 	struct device_info *dev = c.devices + i;
798 
799 	if (c.sparse_mode) {
800 		fd = open((char *)dev->path, O_RDWR | O_CREAT | O_BINARY, 0644);
801 	} else {
802 		fd = open((char *)dev->path, O_RDWR);
803 	}
804 	if (fd < 0) {
805 		MSG(0, "\tError: Failed to open the device!\n");
806 		return -1;
807 	}
808 
809 	dev->fd = fd;
810 
811 	if (c.sparse_mode) {
812 		if (f2fs_init_sparse_file())
813 			return -1;
814 	}
815 
816 	if (c.kd == -1) {
817 #if !defined(WITH_ANDROID) && defined(__linux__)
818 		c.kd = open("/proc/version", O_RDONLY);
819 #endif
820 		if (c.kd < 0) {
821 			MSG(0, "\tInfo: No support kernel version!\n");
822 			c.kd = -2;
823 		}
824 	}
825 
826 	stat_buf = malloc(sizeof(struct stat));
827 	if (fstat(fd, stat_buf) < 0 ) {
828 		MSG(0, "\tError: Failed to get the device stat!\n");
829 		free(stat_buf);
830 		return -1;
831 	}
832 
833 	if (c.sparse_mode) {
834 		dev->total_sectors = c.device_size / dev->sector_size;
835 	} else if (S_ISREG(stat_buf->st_mode)) {
836 		dev->total_sectors = stat_buf->st_size / dev->sector_size;
837 	} else if (S_ISBLK(stat_buf->st_mode)) {
838 #ifdef BLKSSZGET
839 		if (ioctl(fd, BLKSSZGET, &sector_size) < 0)
840 			MSG(0, "\tError: Using the default sector size\n");
841 		else if (dev->sector_size < sector_size)
842 			dev->sector_size = sector_size;
843 #endif
844 #ifdef BLKGETSIZE64
845 		if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
846 			MSG(0, "\tError: Cannot get the device size\n");
847 			free(stat_buf);
848 			return -1;
849 		}
850 #else
851 		if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
852 			MSG(0, "\tError: Cannot get the device size\n");
853 			free(stat_buf);
854 			return -1;
855 		}
856 		dev->total_sectors = total_sectors;
857 #endif
858 		dev->total_sectors /= dev->sector_size;
859 
860 		if (i == 0) {
861 #ifdef HDIO_GETGIO
862 			if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
863 				c.start_sector = 0;
864 			else
865 				c.start_sector = geom.start;
866 #else
867 			c.start_sector = 0;
868 #endif
869 		}
870 
871 #if !defined(WITH_ANDROID) && defined(__linux__)
872 		/* Send INQUIRY command */
873 		memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
874 		io_hdr.interface_id = 'S';
875 		io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
876 		io_hdr.dxfer_len = sizeof(reply_buffer);
877 		io_hdr.dxferp = reply_buffer;
878 		io_hdr.cmd_len = sizeof(model_inq);
879 		io_hdr.cmdp = model_inq;
880 		io_hdr.timeout = 1000;
881 
882 		if (!ioctl(fd, SG_IO, &io_hdr)) {
883 			int i = 16;
884 
885 			MSG(0, "Info: [%s] Disk Model: ",
886 					dev->path);
887 			while (reply_buffer[i] != '`' && i < 80)
888 				printf("%c", reply_buffer[i++]);
889 			printf("\n");
890 		}
891 #endif
892 	} else {
893 		MSG(0, "\tError: Volume type is not supported!!!\n");
894 		free(stat_buf);
895 		return -1;
896 	}
897 
898 	if (!c.sector_size) {
899 		c.sector_size = dev->sector_size;
900 		c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
901 	} else if (c.sector_size != c.devices[i].sector_size) {
902 		MSG(0, "\tError: Different sector sizes!!!\n");
903 		free(stat_buf);
904 		return -1;
905 	}
906 
907 #if !defined(WITH_ANDROID) && defined(__linux__)
908 	if (S_ISBLK(stat_buf->st_mode))
909 		f2fs_get_zoned_model(i);
910 
911 	if (dev->zoned_model != F2FS_ZONED_NONE) {
912 		if (dev->zoned_model == F2FS_ZONED_HM)
913 			c.zoned_model = F2FS_ZONED_HM;
914 
915 		if (f2fs_get_zone_blocks(i)) {
916 			MSG(0, "\tError: Failed to get number of blocks per zone\n");
917 			free(stat_buf);
918 			return -1;
919 		}
920 
921 		if (f2fs_check_zones(i)) {
922 			MSG(0, "\tError: Failed to check zone configuration\n");
923 			free(stat_buf);
924 			return -1;
925 		}
926 		MSG(0, "Info: Host-%s zoned block device:\n",
927 				(dev->zoned_model == F2FS_ZONED_HA) ?
928 					"aware" : "managed");
929 		MSG(0, "      %u zones, %u randomly writeable zones\n",
930 				dev->nr_zones, dev->nr_rnd_zones);
931 		MSG(0, "      %lu blocks per zone\n",
932 				dev->zone_blocks);
933 	}
934 #endif
935 	/* adjust wanted_total_sectors */
936 	if (c.wanted_total_sectors != -1) {
937 		MSG(0, "Info: wanted sectors = %"PRIu64" (in %"PRIu64" bytes)\n",
938 				c.wanted_total_sectors, c.wanted_sector_size);
939 		if (c.wanted_sector_size == -1) {
940 			c.wanted_sector_size = dev->sector_size;
941 		} else if (dev->sector_size != c.wanted_sector_size) {
942 			c.wanted_total_sectors *= c.wanted_sector_size;
943 			c.wanted_total_sectors /= dev->sector_size;
944 		}
945 	}
946 
947 	c.total_sectors += dev->total_sectors;
948 	free(stat_buf);
949 	return 0;
950 }
951 
952 #else
953 
954 #include "windows.h"
955 #include "winioctl.h"
956 
957 #if (_WIN32_WINNT >= 0x0500)
958 #define HAVE_GET_FILE_SIZE_EX 1
959 #endif
960 
win_get_device_size(const char * file,uint64_t * device_size)961 static int win_get_device_size(const char *file, uint64_t *device_size)
962 {
963 	HANDLE dev;
964 	PARTITION_INFORMATION pi;
965 	DISK_GEOMETRY gi;
966 	DWORD retbytes;
967 #ifdef HAVE_GET_FILE_SIZE_EX
968 	LARGE_INTEGER filesize;
969 #else
970 	DWORD filesize;
971 #endif /* HAVE_GET_FILE_SIZE_EX */
972 
973 	dev = CreateFile(file, GENERIC_READ,
974 			FILE_SHARE_READ | FILE_SHARE_WRITE ,
975 			NULL,  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,  NULL);
976 
977 	if (dev == INVALID_HANDLE_VALUE)
978 		return EBADF;
979 	if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
980 				&pi, sizeof(PARTITION_INFORMATION),
981 				&pi, sizeof(PARTITION_INFORMATION),
982 				&retbytes, NULL)) {
983 
984 		*device_size = 	pi.PartitionLength.QuadPart;
985 
986 	} else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
987 				&gi, sizeof(DISK_GEOMETRY),
988 				&gi, sizeof(DISK_GEOMETRY),
989 				&retbytes, NULL)) {
990 
991 		*device_size = gi.BytesPerSector *
992 			gi.SectorsPerTrack *
993 			gi.TracksPerCylinder *
994 			gi.Cylinders.QuadPart;
995 
996 #ifdef HAVE_GET_FILE_SIZE_EX
997 	} else if (GetFileSizeEx(dev, &filesize)) {
998 		*device_size = filesize.QuadPart;
999 	}
1000 #else
1001 	} else {
1002 		filesize = GetFileSize(dev, NULL);
1003 		if (INVALID_FILE_SIZE != filesize)
1004 			return -1;
1005 		*device_size = filesize;
1006 	}
1007 #endif /* HAVE_GET_FILE_SIZE_EX */
1008 
1009 	CloseHandle(dev);
1010 	return 0;
1011 }
1012 
get_device_info(int i)1013 int get_device_info(int i)
1014 {
1015 	struct device_info *dev = c.devices + i;
1016 	uint64_t device_size = 0;
1017 	int32_t fd = 0;
1018 
1019 	/* Block device target is not supported on Windows. */
1020 	if (!c.sparse_mode) {
1021 		if (win_get_device_size(dev->path, &device_size)) {
1022 			MSG(0, "\tError: Failed to get device size!\n");
1023 			return -1;
1024 		}
1025 	} else {
1026 		device_size = c.device_size;
1027 	}
1028 	if (c.sparse_mode) {
1029 		fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1030 	} else {
1031 		fd = open((char *)dev->path, O_RDWR | O_BINARY);
1032 	}
1033 	if (fd < 0) {
1034 		MSG(0, "\tError: Failed to open the device!\n");
1035 		return -1;
1036 	}
1037 	dev->fd = fd;
1038 	dev->total_sectors = device_size / dev->sector_size;
1039 	c.start_sector = 0;
1040 	c.sector_size = dev->sector_size;
1041 	c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1042 	c.total_sectors += dev->total_sectors;
1043 
1044 	return 0;
1045 }
1046 #endif
1047 
f2fs_get_device_info(void)1048 int f2fs_get_device_info(void)
1049 {
1050 	int i;
1051 
1052 	for (i = 0; i < c.ndevs; i++)
1053 		if (get_device_info(i))
1054 			return -1;
1055 
1056 	if (c.wanted_total_sectors < c.total_sectors) {
1057 		MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
1058 				c.total_sectors, c.sector_size);
1059 		c.total_sectors = c.wanted_total_sectors;
1060 		c.devices[0].total_sectors = c.total_sectors;
1061 	}
1062 	if (c.total_sectors * c.sector_size >
1063 		(u_int64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) {
1064 		MSG(0, "\tError: F2FS can support 16TB at most!!!\n");
1065 		return -1;
1066 	}
1067 
1068 	for (i = 0; i < c.ndevs; i++) {
1069 		if (c.devices[i].zoned_model != F2FS_ZONED_NONE) {
1070 			if (c.zone_blocks &&
1071 				c.zone_blocks != c.devices[i].zone_blocks) {
1072 				MSG(0, "\tError: not support different zone sizes!!!\n");
1073 				return -1;
1074 			}
1075 			c.zone_blocks = c.devices[i].zone_blocks;
1076 		}
1077 	}
1078 
1079 	/*
1080 	 * Align sections to the device zone size
1081 	 * and align F2FS zones to the device zones.
1082 	 */
1083 	if (c.zone_blocks) {
1084 		c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT;
1085 		c.secs_per_zone = 1;
1086 	} else {
1087 		c.zoned_mode = 0;
1088 	}
1089 
1090 	c.segs_per_zone = c.segs_per_sec * c.secs_per_zone;
1091 
1092 	MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec);
1093 	MSG(0, "Info: Sections per zone = %d\n", c.secs_per_zone);
1094 	MSG(0, "Info: sector size = %u\n", c.sector_size);
1095 	MSG(0, "Info: total sectors = %"PRIu64" (%"PRIu64" MB)\n",
1096 				c.total_sectors, (c.total_sectors *
1097 					(c.sector_size >> 9)) >> 11);
1098 	return 0;
1099 }
1100