wok rev 17423

linux-uml: hardlink on fifos, sockets, char & block devices and symlinks in initramfs
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Dec 04 16:09:50 2014 +0100 (2014-12-04)
parents e2056bc81ae5
children aee33ab23215
files linux-uml/receipt linux-uml/stuff/linux-hardlinks.u
line diff
     1.1 --- a/linux-uml/receipt	Thu Dec 04 14:08:30 2014 +0200
     1.2 +++ b/linux-uml/receipt	Thu Dec 04 16:09:50 2014 +0100
     1.3 @@ -27,6 +27,7 @@
     1.4  		xzcat $SRC/$(basename $PATCH) | patch -Np1
     1.5  		touch done.patch-$VERSION
     1.6  	fi
     1.7 +	patch -p1 < $stuff/linux-hardlinks.u
     1.8  	sed -i 's/uname -m/echo i386/;s|/bin/bash|/bin/ash|g' Makefile
     1.9  	make ARCH=um mrproper	
    1.10  	cat > mini.config << EOF &&
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/linux-uml/stuff/linux-hardlinks.u	Thu Dec 04 16:09:50 2014 +0100
     2.3 @@ -0,0 +1,244 @@
     2.4 +Fix hardlink on fifos, sockets, char & block devices and symlinks
     2.5 +--- linux-3.2.53/init/initramfs.c
     2.6 ++++ linux-3.2.53/init/initramfs.c
     2.7 +@@ -20,10 +20,24 @@
     2.8 + 
     2.9 + #define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
    2.10 + 
    2.11 ++static __initdata unsigned long ino, major, minor, nlink;
    2.12 ++static __initdata time_t mtime;
    2.13 ++static __initdata mode_t mode;
    2.14 ++static __initdata unsigned long body_len, name_len;
    2.15 ++static __initdata uid_t uid;
    2.16 ++static __initdata gid_t gid;
    2.17 ++static __initdata unsigned rdev;
    2.18 ++
    2.19 ++struct names {
    2.20 ++	struct names *next;
    2.21 ++	char name[1];
    2.22 ++};
    2.23 ++
    2.24 + static __initdata struct hash {
    2.25 +-	int ino, minor, major;
    2.26 ++	int ino, nlink, minor, major;
    2.27 + 	mode_t mode;
    2.28 + 	struct hash *next;
    2.29 ++	struct names *next_name;
    2.30 + 	char name[N_ALIGN(PATH_MAX)];
    2.31 + } *head[32];
    2.32 + 
    2.33 +@@ -34,8 +48,7 @@
    2.34 + 	return tmp & 31;
    2.35 + }
    2.36 + 
    2.37 +-static char __init *find_link(int major, int minor, int ino,
    2.38 +-			      mode_t mode, char *name)
    2.39 ++static struct hash  __init *find_link(char *name)
    2.40 + {
    2.41 + 	struct hash **p, *q;
    2.42 + 	for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
    2.43 +@@ -47,7 +60,16 @@
    2.44 + 			continue;
    2.45 + 		if (((*p)->mode ^ mode) & S_IFMT)
    2.46 + 			continue;
    2.47 +-		return (*p)->name;
    2.48 ++		if (--(*p)->nlink) {
    2.49 ++			struct names **n;
    2.50 ++			for (n = &(*p)->next_name; *n; n = &(*n)->next);
    2.51 ++			*n = kmalloc(sizeof(struct names) + strlen(name), GFP_KERNEL);
    2.52 ++			if (!*n)
    2.53 ++				panic("can't allocate link name entry");
    2.54 ++			strcpy((*n)->name, name);
    2.55 ++			(*n)->next = NULL;
    2.56 ++		}
    2.57 ++		return *p;
    2.58 + 	}
    2.59 + 	q = kmalloc(sizeof(struct hash), GFP_KERNEL);
    2.60 + 	if (!q)
    2.61 +@@ -55,11 +77,13 @@
    2.62 + 	q->major = major;
    2.63 + 	q->minor = minor;
    2.64 + 	q->ino = ino;
    2.65 ++	q->nlink = nlink;
    2.66 + 	q->mode = mode;
    2.67 + 	strcpy(q->name, name);
    2.68 ++	q->next_name = NULL;
    2.69 + 	q->next = NULL;
    2.70 + 	*p = q;
    2.71 +-	return NULL;
    2.72 ++	return q;
    2.73 + }
    2.74 + 
    2.75 + static void __init free_hash(void)
    2.76 +@@ -115,17 +139,8 @@
    2.77 + 	}
    2.78 + }
    2.79 + 
    2.80 +-static __initdata time_t mtime;
    2.81 +-
    2.82 + /* cpio header parsing */
    2.83 + 
    2.84 +-static __initdata unsigned long ino, major, minor, nlink;
    2.85 +-static __initdata mode_t mode;
    2.86 +-static __initdata unsigned long body_len, name_len;
    2.87 +-static __initdata uid_t uid;
    2.88 +-static __initdata gid_t gid;
    2.89 +-static __initdata unsigned rdev;
    2.90 +-
    2.91 + static void __init parse_header(char *s)
    2.92 + {
    2.93 + 	unsigned long parsed[12];
    2.94 +@@ -193,7 +208,7 @@
    2.95 + 	}
    2.96 + }
    2.97 + 
    2.98 +-static __initdata char *header_buf, *symlink_buf, *name_buf;
    2.99 ++static __initdata char *header_buf, *name_buf;
   2.100 + 
   2.101 + static int __init do_start(void)
   2.102 + {
   2.103 +@@ -231,17 +246,9 @@
   2.104 + 	state = SkipIt;
   2.105 + 	if (name_len <= 0 || name_len > PATH_MAX)
   2.106 + 		return 0;
   2.107 +-	if (S_ISLNK(mode)) {
   2.108 +-		if (body_len > PATH_MAX)
   2.109 +-			return 0;
   2.110 +-		collect = collected = symlink_buf;
   2.111 +-		remains = N_ALIGN(name_len) + body_len;
   2.112 +-		next_state = GotSymlink;
   2.113 +-		state = Collect;
   2.114 ++	if (S_ISLNK(mode) && (body_len > PATH_MAX))
   2.115 + 		return 0;
   2.116 +-	}
   2.117 +-	if (S_ISREG(mode) || !body_len)
   2.118 +-		read_into(name_buf, N_ALIGN(name_len), GotName);
   2.119 ++	read_into(name_buf, N_ALIGN(name_len), GotName);
   2.120 + 	return 0;
   2.121 + }
   2.122 + 
   2.123 +@@ -269,13 +276,34 @@
   2.124 + static int __init maybe_link(void)
   2.125 + {
   2.126 + 	if (nlink >= 2) {
   2.127 +-		char *old = find_link(major, minor, ino, mode, collected);
   2.128 +-		if (old)
   2.129 +-			return (sys_link(old, collected) < 0) ? -1 : 1;
   2.130 ++		struct hash *p = find_link(collected);
   2.131 ++		if (p->nlink >= 2)
   2.132 ++			return 1;
   2.133 + 	}
   2.134 + 	return 0;
   2.135 + }
   2.136 + 
   2.137 ++static void __init walk_names(struct names *p, char *name)
   2.138 ++{
   2.139 ++	if (!p)
   2.140 ++		return;
   2.141 ++	walk_names(p->next, name);
   2.142 ++	sys_link(name, p->name);
   2.143 ++	kfree(p);
   2.144 ++}
   2.145 ++
   2.146 ++static void __init make_links(char *name)
   2.147 ++{
   2.148 ++	if (nlink >= 2) {
   2.149 ++		struct hash *p = find_link(name);
   2.150 ++		if (!p->nlink) {
   2.151 ++			walk_names(p->next_name, name);
   2.152 ++			sys_link(name, p->name);
   2.153 ++			p->next_name = NULL;
   2.154 ++		}
   2.155 ++	}
   2.156 ++}
   2.157 ++
   2.158 + static void __init clean_path(char *path, mode_t mode)
   2.159 + {
   2.160 + 	struct stat st;
   2.161 +@@ -300,11 +328,8 @@
   2.162 + 	}
   2.163 + 	clean_path(collected, mode);
   2.164 + 	if (S_ISREG(mode)) {
   2.165 +-		int ml = maybe_link();
   2.166 +-		if (ml >= 0) {
   2.167 +-			int openflags = O_WRONLY|O_CREAT;
   2.168 +-			if (ml != 1)
   2.169 +-				openflags |= O_TRUNC;
   2.170 ++		if (maybe_link() == 0) {
   2.171 ++			int openflags = O_WRONLY|O_CREAT|O_TRUNC;
   2.172 + 			wfd = sys_open(collected, openflags, mode);
   2.173 + 
   2.174 + 			if (wfd >= 0) {
   2.175 +@@ -316,6 +341,11 @@
   2.176 + 				state = CopyFile;
   2.177 + 			}
   2.178 + 		}
   2.179 ++	} else if (S_ISLNK(mode)) {
   2.180 ++		if (maybe_link() == 0) {
   2.181 ++			vcollected = kstrdup(collected, GFP_KERNEL);
   2.182 ++			state = GotSymlink;
   2.183 ++		}
   2.184 + 	} else if (S_ISDIR(mode)) {
   2.185 + 		sys_mkdir(collected, mode);
   2.186 + 		sys_chown(collected, uid, gid);
   2.187 +@@ -328,6 +358,7 @@
   2.188 + 			sys_chown(collected, uid, gid);
   2.189 + 			sys_chmod(collected, mode);
   2.190 + 			do_utime(collected, mtime);
   2.191 ++			make_links(collected);
   2.192 + 		}
   2.193 + 	}
   2.194 + 	return 0;
   2.195 +@@ -339,6 +370,7 @@
   2.196 + 		sys_write(wfd, victim, body_len);
   2.197 + 		sys_close(wfd);
   2.198 + 		do_utime(vcollected, mtime);
   2.199 ++		make_links(vcollected);
   2.200 + 		kfree(vcollected);
   2.201 + 		eat(body_len);
   2.202 + 		state = SkipIt;
   2.203 +@@ -353,13 +385,18 @@
   2.204 + 
   2.205 + static int __init do_symlink(void)
   2.206 + {
   2.207 +-	collected[N_ALIGN(name_len) + body_len] = '\0';
   2.208 +-	clean_path(collected, 0);
   2.209 +-	sys_symlink(collected + N_ALIGN(name_len), collected);
   2.210 +-	sys_lchown(collected, uid, gid);
   2.211 +-	do_utime(collected, mtime);
   2.212 ++	char c = victim[body_len];
   2.213 ++
   2.214 ++	victim[body_len] = '\0';
   2.215 ++	clean_path(vcollected, 0);
   2.216 ++	sys_symlink(victim, vcollected);
   2.217 ++	victim[body_len] = c;
   2.218 ++	sys_lchown(vcollected, uid, gid);
   2.219 ++	do_utime(vcollected, mtime);
   2.220 ++	make_links(vcollected);
   2.221 ++	kfree(vcollected);
   2.222 ++	eat(body_len);
   2.223 + 	state = SkipIt;
   2.224 +-	next_state = Reset;
   2.225 + 	return 0;
   2.226 + }
   2.227 + 
   2.228 +@@ -419,10 +456,9 @@
   2.229 + 	static __initdata char msg_buf[64];
   2.230 + 
   2.231 + 	header_buf = kmalloc(110, GFP_KERNEL);
   2.232 +-	symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
   2.233 + 	name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
   2.234 + 
   2.235 +-	if (!header_buf || !symlink_buf || !name_buf)
   2.236 ++	if (!header_buf || !name_buf)
   2.237 + 		panic("can't allocate buffers");
   2.238 + 
   2.239 + 	state = Start;
   2.240 +@@ -467,7 +503,6 @@
   2.241 + 	}
   2.242 + 	dir_utime();
   2.243 + 	kfree(name_buf);
   2.244 +-	kfree(symlink_buf);
   2.245 + 	kfree(header_buf);
   2.246 + 	return message;
   2.247 + }