wok annotate linux-uml/stuff/linux-hardlinks.u @ rev 25576

Up nimrod (1.6.12)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat May 13 17:57:27 2023 +0000 (19 months ago)
parents
children
rev   line source
pascal@17423 1 Fix hardlink on fifos, sockets, char & block devices and symlinks
pascal@17423 2 --- linux-3.2.53/init/initramfs.c
pascal@17423 3 +++ linux-3.2.53/init/initramfs.c
pascal@17423 4 @@ -20,10 +20,24 @@
pascal@17423 5
pascal@17423 6 #define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
pascal@17423 7
pascal@17423 8 +static __initdata unsigned long ino, major, minor, nlink;
pascal@17423 9 +static __initdata time_t mtime;
pascal@17423 10 +static __initdata mode_t mode;
pascal@17423 11 +static __initdata unsigned long body_len, name_len;
pascal@17423 12 +static __initdata uid_t uid;
pascal@17423 13 +static __initdata gid_t gid;
pascal@17423 14 +static __initdata unsigned rdev;
pascal@17423 15 +
pascal@17423 16 +struct names {
pascal@17423 17 + struct names *next;
pascal@17423 18 + char name[1];
pascal@17423 19 +};
pascal@17423 20 +
pascal@17423 21 static __initdata struct hash {
pascal@17423 22 - int ino, minor, major;
pascal@17423 23 + int ino, nlink, minor, major;
pascal@17423 24 mode_t mode;
pascal@17423 25 struct hash *next;
pascal@17423 26 + struct names *next_name;
pascal@17423 27 char name[N_ALIGN(PATH_MAX)];
pascal@17423 28 } *head[32];
pascal@17423 29
pascal@17423 30 @@ -34,8 +48,7 @@
pascal@17423 31 return tmp & 31;
pascal@17423 32 }
pascal@17423 33
pascal@17423 34 -static char __init *find_link(int major, int minor, int ino,
pascal@17423 35 - mode_t mode, char *name)
pascal@17423 36 +static struct hash __init *find_link(char *name)
pascal@17423 37 {
pascal@17423 38 struct hash **p, *q;
pascal@17423 39 for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
pascal@17423 40 @@ -47,7 +60,16 @@
pascal@17423 41 continue;
pascal@17423 42 if (((*p)->mode ^ mode) & S_IFMT)
pascal@17423 43 continue;
pascal@17423 44 - return (*p)->name;
pascal@17423 45 + if (--(*p)->nlink) {
pascal@17423 46 + struct names **n;
pascal@17423 47 + for (n = &(*p)->next_name; *n; n = &(*n)->next);
pascal@17423 48 + *n = kmalloc(sizeof(struct names) + strlen(name), GFP_KERNEL);
pascal@17423 49 + if (!*n)
pascal@17423 50 + panic("can't allocate link name entry");
pascal@17423 51 + strcpy((*n)->name, name);
pascal@17423 52 + (*n)->next = NULL;
pascal@17423 53 + }
pascal@17423 54 + return *p;
pascal@17423 55 }
pascal@17423 56 q = kmalloc(sizeof(struct hash), GFP_KERNEL);
pascal@17423 57 if (!q)
pascal@17423 58 @@ -55,11 +77,13 @@
pascal@17423 59 q->major = major;
pascal@17423 60 q->minor = minor;
pascal@17423 61 q->ino = ino;
pascal@17423 62 + q->nlink = nlink;
pascal@17423 63 q->mode = mode;
pascal@17423 64 strcpy(q->name, name);
pascal@17423 65 + q->next_name = NULL;
pascal@17423 66 q->next = NULL;
pascal@17423 67 *p = q;
pascal@17423 68 - return NULL;
pascal@17423 69 + return q;
pascal@17423 70 }
pascal@17423 71
pascal@17423 72 static void __init free_hash(void)
pascal@17423 73 @@ -115,17 +139,8 @@
pascal@17423 74 }
pascal@17423 75 }
pascal@17423 76
pascal@17423 77 -static __initdata time_t mtime;
pascal@17423 78 -
pascal@17423 79 /* cpio header parsing */
pascal@17423 80
pascal@17423 81 -static __initdata unsigned long ino, major, minor, nlink;
pascal@17423 82 -static __initdata mode_t mode;
pascal@17423 83 -static __initdata unsigned long body_len, name_len;
pascal@17423 84 -static __initdata uid_t uid;
pascal@17423 85 -static __initdata gid_t gid;
pascal@17423 86 -static __initdata unsigned rdev;
pascal@17423 87 -
pascal@17423 88 static void __init parse_header(char *s)
pascal@17423 89 {
pascal@17423 90 unsigned long parsed[12];
pascal@17423 91 @@ -193,7 +208,7 @@
pascal@17423 92 }
pascal@17423 93 }
pascal@17423 94
pascal@17423 95 -static __initdata char *header_buf, *symlink_buf, *name_buf;
pascal@17423 96 +static __initdata char *header_buf, *name_buf;
pascal@17423 97
pascal@17423 98 static int __init do_start(void)
pascal@17423 99 {
pascal@17423 100 @@ -231,17 +246,9 @@
pascal@17423 101 state = SkipIt;
pascal@17423 102 if (name_len <= 0 || name_len > PATH_MAX)
pascal@17423 103 return 0;
pascal@17423 104 - if (S_ISLNK(mode)) {
pascal@17423 105 - if (body_len > PATH_MAX)
pascal@17423 106 - return 0;
pascal@17423 107 - collect = collected = symlink_buf;
pascal@17423 108 - remains = N_ALIGN(name_len) + body_len;
pascal@17423 109 - next_state = GotSymlink;
pascal@17423 110 - state = Collect;
pascal@17423 111 + if (S_ISLNK(mode) && (body_len > PATH_MAX))
pascal@17423 112 return 0;
pascal@17423 113 - }
pascal@17423 114 - if (S_ISREG(mode) || !body_len)
pascal@17423 115 - read_into(name_buf, N_ALIGN(name_len), GotName);
pascal@17423 116 + read_into(name_buf, N_ALIGN(name_len), GotName);
pascal@17423 117 return 0;
pascal@17423 118 }
pascal@17423 119
pascal@17423 120 @@ -269,13 +276,34 @@
pascal@17423 121 static int __init maybe_link(void)
pascal@17423 122 {
pascal@17423 123 if (nlink >= 2) {
pascal@17423 124 - char *old = find_link(major, minor, ino, mode, collected);
pascal@17423 125 - if (old)
pascal@17423 126 - return (sys_link(old, collected) < 0) ? -1 : 1;
pascal@17423 127 + struct hash *p = find_link(collected);
pascal@17423 128 + if (p->nlink >= 2)
pascal@17423 129 + return 1;
pascal@17423 130 }
pascal@17423 131 return 0;
pascal@17423 132 }
pascal@17423 133
pascal@17423 134 +static void __init walk_names(struct names *p, char *name)
pascal@17423 135 +{
pascal@17423 136 + if (!p)
pascal@17423 137 + return;
pascal@17423 138 + walk_names(p->next, name);
pascal@17423 139 + sys_link(name, p->name);
pascal@17423 140 + kfree(p);
pascal@17423 141 +}
pascal@17423 142 +
pascal@17423 143 +static void __init make_links(char *name)
pascal@17423 144 +{
pascal@17423 145 + if (nlink >= 2) {
pascal@17423 146 + struct hash *p = find_link(name);
pascal@17423 147 + if (!p->nlink) {
pascal@17423 148 + walk_names(p->next_name, name);
pascal@17423 149 + sys_link(name, p->name);
pascal@17423 150 + p->next_name = NULL;
pascal@17423 151 + }
pascal@17423 152 + }
pascal@17423 153 +}
pascal@17423 154 +
pascal@17423 155 static void __init clean_path(char *path, mode_t mode)
pascal@17423 156 {
pascal@17423 157 struct stat st;
pascal@17423 158 @@ -300,11 +328,8 @@
pascal@17423 159 }
pascal@17423 160 clean_path(collected, mode);
pascal@17423 161 if (S_ISREG(mode)) {
pascal@17423 162 - int ml = maybe_link();
pascal@17423 163 - if (ml >= 0) {
pascal@17423 164 - int openflags = O_WRONLY|O_CREAT;
pascal@17423 165 - if (ml != 1)
pascal@17423 166 - openflags |= O_TRUNC;
pascal@17423 167 + if (maybe_link() == 0) {
pascal@17423 168 + int openflags = O_WRONLY|O_CREAT|O_TRUNC;
pascal@17423 169 wfd = sys_open(collected, openflags, mode);
pascal@17423 170
pascal@17423 171 if (wfd >= 0) {
pascal@17423 172 @@ -316,6 +341,11 @@
pascal@17423 173 state = CopyFile;
pascal@17423 174 }
pascal@17423 175 }
pascal@17423 176 + } else if (S_ISLNK(mode)) {
pascal@17423 177 + if (maybe_link() == 0) {
pascal@17423 178 + vcollected = kstrdup(collected, GFP_KERNEL);
pascal@17423 179 + state = GotSymlink;
pascal@17423 180 + }
pascal@17423 181 } else if (S_ISDIR(mode)) {
pascal@17423 182 sys_mkdir(collected, mode);
pascal@17423 183 sys_chown(collected, uid, gid);
pascal@17423 184 @@ -328,6 +358,7 @@
pascal@17423 185 sys_chown(collected, uid, gid);
pascal@17423 186 sys_chmod(collected, mode);
pascal@17423 187 do_utime(collected, mtime);
pascal@17423 188 + make_links(collected);
pascal@17423 189 }
pascal@17423 190 }
pascal@17423 191 return 0;
pascal@17423 192 @@ -339,6 +370,7 @@
pascal@17423 193 sys_write(wfd, victim, body_len);
pascal@17423 194 sys_close(wfd);
pascal@17423 195 do_utime(vcollected, mtime);
pascal@17423 196 + make_links(vcollected);
pascal@17423 197 kfree(vcollected);
pascal@17423 198 eat(body_len);
pascal@17423 199 state = SkipIt;
pascal@17423 200 @@ -353,13 +385,18 @@
pascal@17423 201
pascal@17423 202 static int __init do_symlink(void)
pascal@17423 203 {
pascal@17423 204 - collected[N_ALIGN(name_len) + body_len] = '\0';
pascal@17423 205 - clean_path(collected, 0);
pascal@17423 206 - sys_symlink(collected + N_ALIGN(name_len), collected);
pascal@17423 207 - sys_lchown(collected, uid, gid);
pascal@17423 208 - do_utime(collected, mtime);
pascal@17423 209 + char c = victim[body_len];
pascal@17423 210 +
pascal@17423 211 + victim[body_len] = '\0';
pascal@17423 212 + clean_path(vcollected, 0);
pascal@17423 213 + sys_symlink(victim, vcollected);
pascal@17423 214 + victim[body_len] = c;
pascal@17423 215 + sys_lchown(vcollected, uid, gid);
pascal@17423 216 + do_utime(vcollected, mtime);
pascal@17423 217 + make_links(vcollected);
pascal@17423 218 + kfree(vcollected);
pascal@17423 219 + eat(body_len);
pascal@17423 220 state = SkipIt;
pascal@17423 221 - next_state = Reset;
pascal@17423 222 return 0;
pascal@17423 223 }
pascal@17423 224
pascal@17423 225 @@ -419,10 +456,9 @@
pascal@17423 226 static __initdata char msg_buf[64];
pascal@17423 227
pascal@17423 228 header_buf = kmalloc(110, GFP_KERNEL);
pascal@17423 229 - symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
pascal@17423 230 name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
pascal@17423 231
pascal@17423 232 - if (!header_buf || !symlink_buf || !name_buf)
pascal@17423 233 + if (!header_buf || !name_buf)
pascal@17423 234 panic("can't allocate buffers");
pascal@17423 235
pascal@17423 236 state = Start;
pascal@17423 237 @@ -467,7 +503,6 @@
pascal@17423 238 }
pascal@17423 239 dir_utime();
pascal@17423 240 kfree(name_buf);
pascal@17423 241 - kfree(symlink_buf);
pascal@17423 242 kfree(header_buf);
pascal@17423 243 return message;
pascal@17423 244 }