diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-01-25 17:20:16 +0900 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-04-04 09:19:07 +0900 |
commit | e69e4378500b836863dfb7f6e88e39935f23ae80 (patch) | |
tree | 20bb677b7d41c7e6b95379dd0c1f7552f962257e /lib | |
parent | 2784bd55dd9730f3a5d2126c82094990fad053c1 (diff) | |
download | android_external_f2fs-tools-e69e4378500b836863dfb7f6e88e39935f23ae80.tar.gz android_external_f2fs-tools-e69e4378500b836863dfb7f6e88e39935f23ae80.tar.bz2 android_external_f2fs-tools-e69e4378500b836863dfb7f6e88e39935f23ae80.zip |
build: make several base functions as a library
Let's make a library and relocate functions for other tools like fsck.f2fs.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 7 | ||||
-rw-r--r-- | lib/libf2fs.c | 247 |
2 files changed, 254 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..6498df9 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,7 @@ +## Makefile.am + +lib_LTLIBRARIES = libf2fs.la + +libf2fs_la_SOURCES = libf2fs.c +libf2fs_la_CFLAGS = -Wall +libf2fs_la_CPPFLAGS = -I$(top_srcdir)/include diff --git a/lib/libf2fs.c b/lib/libf2fs.c new file mode 100644 index 0000000..d3b140f --- /dev/null +++ b/lib/libf2fs.c @@ -0,0 +1,247 @@ +/** + * libf2fs.c + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define _LARGEFILE64_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <mntent.h> +#include <time.h> +#include <sys/stat.h> +#include <sys/mount.h> +#include <sys/ioctl.h> +#include <linux/hdreg.h> +#include <linux/fs.h> + +#include "f2fs_fs.h" + +struct f2fs_configuration config; + +void ASCIIToUNICODE(u_int16_t *out_buf, u_int8_t *in_buf) +{ + u_int8_t *pchTempPtr = in_buf; + u_int16_t *pwTempPtr = out_buf; + + while (*pchTempPtr != '\0') { + *pwTempPtr = (u_int16_t)*pchTempPtr; + pchTempPtr++; + pwTempPtr++; + } + *pwTempPtr = '\0'; + return; +} + +int log_base_2(u_int32_t num) +{ + int ret = 0; + if (num <= 0 || (num & (num - 1)) != 0) + return -1; + + while (num >>= 1) + ret++; + return ret; +} + +/* + * f2fs bit operations + */ +int f2fs_test_bit(unsigned int nr, const char *p) +{ + int mask; + char *addr = (char *)p; + + addr += (nr >> 3); + mask = 1 << (7 - (nr & 0x07)); + return (mask & *addr) != 0; +} + +int f2fs_set_bit(unsigned int nr, unsigned char *addr) +{ + int mask; + int ret; + + addr += (nr >> 3); + mask = 1 << (7 - (nr & 0x07)); + ret = mask & *addr; + *addr |= mask; + return ret; +} + +int f2fs_clear_bit(unsigned int nr, char *addr) +{ + int mask; + int ret; + + addr += (nr >> 3); + mask = 1 << (7 - (nr & 0x07)); + ret = mask & *addr; + *addr &= ~mask; + return ret; +} + +/* + * CRC32 + */ +#define CRCPOLY_LE 0xedb88320 + +u_int32_t f2fs_cal_crc32(u_int32_t crc, void *buf, int len) +{ + int i; + unsigned char *p = (unsigned char *)buf; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + } + return crc; +} + +/* + * device information + */ +void f2fs_init_configuration(struct f2fs_configuration *c) +{ + c->sector_size = DEFAULT_SECTOR_SIZE; + c->sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK; + c->blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT; + + /* calculated by overprovision ratio */ + c->reserved_segments = 48; + c->overprovision = 5; + c->segs_per_sec = 1; + c->secs_per_zone = 1; + c->heap = 1; + memset(c->vol_label, 0, sizeof(c->vol_label)); + + c->vol_label[0] = 'F'; + c->vol_label[1] = '2'; + c->vol_label[2] = 'F'; + c->vol_label[3] = 'S'; + c->vol_label[4] = '\0'; + c->device_name = NULL; +} + +int f2fs_dev_is_mounted(struct f2fs_configuration *c) +{ + FILE *file = NULL; + struct mntent *mnt = NULL; + + file = setmntent(MOUNTED, "r"); + if (file == NULL) + return 0; + + while (1) { + mnt = getmntent(file); + if (mnt == NULL) + break; + if (!strcmp(c->device_name, mnt->mnt_fsname)) { + endmntent(file); + return -1; + } + } + endmntent(file); + return 0; +} + +int f2fs_get_device_info(struct f2fs_configuration *c) +{ + int32_t fd = 0; + int32_t sector_size; + struct stat stat_buf; + struct hd_geometry geom; + + fd = open(c->device_name, O_RDWR); + if (fd < 0) { + MSG(0, "\tError: Failed to open the device!\n"); + return -1; + } + c->fd = fd; + + if (fstat(fd, &stat_buf) < 0 ) { + MSG(0, "\tError: Failed to get the device stat!\n"); + return -1; + } + + if (S_ISREG(stat_buf.st_mode)) { + c->total_sectors = stat_buf.st_size / c->sector_size; + } else if (S_ISBLK(stat_buf.st_mode)) { + if (ioctl(fd, BLKSSZGET, §or_size) < 0) { + MSG(0, "\tError: Using the default sector size\n"); + } else { + if (c->sector_size < sector_size) { + MSG(0, "\tError: Cannot set the sector size to:" + " %d as the device does not support" + "\nSetting the sector size to : %d\n", + c->sector_size, sector_size); + c->sector_size = sector_size; + c->sectors_per_blk = PAGE_SIZE / sector_size; + } + } + + if (ioctl(fd, BLKGETSIZE, &c->total_sectors) < 0) { + MSG(0, "\tError: Cannot get the device size\n"); + return -1; + } + + if (ioctl(fd, HDIO_GETGEO, &geom) < 0) + c->start_sector = 0; + else + c->start_sector = geom.start; + } else { + MSG(0, "\tError: Volume type is not supported!!!\n"); + return -1; + } + + MSG(0, "Info: sector size = %u\n", c->sector_size); + MSG(0, "Info: total sectors = %"PRIu64" (in 512bytes)\n", + c->total_sectors); + if (c->total_sectors < + (F2FS_MIN_VOLUME_SIZE / DEFAULT_SECTOR_SIZE)) { + MSG(0, "Error: Min volume size supported is %d\n", + F2FS_MIN_VOLUME_SIZE); + return -1; + } + + return 0; +} + +/* + * IO interfaces + */ +int dev_read(int fd, void *buf, __u64 offset, size_t len) +{ + if (lseek64(fd, (off64_t)offset, SEEK_SET) < 0) + return -1; + if (read(fd, buf, len) < 0) + return -1; + return 0; +} + +int dev_write(int fd, void *buf, __u64 offset, size_t len) +{ + if (lseek64(fd, (off64_t)offset, SEEK_SET) < 0) + return -1; + if (write(fd, buf, len) < 0) + return -1; + return 0; +} + +int dev_read_block(int fd, void *buf, __u64 blk_addr) +{ + return dev_read(fd, buf, blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE); +} + +int dev_read_blocks(int fd, void *buf, __u64 addr, __u32 nr_blks) +{ + return dev_read(fd, buf, addr * F2FS_BLKSIZE, nr_blks * F2FS_BLKSIZE); +} |