| File: | pr/Linux6.7_x86_64_gcc_glibc_PTH_64_DBG.OBJ/config/../../config/nsinstall.c |
| Warning: | line 425, column 13 Access to field 'd_ino' results in a dereference of a null pointer (loaded from variable 'ep') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
| 2 | /* This Source Code Form is subject to the terms of the Mozilla Public | |||
| 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
| 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
| 5 | ||||
| 6 | /* | |||
| 7 | ** Netscape portable install command. | |||
| 8 | ** | |||
| 9 | ** Brendan Eich, 7/20/95 | |||
| 10 | */ | |||
| 11 | #include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */ | |||
| 12 | #include <assert.h> | |||
| 13 | #include <fcntl.h> | |||
| 14 | #include <grp.h> | |||
| 15 | #include <pwd.h> | |||
| 16 | #include <stdlib.h> | |||
| 17 | #include <string.h> | |||
| 18 | #include <unistd.h> | |||
| 19 | #include <utime.h> | |||
| 20 | #include <sys/types.h> | |||
| 21 | #include <sys/stat.h> | |||
| 22 | #include <dirent.h> | |||
| 23 | #include <errno(*__errno_location ()).h> | |||
| 24 | #include <stdarg.h> | |||
| 25 | #ifdef USE_REENTRANT_LIBC | |||
| 26 | #include "libc_r.h" | |||
| 27 | #endif /* USE_REENTRANT_LIBC */ | |||
| 28 | ||||
| 29 | #include "pathsub.h" | |||
| 30 | ||||
| 31 | #define HAVE_FCHMOD | |||
| 32 | ||||
| 33 | ||||
| 34 | /* | |||
| 35 | * Does getcwd() take NULL as the first argument and malloc | |||
| 36 | * the result buffer? | |||
| 37 | */ | |||
| 38 | #if !defined(DARWIN) | |||
| 39 | #define GETCWD_CAN_MALLOC | |||
| 40 | #endif | |||
| 41 | ||||
| 42 | #if defined(LINUX1) || defined(__GNU__) || defined(__GLIBC__2) | |||
| 43 | #include <getopt.h> | |||
| 44 | #endif | |||
| 45 | ||||
| 46 | #ifdef QNX | |||
| 47 | #define d_ino d_stat.st_ino | |||
| 48 | #endif | |||
| 49 | ||||
| 50 | static void | |||
| 51 | usage(void) | |||
| 52 | { | |||
| 53 | fprintf(stderrstderr, | |||
| 54 | "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n" | |||
| 55 | " %*s [-DdltR] file [file ...] directory\n", | |||
| 56 | program, (int)strlen(program), ""); | |||
| 57 | exit(2); | |||
| 58 | } | |||
| 59 | ||||
| 60 | static int | |||
| 61 | mkdirs(char *path, mode_t mode) | |||
| 62 | { | |||
| 63 | char *cp; | |||
| 64 | struct stat sb; | |||
| 65 | int res; | |||
| 66 | ||||
| 67 | while (*path == '/' && path[1] == '/') { | |||
| 68 | path++; | |||
| 69 | } | |||
| 70 | for (cp = strrchr(path, '/'); cp && cp != path && cp[-1] == '/'; cp--) | |||
| 71 | ; | |||
| 72 | if (cp && cp != path) { | |||
| 73 | *cp = '\0'; | |||
| 74 | if ((stat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)((((sb.st_mode)) & 0170000) == (0040000))) && | |||
| 75 | mkdirs(path, mode) < 0) { | |||
| 76 | return -1; | |||
| 77 | } | |||
| 78 | *cp = '/'; | |||
| 79 | } | |||
| 80 | res = mkdir(path, mode); | |||
| 81 | if ((res != 0) && (errno(*__errno_location ()) == EEXIST17)) { | |||
| 82 | return 0; | |||
| 83 | } | |||
| 84 | else { | |||
| 85 | return res; | |||
| 86 | } | |||
| 87 | } | |||
| 88 | ||||
| 89 | static uid_t | |||
| 90 | touid(char *owner) | |||
| 91 | { | |||
| 92 | struct passwd *pw; | |||
| 93 | uid_t uid; | |||
| 94 | char *cp; | |||
| 95 | ||||
| 96 | pw = getpwnam(owner); | |||
| 97 | if (pw) { | |||
| 98 | return pw->pw_uid; | |||
| 99 | } | |||
| 100 | uid = strtol(owner, &cp, 0); | |||
| 101 | if (uid == 0 && cp == owner) { | |||
| 102 | fail("cannot find uid for %s", owner); | |||
| 103 | } | |||
| 104 | return uid; | |||
| 105 | } | |||
| 106 | ||||
| 107 | static gid_t | |||
| 108 | togid(char *group) | |||
| 109 | { | |||
| 110 | struct group *gr; | |||
| 111 | gid_t gid; | |||
| 112 | char *cp; | |||
| 113 | ||||
| 114 | gr = getgrnam(group); | |||
| 115 | if (gr) { | |||
| 116 | return gr->gr_gid; | |||
| 117 | } | |||
| 118 | gid = strtol(group, &cp, 0); | |||
| 119 | if (gid == 0 && cp == group) { | |||
| 120 | fail("cannot find gid for %s", group); | |||
| 121 | } | |||
| 122 | return gid; | |||
| 123 | } | |||
| 124 | ||||
| 125 | int | |||
| 126 | main(int argc, char **argv) | |||
| 127 | { | |||
| 128 | int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc; | |||
| 129 | mode_t mode = 0755; | |||
| 130 | char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ8192]; | |||
| 131 | uid_t uid; | |||
| 132 | gid_t gid; | |||
| 133 | struct stat sb, tosb; | |||
| 134 | struct utimbuf utb; | |||
| 135 | ||||
| 136 | program = argv[0]; | |||
| 137 | cwd = linkname = linkprefix = owner = group = 0; | |||
| 138 | onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0; | |||
| 139 | ||||
| 140 | while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF(-1)) { | |||
| 141 | switch (opt) { | |||
| 142 | case 'C': | |||
| 143 | cwd = optarg; | |||
| 144 | break; | |||
| 145 | case 'D': | |||
| 146 | onlydir = 1; | |||
| 147 | break; | |||
| 148 | case 'd': | |||
| 149 | dodir = 1; | |||
| 150 | break; | |||
| 151 | case 'l': | |||
| 152 | dolink = 1; | |||
| 153 | break; | |||
| 154 | case 'L': | |||
| 155 | linkprefix = optarg; | |||
| 156 | lplen = strlen(linkprefix); | |||
| 157 | dolink = 1; | |||
| 158 | break; | |||
| 159 | case 'R': | |||
| 160 | dolink = dorelsymlink = 1; | |||
| 161 | break; | |||
| 162 | case 'm': | |||
| 163 | mode = strtoul(optarg, &cp, 8); | |||
| 164 | if (mode == 0 && cp == optarg) { | |||
| 165 | usage(); | |||
| 166 | } | |||
| 167 | break; | |||
| 168 | case 'o': | |||
| 169 | owner = optarg; | |||
| 170 | break; | |||
| 171 | case 'g': | |||
| 172 | group = optarg; | |||
| 173 | break; | |||
| 174 | case 't': | |||
| 175 | dotimes = 1; | |||
| 176 | break; | |||
| 177 | default: | |||
| 178 | usage(); | |||
| 179 | } | |||
| 180 | } | |||
| 181 | ||||
| 182 | argc -= optind; | |||
| 183 | argv += optind; | |||
| 184 | if (argc < 2 - onlydir) { | |||
| 185 | usage(); | |||
| 186 | } | |||
| 187 | ||||
| 188 | todir = argv[argc-1]; | |||
| 189 | if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)((((sb.st_mode)) & 0170000) == (0040000))) && | |||
| 190 | mkdirs(todir, 0777) < 0) { | |||
| 191 | fail("cannot make directory %s", todir); | |||
| 192 | } | |||
| 193 | if (onlydir) { | |||
| 194 | return 0; | |||
| 195 | } | |||
| 196 | ||||
| 197 | if (!cwd) { | |||
| 198 | #ifdef GETCWD_CAN_MALLOC | |||
| 199 | cwd = getcwd(0, PATH_MAX4096); | |||
| 200 | #else | |||
| 201 | cwd = malloc(PATH_MAX4096 + 1); | |||
| 202 | cwd = getcwd(cwd, PATH_MAX4096); | |||
| 203 | #endif | |||
| 204 | } | |||
| 205 | xchdir(todir); | |||
| 206 | #ifdef GETCWD_CAN_MALLOC | |||
| 207 | todir = getcwd(0, PATH_MAX4096); | |||
| 208 | #else | |||
| 209 | todir = malloc(PATH_MAX4096 + 1); | |||
| 210 | todir = getcwd(todir, PATH_MAX4096); | |||
| 211 | #endif | |||
| 212 | xchdir(cwd); | |||
| 213 | tdlen = strlen(todir); | |||
| 214 | ||||
| 215 | uid = owner ? touid(owner) : -1; | |||
| 216 | gid = group ? togid(group) : -1; | |||
| 217 | ||||
| 218 | while (--argc > 0) { | |||
| 219 | name = *argv++; | |||
| 220 | len = strlen(name); | |||
| 221 | base = xbasename(name); | |||
| 222 | bnlen = strlen(base); | |||
| 223 | toname = (char*)xmalloc(tdlen + 1 + bnlen + 1); | |||
| 224 | sprintf(toname, "%s/%s", todir, base); | |||
| 225 | exists = (lstat(toname, &tosb) == 0); | |||
| 226 | ||||
| 227 | if (dodir) { | |||
| 228 | /* -d means create a directory, always */ | |||
| 229 | if (exists && !S_ISDIR(tosb.st_mode)((((tosb.st_mode)) & 0170000) == (0040000))) { | |||
| 230 | (void) unlink(toname); | |||
| 231 | exists = 0; | |||
| 232 | } | |||
| 233 | if (!exists && mkdir(toname, mode) < 0) { | |||
| 234 | fail("cannot make directory %s", toname); | |||
| 235 | } | |||
| 236 | if ((owner || group) && chown(toname, uid, gid) < 0) { | |||
| 237 | fail("cannot change owner of %s", toname); | |||
| 238 | } | |||
| 239 | } else if (dolink) { | |||
| 240 | if (*name == '/') { | |||
| 241 | /* source is absolute pathname, link to it directly */ | |||
| 242 | linkname = 0; | |||
| 243 | } else { | |||
| 244 | if (linkprefix) { | |||
| 245 | /* -L implies -l and prefixes names with a $cwd arg. */ | |||
| 246 | len += lplen + 1; | |||
| 247 | linkname = (char*)xmalloc(len + 1); | |||
| 248 | sprintf(linkname, "%s/%s", linkprefix, name); | |||
| 249 | } else if (dorelsymlink) { | |||
| 250 | /* Symlink the relative path from todir to source name. */ | |||
| 251 | linkname = (char*)xmalloc(PATH_MAX4096); | |||
| 252 | ||||
| 253 | if (*todir == '/') { | |||
| 254 | /* todir is absolute: skip over common prefix. */ | |||
| 255 | lplen = relatepaths(todir, cwd, linkname); | |||
| 256 | strcpy(linkname + lplen, name); | |||
| 257 | } else { | |||
| 258 | /* todir is named by a relative path: reverse it. */ | |||
| 259 | reversepath(todir, name, len, linkname); | |||
| 260 | xchdir(cwd); | |||
| 261 | } | |||
| 262 | ||||
| 263 | len = strlen(linkname); | |||
| 264 | } | |||
| 265 | name = linkname; | |||
| 266 | } | |||
| 267 | ||||
| 268 | /* Check for a pre-existing symlink with identical content. */ | |||
| 269 | if (exists && | |||
| 270 | (!S_ISLNK(tosb.st_mode)((((tosb.st_mode)) & 0170000) == (0120000)) || | |||
| 271 | readlink(toname, buf, sizeof buf) != len || | |||
| 272 | strncmp(buf, name, len) != 0)) { | |||
| 273 | (void) (S_ISDIR(tosb.st_mode)((((tosb.st_mode)) & 0170000) == (0040000)) ? rmdir : unlink)(toname); | |||
| 274 | exists = 0; | |||
| 275 | } | |||
| 276 | if (!exists && symlink(name, toname) < 0) { | |||
| 277 | fail("cannot make symbolic link %s", toname); | |||
| 278 | } | |||
| 279 | #ifdef HAVE_LCHOWN1 | |||
| 280 | if ((owner || group) && lchown(toname, uid, gid) < 0) { | |||
| 281 | fail("cannot change owner of %s", toname); | |||
| 282 | } | |||
| 283 | #endif | |||
| 284 | ||||
| 285 | if (linkname) { | |||
| 286 | free(linkname); | |||
| 287 | linkname = 0; | |||
| 288 | } | |||
| 289 | } else { | |||
| 290 | /* Copy from name to toname, which might be the same file. */ | |||
| 291 | fromfd = open(name, O_RDONLY00); | |||
| 292 | if (fromfd < 0 || fstat(fromfd, &sb) < 0) { | |||
| 293 | fail("cannot access %s", name); | |||
| 294 | } | |||
| 295 | if (exists && (!S_ISREG(tosb.st_mode)((((tosb.st_mode)) & 0170000) == (0100000)) || access(toname, W_OK2) < 0)) { | |||
| 296 | (void) (S_ISDIR(tosb.st_mode)((((tosb.st_mode)) & 0170000) == (0040000)) ? rmdir : unlink)(toname); | |||
| 297 | } | |||
| 298 | tofd = open(toname, O_CREAT0100 | O_WRONLY01, 0666); | |||
| 299 | if (tofd < 0) { | |||
| 300 | fail("cannot create %s", toname); | |||
| 301 | } | |||
| 302 | ||||
| 303 | bp = buf; | |||
| 304 | while ((cc = read(fromfd, bp, sizeof buf)) > 0) { | |||
| 305 | while ((wc = write(tofd, bp, cc)) > 0) { | |||
| 306 | if ((cc -= wc) == 0) { | |||
| 307 | break; | |||
| 308 | } | |||
| 309 | bp += wc; | |||
| 310 | } | |||
| 311 | if (wc < 0) { | |||
| 312 | fail("cannot write to %s", toname); | |||
| 313 | } | |||
| 314 | } | |||
| 315 | if (cc < 0) { | |||
| 316 | fail("cannot read from %s", name); | |||
| 317 | } | |||
| 318 | ||||
| 319 | if (ftruncate(tofd, sb.st_size) < 0) { | |||
| 320 | fail("cannot truncate %s", toname); | |||
| 321 | } | |||
| 322 | if (dotimes) { | |||
| 323 | utb.actime = sb.st_atimest_atim.tv_sec; | |||
| 324 | utb.modtime = sb.st_mtimest_mtim.tv_sec; | |||
| 325 | if (utime(toname, &utb) < 0) { | |||
| 326 | fail("cannot set times of %s", toname); | |||
| 327 | } | |||
| 328 | } | |||
| 329 | #ifdef HAVE_FCHMOD | |||
| 330 | if (fchmod(tofd, mode) < 0) | |||
| 331 | #else | |||
| 332 | if (chmod(toname, mode) < 0) | |||
| 333 | #endif | |||
| 334 | fail("cannot change mode of %s", toname); | |||
| 335 | if ((owner || group) && fchown(tofd, uid, gid) < 0) { | |||
| 336 | fail("cannot change owner of %s", toname); | |||
| 337 | } | |||
| 338 | ||||
| 339 | /* Must check for delayed (NFS) write errors on close. */ | |||
| 340 | if (close(tofd) < 0) { | |||
| 341 | fail("cannot write to %s", toname); | |||
| 342 | } | |||
| 343 | close(fromfd); | |||
| 344 | } | |||
| 345 | ||||
| 346 | free(toname); | |||
| 347 | } | |||
| 348 | ||||
| 349 | free(cwd); | |||
| 350 | free(todir); | |||
| 351 | return 0; | |||
| 352 | } | |||
| 353 | ||||
| 354 | /* | |||
| 355 | ** Pathname subroutines. | |||
| 356 | ** | |||
| 357 | ** Brendan Eich, 8/29/95 | |||
| 358 | */ | |||
| 359 | ||||
| 360 | char *program; | |||
| 361 | ||||
| 362 | void | |||
| 363 | fail(char *format, ...) | |||
| 364 | { | |||
| 365 | int error; | |||
| 366 | va_list ap; | |||
| 367 | ||||
| 368 | #ifdef USE_REENTRANT_LIBC | |||
| 369 | R_STRERROR_INIT_R(); | |||
| 370 | #endif | |||
| 371 | ||||
| 372 | error = errno(*__errno_location ()); | |||
| 373 | fprintf(stderrstderr, "%s: ", program); | |||
| 374 | va_start(ap, format)__builtin_va_start(ap, format); | |||
| 375 | vfprintf(stderrstderr, format, ap); | |||
| 376 | va_end(ap)__builtin_va_end(ap); | |||
| 377 | if (error) | |||
| 378 | ||||
| 379 | #ifdef USE_REENTRANT_LIBC | |||
| 380 | R_STRERROR_R(errno(*__errno_location ())); | |||
| 381 | fprintf(stderrstderr, ": %s", r_strerror_r); | |||
| 382 | #else | |||
| 383 | fprintf(stderrstderr, ": %s", strerror(errno(*__errno_location ()))); | |||
| 384 | #endif | |||
| 385 | ||||
| 386 | putc('\n', stderrstderr); | |||
| 387 | exit(1); | |||
| 388 | } | |||
| 389 | ||||
| 390 | char * | |||
| 391 | getcomponent(char *path, char *name) | |||
| 392 | { | |||
| 393 | if (*path == '\0') { | |||
| 394 | return 0; | |||
| 395 | } | |||
| 396 | if (*path == '/') { | |||
| 397 | *name++ = '/'; | |||
| 398 | } else { | |||
| 399 | do { | |||
| 400 | *name++ = *path++; | |||
| 401 | } while (*path != '/' && *path != '\0'); | |||
| 402 | } | |||
| 403 | *name = '\0'; | |||
| 404 | while (*path == '/') { | |||
| 405 | path++; | |||
| 406 | } | |||
| 407 | return path; | |||
| 408 | } | |||
| 409 | ||||
| 410 | char * | |||
| 411 | ino2name(ino_t ino, char *dir) | |||
| 412 | { | |||
| 413 | DIR *dp; | |||
| 414 | struct dirent *ep; | |||
| 415 | char *name; | |||
| 416 | ||||
| 417 | dp = opendir(".."); | |||
| 418 | if (!dp) { | |||
| 419 | fail("cannot read parent directory"); | |||
| 420 | } | |||
| 421 | for (;;) { | |||
| 422 | if (!(ep = readdir(dp))) { | |||
| 423 | fail("cannot find current directory"); | |||
| 424 | } | |||
| 425 | if (ep->d_ino == ino) { | |||
| ||||
| 426 | break; | |||
| 427 | } | |||
| 428 | } | |||
| 429 | name = xstrdup(ep->d_name); | |||
| 430 | closedir(dp); | |||
| 431 | return name; | |||
| 432 | } | |||
| 433 | ||||
| 434 | void * | |||
| 435 | xmalloc(size_t size) | |||
| 436 | { | |||
| 437 | void *p = malloc(size); | |||
| 438 | if (!p) { | |||
| 439 | fail("cannot allocate %u bytes", size); | |||
| 440 | } | |||
| 441 | return p; | |||
| 442 | } | |||
| 443 | ||||
| 444 | char * | |||
| 445 | xstrdup(char *s) | |||
| 446 | { | |||
| 447 | return strcpy((char*)xmalloc(strlen(s) + 1), s); | |||
| 448 | } | |||
| 449 | ||||
| 450 | char * | |||
| 451 | xbasename(char *path) | |||
| 452 | { | |||
| 453 | char *cp; | |||
| 454 | ||||
| 455 | while ((cp = strrchr(path, '/')) && cp[1] == '\0') { | |||
| 456 | *cp = '\0'; | |||
| 457 | } | |||
| 458 | if (!cp) { | |||
| 459 | return path; | |||
| 460 | } | |||
| 461 | return cp + 1; | |||
| 462 | } | |||
| 463 | ||||
| 464 | void | |||
| 465 | xchdir(char *dir) | |||
| 466 | { | |||
| 467 | if (chdir(dir) < 0) { | |||
| 468 | fail("cannot change directory to %s", dir); | |||
| 469 | } | |||
| 470 | } | |||
| 471 | ||||
| 472 | int | |||
| 473 | relatepaths(char *from, char *to, char *outpath) | |||
| 474 | { | |||
| 475 | char *cp, *cp2; | |||
| 476 | int len; | |||
| 477 | char buf[NAME_MAX256]; | |||
| 478 | ||||
| 479 | assert(*from == '/' && *to == '/')((void) sizeof ((*from == '/' && *to == '/') ? 1 : 0) , __extension__ ({ if (*from == '/' && *to == '/') ; else __assert_fail ("*from == '/' && *to == '/'", "../../config/nsinstall.c" , 479, __extension__ __PRETTY_FUNCTION__); })); | |||
| 480 | for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++) | |||
| 481 | if (*cp == '\0') { | |||
| 482 | break; | |||
| 483 | } | |||
| 484 | while (cp[-1] != '/') { | |||
| 485 | cp--, cp2--; | |||
| 486 | } | |||
| 487 | if (cp - 1 == to) { | |||
| 488 | /* closest common ancestor is /, so use full pathname */ | |||
| 489 | len = strlen(strcpy(outpath, to)); | |||
| 490 | if (outpath[len] != '/') { | |||
| 491 | outpath[len++] = '/'; | |||
| 492 | outpath[len] = '\0'; | |||
| 493 | } | |||
| 494 | } else { | |||
| 495 | len = 0; | |||
| 496 | while ((cp2 = getcomponent(cp2, buf)) != 0) { | |||
| 497 | strcpy(outpath + len, "../"); | |||
| 498 | len += 3; | |||
| 499 | } | |||
| 500 | while ((cp = getcomponent(cp, buf)) != 0) { | |||
| 501 | sprintf(outpath + len, "%s/", buf); | |||
| 502 | len += strlen(outpath + len); | |||
| 503 | } | |||
| 504 | } | |||
| 505 | return len; | |||
| 506 | } | |||
| 507 | ||||
| 508 | void | |||
| 509 | reversepath(char *inpath, char *name, int len, char *outpath) | |||
| 510 | { | |||
| 511 | char *cp, *cp2; | |||
| 512 | char buf[NAME_MAX256]; | |||
| 513 | struct stat sb; | |||
| 514 | ||||
| 515 | cp = strcpy(outpath + PATH_MAX4096 - (len + 1), name); | |||
| 516 | cp2 = inpath; | |||
| 517 | while ((cp2 = getcomponent(cp2, buf)) != 0) { | |||
| ||||
| 518 | if (strcmp(buf, ".") == 0) { | |||
| 519 | continue; | |||
| 520 | } | |||
| 521 | if (strcmp(buf, "..") == 0) { | |||
| 522 | if (stat(".", &sb) < 0) { | |||
| 523 | fail("cannot stat current directory"); | |||
| 524 | } | |||
| 525 | name = ino2name(sb.st_ino, ".."); | |||
| 526 | len = strlen(name); | |||
| 527 | cp -= len + 1; | |||
| 528 | strcpy(cp, name); | |||
| 529 | cp[len] = '/'; | |||
| 530 | free(name); | |||
| 531 | xchdir(".."); | |||
| 532 | } else { | |||
| 533 | cp -= 3; | |||
| 534 | memcpy(cp, "../", 3); | |||
| 535 | xchdir(buf); | |||
| 536 | } | |||
| 537 | } | |||
| 538 | strcpy(outpath, cp); | |||
| 539 | } |