⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libubi.c

📁 mtd-utils 是一套更改linux mtd設備的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) International Business Machines Corp., 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Artem Bityutskiy * * UBI (Unsorted Block Images) library. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <fcntl.h>#include <sys/stat.h>#include <sys/types.h>#include <dirent.h>#include <unistd.h>#include <sys/ioctl.h>#include <limits.h>#include "libubi.h"#include "libubi_int.h"#include "common.h"#define PROGRAM_NAME "libubi"/** * mkpath - compose full path from 2 given components. * @path: the first component * @name: the second component * * This function returns the resulting path in case of success and %NULL in * case of failure. */static char *mkpath(const char *path, const char *name){	char *n;	int len1 = strlen(path);	int len2 = strlen(name);	n = malloc(len1 + len2 + 2);	if (!n) {		sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);		return NULL;	}	memcpy(n, path, len1);	if (n[len1 - 1] != '/')		n[len1++] = '/';	memcpy(n + len1, name, len2 + 1);	return n;}/** * read_positive_ll - read a positive 'long long' value from a file. * @file: the file to read from * @value: the result is stored here * * This function reads file @file and interprets its contents as a positive * 'long long' integer. If this is not true, it fails with %EINVAL error code. * Returns %0 in case of success and %-1 in case of failure. */static int read_positive_ll(const char *file, long long *value){	int fd, rd;	char buf[50];	fd = open(file, O_RDONLY);	if (fd == -1)		return -1;	rd = read(fd, buf, 50);	if (rd == -1) {		sys_errmsg("cannot read \"%s\"", file);		goto out_error;	}	if (rd == 50) {		errmsg("contents of \"%s\" is too long", file);		errno = EINVAL;		goto out_error;	}	if (sscanf(buf, "%lld\n", value) != 1) {		/* This must be a UBI bug */		errmsg("cannot read integer from \"%s\"\n", file);		errno = EINVAL;		goto out_error;	}	if (*value < 0) {		errmsg("negative value %lld in \"%s\"", *value, file);		errno = EINVAL;		goto out_error;	}	if (close(fd))		return sys_errmsg("close failed on \"%s\"", file);	return 0;out_error:	close(fd);	return -1;}/** * read_positive_int - read a positive 'int' value from a file. * @file: the file to read from * @value: the result is stored here * * This function is the same as 'read_positive_ll()', but it reads an 'int' * value, not 'long long'. */static int read_positive_int(const char *file, int *value){	long long res;	if (read_positive_ll(file, &res))		return -1;	/* Make sure the value is not too big */	if (res > INT_MAX) {		errmsg("value %lld read from file \"%s\" is out of range",		       res, file);		errno = EINVAL;		return -1;	}	*value = res;	return 0;}/** * read_data - read data from a file. * @file: the file to read from * @buf: the buffer to read to * @buf_len: buffer length * * This function returns number of read bytes in case of success and %-1 in * case of failure. Note, if the file contains more then @buf_len bytes of * date, this function fails with %EINVAL error code. */static int read_data(const char *file, void *buf, int buf_len){	int fd, rd, tmp, tmp1;	fd = open(file, O_RDONLY);	if (fd == -1)		return -1;	rd = read(fd, buf, buf_len);	if (rd == -1) {		sys_errmsg("cannot read \"%s\"", file);		goto out_error;	}	/* Make sure all data is read */	tmp1 = read(fd, &tmp, 1);	if (tmp1 == 1) {		sys_errmsg("cannot read \"%s\"", file);		goto out_error;	}	if (tmp1) {		errmsg("file \"%s\" contains too much data (> %d bytes)",		       file, buf_len);		errno = EINVAL;		goto out_error;	}	if (close(fd)) {		sys_errmsg("close failed on \"%s\"", file);		return -1;	}	return rd;out_error:	close(fd);	return -1;}/** * read_major - read major and minor numbers from a file. * @file: name of the file to read from * @major: major number is returned here * @minor: minor number is returned here * * This function returns % in case of succes, and %-1 in case of failure. */static int read_major(const char *file, int *major, int *minor){	int ret;	char buf[50];	ret = read_data(file, buf, 50);	if (ret < 0)		return ret;	ret = sscanf(buf, "%d:%d\n", major, minor);	if (ret != 2) {		errno = EINVAL;		return errmsg("\"%s\" does not have major:minor format", file);	}	if (*major < 0 || *minor < 0) {		errno = EINVAL;		return errmsg("bad major:minor %d:%d in \"%s\"",			      *major, *minor, file);	}	return 0;}/** * dev_read_int - read a positive 'int' value from an UBI device sysfs file. * @patt: file pattern to read from * @dev_num:  UBI device number * @value: the result is stored here * * This function returns %0 in case of success and %-1 in case of failure. */static int dev_read_int(const char *patt, int dev_num, int *value){	char file[strlen(patt) + 50];	sprintf(file, patt, dev_num);	return read_positive_int(file, value);}/** * vol_read_int - read a positive 'int' value from an UBI volume sysfs file. * @patt: file pattern to read from * @dev_num: UBI device number * @vol_id: volume ID * @value: the result is stored here * * This function returns %0 in case of success and %-1 in case of failure. */static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value){	char file[strlen(patt) + 100];	sprintf(file, patt, dev_num, vol_id);	return read_positive_int(file, value);}/** * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file. * @patt: file pattern to read from * @dev_num: UBI device number * @value: the result is stored here * * This function returns %0 in case of success and %-1 in case of failure. */static int dev_read_ll(const char *patt, int dev_num, long long *value){	char file[strlen(patt) + 50];	sprintf(file, patt, dev_num);	return read_positive_ll(file, value);}/** * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file. * @patt: file pattern to read from * @dev_num: UBI device number * @vol_id: volume ID * @value: the result is stored here * * This function returns %0 in case of success and %-1 in case of failure. */static int vol_read_ll(const char *patt, int dev_num, int vol_id,		       long long *value){	char file[strlen(patt) + 100];	sprintf(file, patt, dev_num, vol_id);	return read_positive_ll(file, value);}/** * vol_read_data - read data from an UBI volume's sysfs file. * @patt: file pattern to read from * @dev_num: UBI device number * @vol_id: volume ID * @buf: buffer to read to * @buf_len: buffer length * * This function returns number of read bytes in case of success and %-1 in * case of failure. */static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,			 int buf_len){	char file[strlen(patt) + 100];	sprintf(file, patt, dev_num, vol_id);	return read_data(file, buf, buf_len);}/** * dev_get_major - get major and minor numbers of an UBI device. * @lib: libubi descriptor * @dev_num: UBI device number * @major: major number is returned here * @minor: minor number is returned here * * This function returns zero in case of succes and %-1 in case of failure. */static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor){	char file[strlen(lib->dev_dev) + 50];	sprintf(file, lib->dev_dev, dev_num);	return read_major(file, major, minor);}/** * vol_get_major - get major and minor numbers of an UBI volume. * @lib: libubi descriptor * @dev_num: UBI device number * @vol_id: volume ID * @major: major number is returned here * @minor: minor number is returned here * * This function returns zero in case of succes and %-1 in case of failure. */static int vol_get_major(struct libubi *lib, int dev_num, int vol_id,			 int *major, int *minor){	char file[strlen(lib->vol_dev) + 100];	sprintf(file, lib->vol_dev, dev_num, vol_id);	return read_major(file, major, minor);}/** * vol_node2nums - find UBI device number and volume ID by volume device node *                 file. * @lib: UBI library descriptor * @node: UBI character device node name * @dev_num: UBI device number is returned here * @vol_id: volume ID is returned hers * * This function returns zero in case of succes and %-1 in case of failure. */static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,			 int *vol_id){	struct stat st;	struct ubi_info info;	int i, fd, major, minor;	char file[strlen(lib->ubi_vol) + 100];	if (stat(node, &st))		return -1;	if (!S_ISCHR(st.st_mode)) {		errno = EINVAL;		return errmsg("\"%s\" is not a character device", node);	}	major = major(st.st_rdev);	minor = minor(st.st_rdev);	if (minor == 0) {		errno = EINVAL;		return errmsg("\"%s\" is not a volume character device", node);	}	if (ubi_get_info((libubi_t *)lib, &info))		return -1;	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {		int major1, minor1, ret;		ret = dev_get_major(lib, i, &major1, &minor1);		if (ret) {			if (errno == ENOENT)				continue;			return -1;		}		if (major1 == major)			break;	}	if (i > info.highest_dev_num) {		errno = ENODEV;		return -1;	}	/* Make sure this UBI volume exists */	sprintf(file, lib->ubi_vol, i, minor - 1);	fd = open(file, O_RDONLY);	if (fd == -1) {		errno = ENODEV;		return -1;	}	*dev_num = i;	*vol_id = minor - 1;	errno = 0;	return 0;}/** * dev_node2num - find UBI device number by its character device node. * @lib: UBI library descriptor * @node: UBI character device node name * * This function returns positive UBI device number in case of success and %-1 * in case of failure. */static int dev_node2num(struct libubi *lib, const char *node, int *dev_num){	struct stat st;	struct ubi_info info;	int i, major, minor;	if (stat(node, &st))		return -1;	if (!S_ISCHR(st.st_mode)) {		errno = EINVAL;		return errmsg("\"%s\" is not a character device", node);	}	major = major(st.st_rdev);	minor = minor(st.st_rdev);	if (minor != 0) {		errno = EINVAL;		return errmsg("\"%s\" is not an UBI character device", node);	}	if (ubi_get_info((libubi_t *)lib, &info))		return -1;	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {		int major1, minor1, ret;		ret = dev_get_major(lib, i, &major1, &minor1);		if (ret) {			if (errno == ENOENT)				continue;			return -1;		}		if (major1 == major) {			if (minor1 != 0) {				errmsg("UBI character device minor number is "				       "%d, but must be 0", minor1);				errno = EINVAL;				return -1;			}			errno = 0;			*dev_num = i;			return 0;		}	}	errno = ENODEV;	return -1;}int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num){	struct ubi_info info;	int i, ret, mtd_num1;	struct libubi *lib = desc;	if (ubi_get_info(desc, &info))		return -1;	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {		ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1);		if (ret) {			if (errno == ENOENT)				continue;			return -1;		}		if (mtd_num1 == mtd_num) {			errno = 0;			*dev_num = i;			return 0;		}	}	errno = 0;	return -1;}libubi_t libubi_open(int required){	int fd, version;	struct libubi *lib;	lib = calloc(1, sizeof(struct libubi));	if (!lib)		return NULL;	/* TODO: this must be discovered instead */	lib->sysfs = strdup("/sys");	if (!lib->sysfs)		goto out_error;	lib->sysfs_ctrl = mkpath(lib->sysfs, SYSFS_CTRL);	if (!lib->sysfs_ctrl)		goto out_error;	lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV);	if (!lib->ctrl_dev)		goto out_error;	lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI);	if (!lib->sysfs_ubi)		goto out_error;	/* Make sure UBI is present */	fd = open(lib->sysfs_ubi, O_RDONLY);	if (fd == -1) {		if (required)			errmsg("cannot open \"%s\", UBI does not seem to "			       "exist in system", lib->sysfs_ubi);		goto out_error;	}	if (close(fd)) {		sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi);		goto out_error;	}	lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);	if (!lib->ubi_dev)		goto out_error;	lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);	if (!lib->ubi_version)		goto out_error;	lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);	if (!lib->dev_dev)		goto out_error;	lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);	if (!lib->dev_avail_ebs)		goto out_error;	lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);	if (!lib->dev_total_ebs)		goto out_error;	lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);	if (!lib->dev_bad_count)		goto out_error;	lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);	if (!lib->dev_eb_size)		goto out_error;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -