123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- * Copyright (C) 2007 Nokia Corporation.
- *
- * 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.
- *
- * 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., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /*
- * An utility to delete UBI devices (detach MTD devices from UBI).
- *
- * Author: Artem Bityutskiy
- */
- #define PROGRAM_NAME "ubidetach"
- #define VERSION "owrt-fstools"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <getopt.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include "libubi-tiny.h"
- #define DEFAULT_CTRL_DEV "/dev/ubi_ctrl"
- static int ubi_write(char *node, int fd, const void *buf, int len)
- {
- int ret;
- while (len) {
- ret = write(fd, buf, len);
- if (ret < 0) {
- if (errno == EINTR) {
- fprintf(stderr, "do not interrupt me!");
- continue;
- }
- fprintf(stderr, "cannot write %d bytes to volume \"%s\"", len, node);
- return -1;
- }
- if (ret == 0) {
- fprintf(stderr, "cannot write %d bytes to volume \"%s\"", len, node);
- return -1;
- }
- len -= ret;
- buf += ret;
- }
- return 0;
- }
- static int update_volume(libubi_t libubi, struct ubi_vol_info *vol_info, char *node, char *img, int skip)
- {
- int err, fd, ifd;
- long long bytes;
- char *buf;
- struct stat st;
- buf = malloc(vol_info->leb_size);
- if (!buf) {
- fprintf(stderr, "cannot allocate %d bytes of memory", vol_info->leb_size);
- return -1;
- }
- err = stat(img, &st);
- if (err < 0) {
- fprintf(stderr, "stat failed on \"%s\"", img);
- goto out_free;
- }
- bytes = st.st_size - skip;
- if (bytes > vol_info->rsvd_bytes) {
- fprintf(stderr, "\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)",
- img, bytes, node, vol_info->rsvd_bytes);
- goto out_free;
- }
- fd = open(node, O_RDWR);
- if (fd == -1) {
- fprintf(stderr, "cannot open UBI volume \"%s\"", node);
- goto out_free;
- }
- ifd = open(img, O_RDONLY);
- if (ifd == -1) {
- fprintf(stderr, "cannot open \"%s\"", img);
- goto out_close1;
- }
- if (skip && lseek(ifd, skip, SEEK_CUR) == -1) {
- fprintf(stderr, "lseek input by %d failed", skip);
- goto out_close;
- }
- err = ubi_update_start(libubi, fd, bytes);
- if (err) {
- fprintf(stderr, "cannot start volume \"%s\" update", node);
- goto out_close;
- }
- while (bytes) {
- ssize_t ret;
- int to_copy = vol_info->leb_size;
- if (to_copy > bytes)
- to_copy = bytes;
- ret = read(ifd, buf, to_copy);
- if (ret <= 0) {
- if (errno == EINTR) {
- fprintf(stderr, "do not interrupt me!");
- continue;
- } else {
- fprintf(stderr, "cannot read %d bytes from \"%s\"",
- to_copy, img);
- goto out_close;
- }
- }
- err = ubi_write(node, fd, buf, ret);
- if (err)
- goto out_close;
- bytes -= ret;
- }
- close(ifd);
- close(fd);
- free(buf);
- return 0;
- out_close:
- close(ifd);
- out_close1:
- close(fd);
- out_free:
- free(buf);
- return -1;
- }
- int ubiattach(libubi_t libubi, char *mtd)
- {
- struct ubi_attach_request req = {
- .dev_num = UBI_DEV_NUM_AUTO,
- .mtd_num = -1,
- .vid_hdr_offset = 0,
- .max_beb_per1024 = 0,
- .mtd_dev_node = mtd,
- };
- int err = ubi_attach(libubi, DEFAULT_CTRL_DEV, &req);
- if (err) {
- fprintf(stderr, "cannot attach \"%s\"", mtd);
- return err;
- }
- return 0;
- }
- int ubidetach(libubi_t libubi, char *mtd)
- {
- return ubi_detach(libubi, DEFAULT_CTRL_DEV, mtd);
- }
- int ubirsvol(libubi_t libubi, char *node, char *name, int bytes)
- {
- struct ubi_dev_info dev_info;
- struct ubi_vol_info vol_info;
- int err = ubi_get_dev_info(libubi, node, &dev_info);
- if (err) {
- fprintf(stderr, "cannot get information about UBI device \"%s\"",
- node);
- return -1;
- }
- err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num, name, &vol_info);
- if (err) {
- fprintf(stderr, "cannot find UBI volume \"%s\"", name);
- return -1;
- }
- err = ubi_rsvol(libubi, node, vol_info.vol_id, bytes);
- if (err) {
- fprintf(stderr, "cannot UBI resize volume");
- return -1;
- }
- return 0;
- }
- int ubirmvol(libubi_t libubi, char *node, char *name)
- {
- struct ubi_dev_info dev_info;
- struct ubi_vol_info vol_info;
- int err = ubi_get_dev_info(libubi, node, &dev_info);
- if (err) {
- fprintf(stderr, "cannot get information about UBI device \"%s\"",
- node);
- return -1;
- }
- err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num, name, &vol_info);
- if (err) {
- fprintf(stderr, "cannot find UBI volume \"%s\"", name);
- return -1;
- }
- err = ubi_rmvol(libubi, node, vol_info.vol_id);
- if (err) {
- fprintf(stderr, "cannot UBI remove volume");
- return -1;
- }
- return 0;
- }
- int ubimkvol(libubi_t libubi, char *node, char *name, int maxavs)
- {
- struct ubi_dev_info dev_info;
- struct ubi_vol_info vol_info;
- struct ubi_mkvol_request req;
- int err = ubi_get_dev_info(libubi, node, &dev_info);
- if (err) {
- fprintf(stderr, "cannot get information about UBI device \"%s\"",
- node);
- return -1;
- }
- if (dev_info.avail_bytes == 0) {
- fprintf(stderr, "UBI device does not have free logical eraseblocks");
- return -1;
- }
- if (maxavs)
- printf("Set volume size to %lld\n", dev_info.avail_bytes);
- req.vol_id = UBI_VOL_NUM_AUTO;
- req.alignment = 1;
- req.bytes = dev_info.avail_bytes;
- req.vol_type = UBI_DYNAMIC_VOLUME;
- req.name = name;
- err = ubi_mkvol(libubi, node, &req);
- if (err < 0) {
- fprintf(stderr, "cannot UBI create volume");
- return -1;
- }
- /* Print information about the created device */
- err = ubi_get_vol_info1(libubi, dev_info.dev_num, req.vol_id, &vol_info);
- if (err) {
- fprintf(stderr, "cannot get information about newly created UBI volume");
- return -1;
- }
- printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs);
- ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
- printf("), LEB size ");
- ubiutils_print_bytes(vol_info.leb_size, 1);
- printf(", %s, name \"%s\", alignment %d\n",
- req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static",
- vol_info.name, vol_info.alignment);
- return 0;
- }
- int ubiupdatevol(libubi_t libubi, char *node, char *file)
- {
- struct ubi_vol_info vol_info;
- int err = ubi_get_vol_info(libubi, node, &vol_info);
- if (err) {
- fprintf(stderr, "cannot get information about UBI volume \"%s\"",
- node);
- return -1;
- }
- return update_volume(libubi, &vol_info, node, file, 0);
- }
- int ubitruncatevol(libubi_t libubi, char *node)
- {
- int err, fd;
- fd = open(node, O_RDWR);
- if (fd == -1) {
- fprintf(stderr, "cannot open \"%s\"", node);
- return -1;
- }
- err = ubi_update_start(libubi, fd, 0);
- if (err) {
- fprintf(stderr, "cannot truncate volume \"%s\"", node);
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
- }
|