| /* |
| * 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 B. Bityutskiy |
| * |
| * Test UBI volume creation and deletion ioctl()s with bad input and in case of |
| * incorrect usage. |
| */ |
| |
| #include <string.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include "libubi.h" |
| #define TESTNAME "mkvol_bad" |
| #include "common.h" |
| |
| static libubi_t libubi; |
| static struct ubi_dev_info dev_info; |
| const char *node; |
| |
| /** |
| * test_mkvol - test that UBI mkvol ioctl rejects bad input parameters. |
| * |
| * This function returns %0 if the test passed and %-1 if not. |
| */ |
| static int test_mkvol(void) |
| { |
| int ret, i; |
| struct ubi_mkvol_request req; |
| const char *name = TESTNAME ":test_mkvol()"; |
| |
| req.alignment = 1; |
| req.bytes = dev_info.avail_bytes; |
| req.vol_type = UBI_DYNAMIC_VOLUME; |
| req.name = name; |
| |
| /* Bad volume ID */ |
| req.vol_id = -2; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_id = %d", req.vol_id)) |
| return -1; |
| |
| req.vol_id = dev_info.max_vol_count; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_id = %d", req.vol_id)) |
| return -1; |
| |
| /* Bad alignment */ |
| req.vol_id = 0; |
| req.alignment = 0; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d", |
| req.alignment)) |
| return -1; |
| |
| req.alignment = -1; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d", |
| req.alignment)) |
| return -1; |
| |
| req.alignment = dev_info.leb_size + 1; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d", |
| req.alignment)) |
| return -1; |
| |
| if (dev_info.min_io_size > 1) { |
| req.alignment = dev_info.min_io_size + 1; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d", |
| req.alignment)) |
| return -1; |
| } |
| |
| /* Bad bytes */ |
| req.alignment = 1; |
| req.bytes = -1; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "bytes = %lld", req.bytes)) |
| return -1; |
| |
| req.bytes = 0; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "bytes = %lld", req.bytes)) |
| return -1; |
| |
| req.bytes = dev_info.avail_bytes + 1; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, ENOSPC, "ubi_mkvol", "bytes = %lld", req.bytes)) |
| return -1; |
| |
| req.alignment = dev_info.leb_size - dev_info.min_io_size; |
| req.bytes = (dev_info.leb_size - dev_info.leb_size % req.alignment) * |
| dev_info.avail_lebs + 1; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, ENOSPC, "ubi_mkvol", "bytes = %lld", req.bytes)) |
| return -1; |
| |
| /* Bad vol_type */ |
| req.alignment = 1; |
| req.bytes = dev_info.leb_size; |
| req.vol_type = UBI_DYNAMIC_VOLUME + UBI_STATIC_VOLUME; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_type = %d", |
| req.vol_type)) |
| return -1; |
| |
| req.vol_type = UBI_DYNAMIC_VOLUME; |
| |
| /* Too long name */ |
| { |
| char name[UBI_VOL_NAME_MAX + 5]; |
| |
| memset(name, 'x', UBI_VOL_NAME_MAX + 1); |
| name[UBI_VOL_NAME_MAX + 1] = '\0'; |
| |
| req.name = name; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EINVAL, "ubi_mkvol", "name_len = %d", |
| UBI_VOL_NAME_MAX + 1)) |
| return -1; |
| } |
| |
| /* Try to create 2 volumes with the same ID and name */ |
| req.name = name; |
| req.vol_id = 0; |
| if (ubi_mkvol(libubi, node, &req)) { |
| failed("ubi_mkvol"); |
| return -1; |
| } |
| |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EEXIST, "ubi_mkvol", |
| "volume with ID 0 created twice")) |
| return -1; |
| |
| req.vol_id = 1; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EEXIST, "ubi_mkvol", |
| "volume with name \"%s\" created twice", name)) |
| return -1; |
| |
| if (ubi_rmvol(libubi, node, 0)) { |
| failed("ubi_rmvol"); |
| return -1; |
| } |
| |
| /* Try to use too much space */ |
| req.vol_id = 0; |
| req.bytes = dev_info.avail_bytes; |
| if (ubi_mkvol(libubi, node, &req)) { |
| failed("ubi_mkvol"); |
| return -1; |
| } |
| |
| req.bytes = 1; |
| req.vol_id = 1; |
| ret = ubi_mkvol(libubi, node, &req); |
| if (check_failed(ret, EEXIST, "ubi_mkvol", |
| "created volume of maximum size %lld, but still " |
| "can create more volumes", dev_info.avail_bytes)) |
| return -1; |
| |
| if (ubi_rmvol(libubi, node, 0)) { |
| failed("ubi_rmvol"); |
| return -1; |
| } |
| |
| /* Try to create too many volumes */ |
| for (i = 0; i < dev_info.max_vol_count; i++) { |
| char nm[strlen(name) + 50]; |
| |
| req.vol_id = UBI_VOL_NUM_AUTO; |
| req.alignment = 1; |
| req.bytes = 1; |
| req.vol_type = UBI_STATIC_VOLUME; |
| |
| sprintf(nm, "%s:%d", name, i); |
| req.name = nm; |
| |
| if (ubi_mkvol(libubi, node, &req)) { |
| /* |
| * Note, because of gluebi we may be unable to create |
| * dev_info.max_vol_count devices (MTD restrictions). |
| */ |
| if (errno == ENFILE) |
| break; |
| failed("ubi_mkvol"); |
| err_msg("vol_id %d", i); |
| goto remove; |
| } |
| } |
| |
| for (i = 0; i < dev_info.max_vol_count + 1; i++) |
| ubi_rmvol(libubi, node, i); |
| |
| return 0; |
| |
| remove: |
| for (i = 0; i < dev_info.max_vol_count + 1; i++) |
| ubi_rmvol(libubi, node, i); |
| return -1; |
| } |
| |
| /** |
| * test_rmvol - test that UBI rmvol ioctl rejects bad input parameters. |
| * |
| * This function returns %0 if the test passed and %-1 if not. |
| */ |
| static int test_rmvol(void) |
| { |
| int ret; |
| struct ubi_mkvol_request req; |
| const char *name = TESTNAME ":test_rmvol()"; |
| |
| /* Bad vol_id */ |
| ret = ubi_rmvol(libubi, node, -1); |
| if (check_failed(ret, EINVAL, "ubi_rmvol", "vol_id = -1")) |
| return -1; |
| |
| ret = ubi_rmvol(libubi, node, dev_info.max_vol_count); |
| if (check_failed(ret, EINVAL, "ubi_rmvol", "vol_id = %d", |
| dev_info.max_vol_count)) |
| return -1; |
| |
| /* Try to remove non-existing volume */ |
| ret = ubi_rmvol(libubi, node, 0); |
| if (check_failed(ret, ENODEV, "ubi_rmvol", |
| "removed non-existing volume 0")) |
| return -1; |
| |
| /* Try to remove volume twice */ |
| 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; |
| if (ubi_mkvol(libubi, node, &req)) { |
| failed("ubi_mkvol"); |
| return -1; |
| } |
| |
| if (ubi_rmvol(libubi, node, req.vol_id)) { |
| failed("ubi_rmvol"); |
| return -1; |
| } |
| |
| ret = ubi_rmvol(libubi, node, req.vol_id); |
| if (check_failed(ret, ENODEV, "ubi_rmvol", "volume %d removed twice", |
| req.vol_id)) |
| return -1; |
| |
| return 0; |
| } |
| |
| int main(int argc, char * const argv[]) |
| { |
| if (initial_check(argc, argv)) |
| return 1; |
| |
| node = argv[1]; |
| |
| libubi = libubi_open(); |
| if (libubi == NULL) { |
| failed("libubi_open"); |
| return 1; |
| } |
| |
| if (ubi_get_dev_info(libubi, node, &dev_info)) { |
| failed("ubi_get_dev_info"); |
| goto close; |
| } |
| |
| if (test_mkvol()) |
| goto close; |
| |
| if (test_rmvol()) |
| goto close; |
| |
| libubi_close(libubi); |
| return 0; |
| |
| close: |
| libubi_close(libubi); |
| return 1; |
| } |