wok-current diff linux-uml/stuff/linux-hardlinks.u @ rev 23364

updated perl-lwp-mediatypes (6.02 -> 6.04)
author Hans-G?nter Theisgen
date Tue Mar 31 11:15:57 2020 +0100 (2020-03-31)
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/linux-uml/stuff/linux-hardlinks.u	Tue Mar 31 11:15:57 2020 +0100
     1.3 @@ -0,0 +1,244 @@
     1.4 +Fix hardlink on fifos, sockets, char & block devices and symlinks
     1.5 +--- linux-3.2.53/init/initramfs.c
     1.6 ++++ linux-3.2.53/init/initramfs.c
     1.7 +@@ -20,10 +20,24 @@
     1.8 + 
     1.9 + #define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
    1.10 + 
    1.11 ++static __initdata unsigned long ino, major, minor, nlink;
    1.12 ++static __initdata time_t mtime;
    1.13 ++static __initdata mode_t mode;
    1.14 ++static __initdata unsigned long body_len, name_len;
    1.15 ++static __initdata uid_t uid;
    1.16 ++static __initdata gid_t gid;
    1.17 ++static __initdata unsigned rdev;
    1.18 ++
    1.19 ++struct names {
    1.20 ++	struct names *next;
    1.21 ++	char name[1];
    1.22 ++};
    1.23 ++
    1.24 + static __initdata struct hash {
    1.25 +-	int ino, minor, major;
    1.26 ++	int ino, nlink, minor, major;
    1.27 + 	mode_t mode;
    1.28 + 	struct hash *next;
    1.29 ++	struct names *next_name;
    1.30 + 	char name[N_ALIGN(PATH_MAX)];
    1.31 + } *head[32];
    1.32 + 
    1.33 +@@ -34,8 +48,7 @@
    1.34 + 	return tmp & 31;
    1.35 + }
    1.36 + 
    1.37 +-static char __init *find_link(int major, int minor, int ino,
    1.38 +-			      mode_t mode, char *name)
    1.39 ++static struct hash  __init *find_link(char *name)
    1.40 + {
    1.41 + 	struct hash **p, *q;
    1.42 + 	for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
    1.43 +@@ -47,7 +60,16 @@
    1.44 + 			continue;
    1.45 + 		if (((*p)->mode ^ mode) & S_IFMT)
    1.46 + 			continue;
    1.47 +-		return (*p)->name;
    1.48 ++		if (--(*p)->nlink) {
    1.49 ++			struct names **n;
    1.50 ++			for (n = &(*p)->next_name; *n; n = &(*n)->next);
    1.51 ++			*n = kmalloc(sizeof(struct names) + strlen(name), GFP_KERNEL);
    1.52 ++			if (!*n)
    1.53 ++				panic("can't allocate link name entry");
    1.54 ++			strcpy((*n)->name, name);
    1.55 ++			(*n)->next = NULL;
    1.56 ++		}
    1.57 ++		return *p;
    1.58 + 	}
    1.59 + 	q = kmalloc(sizeof(struct hash), GFP_KERNEL);
    1.60 + 	if (!q)
    1.61 +@@ -55,11 +77,13 @@
    1.62 + 	q->major = major;
    1.63 + 	q->minor = minor;
    1.64 + 	q->ino = ino;
    1.65 ++	q->nlink = nlink;
    1.66 + 	q->mode = mode;
    1.67 + 	strcpy(q->name, name);
    1.68 ++	q->next_name = NULL;
    1.69 + 	q->next = NULL;
    1.70 + 	*p = q;
    1.71 +-	return NULL;
    1.72 ++	return q;
    1.73 + }
    1.74 + 
    1.75 + static void __init free_hash(void)
    1.76 +@@ -115,17 +139,8 @@
    1.77 + 	}
    1.78 + }
    1.79 + 
    1.80 +-static __initdata time_t mtime;
    1.81 +-
    1.82 + /* cpio header parsing */
    1.83 + 
    1.84 +-static __initdata unsigned long ino, major, minor, nlink;
    1.85 +-static __initdata mode_t mode;
    1.86 +-static __initdata unsigned long body_len, name_len;
    1.87 +-static __initdata uid_t uid;
    1.88 +-static __initdata gid_t gid;
    1.89 +-static __initdata unsigned rdev;
    1.90 +-
    1.91 + static void __init parse_header(char *s)
    1.92 + {
    1.93 + 	unsigned long parsed[12];
    1.94 +@@ -193,7 +208,7 @@
    1.95 + 	}
    1.96 + }
    1.97 + 
    1.98 +-static __initdata char *header_buf, *symlink_buf, *name_buf;
    1.99 ++static __initdata char *header_buf, *name_buf;
   1.100 + 
   1.101 + static int __init do_start(void)
   1.102 + {
   1.103 +@@ -231,17 +246,9 @@
   1.104 + 	state = SkipIt;
   1.105 + 	if (name_len <= 0 || name_len > PATH_MAX)
   1.106 + 		return 0;
   1.107 +-	if (S_ISLNK(mode)) {
   1.108 +-		if (body_len > PATH_MAX)
   1.109 +-			return 0;
   1.110 +-		collect = collected = symlink_buf;
   1.111 +-		remains = N_ALIGN(name_len) + body_len;
   1.112 +-		next_state = GotSymlink;
   1.113 +-		state = Collect;
   1.114 ++	if (S_ISLNK(mode) && (body_len > PATH_MAX))
   1.115 + 		return 0;
   1.116 +-	}
   1.117 +-	if (S_ISREG(mode) || !body_len)
   1.118 +-		read_into(name_buf, N_ALIGN(name_len), GotName);
   1.119 ++	read_into(name_buf, N_ALIGN(name_len), GotName);
   1.120 + 	return 0;
   1.121 + }
   1.122 + 
   1.123 +@@ -269,13 +276,34 @@
   1.124 + static int __init maybe_link(void)
   1.125 + {
   1.126 + 	if (nlink >= 2) {
   1.127 +-		char *old = find_link(major, minor, ino, mode, collected);
   1.128 +-		if (old)
   1.129 +-			return (sys_link(old, collected) < 0) ? -1 : 1;
   1.130 ++		struct hash *p = find_link(collected);
   1.131 ++		if (p->nlink >= 2)
   1.132 ++			return 1;
   1.133 + 	}
   1.134 + 	return 0;
   1.135 + }
   1.136 + 
   1.137 ++static void __init walk_names(struct names *p, char *name)
   1.138 ++{
   1.139 ++	if (!p)
   1.140 ++		return;
   1.141 ++	walk_names(p->next, name);
   1.142 ++	sys_link(name, p->name);
   1.143 ++	kfree(p);
   1.144 ++}
   1.145 ++
   1.146 ++static void __init make_links(char *name)
   1.147 ++{
   1.148 ++	if (nlink >= 2) {
   1.149 ++		struct hash *p = find_link(name);
   1.150 ++		if (!p->nlink) {
   1.151 ++			walk_names(p->next_name, name);
   1.152 ++			sys_link(name, p->name);
   1.153 ++			p->next_name = NULL;
   1.154 ++		}
   1.155 ++	}
   1.156 ++}
   1.157 ++
   1.158 + static void __init clean_path(char *path, mode_t mode)
   1.159 + {
   1.160 + 	struct stat st;
   1.161 +@@ -300,11 +328,8 @@
   1.162 + 	}
   1.163 + 	clean_path(collected, mode);
   1.164 + 	if (S_ISREG(mode)) {
   1.165 +-		int ml = maybe_link();
   1.166 +-		if (ml >= 0) {
   1.167 +-			int openflags = O_WRONLY|O_CREAT;
   1.168 +-			if (ml != 1)
   1.169 +-				openflags |= O_TRUNC;
   1.170 ++		if (maybe_link() == 0) {
   1.171 ++			int openflags = O_WRONLY|O_CREAT|O_TRUNC;
   1.172 + 			wfd = sys_open(collected, openflags, mode);
   1.173 + 
   1.174 + 			if (wfd >= 0) {
   1.175 +@@ -316,6 +341,11 @@
   1.176 + 				state = CopyFile;
   1.177 + 			}
   1.178 + 		}
   1.179 ++	} else if (S_ISLNK(mode)) {
   1.180 ++		if (maybe_link() == 0) {
   1.181 ++			vcollected = kstrdup(collected, GFP_KERNEL);
   1.182 ++			state = GotSymlink;
   1.183 ++		}
   1.184 + 	} else if (S_ISDIR(mode)) {
   1.185 + 		sys_mkdir(collected, mode);
   1.186 + 		sys_chown(collected, uid, gid);
   1.187 +@@ -328,6 +358,7 @@
   1.188 + 			sys_chown(collected, uid, gid);
   1.189 + 			sys_chmod(collected, mode);
   1.190 + 			do_utime(collected, mtime);
   1.191 ++			make_links(collected);
   1.192 + 		}
   1.193 + 	}
   1.194 + 	return 0;
   1.195 +@@ -339,6 +370,7 @@
   1.196 + 		sys_write(wfd, victim, body_len);
   1.197 + 		sys_close(wfd);
   1.198 + 		do_utime(vcollected, mtime);
   1.199 ++		make_links(vcollected);
   1.200 + 		kfree(vcollected);
   1.201 + 		eat(body_len);
   1.202 + 		state = SkipIt;
   1.203 +@@ -353,13 +385,18 @@
   1.204 + 
   1.205 + static int __init do_symlink(void)
   1.206 + {
   1.207 +-	collected[N_ALIGN(name_len) + body_len] = '\0';
   1.208 +-	clean_path(collected, 0);
   1.209 +-	sys_symlink(collected + N_ALIGN(name_len), collected);
   1.210 +-	sys_lchown(collected, uid, gid);
   1.211 +-	do_utime(collected, mtime);
   1.212 ++	char c = victim[body_len];
   1.213 ++
   1.214 ++	victim[body_len] = '\0';
   1.215 ++	clean_path(vcollected, 0);
   1.216 ++	sys_symlink(victim, vcollected);
   1.217 ++	victim[body_len] = c;
   1.218 ++	sys_lchown(vcollected, uid, gid);
   1.219 ++	do_utime(vcollected, mtime);
   1.220 ++	make_links(vcollected);
   1.221 ++	kfree(vcollected);
   1.222 ++	eat(body_len);
   1.223 + 	state = SkipIt;
   1.224 +-	next_state = Reset;
   1.225 + 	return 0;
   1.226 + }
   1.227 + 
   1.228 +@@ -419,10 +456,9 @@
   1.229 + 	static __initdata char msg_buf[64];
   1.230 + 
   1.231 + 	header_buf = kmalloc(110, GFP_KERNEL);
   1.232 +-	symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
   1.233 + 	name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
   1.234 + 
   1.235 +-	if (!header_buf || !symlink_buf || !name_buf)
   1.236 ++	if (!header_buf || !name_buf)
   1.237 + 		panic("can't allocate buffers");
   1.238 + 
   1.239 + 	state = Start;
   1.240 +@@ -467,7 +503,6 @@
   1.241 + 	}
   1.242 + 	dir_utime();
   1.243 + 	kfree(name_buf);
   1.244 +-	kfree(symlink_buf);
   1.245 + 	kfree(header_buf);
   1.246 + 	return message;
   1.247 + }