diff options
Diffstat (limited to 'ubi-utils/sort-me-out/libubimirror.c')
-rw-r--r-- | ubi-utils/sort-me-out/libubimirror.c | 237 |
1 files changed, 0 insertions, 237 deletions
diff --git a/ubi-utils/sort-me-out/libubimirror.c b/ubi-utils/sort-me-out/libubimirror.c deleted file mode 100644 index d06770e..0000000 --- a/ubi-utils/sort-me-out/libubimirror.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * 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. - */ - -#include <stdio.h> -#include <errno.h> -#include <unistd.h> -#include <memory.h> -#include <limits.h> -#include <fcntl.h> - -#include <libubi.h> -#include "ubimirror.h" - -#define COMPARE_BUF_SIZE (128 * 1024) - -#define DEFAULT_DEV_PATTERN "/dev/ubi%d" -#define DEFAULT_VOL_PATTERN "/dev/ubi%d_%d" - -#define EBUF(fmt...) do { \ - snprintf(err_buf, err_buf_size, fmt); \ -} while (0) - -enum { - compare_error = -1, - seek_error = -2, - write_error = -3, - read_error = -4, - update_error = -5, - ubi_error = -6, - open_error = -7, - close_error = -8, - compare_equal = 0, - compare_different = 1 -}; - -/* - * Read len number of bytes from fd. - * Return 0 on EOF, -1 on error. - */ -static ssize_t fill_buffer(int fd, unsigned char *buf, ssize_t len) -{ - ssize_t got, have = 0; - - do { - got = read(fd, buf + have, len - have); - if (got == -1 && errno != EINTR) - return -1; - have += got; - } while (got > 0 && have < len); - return have; -} - -/* - * Write len number of bytes to fd. - * Return bytes written (>= 0), -1 on error. - */ -static ssize_t flush_buffer(int fd, unsigned char *buf, ssize_t len) -{ - ssize_t done, have = 0; - - do { - done = write(fd, buf + have, len - have); - if (done == -1 && errno != EINTR) - return -1; - have += done; - } while (done > 0 && have < len); - return have; -} - -/* - * Compare two files. Return 0, 1, or -1, depending on whether the - * files are equal, different, or an error occured. - * Return compare-different when target volume can not be read. Might be - * an interrupted volume update and then the target device returns -EIO but - * can be updated. - * - * fd_a is source - * fd_b is destination - */ -static int compare_files(int fd_a, int fd_b) -{ - unsigned char buf_a[COMPARE_BUF_SIZE], buf_b[COMPARE_BUF_SIZE]; - ssize_t len_a, len_b; - int rc; - - for (;;) { - len_a = fill_buffer(fd_a, buf_a, sizeof(buf_a)); - if (len_a == -1) { - rc = compare_error; - break; - } - len_b = fill_buffer(fd_b, buf_b, sizeof(buf_b)); - if (len_b == -1) { - rc = compare_different; - break; - } - if (len_a != len_b) { - rc = compare_different; - break; - } - if (len_a == 0) { /* Size on both files equal and EOF */ - rc = compare_equal; - break; - } - if (memcmp(buf_a, buf_b, len_a) != 0 ) { - rc = compare_different; - break; - } - } - /* Position both files at the beginning */ - if (lseek(fd_a, 0, SEEK_SET) == -1 || - lseek(fd_b, 0, SEEK_SET) == -1) - rc = seek_error; - return rc; -} - -int vol_get_used_bytes(int vol_fd, unsigned long long *bytes) -{ - off_t res; - - res = lseek(vol_fd, 0, SEEK_END); - if (res == (off_t)-1) - return -1; - *bytes = (unsigned long long) res; - res = lseek(vol_fd, 0, SEEK_SET); - return res == (off_t)-1 ? -1 : 0; -} - -static int copy_files(libubi_t ulib, int fd_in, int fd_out) -{ - unsigned char buf_a[COMPARE_BUF_SIZE]; - ssize_t len_a, len_b; - unsigned long long update_size, copied; - - if (vol_get_used_bytes(fd_in, &update_size) == -1 || - ubi_update_start(ulib, fd_out, update_size) == -1) - return update_error; - for (copied = 0; copied < update_size; copied += len_b ) { - len_a = fill_buffer(fd_in, buf_a, sizeof(buf_a)); - if (len_a == -1) - return read_error; - if (len_a == 0) /* Reach EOF */ - return 0; - len_b = flush_buffer(fd_out, buf_a, len_a); - if (len_b != len_a) - return write_error; - } - return 0; -} - -int ubimirror(uint32_t devno, int seqnum, uint32_t *ids, ssize_t ids_size, - char *err_buf, size_t err_buf_size) -{ - int rc = 0; - uint32_t src_id; - char path[PATH_MAX]; - libubi_t ulib; - int fd_in = -1, i = 0, fd_out = -1; - - if (ids_size == 0) - return 0; - else { - if ((seqnum < 0) || (seqnum > (ids_size - 1))) { - EBUF("volume id %d out of range", seqnum); - return EUBIMIRROR_NO_SRC; - } - src_id = ids[seqnum]; - } - - ulib = libubi_open(); - if (ulib == NULL) - return ubi_error; - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, src_id); - - fd_in = open(path, O_RDONLY); - if (fd_in == -1) { - EBUF("open error source volume %d", ids[i]); - rc = open_error; - goto err; - } - - for (i = 0; i < ids_size; i++) { - if (ids[i] == src_id) /* skip self-mirror */ - continue; - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, ids[i]); - - fd_out = open(path, O_RDWR); - if (fd_out < 0){ - EBUF("open error destination volume %d", ids[i]); - rc = open_error; - goto err; - } - rc = compare_files(fd_in, fd_out); - if (rc < 0) { - EBUF("compare error volume %d and %d", src_id, ids[i]); - goto err; - } else if (rc == compare_different) { - rc = copy_files(ulib, fd_in, fd_out); - if (rc != 0) { - EBUF("mirror error volume %d to %d", src_id, - ids[i]); - goto err; - } - } - if ((rc = close(fd_out)) == -1) { - EBUF("close error volume %d", ids[i]); - rc = close_error; - goto err; - } else - fd_out = -1; - } -err: - if (fd_out != -1) - close(fd_out); - if (fd_in != -1) - close(fd_in); - if (ulib != NULL) - libubi_close(ulib); - return rc; -} |