/* vi: set sw=4 ts=4: */
/*
 *
 * mdev - Mini udev for busybox
 *
 * Copyright 2005 Rob Landley <rob@landley.net>
 * Copyright 2005 Frank Sorenson <frank@tuxrocks.com>
 *
 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
 */

#include "libbb.h"
#include "xregex.h"

#define DEV_PATH	"/dev"

struct mdev_globals
{
	int root_major, root_minor;
} mdev_globals;

#define bbg mdev_globals

/* mknod in /dev based on a path like "/sys/block/hda/hda1" */
static void make_device(char *path, int delete)
{
	char *device_name;
	int major, minor, type, len;
	int mode = 0660;
	uid_t uid = 0;
	gid_t gid = 0;
	char *temp = path + strlen(path);
	char *command = NULL;

	/* Try to read major/minor string.  Note that the kernel puts \n after
	 * the data, so we don't need to worry about null terminating the string
	 * because sscanf() will stop at the first nondigit, which \n is.  We
	 * also depend on path having writeable space after it. */

	if (!delete) {
		strcat(path, "/dev");
		len = open_read_close(path, temp + 1, 64);
		*temp++ = 0;
		if (len < 1) return;
	}

	/* Determine device name, type, major and minor */

	device_name = strrchr(path, '/') + 1;
	type = path[5]=='c' ? S_IFCHR : S_IFBLK;

	/* If we have a config file, look up permissions for this device */

	if (ENABLE_FEATURE_MDEV_CONF) {
		char *conf, *pos, *end;
		int line, fd;

		/* mmap the config file */
		fd = open("/etc/mdev.conf", O_RDONLY);
		if (fd < 0)
			goto end_parse;
		len = xlseek(fd, 0, SEEK_END);
		conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
		close(fd);
		if (!conf)
			goto end_parse;

		line = 0;
		/* Loop through lines in mmaped file*/
		for (pos=conf; pos-conf<len;) {
			int field;
			char *end2;

			line++;
			/* find end of this line */
			for (end=pos; end-conf<len && *end!='\n'; end++)
				;

			/* Three fields: regex, uid:gid, mode */
			for (field=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC);
					field++)
			{
				/* Skip whitespace */
				while (pos<end && isspace(*pos)) pos++;
				if (pos==end || *pos=='#') break;
				for (end2=pos;
					end2<end && !isspace(*end2) && *end2!='#'; end2++)
					;

				if (field == 0) {
					/* Regex to match this device */

					char *regex = strndupa(pos, end2-pos);
					regex_t match;
					regmatch_t off;
					int result;

					/* Is this it? */
					xregcomp(&match,regex, REG_EXTENDED);
					result = regexec(&match, device_name, 1, &off, 0);
					regfree(&match);

					/* If not this device, skip rest of line */
					if (result || off.rm_so
							|| off.rm_eo != strlen(device_name))
						break;
				}
				if (field == 1) {
					/* uid:gid */

					char *s, *s2;

					/* Find : */
					for (s=pos; s<end2 && *s!=':'; s++)
						;
					if (s == end2) break;

					/* Parse UID */
					uid = strtoul(pos, &s2, 10);
					if (s != s2) {
						struct passwd *pass;
						pass = getpwnam(strndupa(pos, s-pos));
						if (!pass) break;
						uid = pass->pw_uid;
					}
					s++;
					/* parse GID */
					gid = strtoul(s, &s2, 10);
					if (end2 != s2) {
						struct group *grp;
						grp = getgrnam(strndupa(s, end2-s));
						if (!grp) break;
						gid = grp->gr_gid;
					}
				}
				if (field == 2) {
					/* mode */

					mode = strtoul(pos, &pos, 8);
					if (pos != end2) break;
				}
				if (ENABLE_FEATURE_MDEV_EXEC && field == 3) {
					// Command to run
					const char *s = "@$*";
					const char *s2;
					s2 = strchr(s, *pos++);
					if (!s2) {
						// Force error
						field = 1;
						break;
					}
					if ((s2-s+1) & (1<<delete))
						command = xstrndup(pos, end-pos);
				}

				pos = end2;
			}

			/* Did everything parse happily? */

			if (field > 2) break;
			if (field) bb_error_msg_and_die("bad line %d",line);

			/* Next line */
			pos = ++end;
		}
		munmap(conf, len);
 end_parse:	/* nothing */ ;
	}

	umask(0);
	if (!delete) {
		if (sscanf(temp, "%d:%d", &major, &minor) != 2) return;
		if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
			bb_perror_msg_and_die("mknod %s", device_name);

		if (major == bbg.root_major && minor == bbg.root_minor)
			symlink(device_name, "root");

		if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid);
	}
	if (command) {
		int rc;
		char *s;

		s = xasprintf("MDEV=%s", device_name);
		putenv(s);
		rc = system(command);
		s[4] = 0;
		putenv(s);
		free(s);
		free(command);
		if (rc == -1) bb_perror_msg_and_die("cannot run %s", command);
	}
	if (delete) unlink(device_name);
}

/* Recursive search of /sys/block or /sys/class.  path must be a writeable
 * buffer of size PATH_MAX containing the directory string to start at. */

static void find_dev(char *path)
{
	DIR *dir;
	size_t len = strlen(path);
	struct dirent *entry;

	dir = opendir(path);
	if (dir == NULL)
		return;

	while ((entry = readdir(dir)) != NULL) {
		struct stat st;

		/* Skip "." and ".." (also skips hidden files, which is ok) */

		if (entry->d_name[0] == '.')
			continue;

		// uClibc doesn't fill out entry->d_type reliably. so we use lstat().

		snprintf(path+len, PATH_MAX-len, "/%s", entry->d_name);
		if (!lstat(path, &st) && S_ISDIR(st.st_mode)) find_dev(path);
		path[len] = 0;

		/* If there's a dev entry, mknod it */

		if (!strcmp(entry->d_name, "dev")) make_device(path, 0);
	}

	closedir(dir);
}

int mdev_main(int argc, char **argv);
int mdev_main(int argc, char **argv)
{
	char *action;
	char *env_path;
	RESERVE_CONFIG_BUFFER(temp,PATH_MAX);

	xchdir(DEV_PATH);

	/* Scan */

	if (argc == 2 && !strcmp(argv[1],"-s")) {
		struct stat st;

		xstat("/", &st);
		bbg.root_major = major(st.st_dev);
		bbg.root_minor = minor(st.st_dev);
		strcpy(temp,"/sys/block");
		find_dev(temp);
		strcpy(temp,"/sys/class");
		find_dev(temp);

	/* Hotplug */

	} else {
		action = getenv("ACTION");
		env_path = getenv("DEVPATH");
		if (!action || !env_path)
			bb_show_usage();

		sprintf(temp, "/sys%s", env_path);
		if (!strcmp(action, "add")) make_device(temp,0);
		else if (!strcmp(action, "remove")) make_device(temp,1);
	}

	if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp);
	return 0;
}
