/* * 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 PROGRAM_NAME "mkvol_bad" #include "common.h" #include "helpers.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 = PROGRAM_NAME ":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 = (long long)(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"); errorm("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 = PROGRAM_NAME ":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; }