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