📄 libubi.c
字号:
lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC); if (!lib->dev_max_ec) goto out_error; lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD); if (!lib->dev_bad_rsvd) goto out_error; lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS); if (!lib->dev_max_vols) goto out_error; lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE); if (!lib->dev_min_io_size) goto out_error; lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM); if (!lib->dev_mtd_num) goto out_error; lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT); if (!lib->ubi_vol) goto out_error; lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE); if (!lib->vol_type) goto out_error; lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV); if (!lib->vol_dev) goto out_error; lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT); if (!lib->vol_alignment) goto out_error; lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES); if (!lib->vol_data_bytes) goto out_error; lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS); if (!lib->vol_rsvd_ebs) goto out_error; lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE); if (!lib->vol_eb_size) goto out_error; lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED); if (!lib->vol_corrupted) goto out_error; lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME); if (!lib->vol_name) goto out_error; if (read_positive_int(lib->ubi_version, &version)) goto out_error; if (version != LIBUBI_UBI_VERSION) { errmsg("this library was made for UBI version %d, but UBI " "version %d is detected\n", LIBUBI_UBI_VERSION, version); goto out_error; } return lib;out_error: libubi_close((libubi_t)lib); return NULL;}void libubi_close(libubi_t desc){ struct libubi *lib = (struct libubi *)desc; free(lib->vol_name); free(lib->vol_corrupted); free(lib->vol_eb_size); free(lib->vol_rsvd_ebs); free(lib->vol_data_bytes); free(lib->vol_alignment); free(lib->vol_dev); free(lib->vol_type); free(lib->ubi_vol); free(lib->dev_mtd_num); free(lib->dev_min_io_size); free(lib->dev_max_vols); free(lib->dev_bad_rsvd); free(lib->dev_max_ec); free(lib->dev_eb_size); free(lib->dev_bad_count); free(lib->dev_total_ebs); free(lib->dev_avail_ebs); free(lib->dev_dev); free(lib->ubi_version); free(lib->ubi_dev); free(lib->sysfs_ubi); free(lib->ctrl_dev); free(lib->sysfs_ctrl); free(lib->sysfs); free(lib);}int ubi_attach_mtd(libubi_t desc, const char *node, struct ubi_attach_request *req){ int fd, ret; struct ubi_attach_req r; memset(&r, sizeof(struct ubi_attach_req), '\0'); desc = desc; r.ubi_num = req->dev_num; r.mtd_num = req->mtd_num; r.vid_hdr_offset = req->vid_hdr_offset; fd = open(node, O_RDONLY); if (fd == -1) return -1; ret = ioctl(fd, UBI_IOCATT, &r); close(fd); if (ret == -1) return -1; req->dev_num = r.ubi_num;#ifdef UDEV_SETTLE_HACK if (system("udevsettle") == -1) return -1; if (system("udevsettle") == -1) return -1;#endif return ret;}int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num){ int ret, ubi_dev; ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev); if (ret == -1) { errno = ENODEV; return ret; } return ubi_remove_dev(desc, node, ubi_dev);}int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev){ int fd, ret; desc = desc; fd = open(node, O_RDONLY); if (fd == -1) return -1; ret = ioctl(fd, UBI_IOCDET, &ubi_dev); if (ret == -1) goto out_close;#ifdef UDEV_SETTLE_HACK if (system("udevsettle") == -1) return -1;#endifout_close: close(fd); return ret;}int ubi_node_type(libubi_t desc, const char *node){ struct stat st; struct ubi_info info; int i, fd, major, minor; struct libubi *lib = (struct libubi *)desc; char file[strlen(lib->ubi_vol) + 100]; if (stat(node, &st)) return -1; if (!S_ISCHR(st.st_mode)) { errno = EINVAL; return -1; } major = major(st.st_rdev); minor = minor(st.st_rdev); 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) { /* * The character device node does not correspond to any * existing UBI device or volume, but we do not want to return * any error number in this case, to indicate the fact that it * could be a UBI device/volume, but it doesn't. */ errno = 0; return -1; } if (minor == 0) return 1; /* This is supposdely an UBI volume device node */ sprintf(file, lib->ubi_vol, i, minor - 1); fd = open(file, O_RDONLY); if (fd == -1) { errno = 0; return -1; } return 2;}int ubi_get_info(libubi_t desc, struct ubi_info *info){ DIR *sysfs_ubi; struct dirent *dirent; struct libubi *lib = (struct libubi *)desc; memset(info, '\0', sizeof(struct ubi_info)); if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) { /* * Older UBI versions did not have control device, so we do not * panic here for compatibility reasons. May be few years later * we could return -1 here, but for now just set major:minor to * -1. */ info->ctrl_major = info->ctrl_minor = -1; } /* * We have to scan the UBI sysfs directory to identify how many UBI * devices are present. */ sysfs_ubi = opendir(lib->sysfs_ubi); if (!sysfs_ubi) return sys_errmsg("cannot open %s", lib->sysfs_ubi); info->lowest_dev_num = INT_MAX; while (1) { int dev_num, ret; char tmp_buf[256]; errno = 0; dirent = readdir(sysfs_ubi); if (!dirent) break; if (strlen(dirent->d_name) > 256) { errmsg("invalid entry in %s: \"%s\"", lib->sysfs_ubi, dirent->d_name); goto out_close; } ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s", &dev_num, tmp_buf); if (ret == 1) { info->dev_count += 1; if (dev_num > info->highest_dev_num) info->highest_dev_num = dev_num; if (dev_num < info->lowest_dev_num) info->lowest_dev_num = dev_num; } } if (!dirent && errno) { sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); goto out_close; } if (closedir(sysfs_ubi)) return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); if (info->lowest_dev_num == INT_MAX) info->lowest_dev_num = 0; if (read_positive_int(lib->ubi_version, &info->version)) return -1; return 0;out_close: closedir(sysfs_ubi); return -1;}int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req){ int fd, ret; struct ubi_mkvol_req r; size_t n; memset(&r, sizeof(struct ubi_mkvol_req), '\0'); desc = desc; r.vol_id = req->vol_id; r.alignment = req->alignment; r.bytes = req->bytes; r.vol_type = req->vol_type; n = strlen(req->name); if (n > UBI_MAX_VOLUME_NAME) return -1; strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1); r.name_len = n; fd = open(node, O_RDONLY); if (fd == -1) return -1; ret = ioctl(fd, UBI_IOCMKVOL, &r); if (ret == -1) goto out_close; req->vol_id = r.vol_id;#ifdef UDEV_SETTLE_HACK if (system("udevsettle") == -1) return -1;#endifout_close: close(fd); return ret;}int ubi_rmvol(libubi_t desc, const char *node, int vol_id){ int fd, ret; desc = desc; fd = open(node, O_RDONLY); if (fd == -1) return -1; ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); if (ret == -1) goto out_close;#ifdef UDEV_SETTLE_HACK if (system("udevsettle") == -1) return -1;#endifout_close: close(fd); return ret;}int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes){ int fd, ret; struct ubi_rsvol_req req; desc = desc; fd = open(node, O_RDONLY); if (fd == -1) return -1; req.bytes = bytes; req.vol_id = vol_id; ret = ioctl(fd, UBI_IOCRSVOL, &req); close(fd); return ret;}int ubi_update_start(libubi_t desc, int fd, long long bytes){ desc = desc; if (ioctl(fd, UBI_IOCVOLUP, &bytes)) return -1; return 0;}int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype){ struct ubi_leb_change_req req; desc = desc; memset(&req, 0, sizeof(struct ubi_leb_change_req)); req.lnum = lnum; req.bytes = bytes; req.dtype = dtype; if (ioctl(fd, UBI_IOCEBCH, &req)) return -1; return 0;}int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info){ DIR *sysfs_ubi; struct dirent *dirent; struct libubi *lib = (struct libubi *)desc; memset(info, '\0', sizeof(struct ubi_dev_info)); info->dev_num = dev_num; sysfs_ubi = opendir(lib->sysfs_ubi); if (!sysfs_ubi) return -1; info->lowest_vol_num = INT_MAX; while (1) { int vol_id, ret, devno; char tmp_buf[256]; errno = 0; dirent = readdir(sysfs_ubi); if (!dirent) break; if (strlen(dirent->d_name) > 256) { errmsg("invalid entry in %s: \"%s\"", lib->sysfs_ubi, dirent->d_name); goto out_close; } ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf); if (ret == 2 && devno == dev_num) { info->vol_count += 1; if (vol_id > info->highest_vol_num) info->highest_vol_num = vol_id; if (vol_id < info->lowest_vol_num) info->lowest_vol_num = vol_id; } } if (!dirent && errno) { sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); goto out_close; } if (closedir(sysfs_ubi)) return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); if (info->lowest_vol_num == INT_MAX) info->lowest_vol_num = 0; if (dev_get_major(lib, dev_num, &info->major, &info->minor)) return -1; if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs)) return -1; if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs)) return -1; if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count)) return -1; if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size)) return -1; if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd)) return -1; if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec)) return -1; if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count)) return -1; if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size)) return -1; info->avail_bytes = info->avail_lebs * info->leb_size; info->total_bytes = info->total_lebs * info->leb_size; return 0;out_close: closedir(sysfs_ubi); return -1;}int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info){ int dev_num; struct libubi *lib = (struct libubi *)desc; if (dev_node2num(lib, node, &dev_num)) return -1; return ubi_get_dev_info1(desc, dev_num, info);}int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, struct ubi_vol_info *info){ int ret; struct libubi *lib = (struct libubi *)desc; char buf[50]; memset(info, '\0', sizeof(struct ubi_vol_info)); info->dev_num = dev_num; info->vol_id = vol_id; if (dev_get_major(lib, dev_num, &info->dev_major, &info->dev_minor)) return -1; if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor)) return -1; ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50); if (ret < 0) return -1; if (strncmp(buf, "static\n", ret) == 0) info->type = UBI_STATIC_VOLUME; else if (strncmp(buf, "dynamic\n", ret) == 0) info->type = UBI_DYNAMIC_VOLUME; else { errmsg("bad value at \"%s\"", buf); errno = EINVAL; return -1; } ret = vol_read_int(lib->vol_alignment, dev_num, vol_id, &info->alignment); if (ret) return -1; ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id, &info->data_bytes); if (ret) return -1; ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs); if (ret) return -1; ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size); if (ret) return -1; ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id, &info->corrupted); if (ret) return -1; info->rsvd_bytes = info->leb_size * info->rsvd_lebs; ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name, UBI_VOL_NAME_MAX + 2); if (ret < 0) return -1; info->name[ret - 1] = '\0'; return 0;}int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info){ int vol_id, dev_num; struct libubi *lib = (struct libubi *)desc; if (vol_node2nums(lib, node, &dev_num, &vol_id)) return -1; return ubi_get_vol_info1(desc, dev_num, vol_id, info);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -