Home | History | Annotate | Download | only in oslib
      1 /*
      2  * Copyright (c) International Business Machines Corp., 2006
      3  * Copyright (C) 2009 Nokia Corporation
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 2 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
     13  * the GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program; if not, write to the Free Software
     17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     18  *
     19  * Author: Artem Bityutskiy
     20  *
     21  * MTD library.
     22  */
     23 
     24 /* Imported from mtd-utils by dehrenberg */
     25 
     26 #include <limits.h>
     27 #include <stdlib.h>
     28 #include <stdio.h>
     29 #include <errno.h>
     30 #include <unistd.h>
     31 #include <fcntl.h>
     32 #include <dirent.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <sys/ioctl.h>
     36 #include <inttypes.h>
     37 
     38 #include <mtd/mtd-user.h>
     39 #include "libmtd.h"
     40 
     41 #include "libmtd_int.h"
     42 #include "libmtd_common.h"
     43 
     44 /**
     45  * mkpath - compose full path from 2 given components.
     46  * @path: the first component
     47  * @name: the second component
     48  *
     49  * This function returns the resulting path in case of success and %NULL in
     50  * case of failure.
     51  */
     52 static char *mkpath(const char *path, const char *name)
     53 {
     54 	char *n;
     55 	size_t len1 = strlen(path);
     56 	size_t len2 = strlen(name);
     57 
     58 	n = xmalloc(len1 + len2 + 6);
     59 
     60 	memcpy(n, path, len1);
     61 	if (n[len1 - 1] != '/')
     62 		n[len1++] = '/';
     63 
     64 	memcpy(n + len1, name, len2 + 1);
     65 	return n;
     66 }
     67 
     68 /**
     69  * read_data - read data from a file.
     70  * @file: the file to read from
     71  * @buf: the buffer to read to
     72  * @buf_len: buffer length
     73  *
     74  * This function returns number of read bytes in case of success and %-1 in
     75  * case of failure. Note, if the file contains more then @buf_len bytes of
     76  * date, this function fails with %EINVAL error code.
     77  */
     78 static int read_data(const char *file, void *buf, int buf_len)
     79 {
     80 	int fd, rd, tmp, tmp1;
     81 
     82 	fd = open(file, O_RDONLY | O_CLOEXEC);
     83 	if (fd == -1)
     84 		return -1;
     85 
     86 	rd = read(fd, buf, buf_len);
     87 	if (rd == -1) {
     88 		sys_errmsg("cannot read \"%s\"", file);
     89 		goto out_error;
     90 	}
     91 
     92 	if (rd == buf_len) {
     93 		errmsg("contents of \"%s\" is too long", file);
     94 		errno = EINVAL;
     95 		goto out_error;
     96 	}
     97 
     98 	((char *)buf)[rd] = '\0';
     99 
    100 	/* Make sure all data is read */
    101 	tmp1 = read(fd, &tmp, 1);
    102 	if (tmp1 == 1) {
    103 		sys_errmsg("cannot read \"%s\"", file);
    104 		goto out_error;
    105 	}
    106 	if (tmp1) {
    107 		errmsg("file \"%s\" contains too much data (> %d bytes)",
    108 		       file, buf_len);
    109 		errno = EINVAL;
    110 		goto out_error;
    111 	}
    112 
    113 	if (close(fd)) {
    114 		sys_errmsg("close failed on \"%s\"", file);
    115 		return -1;
    116 	}
    117 
    118 	return rd;
    119 
    120 out_error:
    121 	close(fd);
    122 	return -1;
    123 }
    124 
    125 /**
    126  * read_major - read major and minor numbers from a file.
    127  * @file: name of the file to read from
    128  * @major: major number is returned here
    129  * @minor: minor number is returned here
    130  *
    131  * This function returns % in case of success, and %-1 in case of failure.
    132  */
    133 static int read_major(const char *file, int *major, int *minor)
    134 {
    135 	int ret;
    136 	char buf[50];
    137 
    138 	ret = read_data(file, buf, 50);
    139 	if (ret < 0)
    140 		return ret;
    141 
    142 	ret = sscanf(buf, "%d:%d\n", major, minor);
    143 	if (ret != 2) {
    144 		errno = EINVAL;
    145 		return errmsg("\"%s\" does not have major:minor format", file);
    146 	}
    147 
    148 	if (*major < 0 || *minor < 0) {
    149 		errno = EINVAL;
    150 		return errmsg("bad major:minor %d:%d in \"%s\"",
    151 			      *major, *minor, file);
    152 	}
    153 
    154 	return 0;
    155 }
    156 
    157 /**
    158  * dev_get_major - get major and minor numbers of an MTD device.
    159  * @lib: libmtd descriptor
    160  * @mtd_num: MTD device number
    161  * @major: major number is returned here
    162  * @minor: minor number is returned here
    163  *
    164  * This function returns zero in case of success and %-1 in case of failure.
    165  */
    166 static int dev_get_major(struct libmtd *lib, int mtd_num, int *major, int *minor)
    167 {
    168 	char file[strlen(lib->mtd_dev) + 50];
    169 
    170 	sprintf(file, lib->mtd_dev, mtd_num);
    171 	return read_major(file, major, minor);
    172 }
    173 
    174 /**
    175  * dev_read_data - read data from an MTD device's sysfs file.
    176  * @patt: file pattern to read from
    177  * @mtd_num: MTD device number
    178  * @buf: buffer to read to
    179  * @buf_len: buffer length
    180  *
    181  * This function returns number of read bytes in case of success and %-1 in
    182  * case of failure.
    183  */
    184 static int dev_read_data(const char *patt, int mtd_num, void *buf, int buf_len)
    185 {
    186 	char file[strlen(patt) + 100];
    187 
    188 	sprintf(file, patt, mtd_num);
    189 	return read_data(file, buf, buf_len);
    190 }
    191 
    192 /**
    193  * read_hex_ll - read a hex 'long long' value from a file.
    194  * @file: the file to read from
    195  * @value: the result is stored here
    196  *
    197  * This function reads file @file and interprets its contents as hexadecimal
    198  * 'long long' integer. If this is not true, it fails with %EINVAL error code.
    199  * Returns %0 in case of success and %-1 in case of failure.
    200  */
    201 static int read_hex_ll(const char *file, long long *value)
    202 {
    203 	int fd, rd;
    204 	char buf[50];
    205 
    206 	fd = open(file, O_RDONLY | O_CLOEXEC);
    207 	if (fd == -1)
    208 		return -1;
    209 
    210 	rd = read(fd, buf, sizeof(buf));
    211 	if (rd == -1) {
    212 		sys_errmsg("cannot read \"%s\"", file);
    213 		goto out_error;
    214 	}
    215 	if (rd == sizeof(buf)) {
    216 		errmsg("contents of \"%s\" is too long", file);
    217 		errno = EINVAL;
    218 		goto out_error;
    219 	}
    220 	buf[rd] = '\0';
    221 
    222 	if (sscanf(buf, "%llx\n", value) != 1) {
    223 		errmsg("cannot read integer from \"%s\"\n", file);
    224 		errno = EINVAL;
    225 		goto out_error;
    226 	}
    227 
    228 	if (*value < 0) {
    229 		errmsg("negative value %lld in \"%s\"", *value, file);
    230 		errno = EINVAL;
    231 		goto out_error;
    232 	}
    233 
    234 	if (close(fd))
    235 		return sys_errmsg("close failed on \"%s\"", file);
    236 
    237 	return 0;
    238 
    239 out_error:
    240 	close(fd);
    241 	return -1;
    242 }
    243 
    244 /**
    245  * read_pos_ll - read a positive 'long long' value from a file.
    246  * @file: the file to read from
    247  * @value: the result is stored here
    248  *
    249  * This function reads file @file and interprets its contents as a positive
    250  * 'long long' integer. If this is not true, it fails with %EINVAL error code.
    251  * Returns %0 in case of success and %-1 in case of failure.
    252  */
    253 static int read_pos_ll(const char *file, long long *value)
    254 {
    255 	int fd, rd;
    256 	char buf[50];
    257 
    258 	fd = open(file, O_RDONLY | O_CLOEXEC);
    259 	if (fd == -1)
    260 		return -1;
    261 
    262 	rd = read(fd, buf, 50);
    263 	if (rd == -1) {
    264 		sys_errmsg("cannot read \"%s\"", file);
    265 		goto out_error;
    266 	}
    267 	if (rd == 50) {
    268 		errmsg("contents of \"%s\" is too long", file);
    269 		errno = EINVAL;
    270 		goto out_error;
    271 	}
    272 
    273 	if (sscanf(buf, "%lld\n", value) != 1) {
    274 		errmsg("cannot read integer from \"%s\"\n", file);
    275 		errno = EINVAL;
    276 		goto out_error;
    277 	}
    278 
    279 	if (*value < 0) {
    280 		errmsg("negative value %lld in \"%s\"", *value, file);
    281 		errno = EINVAL;
    282 		goto out_error;
    283 	}
    284 
    285 	if (close(fd))
    286 		return sys_errmsg("close failed on \"%s\"", file);
    287 
    288 	return 0;
    289 
    290 out_error:
    291 	close(fd);
    292 	return -1;
    293 }
    294 
    295 /**
    296  * read_hex_int - read an 'int' value from a file.
    297  * @file: the file to read from
    298  * @value: the result is stored here
    299  *
    300  * This function is the same as 'read_pos_ll()', but it reads an 'int'
    301  * value, not 'long long'.
    302  */
    303 static int read_hex_int(const char *file, int *value)
    304 {
    305 	long long res;
    306 
    307 	if (read_hex_ll(file, &res))
    308 		return -1;
    309 
    310 	/* Make sure the value has correct range */
    311 	if (res > INT_MAX || res < INT_MIN) {
    312 		errmsg("value %lld read from file \"%s\" is out of range",
    313 		       res, file);
    314 		errno = EINVAL;
    315 		return -1;
    316 	}
    317 
    318 	*value = res;
    319 	return 0;
    320 }
    321 
    322 /**
    323  * read_pos_int - read a positive 'int' value from a file.
    324  * @file: the file to read from
    325  * @value: the result is stored here
    326  *
    327  * This function is the same as 'read_pos_ll()', but it reads an 'int'
    328  * value, not 'long long'.
    329  */
    330 static int read_pos_int(const char *file, int *value)
    331 {
    332 	long long res;
    333 
    334 	if (read_pos_ll(file, &res))
    335 		return -1;
    336 
    337 	/* Make sure the value is not too big */
    338 	if (res > INT_MAX) {
    339 		errmsg("value %lld read from file \"%s\" is out of range",
    340 		       res, file);
    341 		errno = EINVAL;
    342 		return -1;
    343 	}
    344 
    345 	*value = res;
    346 	return 0;
    347 }
    348 
    349 /**
    350  * dev_read_hex_int - read an hex 'int' value from an MTD device sysfs file.
    351  * @patt: file pattern to read from
    352  * @mtd_num: MTD device number
    353  * @value: the result is stored here
    354  *
    355  * This function returns %0 in case of success and %-1 in case of failure.
    356  */
    357 static int dev_read_hex_int(const char *patt, int mtd_num, int *value)
    358 {
    359 	char file[strlen(patt) + 50];
    360 
    361 	sprintf(file, patt, mtd_num);
    362 	return read_hex_int(file, value);
    363 }
    364 
    365 /**
    366  * dev_read_pos_int - read a positive 'int' value from an MTD device sysfs file.
    367  * @patt: file pattern to read from
    368  * @mtd_num: MTD device number
    369  * @value: the result is stored here
    370  *
    371  * This function returns %0 in case of success and %-1 in case of failure.
    372  */
    373 static int dev_read_pos_int(const char *patt, int mtd_num, int *value)
    374 {
    375 	char file[strlen(patt) + 50];
    376 
    377 	sprintf(file, patt, mtd_num);
    378 	return read_pos_int(file, value);
    379 }
    380 
    381 /**
    382  * dev_read_pos_ll - read a positive 'long long' value from an MTD device sysfs file.
    383  * @patt: file pattern to read from
    384  * @mtd_num: MTD device number
    385  * @value: the result is stored here
    386  *
    387  * This function returns %0 in case of success and %-1 in case of failure.
    388  */
    389 static int dev_read_pos_ll(const char *patt, int mtd_num, long long *value)
    390 {
    391 	char file[strlen(patt) + 50];
    392 
    393 	sprintf(file, patt, mtd_num);
    394 	return read_pos_ll(file, value);
    395 }
    396 
    397 /**
    398  * type_str2int - convert MTD device type to integer.
    399  * @str: MTD device type string to convert
    400  *
    401  * This function converts MTD device type string @str, read from sysfs, into an
    402  * integer.
    403  */
    404 static int type_str2int(const char *str)
    405 {
    406 	if (!strcmp(str, "nand"))
    407 		return MTD_NANDFLASH;
    408 	if (!strcmp(str, "mlc-nand"))
    409 		return MTD_MLCNANDFLASH;
    410 	if (!strcmp(str, "nor"))
    411 		return MTD_NORFLASH;
    412 	if (!strcmp(str, "rom"))
    413 		return MTD_ROM;
    414 	if (!strcmp(str, "absent"))
    415 		return MTD_ABSENT;
    416 	if (!strcmp(str, "dataflash"))
    417 		return MTD_DATAFLASH;
    418 	if (!strcmp(str, "ram"))
    419 		return MTD_RAM;
    420 	if (!strcmp(str, "ubi"))
    421 		return MTD_UBIVOLUME;
    422 	return -1;
    423 }
    424 
    425 /**
    426  * dev_node2num - find UBI device number by its character device node.
    427  * @lib: MTD library descriptor
    428  * @node: name of the MTD device node
    429  * @mtd_num: MTD device number is returned here
    430  *
    431  * This function returns %0 in case of success and %-1 in case of failure.
    432  */
    433 static int dev_node2num(struct libmtd *lib, const char *node, int *mtd_num)
    434 {
    435 	struct stat st;
    436 	int i, mjr, mnr;
    437 	struct mtd_info info;
    438 
    439 	if (stat(node, &st))
    440 		return sys_errmsg("cannot get information about \"%s\"", node);
    441 
    442 	if (!S_ISCHR(st.st_mode)) {
    443 		errmsg("\"%s\" is not a character device", node);
    444 		errno = EINVAL;
    445 		return -1;
    446 	}
    447 
    448 	mjr = major(st.st_rdev);
    449 	mnr = minor(st.st_rdev);
    450 
    451 	if (mtd_get_info((libmtd_t *)lib, &info))
    452 		return -1;
    453 
    454 	for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) {
    455 		int mjr1, mnr1, ret;
    456 
    457 		ret = dev_get_major(lib, i, &mjr1, &mnr1);
    458 		if (ret) {
    459 			if (errno == ENOENT)
    460 				continue;
    461 			if (!errno)
    462 				break;
    463 			return -1;
    464 		}
    465 
    466 		if (mjr1 == mjr && mnr1 == mnr) {
    467 			errno = 0;
    468 			*mtd_num = i;
    469 			return 0;
    470 		}
    471 	}
    472 
    473 	errno = ENODEV;
    474 	return -1;
    475 }
    476 
    477 /**
    478  * sysfs_is_supported - check whether the MTD sub-system supports MTD.
    479  * @lib: MTD library descriptor
    480  *
    481  * The Linux kernel MTD subsystem gained MTD support starting from kernel
    482  * 2.6.30 and libmtd tries to use sysfs interface if possible, because the NAND
    483  * sub-page size is available there (and not available at all in pre-sysfs
    484  * kernels).
    485  *
    486  * Very old kernels did not have "/sys/class/mtd" directory. Not very old
    487  * kernels (e.g., 2.6.29) did have "/sys/class/mtd/mtdX" directories, by there
    488  * were no files there, e.g., the "name" file was not present. So all we can do
    489  * is to check for a "/sys/class/mtd/mtdX/name" file. But this is not a
    490  * reliable check, because if this is a new system with no MTD devices - we'll
    491  * treat it as a pre-sysfs system.
    492  */
    493 static int sysfs_is_supported(struct libmtd *lib)
    494 {
    495 	int fd, num = -1;
    496 	DIR *sysfs_mtd;
    497 	char file[strlen(lib->mtd_name) + 10];
    498 
    499 	sysfs_mtd = opendir(lib->sysfs_mtd);
    500 	if (!sysfs_mtd) {
    501 		if (errno == ENOENT) {
    502 			errno = 0;
    503 			return 0;
    504 		}
    505 		return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd);
    506 	}
    507 
    508 	/*
    509 	 * First of all find an "mtdX" directory. This is needed because there
    510 	 * may be, for example, mtd1 but no mtd0.
    511 	 */
    512 	while (1) {
    513 		int ret, mtd_num;
    514 		char tmp_buf[256];
    515 		struct dirent *dirent;
    516 
    517 		dirent = readdir(sysfs_mtd);
    518 		if (!dirent)
    519 			break;
    520 
    521 		if (strlen(dirent->d_name) >= 255) {
    522 			errmsg("invalid entry in %s: \"%s\"",
    523 			       lib->sysfs_mtd, dirent->d_name);
    524 			errno = EINVAL;
    525 			closedir(sysfs_mtd);
    526 			return -1;
    527 		}
    528 
    529 		ret = sscanf(dirent->d_name, MTD_NAME_PATT"%s",
    530 			     &mtd_num, tmp_buf);
    531 		if (ret == 1) {
    532 			num = mtd_num;
    533 			break;
    534 		}
    535 	}
    536 
    537 	if (closedir(sysfs_mtd))
    538 		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd);
    539 
    540 	if (num == -1)
    541 		/* No mtd device, treat this as pre-sysfs system */
    542 		return 0;
    543 
    544 	sprintf(file, lib->mtd_name, num);
    545 	fd = open(file, O_RDONLY | O_CLOEXEC);
    546 	if (fd == -1)
    547 		return 0;
    548 
    549 	if (close(fd)) {
    550 		sys_errmsg("close failed on \"%s\"", file);
    551 		return -1;
    552 	}
    553 
    554 	return 1;
    555 }
    556 
    557 libmtd_t libmtd_open(void)
    558 {
    559 	struct libmtd *lib;
    560 
    561 	lib = xzalloc(sizeof(*lib));
    562 
    563 	lib->offs64_ioctls = OFFS64_IOCTLS_UNKNOWN;
    564 
    565 	lib->sysfs_mtd = mkpath("/sys", SYSFS_MTD);
    566 	if (!lib->sysfs_mtd)
    567 		goto out_error;
    568 
    569 	lib->mtd = mkpath(lib->sysfs_mtd, MTD_NAME_PATT);
    570 	if (!lib->mtd)
    571 		goto out_error;
    572 
    573 	lib->mtd_name = mkpath(lib->mtd, MTD_NAME);
    574 	if (!lib->mtd_name)
    575 		goto out_error;
    576 
    577 	if (!sysfs_is_supported(lib)) {
    578 		free(lib->mtd);
    579 		free(lib->sysfs_mtd);
    580 		free(lib->mtd_name);
    581 		lib->mtd_name = lib->mtd = lib->sysfs_mtd = NULL;
    582 		return lib;
    583 	}
    584 
    585 	lib->mtd_dev = mkpath(lib->mtd, MTD_DEV);
    586 	if (!lib->mtd_dev)
    587 		goto out_error;
    588 
    589 	lib->mtd_type = mkpath(lib->mtd, MTD_TYPE);
    590 	if (!lib->mtd_type)
    591 		goto out_error;
    592 
    593 	lib->mtd_eb_size = mkpath(lib->mtd, MTD_EB_SIZE);
    594 	if (!lib->mtd_eb_size)
    595 		goto out_error;
    596 
    597 	lib->mtd_size = mkpath(lib->mtd, MTD_SIZE);
    598 	if (!lib->mtd_size)
    599 		goto out_error;
    600 
    601 	lib->mtd_min_io_size = mkpath(lib->mtd, MTD_MIN_IO_SIZE);
    602 	if (!lib->mtd_min_io_size)
    603 		goto out_error;
    604 
    605 	lib->mtd_subpage_size = mkpath(lib->mtd, MTD_SUBPAGE_SIZE);
    606 	if (!lib->mtd_subpage_size)
    607 		goto out_error;
    608 
    609 	lib->mtd_oob_size = mkpath(lib->mtd, MTD_OOB_SIZE);
    610 	if (!lib->mtd_oob_size)
    611 		goto out_error;
    612 
    613 	lib->mtd_region_cnt = mkpath(lib->mtd, MTD_REGION_CNT);
    614 	if (!lib->mtd_region_cnt)
    615 		goto out_error;
    616 
    617 	lib->mtd_flags = mkpath(lib->mtd, MTD_FLAGS);
    618 	if (!lib->mtd_flags)
    619 		goto out_error;
    620 
    621 	lib->sysfs_supported = 1;
    622 	return lib;
    623 
    624 out_error:
    625 	libmtd_close((libmtd_t)lib);
    626 	return NULL;
    627 }
    628 
    629 void libmtd_close(libmtd_t desc)
    630 {
    631 	struct libmtd *lib = (struct libmtd *)desc;
    632 
    633 	free(lib->mtd_flags);
    634 	free(lib->mtd_region_cnt);
    635 	free(lib->mtd_oob_size);
    636 	free(lib->mtd_subpage_size);
    637 	free(lib->mtd_min_io_size);
    638 	free(lib->mtd_size);
    639 	free(lib->mtd_eb_size);
    640 	free(lib->mtd_type);
    641 	free(lib->mtd_dev);
    642 	free(lib->mtd_name);
    643 	free(lib->mtd);
    644 	free(lib->sysfs_mtd);
    645 	free(lib);
    646 }
    647 
    648 int mtd_dev_present(libmtd_t desc, int mtd_num) {
    649 	struct stat st;
    650 	struct libmtd *lib = (struct libmtd *)desc;
    651 
    652 	if (!lib->sysfs_supported) {
    653 		return legacy_dev_present(mtd_num) == 1;
    654 	} else {
    655 		char file[strlen(lib->mtd) + 10];
    656 
    657 		sprintf(file, lib->mtd, mtd_num);
    658 		return !stat(file, &st);
    659 	}
    660 }
    661 
    662 int mtd_get_info(libmtd_t desc, struct mtd_info *info)
    663 {
    664 	DIR *sysfs_mtd;
    665 	struct dirent *dirent;
    666 	struct libmtd *lib = (struct libmtd *)desc;
    667 
    668 	memset(info, 0, sizeof(struct mtd_info));
    669 
    670 	if (!lib->sysfs_supported)
    671 		return legacy_mtd_get_info(info);
    672 
    673 	info->sysfs_supported = 1;
    674 
    675 	/*
    676 	 * We have to scan the MTD sysfs directory to identify how many MTD
    677 	 * devices are present.
    678 	 */
    679 	sysfs_mtd = opendir(lib->sysfs_mtd);
    680 	if (!sysfs_mtd) {
    681 		if (errno == ENOENT) {
    682 			errno = ENODEV;
    683 			return -1;
    684 		}
    685 		return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd);
    686 	}
    687 
    688 	info->lowest_mtd_num = INT_MAX;
    689 	while (1) {
    690 		int mtd_num, ret;
    691 		char tmp_buf[256];
    692 
    693 		errno = 0;
    694 		dirent = readdir(sysfs_mtd);
    695 		if (!dirent)
    696 			break;
    697 
    698 		if (strlen(dirent->d_name) >= 255) {
    699 			errmsg("invalid entry in %s: \"%s\"",
    700 			       lib->sysfs_mtd, dirent->d_name);
    701 			errno = EINVAL;
    702 			goto out_close;
    703 		}
    704 
    705 		ret = sscanf(dirent->d_name, MTD_NAME_PATT"%s",
    706 			     &mtd_num, tmp_buf);
    707 		if (ret == 1) {
    708 			info->mtd_dev_cnt += 1;
    709 			if (mtd_num > info->highest_mtd_num)
    710 				info->highest_mtd_num = mtd_num;
    711 			if (mtd_num < info->lowest_mtd_num)
    712 				info->lowest_mtd_num = mtd_num;
    713 		}
    714 	}
    715 
    716 	if (!dirent && errno) {
    717 		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_mtd);
    718 		goto out_close;
    719 	}
    720 
    721 	if (closedir(sysfs_mtd))
    722 		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd);
    723 
    724 	if (info->lowest_mtd_num == INT_MAX)
    725 		info->lowest_mtd_num = 0;
    726 
    727 	return 0;
    728 
    729 out_close:
    730 	closedir(sysfs_mtd);
    731 	return -1;
    732 }
    733 
    734 int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd)
    735 {
    736 	int ret;
    737 	struct libmtd *lib = (struct libmtd *)desc;
    738 
    739 	memset(mtd, 0, sizeof(struct mtd_dev_info));
    740 	mtd->mtd_num = mtd_num;
    741 
    742 	if (!mtd_dev_present(desc, mtd_num)) {
    743 		errno = ENODEV;
    744 		return -1;
    745 	} else if (!lib->sysfs_supported)
    746 		return legacy_get_dev_info1(mtd_num, mtd);
    747 
    748 	if (dev_get_major(lib, mtd_num, &mtd->major, &mtd->minor))
    749 		return -1;
    750 
    751 	ret = dev_read_data(lib->mtd_name, mtd_num, &mtd->name,
    752 			    MTD_NAME_MAX + 1);
    753 	if (ret < 0)
    754 		return -1;
    755 	((char *)mtd->name)[ret - 1] = '\0';
    756 
    757 	ret = dev_read_data(lib->mtd_type, mtd_num, &mtd->type_str,
    758 			    MTD_TYPE_MAX + 1);
    759 	if (ret < 0)
    760 		return -1;
    761 	((char *)mtd->type_str)[ret - 1] = '\0';
    762 
    763 	if (dev_read_pos_int(lib->mtd_eb_size, mtd_num, &mtd->eb_size))
    764 		return -1;
    765 	if (dev_read_pos_ll(lib->mtd_size, mtd_num, &mtd->size))
    766 		return -1;
    767 	if (dev_read_pos_int(lib->mtd_min_io_size, mtd_num, &mtd->min_io_size))
    768 		return -1;
    769 	if (dev_read_pos_int(lib->mtd_subpage_size, mtd_num, &mtd->subpage_size))
    770 		return -1;
    771 	if (dev_read_pos_int(lib->mtd_oob_size, mtd_num, &mtd->oob_size))
    772 		return -1;
    773 	if (dev_read_pos_int(lib->mtd_region_cnt, mtd_num, &mtd->region_cnt))
    774 		return -1;
    775 	if (dev_read_hex_int(lib->mtd_flags, mtd_num, &ret))
    776 		return -1;
    777 	mtd->writable = !!(ret & MTD_WRITEABLE);
    778 
    779 	mtd->eb_cnt = mtd->size / mtd->eb_size;
    780 	mtd->type = type_str2int(mtd->type_str);
    781 	mtd->bb_allowed = !!(mtd->type == MTD_NANDFLASH ||
    782 				mtd->type == MTD_MLCNANDFLASH);
    783 
    784 	return 0;
    785 }
    786 
    787 int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
    788 {
    789 	int mtd_num;
    790 	struct libmtd *lib = (struct libmtd *)desc;
    791 
    792 	if (!lib->sysfs_supported)
    793 		return legacy_get_dev_info(node, mtd);
    794 
    795 	if (dev_node2num(lib, node, &mtd_num))
    796 		return -1;
    797 
    798 	return mtd_get_dev_info1(desc, mtd_num, mtd);
    799 }
    800 
    801 static inline int mtd_ioctl_error(const struct mtd_dev_info *mtd, int eb,
    802 				  const char *sreq)
    803 {
    804 	return sys_errmsg("%s ioctl failed for eraseblock %d (mtd%d)",
    805 			  sreq, eb, mtd->mtd_num);
    806 }
    807 
    808 static int mtd_valid_erase_block(const struct mtd_dev_info *mtd, int eb)
    809 {
    810 	if (eb < 0 || eb >= mtd->eb_cnt) {
    811 		errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks",
    812 		       eb, mtd->mtd_num, mtd->eb_cnt);
    813 		errno = EINVAL;
    814 		return -1;
    815 	}
    816 	return 0;
    817 }
    818 
    819 static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
    820 		     const char *sreq)
    821 {
    822 	int ret;
    823 	struct erase_info_user ei;
    824 
    825 	ret = mtd_valid_erase_block(mtd, eb);
    826 	if (ret)
    827 		return ret;
    828 
    829 	ei.start = eb * mtd->eb_size;
    830 	ei.length = mtd->eb_size;
    831 
    832 	ret = ioctl(fd, req, &ei);
    833 	if (ret < 0)
    834 		return mtd_ioctl_error(mtd, eb, sreq);
    835 
    836 	return 0;
    837 }
    838 #define mtd_xlock(mtd, fd, eb, req) mtd_xlock(mtd, fd, eb, req, #req)
    839 
    840 int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb)
    841 {
    842 	return mtd_xlock(mtd, fd, eb, MEMLOCK);
    843 }
    844 
    845 int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb)
    846 {
    847 	return mtd_xlock(mtd, fd, eb, MEMUNLOCK);
    848 }
    849 
    850 int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
    851 {
    852 	int ret;
    853 	struct libmtd *lib = (struct libmtd *)desc;
    854 	struct erase_info_user64 ei64;
    855 	struct erase_info_user ei;
    856 
    857 	ret = mtd_valid_erase_block(mtd, eb);
    858 	if (ret)
    859 		return ret;
    860 
    861 	ei64.start = (__u64)eb * mtd->eb_size;
    862 	ei64.length = mtd->eb_size;
    863 
    864 	if (lib->offs64_ioctls == OFFS64_IOCTLS_SUPPORTED ||
    865 	    lib->offs64_ioctls == OFFS64_IOCTLS_UNKNOWN) {
    866 		ret = ioctl(fd, MEMERASE64, &ei64);
    867 		if (ret == 0)
    868 			return ret;
    869 
    870 		if (errno != ENOTTY ||
    871 		    lib->offs64_ioctls != OFFS64_IOCTLS_UNKNOWN)
    872 			return mtd_ioctl_error(mtd, eb, "MEMERASE64");
    873 
    874 		/*
    875 		 * MEMERASE64 support was added in kernel version 2.6.31, so
    876 		 * probably we are working with older kernel and this ioctl is
    877 		 * not supported.
    878 		 */
    879 		lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED;
    880 	}
    881 
    882 	if (ei64.start + ei64.length > 0xFFFFFFFF) {
    883 		errmsg("this system can address only %u eraseblocks",
    884 		       0xFFFFFFFFU / mtd->eb_size);
    885 		errno = EINVAL;
    886 		return -1;
    887 	}
    888 
    889 	ei.start = ei64.start;
    890 	ei.length = ei64.length;
    891 	ret = ioctl(fd, MEMERASE, &ei);
    892 	if (ret < 0)
    893 		return mtd_ioctl_error(mtd, eb, "MEMERASE");
    894 	return 0;
    895 }
    896 
    897 int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo)
    898 {
    899 	int ret;
    900 
    901 	if (regidx < 0) {
    902 		errno = ENODEV;
    903 		return -1;
    904 	}
    905 
    906 	reginfo->regionindex = regidx;
    907 
    908 	ret = ioctl(fd, MEMGETREGIONINFO, reginfo);
    909 	if (ret < 0)
    910 		return sys_errmsg("%s ioctl failed for erase region %d",
    911 			"MEMGETREGIONINFO", regidx);
    912 
    913 	return 0;
    914 }
    915 
    916 int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb)
    917 {
    918 	int ret;
    919 	erase_info_t ei;
    920 
    921 	ei.start = eb * mtd->eb_size;
    922 	ei.length = mtd->eb_size;
    923 
    924 	ret = ioctl(fd, MEMISLOCKED, &ei);
    925 	if (ret < 0) {
    926 		if (errno != ENOTTY && errno != EOPNOTSUPP)
    927 			return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
    928 		else
    929 			errno = EOPNOTSUPP;
    930 	}
    931 
    932 	return ret;
    933 }
    934 
    935 /* Patterns to write to a physical eraseblock when torturing it */
    936 static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
    937 
    938 /**
    939  * check_pattern - check if buffer contains only a certain byte pattern.
    940  * @buf: buffer to check
    941  * @patt: the pattern to check
    942  * @size: buffer size in bytes
    943  *
    944  * This function returns %1 in there are only @patt bytes in @buf, and %0 if
    945  * something else was also found.
    946  */
    947 static int check_pattern(const void *buf, uint8_t patt, int size)
    948 {
    949 	int i;
    950 
    951 	for (i = 0; i < size; i++)
    952 		if (((const uint8_t *)buf)[i] != patt)
    953 			return 0;
    954 	return 1;
    955 }
    956 
    957 int mtd_torture(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
    958 {
    959 	int err, i, patt_count;
    960 	void *buf;
    961 
    962 	normsg("run torture test for PEB %d", eb);
    963 	patt_count = ARRAY_SIZE(patterns);
    964 
    965 	buf = xmalloc(mtd->eb_size);
    966 
    967 	for (i = 0; i < patt_count; i++) {
    968 		err = mtd_erase(desc, mtd, fd, eb);
    969 		if (err)
    970 			goto out;
    971 
    972 		/* Make sure the PEB contains only 0xFF bytes */
    973 		err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
    974 		if (err)
    975 			goto out;
    976 
    977 		err = check_pattern(buf, 0xFF, mtd->eb_size);
    978 		if (err == 0) {
    979 			errmsg("erased PEB %d, but a non-0xFF byte found", eb);
    980 			errno = EIO;
    981 			goto out;
    982 		}
    983 
    984 		/* Write a pattern and check it */
    985 		memset(buf, patterns[i], mtd->eb_size);
    986 		err = mtd_write(desc, mtd, fd, eb, 0, buf, mtd->eb_size, NULL,
    987 				0, 0);
    988 		if (err)
    989 			goto out;
    990 
    991 		memset(buf, ~patterns[i], mtd->eb_size);
    992 		err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
    993 		if (err)
    994 			goto out;
    995 
    996 		err = check_pattern(buf, patterns[i], mtd->eb_size);
    997 		if (err == 0) {
    998 			errmsg("pattern %x checking failed for PEB %d",
    999 				patterns[i], eb);
   1000 			errno = EIO;
   1001 			goto out;
   1002 		}
   1003 	}
   1004 
   1005 	err = 0;
   1006 	normsg("PEB %d passed torture test, do not mark it a bad", eb);
   1007 
   1008 out:
   1009 	free(buf);
   1010 	return -1;
   1011 }
   1012 
   1013 int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb)
   1014 {
   1015 	int ret;
   1016 	loff_t seek;
   1017 
   1018 	ret = mtd_valid_erase_block(mtd, eb);
   1019 	if (ret)
   1020 		return ret;
   1021 
   1022 	if (!mtd->bb_allowed)
   1023 		return 0;
   1024 
   1025 	seek = (loff_t)eb * mtd->eb_size;
   1026 	ret = ioctl(fd, MEMGETBADBLOCK, &seek);
   1027 	if (ret == -1)
   1028 		return mtd_ioctl_error(mtd, eb, "MEMGETBADBLOCK");
   1029 	return ret;
   1030 }
   1031 
   1032 int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb)
   1033 {
   1034 	int ret;
   1035 	loff_t seek;
   1036 
   1037 	if (!mtd->bb_allowed) {
   1038 		errno = EINVAL;
   1039 		return -1;
   1040 	}
   1041 
   1042 	ret = mtd_valid_erase_block(mtd, eb);
   1043 	if (ret)
   1044 		return ret;
   1045 
   1046 	seek = (loff_t)eb * mtd->eb_size;
   1047 	ret = ioctl(fd, MEMSETBADBLOCK, &seek);
   1048 	if (ret == -1)
   1049 		return mtd_ioctl_error(mtd, eb, "MEMSETBADBLOCK");
   1050 	return 0;
   1051 }
   1052 
   1053 int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
   1054 	     void *buf, int len)
   1055 {
   1056 	int ret, rd = 0;
   1057 	off_t seek;
   1058 
   1059 	ret = mtd_valid_erase_block(mtd, eb);
   1060 	if (ret)
   1061 		return ret;
   1062 
   1063 	if (offs < 0 || offs + len > mtd->eb_size) {
   1064 		errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d",
   1065 		       offs, len, mtd->mtd_num, mtd->eb_size);
   1066 		errno = EINVAL;
   1067 		return -1;
   1068 	}
   1069 
   1070 	/* Seek to the beginning of the eraseblock */
   1071 	seek = (off_t)eb * mtd->eb_size + offs;
   1072 	if (lseek(fd, seek, SEEK_SET) != seek)
   1073 		return sys_errmsg("cannot seek mtd%d to offset %"PRIdoff_t,
   1074 				  mtd->mtd_num, seek);
   1075 
   1076 	while (rd < len) {
   1077 		ret = read(fd, buf, len);
   1078 		if (ret < 0)
   1079 			return sys_errmsg("cannot read %d bytes from mtd%d (eraseblock %d, offset %d)",
   1080 					  len, mtd->mtd_num, eb, offs);
   1081 		rd += ret;
   1082 	}
   1083 
   1084 	return 0;
   1085 }
   1086 
   1087 static int legacy_auto_oob_layout(const struct mtd_dev_info *mtd, int fd,
   1088 				  int ooblen, void *oob) {
   1089 	struct nand_oobinfo old_oobinfo;
   1090 	int start, len;
   1091 	uint8_t *tmp_buf;
   1092 
   1093 	/* Read the current oob info */
   1094 	if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo))
   1095 		return sys_errmsg("MEMGETOOBSEL failed");
   1096 
   1097 	tmp_buf = malloc(ooblen);
   1098 	memcpy(tmp_buf, oob, ooblen);
   1099 
   1100 	/*
   1101 	 * We use autoplacement and have the oobinfo with the autoplacement
   1102 	 * information from the kernel available
   1103 	 */
   1104 	if (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
   1105 		int i, tags_pos = 0;
   1106 		for (i = 0; old_oobinfo.oobfree[i][1]; i++) {
   1107 			/* Set the reserved bytes to 0xff */
   1108 			start = old_oobinfo.oobfree[i][0];
   1109 			len = old_oobinfo.oobfree[i][1];
   1110 			memcpy(oob + start, tmp_buf + tags_pos, len);
   1111 			tags_pos += len;
   1112 		}
   1113 	} else {
   1114 		/* Set at least the ecc byte positions to 0xff */
   1115 		start = old_oobinfo.eccbytes;
   1116 		len = mtd->oob_size - start;
   1117 		memcpy(oob + start, tmp_buf + start, len);
   1118 	}
   1119 	free(tmp_buf);
   1120 
   1121 	return 0;
   1122 }
   1123 
   1124 int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb,
   1125 	      int offs, void *data, int len, void *oob, int ooblen,
   1126 	      uint8_t mode)
   1127 {
   1128 	int ret;
   1129 	off_t seek;
   1130 	struct mtd_write_req ops;
   1131 
   1132 	ret = mtd_valid_erase_block(mtd, eb);
   1133 	if (ret)
   1134 		return ret;
   1135 
   1136 	if (offs < 0 || offs + len > mtd->eb_size) {
   1137 		errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d",
   1138 		       offs, len, mtd->mtd_num, mtd->eb_size);
   1139 		errno = EINVAL;
   1140 		return -1;
   1141 	}
   1142 	if (offs % mtd->subpage_size) {
   1143 		errmsg("write offset %d is not aligned to mtd%d min. I/O size %d",
   1144 		       offs, mtd->mtd_num, mtd->subpage_size);
   1145 		errno = EINVAL;
   1146 		return -1;
   1147 	}
   1148 	if (len % mtd->subpage_size) {
   1149 		errmsg("write length %d is not aligned to mtd%d min. I/O size %d",
   1150 		       len, mtd->mtd_num, mtd->subpage_size);
   1151 		errno = EINVAL;
   1152 		return -1;
   1153 	}
   1154 
   1155 	/* Calculate seek address */
   1156 	seek = (off_t)eb * mtd->eb_size + offs;
   1157 
   1158 	if (oob) {
   1159 		ops.start = seek;
   1160 		ops.len = len;
   1161 		ops.ooblen = ooblen;
   1162 		ops.usr_data = (uint64_t)(unsigned long)data;
   1163 		ops.usr_oob = (uint64_t)(unsigned long)oob;
   1164 		ops.mode = mode;
   1165 
   1166 		ret = ioctl(fd, MEMWRITE, &ops);
   1167 		if (ret == 0)
   1168 			return 0;
   1169 		else if (errno != ENOTTY && errno != EOPNOTSUPP)
   1170 			return mtd_ioctl_error(mtd, eb, "MEMWRITE");
   1171 
   1172 		/* Fall back to old OOB ioctl() if necessary */
   1173 		if (mode == MTD_OPS_AUTO_OOB)
   1174 			if (legacy_auto_oob_layout(mtd, fd, ooblen, oob))
   1175 				return -1;
   1176 		if (mtd_write_oob(desc, mtd, fd, seek, ooblen, oob) < 0)
   1177 			return sys_errmsg("cannot write to OOB");
   1178 	}
   1179 	if (data) {
   1180 		/* Seek to the beginning of the eraseblock */
   1181 		if (lseek(fd, seek, SEEK_SET) != seek)
   1182 			return sys_errmsg("cannot seek mtd%d to offset %"PRIdoff_t,
   1183 					mtd->mtd_num, seek);
   1184 		ret = write(fd, data, len);
   1185 		if (ret != len)
   1186 			return sys_errmsg("cannot write %d bytes to mtd%d "
   1187 					  "(eraseblock %d, offset %d)",
   1188 					  len, mtd->mtd_num, eb, offs);
   1189 	}
   1190 
   1191 	return 0;
   1192 }
   1193 
   1194 static int do_oob_op(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
   1195 	      uint64_t start, uint64_t length, void *data, unsigned int cmd64,
   1196 	      unsigned int cmd)
   1197 {
   1198 	int ret, oob_offs;
   1199 	struct mtd_oob_buf64 oob64;
   1200 	struct mtd_oob_buf oob;
   1201 	unsigned long long max_offs;
   1202 	const char *cmd64_str, *cmd_str;
   1203 	struct libmtd *lib = (struct libmtd *)desc;
   1204 
   1205 	if (cmd64 ==  MEMREADOOB64) {
   1206 		cmd64_str = "MEMREADOOB64";
   1207 		cmd_str   = "MEMREADOOB";
   1208 	} else {
   1209 		cmd64_str = "MEMWRITEOOB64";
   1210 		cmd_str   = "MEMWRITEOOB";
   1211 	}
   1212 
   1213 	max_offs = (unsigned long long)mtd->eb_cnt * mtd->eb_size;
   1214 	if (start >= max_offs) {
   1215 		errmsg("bad page address %" PRIu64 ", mtd%d has %d eraseblocks (%llu bytes)",
   1216 		       start, mtd->mtd_num, mtd->eb_cnt, max_offs);
   1217 		errno = EINVAL;
   1218 		return -1;
   1219 	}
   1220 
   1221 	oob_offs = start & (mtd->min_io_size - 1);
   1222 	if (oob_offs + length > mtd->oob_size || length == 0) {
   1223 		errmsg("Cannot write %" PRIu64 " OOB bytes to address %" PRIu64 " (OOB offset %u) - mtd%d OOB size is only %d bytes",
   1224 		       length, start, oob_offs, mtd->mtd_num,  mtd->oob_size);
   1225 		errno = EINVAL;
   1226 		return -1;
   1227 	}
   1228 
   1229 	oob64.start = start;
   1230 	oob64.length = length;
   1231 	oob64.usr_ptr = (uint64_t)(unsigned long)data;
   1232 
   1233 	if (lib->offs64_ioctls == OFFS64_IOCTLS_SUPPORTED ||
   1234 	    lib->offs64_ioctls == OFFS64_IOCTLS_UNKNOWN) {
   1235 		ret = ioctl(fd, cmd64, &oob64);
   1236 		if (ret == 0)
   1237 			return ret;
   1238 
   1239 		if (errno != ENOTTY ||
   1240 		    lib->offs64_ioctls != OFFS64_IOCTLS_UNKNOWN) {
   1241 			sys_errmsg("%s ioctl failed for mtd%d, offset %" PRIu64 " (eraseblock %" PRIu64 ")",
   1242 				   cmd64_str, mtd->mtd_num, start, start / mtd->eb_size);
   1243 		}
   1244 
   1245 		/*
   1246 		 * MEMREADOOB64/MEMWRITEOOB64 support was added in kernel
   1247 		 * version 2.6.31, so probably we are working with older kernel
   1248 		 * and these ioctls are not supported.
   1249 		 */
   1250 		lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED;
   1251 	}
   1252 
   1253 	if (oob64.start > 0xFFFFFFFFULL) {
   1254 		errmsg("this system can address only up to address %lu",
   1255 		       0xFFFFFFFFUL);
   1256 		errno = EINVAL;
   1257 		return -1;
   1258 	}
   1259 
   1260 	oob.start = oob64.start;
   1261 	oob.length = oob64.length;
   1262 	oob.ptr = data;
   1263 
   1264 	ret = ioctl(fd, cmd, &oob);
   1265 	if (ret < 0)
   1266 		sys_errmsg("%s ioctl failed for mtd%d, offset %" PRIu64 " (eraseblock %" PRIu64 ")",
   1267 			   cmd_str, mtd->mtd_num, start, start / mtd->eb_size);
   1268 	return ret;
   1269 }
   1270 
   1271 int mtd_read_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
   1272 		 uint64_t start, uint64_t length, void *data)
   1273 {
   1274 	return do_oob_op(desc, mtd, fd, start, length, data,
   1275 			 MEMREADOOB64, MEMREADOOB);
   1276 }
   1277 
   1278 int mtd_write_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
   1279 		  uint64_t start, uint64_t length, void *data)
   1280 {
   1281 	return do_oob_op(desc, mtd, fd, start, length, data,
   1282 			 MEMWRITEOOB64, MEMWRITEOOB);
   1283 }
   1284 
   1285 int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
   1286 		  const char *img_name)
   1287 {
   1288 	int tmp, ret, in_fd, len, written = 0;
   1289 	off_t seek;
   1290 	struct stat st;
   1291 	char *buf;
   1292 
   1293 	ret = mtd_valid_erase_block(mtd, eb);
   1294 	if (ret)
   1295 		return ret;
   1296 
   1297 	if (offs < 0 || offs >= mtd->eb_size) {
   1298 		errmsg("bad offset %d, mtd%d eraseblock size is %d",
   1299 		       offs, mtd->mtd_num, mtd->eb_size);
   1300 		errno = EINVAL;
   1301 		return -1;
   1302 	}
   1303 	if (offs % mtd->subpage_size) {
   1304 		errmsg("write offset %d is not aligned to mtd%d min. I/O size %d",
   1305 		       offs, mtd->mtd_num, mtd->subpage_size);
   1306 		errno = EINVAL;
   1307 		return -1;
   1308 	}
   1309 
   1310 	in_fd = open(img_name, O_RDONLY | O_CLOEXEC);
   1311 	if (in_fd == -1)
   1312 		return sys_errmsg("cannot open \"%s\"", img_name);
   1313 
   1314 	if (fstat(in_fd, &st)) {
   1315 		sys_errmsg("cannot stat %s", img_name);
   1316 		goto out_close;
   1317 	}
   1318 
   1319 	len = st.st_size;
   1320 	if (len % mtd->subpage_size) {
   1321 		errmsg("size of \"%s\" is %d byte, which is not aligned to "
   1322 		       "mtd%d min. I/O size %d", img_name, len, mtd->mtd_num,
   1323 		       mtd->subpage_size);
   1324 		errno = EINVAL;
   1325 		goto out_close;
   1326 	}
   1327 	tmp = (offs + len + mtd->eb_size - 1) / mtd->eb_size;
   1328 	if (eb + tmp > mtd->eb_cnt) {
   1329 		errmsg("\"%s\" image size is %d bytes, mtd%d size is %d "
   1330 		       "eraseblocks, the image does not fit if we write it "
   1331 		       "starting from eraseblock %d, offset %d",
   1332 		       img_name, len, mtd->mtd_num, mtd->eb_cnt, eb, offs);
   1333 		errno = EINVAL;
   1334 		goto out_close;
   1335 	}
   1336 
   1337 	/* Seek to the beginning of the eraseblock */
   1338 	seek = (off_t)eb * mtd->eb_size + offs;
   1339 	if (lseek(fd, seek, SEEK_SET) != seek) {
   1340 		sys_errmsg("cannot seek mtd%d to offset %"PRIdoff_t,
   1341 			    mtd->mtd_num, seek);
   1342 		goto out_close;
   1343 	}
   1344 
   1345 	buf = xmalloc(mtd->eb_size);
   1346 
   1347 	while (written < len) {
   1348 		int rd = 0;
   1349 
   1350 		do {
   1351 			ret = read(in_fd, buf, mtd->eb_size - offs - rd);
   1352 			if (ret == -1) {
   1353 				sys_errmsg("cannot read \"%s\"", img_name);
   1354 				goto out_free;
   1355 			}
   1356 			rd += ret;
   1357 		} while (ret && rd < mtd->eb_size - offs);
   1358 
   1359 		ret = write(fd, buf, rd);
   1360 		if (ret != rd) {
   1361 			sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)",
   1362 				   len, mtd->mtd_num, eb, offs);
   1363 			goto out_free;
   1364 		}
   1365 
   1366 		offs = 0;
   1367 		eb += 1;
   1368 		written += rd;
   1369 	}
   1370 
   1371 	free(buf);
   1372 	close(in_fd);
   1373 	return 0;
   1374 
   1375 out_free:
   1376 	free(buf);
   1377 out_close:
   1378 	close(in_fd);
   1379 	return -1;
   1380 }
   1381 
   1382 int mtd_probe_node(libmtd_t desc, const char *node)
   1383 {
   1384 	struct stat st;
   1385 	struct mtd_info info;
   1386 	int i, mjr, mnr;
   1387 	struct libmtd *lib = (struct libmtd *)desc;
   1388 
   1389 	if (stat(node, &st))
   1390 		return sys_errmsg("cannot get information about \"%s\"", node);
   1391 
   1392 	if (!S_ISCHR(st.st_mode)) {
   1393 		errmsg("\"%s\" is not a character device", node);
   1394 		errno = EINVAL;
   1395 		return -1;
   1396 	}
   1397 
   1398 	mjr = major(st.st_rdev);
   1399 	mnr = minor(st.st_rdev);
   1400 
   1401 	if (mtd_get_info((libmtd_t *)lib, &info))
   1402 		return -1;
   1403 
   1404 	if (!lib->sysfs_supported)
   1405 		return 0;
   1406 
   1407 	for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) {
   1408 		int mjr1, mnr1, ret;
   1409 
   1410 		ret = dev_get_major(lib, i, &mjr1, &mnr1);
   1411 		if (ret) {
   1412 			if (errno == ENOENT)
   1413 				continue;
   1414 			if (!errno)
   1415 				break;
   1416 			return -1;
   1417 		}
   1418 
   1419 		if (mjr1 == mjr && mnr1 == mnr)
   1420 			return 1;
   1421 	}
   1422 
   1423 	errno = 0;
   1424 	return -1;
   1425 }
   1426