#include <sys/wait.h>
#include <sys/sysmacros.h>
-#include <linux/fs.h>
-
#include <uci.h>
#include <uci_blob.h>
return 0;
}
+static bool mtdblock_is_nand(char *mtdnum)
+{
+ char tmppath[64];
+ char buf[16];
+ FILE *fp;
+
+ snprintf(tmppath, sizeof(tmppath) - 1, "/sys/class/mtd/mtd%s/type", mtdnum);
+ fp = fopen(tmppath, "r");
+ if (!fp)
+ return false;
+
+ if (!fgets(buf, sizeof(buf), fp)) {
+ fclose(fp);
+ return false;
+ }
+ fclose(fp);
+ buf[sizeof(buf) - 1] = '\0'; /* make sure buf is 0-terminated */
+ buf[strlen(buf) - 1] = '\0'; /* strip final char (newline) */
+
+ if (strcmp(buf, "nand"))
+ return false;
+
+ /*
+ * --- CUT HERE ---
+ * Keep probing rootfs and rootfs_data in the meantime to not break
+ * devices using JFFS2 on NAND but only trigger the kernel warnings.
+ * Remove this once all devices using JFFS2 and squashfs directly on
+ * NAND have been converted to UBI.
+ */
+ snprintf(tmppath, sizeof(tmppath) - 1, "/sys/class/mtd/mtd%s/name", mtdnum);
+ fp = fopen(tmppath, "r");
+ if (!fp)
+ return false;
+
+ if (!fgets(buf, sizeof(buf), fp)) {
+ fclose(fp);
+ return false;
+ }
+ fclose(fp);
+ buf[sizeof(buf) - 1] = '\0'; /* make sure buf is 0-terminated */
+ buf[strlen(buf) - 1] = '\0'; /* strip final char (newline) */
+
+ /* only return true if name differs from 'rootfs' and 'rootfs_data' */
+ if (strcmp(buf, "rootfs") && strcmp(buf, "rootfs_data"))
+ return true;
+
+ /* --- CUT HERE --- */
+ return false;
+}
+
static struct probe_info* _probe_path(char *path)
{
- struct probe_info *pr;
+ struct probe_info *pr, *epr;
char tmppath[64];
- /* skip ubi device if ubiblock device is present */
+ if (!strncmp(path, "/dev/mtdblock", 13) && mtdblock_is_nand(path + 13))
+ return NULL;
+
+ pr = probe_path(path);
+ if (!pr)
+ return NULL;
+
if (path[5] == 'u' && path[6] == 'b' && path[7] == 'i' &&
path[8] >= '0' && path[8] <= '9' ) {
+ /* skip ubi device if not UBIFS (as it requires ubiblock) */
+ if (strcmp("ubifs", pr->type))
+ return NULL;
+
+ /* skip ubi device if ubiblock device is present */
snprintf(tmppath, sizeof(tmppath), "/dev/ubiblock%s", path + 8);
- list_for_each_entry(pr, &devices, list)
- if (!strcasecmp(pr->dev, tmppath))
+ list_for_each_entry(epr, &devices, list)
+ if (!strcmp(epr->dev, tmppath))
return NULL;
}
- return probe_path(path);
+ return pr;
}
static int _cache_load(const char *path)
_cache_load("/dev/nvme*");
_cache_load("/dev/vd*");
_cache_load("/dev/xvd*");
- _cache_load("/dev/mapper/*");
+ _cache_load("/dev/dm-*");
+ _cache_load("/dev/fit*");
}
return err;
}
+static const char * const ntfs_fs[] = { "ntfs3", "ntfs-3g", "antfs", "ntfs" };
+
static int handle_mount(const char *source, const char *target,
const char *fstype, struct mount *m)
{
- int i, err;
size_t mount_opts_len;
char *mount_opts = NULL, *ptr;
+ const char * const *filesystems;
+ int err = -EINVAL;
+ size_t count;
+ int i;
- err = mount(source, target, fstype, m ? m->flags : 0,
- (m && m->options) ? m->options : "");
+ if (!strcmp(fstype, "ntfs")) {
+ filesystems = ntfs_fs;
+ count = ARRAY_SIZE(ntfs_fs);
+ } else {
+ filesystems = &fstype;
+ count = 1;
+ }
+
+ for (i = 0; i < count; i++) {
+ const char *fs = filesystems[i];
+
+ err = mount(source, target, fs, m ? m->flags : 0,
+ (m && m->options) ? m->options : "");
+ if (!err || errno != ENODEV)
+ break;
+ }
/* Requested file system type is not available in kernel,
attempt to call mount helper. */
}
/* ... and now finally invoke the external mount program */
- err = exec_mount(source, target, fstype, mount_opts);
+ for (i = 0; i < count; i++) {
+ const char *fs = filesystems[i];
+
+ err = exec_mount(source, target, fs, mount_opts);
+ if (!err)
+ break;
+ }
}
+ free(mount_opts);
+
return err;
}
static int umount_device(char *path, int type, bool all)
{
- char *mp;
+ char *mp, *devpath;
int err;
- mp = find_mount_point(path);
+ if (strlen(path) > 5 && !strncmp("/dev/", path, 5)) {
+ mp = find_mount_point(path);
+ } else {
+ devpath = malloc(strlen(path) + 6);
+ strcpy(devpath, "/dev/");
+ strcat(devpath, path);
+ mp = find_mount_point(devpath);
+ free(devpath);
+ }
+
if (!mp)
return -1;
- if (!strcmp(mp, "/") && !all)
+ if (!strcmp(mp, "/") && !all) {
+ free(mp);
return 0;
-
+ }
if (type != TYPE_AUTOFS)
blockd_notify("umount", basename(path), NULL, NULL);
if (!action || !device)
return -1;
- if (config_load(NULL))
- return -1;
-
- cache_load(1);
-
- list_for_each_entry(pr, &devices, list)
- if (!strcmp(basename(pr->dev), device))
- path = pr->dev;
-
- if (!path)
- return -1;
-
if (!strcmp(action, "remove")) {
if (type == TYPE_HOTPLUG)
blockd_notify("hotplug", device, NULL, NULL);
- umount_device(path, type, true);
+ umount_device(device, type, true);
return 0;
} else if (strcmp(action, "add")) {
return -1;
}
+ if (config_load(NULL))
+ return -1;
+
+ cache_load(1);
+
+ list_for_each_entry(pr, &devices, list)
+ if (!strcmp(basename(pr->dev), device))
+ path = pr->dev;
+
+ if (!path)
+ return -1;
+
return mount_device(find_block_info(NULL, NULL, path), type);
}
if (config_load(NULL))
return -1;
- cache_load(0);
+ cache_load(1);
list_for_each_entry(pr, &devices, list) {
struct mount *m;
char *mp;
}
#endif
-static int find_root_dev(char *buf, int len)
+static int find_dev(const char *path, char *buf, int len)
{
DIR *d;
dev_t root;
struct stat s;
struct dirent *e;
- if (stat("/", &s))
+ if (stat(path, &s))
return -1;
if (!(d = opendir("/dev")))
return -1;
}
+static int find_root_dev(char *buf, int len)
+{
+ int err = find_dev("/", buf, len);
+ if (err)
+ err = find_dev("/rom", buf, len);
+
+ return err;
+}
+
static int test_fs_support(const char *name)
{
char line[128], *p;
FILE *fp;
int err;
- err = find_block_mtd("\"rootfs\"", devpath, sizeof(devpath));
+ snprintf(tag, sizeof(tag), "%s/etc/.extroot-default", path);
+ if (stat(tag, &s))
+ return 0;
+
+ err = find_root_dev(devpath, sizeof(devpath));
+ if (err)
+ err = find_block_mtd("\"rootfs\"", devpath, sizeof(devpath));
#ifdef UBIFS_EXTROOT
if (err) {
libubi_t libubi;
libubi_close(libubi);
}
#endif
- if (err) {
- err = find_root_dev(devpath, sizeof(devpath));
- }
if (err) {
ULOG_ERR("extroot: unable to determine root device\n");
return -1;
/* enable LOG_INFO messages */
ulog_threshold(LOG_INFO);
+ /* try the currently mounted overlay if exists */
+ err = mount_extroot("/tmp/overlay");
+ if (!err)
+ return err;
+
/*
* Look for "rootfs_data". We will want to mount it and check for
* extroot configuration.
handle_swapfiles(false);
- cache_load(0);
+ cache_load(1);
if (argc == 3)
all = !strcmp(argv[2], "-a");