diff options
| author | Zhihao Cheng <chengzhihao1@huawei.com> | 2024-11-11 16:36:32 +0800 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2024-11-11 10:32:45 +0100 | 
| commit | e7e19cd9d8cc0f54ca463c4aebf7c4ef5e4f84f8 (patch) | |
| tree | 120b7a31d43d8bb995b3d1a1b007a8cf519e04b0 /ubifs-utils/mkfs.ubifs/devtable.c | |
| parent | cba2d7875328b05a4a76f619de0ce7050f2df971 (diff) | |
ubifs-utils: Split common source files from mkfs.ubifs
Split common source files into common dir from mkfs.ubifs, this is a
preparation for importing libubifs(from linux kernel) to replace
current UBIFS libs.
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'ubifs-utils/mkfs.ubifs/devtable.c')
| -rw-r--r-- | ubifs-utils/mkfs.ubifs/devtable.c | 535 | 
1 files changed, 0 insertions, 535 deletions
diff --git a/ubifs-utils/mkfs.ubifs/devtable.c b/ubifs-utils/mkfs.ubifs/devtable.c deleted file mode 100644 index aa815fb..0000000 --- a/ubifs-utils/mkfs.ubifs/devtable.c +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright (C) 2008 Nokia Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * 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., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: Artem Bityutskiy - * - * Part of the device table parsing code was taken from the mkfs.jffs2 utility. - * The original author of that code is Erik Andersen, hence: - *	Copyright (C) 2001, 2002 Erik Andersen <andersen@codepoet.org> - */ - -/* - * This file implemented device table support. Device table entries take the - * form of: - * <path>    <type> <mode> <uid> <gid> <major> <minor> <start>	<inc> <count> - * /dev/mem  c       640   0     0     1       1       0        0     - - * - * Type can be one of: - * f  A regular file - * d  Directory - * c  Character special device file - * b  Block special device file - * p  Fifo (named pipe) - * l  Link - * - * Don't bother with hard links (special cases of regular files), or sockets - * (why bother). - * - * Regular files must exist in the target root directory. If a char, block, - * fifo, or directory does not exist, it will be created. - * - * Please, refer the device_table.txt file which can be found at MTD utilities - * for more information about what the device table is. - */ - -#include "mkfs.ubifs.h" -#include "hashtable/hashtable.h" -#include "hashtable/hashtable_itr.h" - -/* - * The hash table which contains paths to files/directories/device nodes - * referred to in the device table. For example, if the device table refers - * "/dev/loop0", the @path_htbl will contain "/dev" element. - */ -static struct hashtable *path_htbl; - -/* Hash function used for hash tables */ -static unsigned int r5_hash(void *s) -{ -	unsigned int a = 0; -	const signed char *str = s; - -	while (*str) { -		a += *str << 4; -		a += *str >> 4; -		a *= 11; -		str++; -	} - -	return a; -} - -/* - * Check whether 2 keys of a hash table are equivalent. The keys are path/file - * names, so we simply use 'strcmp()'. - */ -static int is_equivalent(void *k1, void *k2) -{ -	return !strcmp(k1, k2); -} - -/** - * separate_last - separate out the last path component - * @buf: the path to split - * @len: length of the @buf string - * @path: the beginning of path is returned here - * @name: the last path component is returned here - * - * This helper function separates out the the last component of the full path - * string. For example, "/dev/loop" would be split on "/dev" and "loop". This - * function allocates memory for @path and @name and return the result there. - * Returns zero in case of success and a negative error code in case of - * failure. - */ -static int separate_last(const char *buf, int len, char **path, char **name) -{ -	int path_len = len, name_len; -	const char *p = buf + len, *n; - -	while (*--p != '/') -		path_len -= 1; - -	/* Drop the final '/' unless this is the root directory */ -	name_len = len - path_len; -	n = buf + path_len; -	if (path_len > 1) -		path_len -= 1; - -	*path = malloc(path_len + 1); -	if (!*path) -		return err_msg("cannot allocate %d bytes of memory", -			       path_len + 1); -	memcpy(*path, buf, path_len); -	(*path)[path_len] = '\0'; - -	*name = malloc(name_len + 1); -	if (!*name) { -		free(*path); -		return err_msg("cannot allocate %d bytes of memory", -			       name_len + 1); -	} -	memcpy(*name, n, name_len + 1); - -	return 0; -} - -static int interpret_table_entry(const char *line) -{ -	char buf[1024], type, *path = NULL, *name = NULL; -	int len; -	struct path_htbl_element *ph_elt = NULL; -	struct name_htbl_element *nh_elt = NULL; -	unsigned int mode = 0755, uid = 0, gid = 0, major = 0, minor = 0; -	unsigned int start = 0, increment = 0, count = 0; - -	if (sscanf(line, "%1023s %c %o %u %u %u %u %u %u %u", -		   buf, &type, &mode, &uid, &gid, &major, &minor, -		   &start, &increment, &count) < 0) -		return sys_err_msg("sscanf failed"); - -	dbg_msg(3, "name %s, type %c, mode %o, uid %u, gid %u, major %u, " -		"minor %u, start %u, inc %u, cnt %u", -		buf, type, mode, uid, gid, major, minor, start, -		increment, count); - -	len = strnlen(buf, 1024); -	if (len == 0) -		return err_msg("empty path"); -	if (len == 1024) -		return err_msg("too long path"); - -	if (buf[0] != '/') -		return err_msg("device table entries require absolute paths"); -	if (strstr(buf, "//")) -		return err_msg("'//' cannot be used in the path"); -	if (len > 1 && buf[len - 1] == '/') -		return err_msg("do not put '/' at the end"); - -	if (strstr(buf, "/./") || strstr(buf, "/../") || -	    !strcmp(buf + len - 2, "/.") || !strcmp(buf + len - 3, "/..")) -		return err_msg("'.' and '..' cannot be used in the path"); - -	switch (type) { -		case 'd': -			mode |= S_IFDIR; -			break; -		case 'f': -			mode |= S_IFREG; -			break; -		case 'p': -			mode |= S_IFIFO; -			break; -		case 'c': -			mode |= S_IFCHR; -			break; -		case 'b': -			mode |= S_IFBLK; -			break; -		case 'l': -			mode |= S_IFLNK; -			if ((mode & 0777) != 0777) -				return err_msg("link permission must be 0777"); -			break; -		default: -			return err_msg("unsupported file type '%c'", type); -	} - -	if (separate_last(buf, len, &path, &name)) -		return -1; - -	/* -	 * Check if this path already exist in the path hash table and add it -	 * if it is not. -	 */ -	ph_elt = hashtable_search(path_htbl, path); -	if (!ph_elt) { -		dbg_msg(3, "inserting '%s' into path hash table", path); -		ph_elt = malloc(sizeof(struct path_htbl_element)); -		if (!ph_elt) { -			err_msg("cannot allocate %zd bytes of memory", -				sizeof(struct path_htbl_element)); -			goto out_free; -		} - -		if (!hashtable_insert(path_htbl, path, ph_elt)) { -			err_msg("cannot insert into path hash table"); -			goto out_free; -		} - -		ph_elt->path = path; -		path = NULL; -		ph_elt->name_htbl = create_hashtable(128, &r5_hash, -						     &is_equivalent); -		if (!ph_elt->name_htbl) { -			err_msg("cannot create name hash table"); -			goto out_free; -		} -	} - -	if (increment != 0 && count == 0) { -		err_msg("count cannot be zero if increment is non-zero"); -		goto out_free; -	} - -	/* -	 * Add the file/directory/device node (last component of the path) to -	 * the name hashtable. The name hashtable resides in the corresponding -	 * path hashtable element. -	 */ - -	if (count == 0) { -		/* This entry does not require any iterating */ -		nh_elt = malloc(sizeof(struct name_htbl_element)); -		if (!nh_elt) { -			err_msg("cannot allocate %zd bytes of memory", -				sizeof(struct name_htbl_element)); -			goto out_free; -		} - -		nh_elt->mode = mode; -		nh_elt->uid = uid; -		nh_elt->gid = gid; -		nh_elt->dev = makedev(major, minor); - -		dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)", -			name, major(nh_elt->dev), minor(nh_elt->dev)); - -		if (hashtable_search(ph_elt->name_htbl, name)) { -			err_msg("'%s' is referred twice", buf); -			goto out_free; -		} - -		nh_elt->name = name; -		if (!hashtable_insert(ph_elt->name_htbl, name, nh_elt)) { -			err_msg("cannot insert into name hash table"); -			goto out_free; -		} -	} else { -		int i, num = start + count, len = strlen(name) + 20; -		char *nm; - -		for (i = start; i < num; i++) { -			nh_elt = malloc(sizeof(struct name_htbl_element)); -			if (!nh_elt) { -				err_msg("cannot allocate %zd bytes of memory", -					sizeof(struct name_htbl_element)); -				goto out_free; -			} - -			nh_elt->mode = mode; -			nh_elt->uid = uid; -			nh_elt->gid = gid; -			nh_elt->dev = makedev(major, minor + (i - start) * increment); - -			nm = malloc(len); -			if (!nm) { -				err_msg("cannot allocate %d bytes of memory", len); -				goto out_free; -			} - -			sprintf(nm, "%s%d", name, i); -			nh_elt->name = nm; - -			dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)", -			        nm, major(nh_elt->dev), minor(nh_elt->dev)); - -			if (hashtable_search(ph_elt->name_htbl, nm)) { -				err_msg("'%s' is referred twice", buf); -				free (nm); -				goto out_free; -			} - -			if (!hashtable_insert(ph_elt->name_htbl, nm, nh_elt)) { -				err_msg("cannot insert into name hash table"); -				free (nm); -				goto out_free; -			} -		} -		free(name); -		name = NULL; -	} - -	return 0; - -out_free: -	free(ph_elt); -	free(nh_elt); -	free(path); -	free(name); -	return -1; -} - -/** - * parse_devtable - parse the device table. - * @tbl_file: device table file name - * - * This function parses the device table and prepare the hash table which will - * later be used by mkfs.ubifs to create the specified files/device nodes. - * Returns zero in case of success and a negative error code in case of - * failure. - */ -int parse_devtable(const char *tbl_file) -{ -	FILE *f; -	char *line = NULL; -	struct stat st; -	size_t len; - -	dbg_msg(1, "parsing device table file '%s'", tbl_file); - -	path_htbl = create_hashtable(128, &r5_hash, &is_equivalent); -	if (!path_htbl) -		return err_msg("cannot create path hash table"); - -	f = fopen(tbl_file, "r"); -	if (!f) -		return sys_err_msg("cannot open '%s'", tbl_file); - -	if (fstat(fileno(f), &st) < 0) { -		sys_err_msg("cannot stat '%s'", tbl_file); -		goto out_close; -	} - -	if (st.st_size < 10) { -		sys_err_msg("'%s' is too short", tbl_file); -		goto out_close; -	} - -	/* -	 * The general plan now is to read in one line at a time, check for -	 * leading comment delimiters ('#'), then try and parse the line as a -	 * device table -	 */ -	while (getline(&line, &len, f) != -1) { -		/* First trim off any white-space */ -		len = strlen(line); - -		/* Trim trailing white-space */ -		while (len > 0 && isspace(line[len - 1])) -			line[--len] = '\0'; -		/* Trim leading white-space */ -		memmove(line, &line[strspn(line, " \n\r\t\v")], len); - -		/* How long are we after trimming? */ -		len = strlen(line); - -		/* If this is not a comment line, try to interpret it */ -		if (len && *line != '#') { -			if (interpret_table_entry(line)) { -				err_msg("cannot parse '%s'", line); -				goto out_close; -			} -		} - -		free(line); -		line = NULL; -	} - -	dbg_msg(1, "finished parsing"); -	fclose(f); -	return 0; - -out_close: -	fclose(f); -	free_devtable_info(); -	return -1; -} - -/** - * devtbl_find_path - find a path in the path hash table. - * @path: UBIFS path to find. - * - * This looks up the path hash table. Returns the path hash table element - * reference if @path was found and %NULL if not. - */ -struct path_htbl_element *devtbl_find_path(const char *path) -{ -	if (!path_htbl) -		return NULL; - -	return hashtable_search(path_htbl, (void *)path); -} - -/** - * devtbl_find_name - find a name in the name hash table. - * @ph_etl: path hash table element to find at - * @name: name to find - * - * This looks up the name hash table. Returns the name hash table element - * reference if @name found and %NULL if not. - */ -struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt, -					   const char *name) -{ -	if (!path_htbl) -		return NULL; - -	return hashtable_search(ph_elt->name_htbl, (void *)name); -} - -/** - * override_attributes - override inode attributes. - * @st: struct stat object to containing the attributes to override - * @ph_elt: path hash table element object - * @nh_elt: name hash table element object containing the new values - * - * The device table file may override attributes like UID of files. For - * example, the device table may contain a "/dev" entry, and the UBIFS FS on - * the host may contain "/dev" directory. In this case the attributes of the - * "/dev" directory inode has to be as the device table specifies. - * - * Note, the hash element is removed by this function as well. - */ -int override_attributes(struct stat *st, struct path_htbl_element *ph_elt, -			struct name_htbl_element *nh_elt) -{ -	if (!path_htbl) -		return 0; - -	if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode) || -	    S_ISFIFO(st->st_mode)) -		return err_msg("%s/%s both exists at UBIFS root at host, " -			       "and is referred from the device table", -			       strcmp(ph_elt->path, "/") ? ph_elt->path : "", -			       nh_elt->name); - -	if ((st->st_mode & S_IFMT) != (nh_elt->mode & S_IFMT)) -		return err_msg("%s/%s is referred from the device table also exists in " -			       "the UBIFS root directory at host, but the file type is " -			       "different", strcmp(ph_elt->path, "/") ? ph_elt->path : "", -			       nh_elt->name); - -	dbg_msg(3, "set UID %d, GID %d, mode %o for %s/%s as device table says", -		nh_elt->uid, nh_elt->gid, nh_elt->mode, ph_elt->path, nh_elt->name); - -	st->st_uid = nh_elt->uid; -	st->st_gid = nh_elt->gid; -	st->st_mode = nh_elt->mode; - -	hashtable_remove(ph_elt->name_htbl, (void *)nh_elt->name); -	return 0; -} - -/** - * first_name_htbl_element - return first element of the name hash table. - * @ph_elt: the path hash table the name hash table belongs to - * @itr: double pointer to a 'struct hashtable_itr' object where the - *       information about further iterations is stored - * - * This function implements name hash table iteration together with - * 'next_name_htbl_element()'. Returns the first name hash table element or - * %NULL if the hash table is empty. - */ -struct name_htbl_element * -first_name_htbl_element(struct path_htbl_element *ph_elt, -			struct hashtable_itr **itr) -{ -	if (!path_htbl || !ph_elt || hashtable_count(ph_elt->name_htbl) == 0) -		return NULL; - -	*itr = hashtable_iterator(ph_elt->name_htbl); -	return hashtable_iterator_value(*itr); -} - -/** - * first_name_htbl_element - return next element of the name hash table. - * @ph_elt: the path hash table the name hash table belongs to - * @itr: double pointer to a 'struct hashtable_itr' object where the - *       information about further iterations is stored - * - * This function implements name hash table iteration together with - * 'first_name_htbl_element()'. Returns the next name hash table element or - * %NULL if there are no more elements. - */ -struct name_htbl_element * -next_name_htbl_element(struct path_htbl_element *ph_elt, -		       struct hashtable_itr **itr) -{ -	if (!path_htbl || !ph_elt || !hashtable_iterator_advance(*itr)) -		return NULL; - -	return hashtable_iterator_value(*itr); -} - -/** - * free_devtable_info - free device table information. - * - * This function frees the path hash table and the name hash tables. - */ -void free_devtable_info(void) -{ -	struct hashtable_itr *ph_itr; -	struct path_htbl_element *ph_elt; - -	if (!path_htbl) -		return; - -	if (hashtable_count(path_htbl) > 0) { -		ph_itr = hashtable_iterator(path_htbl); -		do { -			ph_elt = hashtable_iterator_value(ph_itr); -			/* -			 * Note, since we use the same string for the key and -			 * @name in the name hash table elements, we do not -			 * have to iterate name hash table because @name memory -			 * will be freed when freeing the key. -			 */ -			hashtable_destroy(ph_elt->name_htbl, 1); -		} while (hashtable_iterator_advance(ph_itr)); -		free(ph_itr); -	} -	hashtable_destroy(path_htbl, 1); -}  | 
