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, §or_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