Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 144328 Details for
Bug 220687
nash-command losetup with a file; size(file) > 2,147,483,647 returns error# 27: File too large
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
nash.c from mkinitrd ver. 5.1.19, with line-numbers.
Nash.c (text/plain), 79.12 KB, created by
Thomas Bruecker
on 2006-12-23 04:06:08 UTC
(
hide
)
Description:
nash.c from mkinitrd ver. 5.1.19, with line-numbers.
Filename:
MIME Type:
Creator:
Thomas Bruecker
Created:
2006-12-23 04:06:08 UTC
Size:
79.12 KB
patch
obsolete
> 1 /* > 2 * nash.c > 3 * > 4 * Code to load modules, mount root, and get things going. > 5 * > 6 * Erik Troan (ewt@redhat.com) > 7 * Jeremy Katz (katzj@redhat.com) > 8 * Peter Jones (pjones@redhat.com) > 9 * > 10 * Copyright 2002-2006 Red Hat, Inc. > 11 * > 12 * This software may be freely redistributed under the terms of the GNU > 13 * General Public License, version 2. > 14 * > 15 * You should have received a copy of the GNU General Public License > 16 * along with this program; if not, write to the Free Software > 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > 18 * > 19 */ > 20 > 21 /* We internalize losetup, mount, raidautorun, and echo commands. Other > 22 commands are run from the filesystem. Comments and blank lines work as > 23 well, argument parsing is screwy. */ > 24 > 25 #define _GNU_SOURCE 1 > 26 > 27 #include "version.h" > 28 > 29 #include <ctype.h> > 30 #include <dirent.h> > 31 #include <errno.h> > 32 #include <fcntl.h> > 33 #include <net/if.h> > 34 #include <signal.h> > 35 #include <stdio.h> > 36 #include <stdlib.h> > 37 #include <stdarg.h> > 38 #include <string.h> > 39 #include <sys/ioctl.h> > 40 #include <sys/mount.h> > 41 #include <sys/socket.h> > 42 #include <sys/stat.h> > 43 #include <sys/time.h> > 44 #include <sys/types.h> > 45 #include <sys/un.h> > 46 #include <sys/wait.h> > 47 #include <unistd.h> > 48 #include <sys/ioctl.h> > 49 #include <sys/reboot.h> > 50 #include <termios.h> > 51 #include <mntent.h> > 52 #include <execinfo.h> > 53 > 54 #include <asm/unistd.h> > 55 > 56 #include <libdevmapper.h> > 57 > 58 #include <bdevid.h> > 59 > 60 #include <nash.h> > 61 > 62 #include "lib.h" > 63 #include "util.h" > 64 #include "block.h" > 65 #include "dm.h" > 66 #include "net.h" > 67 #define HAVE_NFS 1 > 68 #include "sundries.h" > 69 > 70 /* Need to tell loop.h what the actual dev_t type is. */ > 71 #undef dev_t > 72 #if defined(__alpha) || (defined(__sparc__) && defined(__arch64__)) > 73 #define dev_t unsigned int > 74 #else > 75 #define dev_t unsigned short > 76 #endif > 77 #include <linux/loop.h> > 78 #undef dev_t > 79 #define dev_t dev_t > 80 > 81 #define syslog klogctl > 82 > 83 #include <linux/cdrom.h> > 84 #define MD_MAJOR 9 > 85 #include <linux/raid/md_u.h> > 86 > 87 #ifndef RAID_AUTORUN > 88 #define RAID_AUTORUN _IO (MD_MAJOR, 0x14) > 89 #endif > 90 > 91 #ifndef MS_REMOUNT > 92 #define MS_REMOUNT 32 > 93 #endif > 94 > 95 #ifndef MS_BIND > 96 #define MS_BIND 4096 > 97 #endif > 98 > 99 #ifndef MS_MOVE > 100 #define MS_MOVE 8192 > 101 #endif > 102 > 103 #ifndef MNT_FORCE > 104 #define MNT_FORCE 0x1 > 105 #endif > 106 > 107 #ifndef MNT_DETACH > 108 #define MNT_DETACH 0x2 > 109 #endif > 110 > 111 #define MAX(a, b) ((a) > (b) ? a : b) > 112 > 113 #define PATH "/usr/bin:/bin:/sbin:/usr/sbin" > 114 static char * env[] = { > 115 "PATH=" PATH, > 116 "LVM_SUPPRESS_FD_WARNINGS=1", > 117 NULL > 118 }; > 119 static char sysPath[] = PATH; > 120 > 121 /* ocPid is set when we're in otherCommand() */ > 122 static pid_t ocPid = -1; > 123 static int exit_status = 0; > 124 > 125 static int > 126 searchPath(char *bin, char **resolved) > 127 { > 128 char *fullPath = NULL; > 129 char *pathStart; > 130 char *pathEnd; > 131 int rc; > 132 > 133 if (!strchr(bin, '/')) { > 134 pathStart = sysPath; > 135 while (*pathStart) { > 136 char pec; > 137 pathEnd = strchr(pathStart, ':'); > 138 > 139 if (!pathEnd) > 140 pathEnd = pathStart + strlen(pathStart); > 141 > 142 pec = *pathEnd; > 143 *pathEnd = '\0'; > 144 > 145 rc = asprintfa(&fullPath, "%s/%s", pathStart, bin); > 146 if (!fullPath) { > 147 int errnum = errno; > 148 eprintf("error searching path: %m\n"); > 149 return -errnum; > 150 } > 151 > 152 *pathEnd = pec; > 153 pathStart = pathEnd; > 154 if (*pathStart) > 155 pathStart++; > 156 > 157 if (!access(fullPath, X_OK)) { > 158 *resolved = strdup(fullPath); > 159 return 0; > 160 } > 161 } > 162 } > 163 > 164 if (!access(bin, X_OK)) { > 165 *resolved = strdup(bin); > 166 if (*resolved) > 167 return 0; > 168 } > 169 return -errno; > 170 } > 171 > 172 static char * > 173 getArg(char * cmd, char * end, char ** arg) > 174 { > 175 char quote = '\0'; > 176 > 177 if (!cmd || cmd >= end) > 178 return NULL; > 179 > 180 while (isspace(*cmd) && cmd < end) > 181 cmd++; > 182 if (cmd >= end) > 183 return NULL; > 184 > 185 if (*cmd == '"') > 186 cmd++, quote = '"'; > 187 else if (*cmd == '\'') > 188 cmd++, quote = '\''; > 189 > 190 if (quote) { > 191 *arg = cmd; > 192 > 193 /* This doesn't support \ escapes */ > 194 while (cmd < end && *cmd != quote) > 195 cmd++; > 196 > 197 if (cmd == end) { > 198 eprintf("error: quote mismatch for %s\n", *arg); > 199 return NULL; > 200 } > 201 > 202 *cmd = '\0'; > 203 cmd++; > 204 } else { > 205 *arg = cmd; > 206 while (!isspace(*cmd) && cmd < end) > 207 cmd++; > 208 *cmd = '\0'; > 209 if (**arg == '$') > 210 *arg = getenv(*arg+1); > 211 if (*arg == NULL) > 212 *arg = ""; > 213 } > 214 > 215 cmd++; > 216 > 217 while (isspace(*cmd)) > 218 cmd++; > 219 > 220 return cmd; > 221 } > 222 > 223 /* get the contents of the kernel command line from /proc/cmdline */ > 224 static char * > 225 getKernelCmdLine(void) > 226 { > 227 int fd, i, errnum; > 228 static char * buf = NULL; > 229 > 230 if (buf) > 231 return buf; > 232 > 233 fd = open("/proc/cmdline", O_RDONLY); > 234 if (fd < 0) { > 235 eprintf("getKernelCmdLine: failed to open /proc/cmdline: %m\n"); > 236 return NULL; > 237 } > 238 > 239 i = readFD(fd, &buf); > 240 errnum = errno; > 241 close(fd); > 242 if (i < 0) { > 243 eprintf("getKernelCmdLine: failed to read /proc/cmdline: %m\n"); > 244 return NULL; > 245 } > 246 return buf; > 247 } > 248 > 249 /* get the start of a kernel arg "arg". returns everything after it > 250 * (useful for things like getting the args to init=). so if you only > 251 * want one arg, you need to terminate it at the n */ > 252 static char * > 253 getKernelArg(char * arg) > 254 { > 255 char * start, * cmdline; > 256 int len; > 257 > 258 cmdline = start = getKernelCmdLine(); > 259 if (start == NULL) > 260 return NULL; > 261 while (*start) { > 262 if (isspace(*start)) { > 263 start++; > 264 continue; > 265 } > 266 len = strlen(arg); > 267 /* don't return if it's some other arg that just starts like > 268 this one */ > 269 if (strncmp(start, arg, len) == 0) { > 270 if (start[len] == '=') > 271 return start + len + 1; > 272 if (!start[len] || isspace(start[len])) > 273 return start + len; > 274 } > 275 while (*++start && !isspace(*start)) > 276 ; > 277 } > 278 > 279 return NULL; > 280 } > 281 > 282 static int > 283 mountCommand(char * cmd, char * end) > 284 { > 285 char * fsType = NULL; > 286 char * device, *spec; > 287 char * mntPoint; > 288 char * options = NULL; > 289 int rc = 0; > 290 int flags = MS_MGC_VAL; > 291 char * newOpts; > 292 > 293 if (!(cmd = getArg(cmd, end, &spec))) { > 294 eprintf( > 295 "usage: mount [--ro] [-o <opts>] -t <type> <device> <mntpoint>\n"); > 296 return 1; > 297 } > 298 > 299 while (cmd && *spec == '-') { > 300 if (!strcmp(spec, "--ro")) { > 301 flags |= MS_RDONLY; > 302 } else if (!strcmp(spec, "--bind")) { > 303 flags = MS_BIND; > 304 fsType = "none"; > 305 } else if (!strcmp(spec, "--move")) { > 306 flags = MS_MOVE; > 307 fsType = "none"; > 308 } else if (!strcmp(spec, "-o")) { > 309 cmd = getArg(cmd, end, &options); > 310 if (!cmd) { > 311 eprintf("mount: -o requires arguments\n"); > 312 return 1; > 313 } > 314 } else if (!strcmp(spec, "-t")) { > 315 if (!(cmd = getArg(cmd, end, &fsType))) { > 316 eprintf("mount: missing filesystem type\n"); > 317 return 1; > 318 } > 319 } > 320 > 321 cmd = getArg(cmd, end, &spec); > 322 } > 323 > 324 if (!cmd) { > 325 eprintf("mount: missing device or mountpoint\n"); > 326 return 1; > 327 } > 328 > 329 if (!(cmd = getArg(cmd, end, &mntPoint))) { > 330 struct mntent *mnt; > 331 FILE *fstab; > 332 > 333 fstab = fopen("/etc/fstab", "r"); > 334 if (!fstab) { > 335 eprintf("mount: missing mount point\n"); > 336 return 1; > 337 } > 338 do { > 339 if (!(mnt = getmntent(fstab))) { > 340 eprintf("mount: missing mount point\n"); > 341 fclose(fstab); > 342 return 1; > 343 } > 344 if (!strcmp(mnt->mnt_dir, spec)) { > 345 spec = mnt->mnt_fsname; > 346 mntPoint = mnt->mnt_dir; > 347 > 348 if (!strcmp(mnt->mnt_type, "bind")) { > 349 flags |= MS_BIND; > 350 fsType = "none"; > 351 } else > 352 fsType = mnt->mnt_type; > 353 > 354 options = mnt->mnt_opts; > 355 break; > 356 } > 357 } while(1); > 358 > 359 fclose(fstab); > 360 } > 361 > 362 if (!fsType) { > 363 eprintf("mount: filesystem type expected\n"); > 364 return 1; > 365 } > 366 > 367 if (cmd && cmd < end) { > 368 eprintf("mount: unexpected arguments\n"); > 369 return 1; > 370 } > 371 > 372 /* need to deal with options */ > 373 if (options) { > 374 char * end; > 375 char * start = options; > 376 > 377 newOpts = alloca(strlen(options) + 1); > 378 *newOpts = '\0'; > 379 > 380 while (*start) { > 381 end = strchr(start, ','); > 382 if (!end) { > 383 end = start + strlen(start); > 384 } else { > 385 *end = '\0'; > 386 end++; > 387 } > 388 > 389 if (!strcmp(start, "ro")) > 390 flags |= MS_RDONLY; > 391 else if (!strcmp(start, "rw")) > 392 flags &= ~MS_RDONLY; > 393 else if (!strcmp(start, "nosuid")) > 394 flags |= MS_NOSUID; > 395 else if (!strcmp(start, "suid")) > 396 flags &= ~MS_NOSUID; > 397 else if (!strcmp(start, "nodev")) > 398 flags |= MS_NODEV; > 399 else if (!strcmp(start, "dev")) > 400 flags &= ~MS_NODEV; > 401 else if (!strcmp(start, "noexec")) > 402 flags |= MS_NOEXEC; > 403 else if (!strcmp(start, "exec")) > 404 flags &= ~MS_NOEXEC; > 405 else if (!strcmp(start, "sync")) > 406 flags |= MS_SYNCHRONOUS; > 407 else if (!strcmp(start, "async")) > 408 flags &= ~MS_SYNCHRONOUS; > 409 else if (!strcmp(start, "nodiratime")) > 410 flags |= MS_NODIRATIME; > 411 else if (!strcmp(start, "diratime")) > 412 flags &= ~MS_NODIRATIME; > 413 else if (!strcmp(start, "noatime")) > 414 flags |= MS_NOATIME; > 415 else if (!strcmp(start, "atime")) > 416 flags &= ~MS_NOATIME; > 417 else if (!strcmp(start, "remount")) > 418 flags |= MS_REMOUNT; > 419 else if (!strcmp(start, "bind")) > 420 flags |= MS_BIND; > 421 else if (!strcmp(start, "defaults")) > 422 ; > 423 else { > 424 if (*newOpts) > 425 strcat(newOpts, ","); > 426 strcat(newOpts, start); > 427 } > 428 > 429 start = end; > 430 } > 431 > 432 options = newOpts; > 433 } > 434 > 435 if (!strncmp(fsType, "nfs", 3)) { > 436 device = strdupa(spec); > 437 } else { > 438 device = nashGetPathBySpec(_nash_context, spec); > 439 } > 440 > 441 if (!device) { > 442 eprintf("mount: could not find filesystem '%s'\n", spec); > 443 return 1; > 444 } > 445 > 446 if (_nash_context->testing) { > 447 printf("mount %s%s%s-t '%s' '%s' '%s' (%s%s%s%s%s%s%s)\n", > 448 options ? "-o '" : "", > 449 options ? options : "", > 450 options ? "\' " : "", > 451 fsType, device, mntPoint, > 452 (flags & MS_RDONLY) ? "ro " : "", > 453 (flags & MS_NOSUID) ? "nosuid " : "", > 454 (flags & MS_NODEV) ? "nodev " : "", > 455 (flags & MS_NOEXEC) ? "noexec " : "", > 456 (flags & MS_SYNCHRONOUS) ? "sync " : "", > 457 (flags & MS_REMOUNT) ? "remount " : "", > 458 (flags & MS_NOATIME) ? "noatime " : "" > 459 ); > 460 } else { > 461 if (!strncmp(fsType, "nfs", 3)) { > 462 char * foo = NULL; > 463 if (nfsmount(device, mntPoint, &flags, &foo, &options, 0)) { > 464 eprintf("nfsmount: error mounting %s on %s as %s: %m\n", > 465 device, mntPoint, fsType); > 466 return 1; > 467 } > 468 } > 469 if (mount(device, mntPoint, fsType, flags, options) < 0) { > 470 eprintf("mount: error mounting %s on %s as %s: %m\n", > 471 device, mntPoint, fsType); > 472 rc = 1; > 473 } > 474 } > 475 > 476 return rc; > 477 } > 478 > 479 static int > 480 otherCommand(char * bin, char * cmd, char * end, int doFork, int killHp) > 481 { > 482 char ** args; > 483 char ** nextArg; > 484 int wpid; > 485 int status = 0; > 486 char * stdoutFile = NULL; > 487 int stdoutFd = fileno(stdout); > 488 > 489 args = (char **)calloc(128, sizeof (char *)); > 490 if (!args) > 491 return 1; > 492 nextArg = args; > 493 > 494 if (access(bin, X_OK)) { > 495 eprintf("failed to execute %s: %m\n", bin); > 496 return 1; > 497 } > 498 > 499 *nextArg = strdup(bin); > 500 > 501 while (cmd && cmd < end) { > 502 nextArg++; > 503 cmd = getArg(cmd, end, nextArg); > 504 } > 505 > 506 if (cmd) > 507 nextArg++; > 508 *nextArg = NULL; > 509 > 510 /* if the next-to-last arg is a >, redirect the output properly */ > 511 if (((nextArg - args) >= 2) && !strcmp(*(nextArg - 2), ">")) { > 512 stdoutFile = *(nextArg - 1); > 513 *(nextArg - 2) = NULL; > 514 > 515 stdoutFd = open(stdoutFile, O_CREAT | O_RDWR | O_TRUNC, 0600); > 516 if (stdoutFd < 0) { > 517 eprintf("nash: failed to open %s: %m\n", stdoutFile); > 518 return 1; > 519 } > 520 setFdCoe(stdoutFd, 0); > 521 } > 522 > 523 if (_nash_context->testing) { > 524 printf("%s ", bin); > 525 nextArg = args + 1; > 526 while (*nextArg) > 527 printf(" '%s'", *nextArg++); > 528 if (stdoutFile) > 529 printf(" (> %s)", stdoutFile); > 530 printf("\n"); > 531 } else { > 532 if (!doFork || !(ocPid = fork())) { > 533 /* child */ > 534 int errnum; > 535 > 536 dm_lib_exit(); /* ARRGH */ > 537 if (killHp) > 538 nashHotplugKill(_nash_context); > 539 dup2(stdoutFd, 1); > 540 execve(args[0], args, env); > 541 errnum = errno; /* so we'll have it after printf */ > 542 eprintf("ERROR: failed in exec of %s: %m\n", args[0]); > 543 return 1; > 544 } > 545 > 546 if (stdoutFd != fileno(stdout)) > 547 close(stdoutFd); > 548 > 549 for (;;) { > 550 wpid = waitpid(ocPid, &status, 0); > 551 if (wpid == -1) > 552 eprintf("ERROR: Failed to wait for process %d: %m\n", wpid); > 553 > 554 if (!WIFEXITED(status) || WEXITSTATUS(status)) { > 555 #if 0 > 556 eprintf("ERROR: %s exited abnormally with value %d (pid %d)\n", > 557 args[0], WEXITSTATUS(status), ocPid); > 558 #endif > 559 status = WEXITSTATUS(status); > 560 } else { > 561 status = 0; > 562 } > 563 break; > 564 } > 565 return status; > 566 } > 567 > 568 return status; > 569 } > 570 > 571 static int > 572 lnCommand(char *cmd, char *end) > 573 { > 574 char *oldpath, *newpath; > 575 int symbolic = 0, rc; > 576 > 577 if (!(cmd = getArg(cmd, end, &oldpath))) { > 578 eprintf("ln: argument expected\n"); > 579 return 1; > 580 } > 581 > 582 if (!strcmp(cmd, "-s")) { > 583 symbolic = 1; > 584 if (!(cmd = getArg(cmd, end, &oldpath))) { > 585 eprintf("ln: argument expected\n"); > 586 return 1; > 587 } > 588 } > 589 > 590 if (!(cmd = getArg(cmd, end, &newpath))) { > 591 eprintf("ln: argument expected\n"); > 592 return 1; > 593 } > 594 > 595 if (symbolic) > 596 rc = symlink(oldpath, newpath); > 597 else > 598 rc = link(oldpath, newpath); > 599 > 600 if (rc > 0) { > 601 eprintf("ln: error: %m\n"); > 602 return 1; > 603 } > 604 > 605 return 0; > 606 } > 607 > 608 static int > 609 copyToFd(const char *file, int destfd) > 610 { > 611 char * buf; > 612 int fd, n; > 613 > 614 if ((fd = open(file, O_RDONLY)) < 0) { > 615 eprintf("cp: error opening %s: %m\n", file); > 616 return 1; > 617 } > 618 > 619 buf = calloc(1024, sizeof (char)); > 620 while ((n = read(fd, buf, 1024)) > 0) { > 621 write(destfd, buf, n); > 622 } > 623 close(fd); > 624 return 0; > 625 } > 626 > 627 static int > 628 cpCommand(char *cmd, char *end) > 629 { > 630 char * src; > 631 char * dest; > 632 int fd; > 633 int rc; > 634 > 635 if (!(cmd = getArg(cmd, end, &src))) { > 636 eprintf("cp: source argument expected\n"); > 637 return 1; > 638 } > 639 > 640 if (!(cmd = getArg(cmd, end, &dest))) { > 641 eprintf("cp: destination argument expected\n"); > 642 return 1; > 643 } > 644 > 645 if ((fd = open(dest, O_CREAT|O_TRUNC|O_WRONLY, 0600)) < 0) { > 646 eprintf("cp: error opening %s: %m\n", dest); > 647 return 1; > 648 } > 649 > 650 rc = copyToFd(src, fd); > 651 > 652 close(fd); > 653 > 654 return rc; > 655 } > 656 > 657 #ifdef DEBUG > 658 static int lsdir(char *thedir, char * prefix) > 659 { > 660 DIR * dir; > 661 struct dirent * entry; > 662 struct stat sb; > 663 char * fn; > 664 > 665 if (!(dir = opendir(thedir))) { > 666 eprintf("error opening %s: %m\n", thedir); > 667 return 1; > 668 } > 669 > 670 fn = calloc(1024, sizeof (char)); > 671 while ((entry = readdir(dir))) { > 672 if (entry->d_name[0] == '.') > 673 continue; > 674 snprintf(fn, 1024, "%s/%s", thedir, entry->d_name); > 675 stat(fn, &sb); > 676 printf("%s%s", prefix, fn); > 677 > 678 if (S_ISDIR(sb.st_mode)) { > 679 char * pfx; > 680 pfx = calloc(strlen(prefix) + 3, sizeof (char)); > 681 sprintf(pfx, "%s ", prefix); > 682 printf("/\n"); > 683 } else if (S_ISCHR(sb.st_mode)) { > 684 printf(" c %d %d\n", major(sb.st_rdev), minor(sb.st_rdev)); > 685 } else if (S_ISBLK(sb.st_mode)) { > 686 printf(" b %d %d\n", major(sb.st_rdev), minor(sb.st_rdev)); > 687 } else if (S_ISLNK(sb.st_mode)) { > 688 char * target; > 689 target = calloc(1024, sizeof (char)); > 690 readlink(fn, target, 1024); > 691 printf("->%s\n", target); > 692 free(target); > 693 } else { > 694 printf("\n"); > 695 } > 696 } > 697 return 0; > 698 } > 699 #endif > 700 > 701 static int > 702 catCommand(char * cmd, char * end) > 703 { > 704 char * file; > 705 int fd = fileno(stdout); > 706 > 707 if (!(cmd = getArg(cmd, end, &file))) { > 708 eprintf("cat: argument expected\n"); > 709 return 1; > 710 } > 711 > 712 return copyToFd(file, fd); > 713 } > 714 > 715 #ifdef DEBUG > 716 static int > 717 lsCommand(char * cmd, char * end) > 718 { > 719 char * dir; > 720 > 721 if (!(cmd = getArg(cmd, end, &dir))) { > 722 eprintf("ls: argument expected\n"); > 723 return 1; > 724 } > 725 > 726 lsdir(dir, ""); > 727 return 0; > 728 } > 729 #endif > 730 > 731 static int > 732 execCommand(char *cmd, char *end) > 733 { > 734 char *bin = NULL, *fullPath = NULL; > 735 int killHp = 1; > 736 int rc; > 737 > 738 while ((cmd = getArg(cmd, end, &bin))) { > 739 if (!strcmp(bin, "--nokill")) { > 740 killHp = 0; > 741 bin = NULL; > 742 continue; > 743 } > 744 break; > 745 } > 746 if (!bin) { > 747 eprintf("exec: argument expected\n"); > 748 return 1; > 749 } > 750 rc = searchPath(bin, &fullPath); > 751 if (rc < 0) > 752 return 1; > 753 > 754 rc = otherCommand(fullPath, cmd, end, 0, killHp); > 755 free(fullPath); > 756 return rc; > 757 } > 758 > 759 static int > 760 exitCommand(char *cmd, char *end) { > 761 char *arg; > 762 int killHp = 1; > 763 int status = 0; > 764 > 765 while ((cmd = getArg(cmd, end, &arg)) && arg) { > 766 if (!strcmp(arg, "--nokill")) { > 767 killHp = 0; > 768 } else { > 769 status = strtol(arg, NULL, 10); > 770 } > 771 } > 772 if (killHp) > 773 nashHotplugKill(_nash_context); > 774 > 775 exit(status); > 776 } > 777 > 778 static int > 779 losetupCommand(char * cmd, char * end) > 780 { > 781 char * device; > 782 char * file; > 783 int fd; > 784 struct loop_info loopInfo; > 785 int dev; > 786 > 787 if (!(cmd = getArg(cmd, end, &device))) { > 788 eprintf("losetup: missing device\n"); > 789 return 1; > 790 } > 791 > 792 if (!(cmd = getArg(cmd, end, &file))) { > 793 eprintf("losetup: missing file\n"); > 794 return 1; > 795 } > 796 > 797 if (cmd < end) { > 798 eprintf("losetup: unexpected arguments\n"); > 799 return 1; > 800 } > 801 > 802 if (_nash_context->testing) { > 803 printf("losetup '%s' '%s'\n", device, file); > 804 } else { > 805 dev = open(device, O_RDWR); > 806 if (dev < 0) { > 807 eprintf("losetup: failed to open %s: %m\n", device); > 808 return 1; > 809 } > 810 > 811 if ((fd = open(file, O_RDWR)) < 0) { > 812 if (errno == EROFS || errno == EPERM || errno == EACCES) { > 813 fd = open(file, O_RDONLY); > 814 } > 815 if (fd < 0) { > 816 eprintf("losetup: failed to open %s: %m\n", file); > 817 close(dev); > 818 return 1; > 819 } > 820 } > 821 > 822 if (ioctl(dev, LOOP_SET_FD, (long)fd)) { > 823 eprintf("losetup: LOOP_SET_FD failed for fd %d: %m\n", fd); > 824 close(dev); > 825 close(fd); > 826 return 1; > 827 } > 828 > 829 close(fd); > 830 > 831 memset(&loopInfo, 0, sizeof(loopInfo)); > 832 strcpy(loopInfo.lo_name, file); > 833 > 834 if (ioctl(dev, LOOP_SET_STATUS, &loopInfo)) > 835 eprintf("losetup: LOOP_SET_STATUS failed: %m\n"); > 836 > 837 close(dev); > 838 } > 839 > 840 return 0; > 841 } > 842 > 843 static int > 844 hotplugCommand(char *cmd, char *end) > 845 { > 846 char *new; > 847 cmd = getArg(cmd, end, &new); > 848 if (cmd) { > 849 eprintf("hotplug: unexpected arguments\n"); > 850 return 1; > 851 } > 852 > 853 nashHotplugInit(_nash_context); > 854 return 0; > 855 } > 856 > 857 static int > 858 killplugCommand(char *cmd, char *end) > 859 { > 860 char *new; > 861 cmd = getArg(cmd, end, &new); > 862 if (cmd) { > 863 eprintf("killplug: unexpected arguments\n"); > 864 return 1; > 865 } > 866 > 867 nashHotplugKill(_nash_context); > 868 return 0; > 869 } > 870 > 871 > 872 #define RAID_MAJOR 9 > 873 static int > 874 raidautorunCommand(char * cmd, char * end) > 875 { > 876 char * device; > 877 int fd; > 878 > 879 if (!(cmd = getArg(cmd, end, &device))) { > 880 eprintf("raidautorun: raid device expected as first argument\n"); > 881 return 1; > 882 } > 883 > 884 if (cmd < end) { > 885 eprintf("raidautorun: unexpected arguments\n"); > 886 return 1; > 887 } > 888 > 889 /* with udev, the raid devices don't exist until they get started. > 890 * this won't work so well with raidautorun. so, let's be smart > 891 * and create them ourselves if we need to */ > 892 if (access(device, R_OK & W_OK)) { > 893 int minor; > 894 if (sscanf(device, "/dev/md%d", &minor) != 1) { > 895 eprintf("raidautorun: unable to autocreate %s\n", device); > 896 return 1; > 897 } > 898 > 899 if (smartmknod(device, S_IFBLK | 0600, makedev(RAID_MAJOR, minor))) { > 900 eprintf("raidautorun: unable to autocreate %s\n", device); > 901 return 1; > 902 } > 903 } > 904 > 905 fd = open(device, O_RDWR); > 906 if (fd < 0) { > 907 eprintf("raidautorun: failed to open %s: %m\n", device); > 908 return 1; > 909 } > 910 > 911 if (ioctl(fd, RAID_AUTORUN, 0)) { > 912 eprintf("raidautorun: RAID_AUTORUN failed: %m\n"); > 913 close(fd); > 914 return 1; > 915 } > 916 > 917 close(fd); > 918 return 0; > 919 } > 920 > 921 /* remove all files/directories below dirName -- don't cross mountpoints */ > 922 static int > 923 recursiveRemove(char * dirName) > 924 { > 925 struct stat sb,rb; > 926 DIR * dir; > 927 struct dirent * d; > 928 char * strBuf = alloca(strlen(dirName) + 1024); > 929 > 930 if (!(dir = opendir(dirName))) { > 931 eprintf("error opening %s: %m\n", dirName); > 932 return 0; > 933 } > 934 > 935 if (fstat(dirfd(dir),&rb)) { > 936 eprintf("unable to stat %s: %m\n", dirName); > 937 closedir(dir); > 938 return 0; > 939 } > 940 > 941 errno = 0; > 942 while ((d = readdir(dir))) { > 943 errno = 0; > 944 > 945 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) { > 946 errno = 0; > 947 continue; > 948 } > 949 > 950 strcpy(strBuf, dirName); > 951 strcat(strBuf, "/"); > 952 strcat(strBuf, d->d_name); > 953 > 954 if (lstat(strBuf, &sb)) { > 955 eprintf("failed to stat %s: %m\n", strBuf); > 956 errno = 0; > 957 continue; > 958 } > 959 > 960 /* only descend into subdirectories if device is same as dir */ > 961 if (S_ISDIR(sb.st_mode)) { > 962 if (sb.st_dev == rb.st_dev) { > 963 recursiveRemove(strBuf); > 964 if (rmdir(strBuf)) > 965 eprintf("failed to rmdir %s: %m\n", strBuf); > 966 } > 967 errno = 0; > 968 continue; > 969 } > 970 > 971 if (unlink(strBuf)) { > 972 eprintf("failed to remove %s: %m\n", strBuf); > 973 errno = 0; > 974 continue; > 975 } > 976 } > 977 > 978 if (errno) { > 979 closedir(dir); > 980 eprintf("error reading from %s: %m\n", dirName); > 981 return 1; > 982 } > 983 > 984 closedir(dir); > 985 > 986 return 0; > 987 } > 988 > 989 static void > 990 mountMntEnt(const struct mntent *mnt) > 991 { > 992 char *start = NULL, *end; > 993 char *target = NULL; > 994 struct stat sb; > 995 > 996 qprintf("mounting %s\n", mnt->mnt_dir); > 997 if (asprintfa(&target, ".%s", mnt->mnt_dir) < 0) { > 998 eprintf("setuproot: out of memory while mounting %s\n", > 999 mnt->mnt_dir); > 1000 return; > 1001 } > 1002 > 1003 if (stat(target, &sb) < 0) > 1004 return; > 1005 > 1006 if (asprintf(&start, "-o %s -t %s %s .%s\n", > 1007 mnt->mnt_opts, mnt->mnt_type, mnt->mnt_fsname, > 1008 mnt->mnt_dir) < 0) { > 1009 eprintf("setuproot: out of memory while mounting %s\n", > 1010 mnt->mnt_dir); > 1011 return; > 1012 } > 1013 > 1014 end = start + 1; > 1015 while (*end && (*end != '\n')) > 1016 end++; > 1017 /* end points to the \n at the end of the command */ > 1018 > 1019 if (mountCommand(start, end) != 0) > 1020 eprintf("setuproot: mount returned error\n"); > 1021 } > 1022 > 1023 static int > 1024 setuprootCommand(char *cmd, char *end) > 1025 { > 1026 FILE *fp; > 1027 char *new; > 1028 > 1029 qprintf("Setting up new root fs\n"); > 1030 > 1031 cmd = getArg(cmd, end, &new); > 1032 if (cmd) { > 1033 eprintf("setuproot: unexpected arguments\n"); > 1034 return 1; > 1035 } > 1036 new = "/sysroot"; > 1037 > 1038 if (chdir(new)) { > 1039 eprintf("setuproot: chdir(%s) failed: %m\n", new); > 1040 return 1; > 1041 } > 1042 > 1043 if (mount("/dev", "./dev", NULL, MS_BIND, NULL) < 0) > 1044 eprintf("setuproot: moving /dev failed: %m\n"); > 1045 > 1046 if (!getKernelArg("nomnt")) { > 1047 fp = setmntent("./etc/fstab.sys", "r"); > 1048 if (fp) > 1049 qprintf("using fstab.sys from mounted FS\n"); > 1050 else { > 1051 fp = setmntent("/etc/fstab.sys", "r"); > 1052 if (fp) > 1053 qprintf("using fstab.sys from initrd\n"); > 1054 } > 1055 if (fp) { > 1056 struct mntent *mnt; > 1057 > 1058 while((mnt = getmntent(fp))) > 1059 mountMntEnt(mnt); > 1060 endmntent(fp); > 1061 } else { > 1062 struct { > 1063 char *source; > 1064 char *target; > 1065 char *type; > 1066 int flags; > 1067 void *data; > 1068 int raise; > 1069 } fstab[] = { > 1070 { "/proc", "./proc", "proc", 0, NULL }, > 1071 { "/sys", "./sys", "sysfs", 0, NULL }, > 1072 #if 0 > 1073 { "/dev/pts", "./dev/pts", "devpts", 0, "gid=5,mode=620" }, > 1074 { "/dev/shm", "./dev/shm", "tmpfs", 0, NULL }, > 1075 { "/selinux", "/selinux", "selinuxfs", 0, NULL }, > 1076 #endif > 1077 { NULL, } > 1078 }; > 1079 int i = 0; > 1080 > 1081 qprintf("no fstab.sys, mounting internal defaults\n"); > 1082 for (; fstab[i].source != NULL; i++) { > 1083 if (mount(fstab[i].source, fstab[i].target, fstab[i].type, > 1084 fstab[i].flags, fstab[i].data) < 0) > 1085 eprintf("setuproot: error mounting %s: %m\n", > 1086 fstab[i].source); > 1087 } > 1088 } > 1089 } > 1090 > 1091 chdir("/"); > 1092 return 0; > 1093 } > 1094 > 1095 #define MAX_INIT_ARGS 32 > 1096 static int > 1097 switchrootCommand(char * cmd, char * end) > 1098 { > 1099 /* Don't try to unmount the old "/", there's no way to do it. */ > 1100 const char *umounts[] = { "/dev", "/proc", "/sys", NULL }; > 1101 const char *initprogs[] = { "/sbin/init", "/etc/init", > 1102 "/bin/init", "/bin/sh", NULL }; > 1103 char *init, **initargs; > 1104 char *cmdline = NULL; > 1105 char *new; > 1106 int fd, i = 0; > 1107 > 1108 cmd = getArg(cmd, end, &new); > 1109 if (cmd) { > 1110 eprintf("switchroot: unexpected arguments\n"); > 1111 return 1; > 1112 } > 1113 new = "/sysroot"; > 1114 > 1115 /* this has to happen before we unmount /proc */ > 1116 init = getKernelArg("init"); > 1117 if (init == NULL) > 1118 cmdline = getKernelCmdLine(); > 1119 > 1120 fd = open("/", O_RDONLY); > 1121 for (; umounts[i] != NULL; i++) { > 1122 qprintf("unmounting old %s\n", umounts[i]); > 1123 if (umount2(umounts[i], MNT_DETACH) < 0) { > 1124 eprintf("ERROR unmounting old %s: %m\n",umounts[i]); > 1125 eprintf("forcing unmount of %s\n", umounts[i]); > 1126 umount2(umounts[i], MNT_FORCE); > 1127 } > 1128 } > 1129 i=0; > 1130 > 1131 chdir(new); > 1132 nashHotplugNewRoot(_nash_context); > 1133 nashHotplugNotifyExit(_nash_context); > 1134 > 1135 recursiveRemove("/"); > 1136 > 1137 if (mount(new, "/", NULL, MS_MOVE, NULL) < 0) { > 1138 eprintf("switchroot: mount failed: %m\n"); > 1139 close(fd); > 1140 return 1; > 1141 } > 1142 > 1143 if (chroot(".")) { > 1144 eprintf("switchroot: chroot() failed: %m\n"); > 1145 close(fd); > 1146 return 1; > 1147 } > 1148 > 1149 /* release the old "/" */ > 1150 close(fd); > 1151 > 1152 close(3); > 1153 if ((fd = open("/dev/console", O_RDWR)) < 0) { > 1154 eprintf("ERROR opening /dev/console: %m\n"); > 1155 eprintf("Trying to use fd 0 instead.\n"); > 1156 fd = dup2(0, 3); > 1157 } else { > 1158 setFdCoe(fd, 0); > 1159 if (fd != 3) { > 1160 dup2(fd, 3); > 1161 close(fd); > 1162 fd = 3; > 1163 } > 1164 } > 1165 close(0); > 1166 dup2(fd, 0); > 1167 close(1); > 1168 dup2(fd, 1); > 1169 close(2); > 1170 dup2(fd, 2); > 1171 close(fd); > 1172 > 1173 if (init == NULL) { > 1174 for (i = 0; initprogs[i] != NULL; i++) { > 1175 if (!access(initprogs[i], X_OK)) { > 1176 init = strdup(initprogs[i]); > 1177 break; > 1178 } > 1179 } > 1180 } > 1181 i = 0; > 1182 > 1183 initargs = (char **)calloc(MAX_INIT_ARGS+1, sizeof (char *)); > 1184 if (cmdline && init) { > 1185 initargs[i++] = strdup(init); > 1186 } else { > 1187 cmdline = init; > 1188 initargs[0] = NULL; > 1189 } > 1190 > 1191 if (cmdline != NULL) { > 1192 char * chptr, * start; > 1193 > 1194 start = chptr = cmdline; > 1195 for (; (i < MAX_INIT_ARGS) && (*start != '\0'); i++) { > 1196 while (*chptr && !isspace(*chptr)) > 1197 chptr++; > 1198 if (*chptr != '\0') *(chptr++) = '\0'; > 1199 /* > 1200 * On x86_64, the kernel adds a magic command line parameter > 1201 * *after* everything you pass. Bash doesn't know what "console=" > 1202 * means, so it exits, init gets killed, etc, etc. Bad news. > 1203 * > 1204 * Apparently being removed "soon", but for now, nash needs to > 1205 * special case it. > 1206 */ > 1207 if (cmdline == init && !strncmp(start, "console=", 8)) { > 1208 if (!*chptr) > 1209 initargs[i] = NULL; > 1210 else > 1211 i--; > 1212 start = chptr; > 1213 continue; > 1214 } > 1215 initargs[i] = strdup(start); > 1216 start = chptr; > 1217 } > 1218 } > 1219 > 1220 initargs[i] = NULL; > 1221 > 1222 if (access(initargs[0], X_OK)) { > 1223 eprintf("WARNING: can't access %s\n", initargs[0]); > 1224 } > 1225 dm_lib_exit(); /* ARRGH */ > 1226 execv(initargs[0], initargs); > 1227 > 1228 eprintf("exec of init (%s) failed!!!: %m\n", initargs[0]); > 1229 return 1; > 1230 } > 1231 > 1232 static int > 1233 isEchoQuiet(int fd) > 1234 { > 1235 if (!_nash_context->reallyquiet) > 1236 return 0; > 1237 if (fd != 1) > 1238 return 0; > 1239 return 1; > 1240 } > 1241 > 1242 static int > 1243 echoCommand(char * cmd, char * end) > 1244 { > 1245 char * args[256]; > 1246 char ** nextArg = args; > 1247 int outFd = 1; > 1248 int num = 0; > 1249 int i; > 1250 int newline = 1; > 1251 int length = 0; > 1252 char *string; > 1253 > 1254 if (_nash_context->testing) > 1255 qprintf("(echo) "); > 1256 > 1257 while ((cmd = getArg(cmd, end, nextArg))) { > 1258 if (!strncmp("-n", *nextArg, MAX(2, strlen(*nextArg)))) { > 1259 newline = 0; > 1260 } else { > 1261 length += strlen(*nextArg); > 1262 nextArg++, num++; > 1263 } > 1264 } > 1265 length += num + 1; > 1266 > 1267 if ((nextArg - args >= 2) && !strcmp(*(nextArg - 2), ">")) { > 1268 outFd = open(*(nextArg - 1), O_WRONLY | O_CREAT | O_TRUNC, 0644); > 1269 if (outFd < 0) { > 1270 eprintf("echo: cannot open %s for write: %m\n", *(nextArg - 1)); > 1271 return 1; > 1272 } > 1273 > 1274 newline = 0; > 1275 num -= 2; > 1276 } > 1277 string = (char *)calloc(length, sizeof (char)); > 1278 *string = '\0'; > 1279 for (i = 0; i < num;i ++) { > 1280 if (i) > 1281 strcat(string, " "); > 1282 strcat(string, args[i]); > 1283 } > 1284 > 1285 if (newline) > 1286 strcat(string, "\n"); > 1287 if (!isEchoQuiet(outFd)) > 1288 write(outFd, string, strlen(string)); > 1289 > 1290 if (outFd != 1) > 1291 close(outFd); > 1292 free(string); > 1293 > 1294 return 0; > 1295 } > 1296 > 1297 static int > 1298 umountCommand(char * cmd, char * end) > 1299 { > 1300 char * path; > 1301 > 1302 if (!(cmd = getArg(cmd, end, &path))) { > 1303 eprintf("umount: path expected\n"); > 1304 return 1; > 1305 } > 1306 > 1307 if (cmd < end) { > 1308 eprintf("umount: unexpected arguments\n"); > 1309 return 1; > 1310 } > 1311 > 1312 if (umount2(path,MNT_DETACH) < 0) { > 1313 eprintf("umount %s failed: %m\n", path); > 1314 return 1; > 1315 } > 1316 > 1317 return 0; > 1318 } > 1319 > 1320 static int > 1321 resolveDeviceCommand(char *cmd, char *end) > 1322 { > 1323 char *spec = NULL; > 1324 char *device = NULL; > 1325 > 1326 if (!(cmd = getArg(cmd, end, &spec))) { > 1327 eprintf("resolveDevice: device spec expected\n"); > 1328 return 1; > 1329 } > 1330 > 1331 device = nashGetPathBySpec(_nash_context, spec); > 1332 if (device) { > 1333 printf("%s\n", device); > 1334 return 0; > 1335 } > 1336 return 1; > 1337 } > 1338 > 1339 /* 2.6 magic swsusp stuff */ > 1340 static int > 1341 resumeCommand(char * cmd, char * end) > 1342 { > 1343 char * resumedev = NULL; > 1344 char * resume = NULL; > 1345 int fd, n; > 1346 struct stat sb; > 1347 char buf[25]; > 1348 > 1349 if (!(cmd = getArg(cmd, end, &resume))) { > 1350 eprintf("resume: resume device expected\n"); > 1351 return 1; > 1352 } > 1353 > 1354 if (access("/sys/power/resume", W_OK)) { > 1355 /* eprintf("/sys/power/resume doesn't exist, can't resume!\n");*/ > 1356 return 0; > 1357 } > 1358 > 1359 if (strstr(getKernelCmdLine(), "noresume")) { > 1360 qprintf("noresume passed, not resuming...\n"); > 1361 return 0; > 1362 } > 1363 > 1364 resumedev = getKernelArg("resume"); > 1365 if (resumedev == NULL) { > 1366 resumedev = resume; > 1367 } > 1368 n = strcspn(resumedev, " \t\r\n"); > 1369 resumedev[n] = '\0'; > 1370 > 1371 qprintf("Trying to resume from %s\n", resumedev); > 1372 > 1373 resume = nashGetPathBySpec(_nash_context, resumedev); > 1374 if (resume) > 1375 resumedev = resume; > 1376 > 1377 if (access(resumedev, R_OK)) { > 1378 eprintf("Unable to access resume device (%s)\n", resumedev); > 1379 return 1; > 1380 } > 1381 > 1382 fd = open(resumedev, O_RDONLY); > 1383 if (fd < 0) > 1384 return 1; > 1385 if (lseek(fd, getpagesize() - 10, SEEK_SET) != getpagesize() - 10) { > 1386 close(fd); > 1387 return 1; > 1388 } > 1389 if (read(fd, &buf, 6) != 6) { > 1390 close(fd); > 1391 return 1; > 1392 } > 1393 if (strncmp(buf, "S1SUSP", 6) && strncmp(buf, "S2SUSP", 6)) { > 1394 qprintf("No suspend signature on swap, not resuming.\n"); > 1395 close(fd); > 1396 return 1; > 1397 } > 1398 > 1399 if (fstat(fd, &sb)) { > 1400 close(fd); > 1401 return 1; > 1402 } > 1403 close(fd); > 1404 > 1405 printf("Resuming from %s.\n", resumedev); > 1406 fflush(stdout); > 1407 fd = open("/sys/power/resume", O_WRONLY); > 1408 memset(buf, '\0', 20); > 1409 snprintf(buf, 20, "%d:%d", major(sb.st_rdev), minor(sb.st_rdev)); > 1410 write(fd, buf, 20); > 1411 close(fd); > 1412 > 1413 eprintf("Resume failed. Continuing with normal startup.\n"); > 1414 return 0; > 1415 } > 1416 > 1417 static int > 1418 mkrootdevCommand(char *cmd, char *end) > 1419 { > 1420 char *chptr = NULL, *root; > 1421 int i; > 1422 FILE *fstab; > 1423 struct mntent mnt = { > 1424 .mnt_fsname = "/dev/root", > 1425 .mnt_dir = "/sysroot", > 1426 .mnt_type = NULL, > 1427 .mnt_opts = NULL, > 1428 .mnt_freq = 0, > 1429 .mnt_passno = 0 > 1430 }; > 1431 > 1432 root = getKernelArg("root"); > 1433 if (root) { > 1434 char c; > 1435 chptr = root; > 1436 while (*chptr && !isspace(*chptr)) > 1437 chptr++; > 1438 c = *chptr; > 1439 *chptr = '\0'; > 1440 root = strdupa(root); > 1441 *chptr = c; > 1442 chptr = NULL; > 1443 } > 1444 > 1445 i = 0; > 1446 while ((cmd = getArg(cmd, end, &chptr))) { > 1447 if (!strcmp(chptr, "-t")) { > 1448 cmd = getArg(cmd, end, &mnt.mnt_type); > 1449 if (!cmd) { > 1450 eprintf("mkrootdev: expected fs type\n"); > 1451 return 1; > 1452 } > 1453 } else if (!strcmp(chptr, "-o")) { > 1454 cmd = getArg(cmd, end, &mnt.mnt_opts); > 1455 if (!cmd) { > 1456 eprintf("mkrootdev: expected device name\n"); > 1457 return 1; > 1458 } > 1459 } else if (root) { > 1460 if (i) { > 1461 eprintf("mkrootdev: unexpected arguments\n"); > 1462 eprintf("cmd: %p end: %p\n", cmd, end); > 1463 eprintf("cmd: %s\n", cmd); > 1464 return 1; > 1465 } > 1466 /* if we get here, we got root from the kernel command line, > 1467 so we don't _really_ care that there wasn't one on the > 1468 mkrootdev command line. */ > 1469 i++; > 1470 } else { > 1471 root = chptr; > 1472 i++; > 1473 } > 1474 } > 1475 if (!root) { > 1476 eprintf("mkrootdev: expected device name\n"); > 1477 return 1; > 1478 } > 1479 > 1480 if (!mnt.mnt_type) { > 1481 eprintf("mkrootdev: expected fs type\n"); > 1482 return 1; > 1483 } > 1484 if (!mnt.mnt_opts) { > 1485 eprintf("mkrootdev: expected fs options\n"); > 1486 return 1; > 1487 } > 1488 /* nfs can't use /dev/root */ > 1489 if (!strncmp(mnt.mnt_type, "nfs", 3)) { > 1490 mnt.mnt_fsname = strdup(root); > 1491 } > 1492 > 1493 umask(0122); > 1494 fstab = fopen("/etc/fstab", "w+"); > 1495 if (!fstab) { > 1496 eprintf("mkrootdev: could not create fstab: %m\n"); > 1497 return 1; > 1498 } > 1499 addmntent(fstab, &mnt); > 1500 fclose(fstab); > 1501 > 1502 if (!strncmp(mnt.mnt_type, "nfs", 3)) return 0; > 1503 return nashMkPathBySpec(_nash_context, root, "/dev/root") < 0 ? 1 : 0; > 1504 } > 1505 > 1506 static int > 1507 mkdirCommand(char * cmd, char * end) > 1508 { > 1509 char * dir; > 1510 int ignoreExists = 0; > 1511 > 1512 cmd = getArg(cmd, end, &dir); > 1513 > 1514 if (cmd && !strcmp(dir, "-p")) { > 1515 ignoreExists = 1; > 1516 cmd = getArg(cmd, end, &dir); > 1517 } > 1518 > 1519 if (!cmd) { > 1520 eprintf("mkdir: directory expected\n"); > 1521 return 1; > 1522 } > 1523 > 1524 if (mkdir(dir, 0755)) { > 1525 if (!ignoreExists && errno == EEXIST) { > 1526 eprintf("mkdir: failed to create %s: %m\n", dir); > 1527 return 1; > 1528 } > 1529 } > 1530 > 1531 return 0; > 1532 } > 1533 > 1534 static int > 1535 accessCommand(char * cmd, char * end) > 1536 { > 1537 char * permStr; > 1538 int perms = 0; > 1539 char * file = NULL; > 1540 > 1541 cmd = getArg(cmd, end, &permStr); > 1542 if (cmd) > 1543 cmd = getArg(cmd, end, &file); > 1544 > 1545 if (!cmd || *permStr != '-') { > 1546 eprintf("usage: access -[perm] file\n"); > 1547 return 1; > 1548 } > 1549 > 1550 permStr++; > 1551 while (*permStr) { > 1552 switch (*permStr) { > 1553 case 'r': perms |= R_OK; break; > 1554 case 'w': perms |= W_OK; break; > 1555 case 'x': perms |= X_OK; break; > 1556 case 'f': perms |= F_OK; break; > 1557 default: > 1558 eprintf("perms must be -[r][w][x][f]\n"); > 1559 return 1; > 1560 } > 1561 > 1562 permStr++; > 1563 } > 1564 > 1565 if ((file == NULL) || (access(file, perms))) > 1566 return 1; > 1567 > 1568 return 0; > 1569 } > 1570 > 1571 static int > 1572 showLabelsCommand(char *cmd, char *end) > 1573 { > 1574 char *new = NULL; > 1575 cmd = getArg(cmd, end, &new); > 1576 if (cmd) { > 1577 eprintf("showlabels: unexpected arguments\n"); > 1578 return 1; > 1579 } > 1580 block_show_labels(_nash_context); > 1581 return 0; > 1582 } > 1583 > 1584 static int > 1585 sleepCommand(char * cmd, char * end) > 1586 { > 1587 char *delaystr; > 1588 long long delay; > 1589 > 1590 if (!(cmd = getArg(cmd, end, &delaystr))) { > 1591 eprintf("sleep: delay expected\n"); > 1592 return 1; > 1593 } > 1594 > 1595 delay = strtoll(delaystr, NULL, 0); > 1596 udelay(delay * 1000000); > 1597 > 1598 return 0; > 1599 } > 1600 > 1601 static int > 1602 stabilizedMtime(char *path, int iterations, struct timespec interval, int goal) > 1603 { > 1604 struct stat sb; > 1605 struct timespec last = {0, 0}; > 1606 int count = 0, changed = 0; > 1607 > 1608 > 1609 do { > 1610 struct timeval now; > 1611 memset(&now, '\0', sizeof(now)); > 1612 gettimeofday(&now, NULL); > 1613 memset(&sb, '\0', sizeof(sb)); > 1614 if (stat(path, &sb) == -1) { > 1615 eprintf("stabilized: stat %s: %m\n", path); > 1616 return -1; > 1617 } > 1618 #if 0 > 1619 qprintf("last: %ld.%ld sb: %ld.%ld now: %ld.%ld\n", last.tv_sec, last.tv_nsec, sb.st_mtime, sb.st_mtim.tv_nsec, now.tv_sec, now.tv_usec * 1000); > 1620 #endif > 1621 if (sb.st_mtime == last.tv_sec > 1622 && sb.st_mtim.tv_nsec == last.tv_nsec) { > 1623 if (++count == goal) > 1624 return changed; > 1625 } else { > 1626 changed = 1; > 1627 count = 0; > 1628 } > 1629 > 1630 udelayspec(interval); > 1631 last.tv_sec = sb.st_mtim.tv_sec; > 1632 last.tv_nsec = sb.st_mtim.tv_nsec; > 1633 if (iterations != -1) > 1634 iterations--; > 1635 } while (iterations == -1 || iterations > 0); > 1636 return -1; > 1637 } > 1638 > 1639 static int > 1640 stabilizedPoll(char *path, int iterations, struct timespec interval, int goal) > 1641 { > 1642 int count = -1, changed = 0; > 1643 struct pollfd pd = { > 1644 .events = POLLIN | POLLPRI | POLLERR |POLLHUP | POLLMSG, > 1645 .revents = 0, > 1646 }; > 1647 struct timespec timeout = {0,0}; > 1648 char buf; > 1649 int last = -1, rc = 0; > 1650 > 1651 if ((pd.fd = open(path, O_RDONLY|O_NONBLOCK)) < 0) { > 1652 eprintf("stabilized: open %s: %m\n", path); > 1653 return -1; > 1654 } > 1655 > 1656 /* first, drain the file */ > 1657 while ((rc = read(pd.fd, &buf, 1)) >= 0) { > 1658 if (rc == 0 && last == 0) > 1659 break; > 1660 last = rc; > 1661 } > 1662 timeout.tv_sec = 0; > 1663 timeout.tv_nsec = 1; > 1664 rc = nash_ppoll(&pd, 1, &timeout, NULL, 0); > 1665 do { > 1666 timeout = interval; > 1667 > 1668 pd.revents = 0; > 1669 while ((rc = nash_ppoll(&pd, 1, &timeout, NULL, 0) < 0)) { > 1670 if (errno != EINTR) > 1671 return -1; > 1672 } > 1673 #if 0 > 1674 qprintf("rc: %d pd.revent: %d\n", rc, pd.revents); > 1675 #endif > 1676 if (pd.revents) { > 1677 changed = 1; > 1678 count = 0; > 1679 } else { > 1680 if (++count == goal) > 1681 return changed; > 1682 } > 1683 if (iterations != -1) > 1684 iterations--; > 1685 } while (iterations == -1 || iterations > 0); > 1686 return -1; > 1687 } > 1688 > 1689 static int > 1690 stabilizedCommand(char *cmd, char *end) > 1691 { > 1692 struct timespec interval_ts = {0,0}; > 1693 int iterations=-1; > 1694 long long interval=750; > 1695 char *buf = NULL, *file = NULL; > 1696 int rc, do_poll = 0; > 1697 > 1698 while ((cmd = getArg(cmd, end, &buf))) { > 1699 if (!strcmp(buf, "--poll")) { > 1700 do_poll = 1; > 1701 continue; > 1702 } > 1703 if (!strcmp(buf, "--iterations")) { > 1704 if (!(cmd = getArg(cmd, end, &buf))) { > 1705 usage: > 1706 eprintf("usage: stabilized [--poll] [ --iterations N ] " > 1707 "[ --interval MILLISECS ] <file>\n"); > 1708 return 1; > 1709 } > 1710 iterations = strtoll(buf, NULL, 0); > 1711 continue; > 1712 } > 1713 if (!strcmp(buf, "--interval")) { > 1714 if (!(cmd = getArg(cmd, end, &buf))) > 1715 goto usage; > 1716 interval = strtoll(buf, NULL, 0); > 1717 continue; > 1718 } > 1719 if (file) > 1720 goto usage; > 1721 file = buf; > 1722 } > 1723 > 1724 if (!file) > 1725 goto usage; > 1726 > 1727 interval_ts.tv_sec = interval / 1000; > 1728 interval_ts.tv_nsec = (interval % 1000) * 1000000; > 1729 > 1730 if (do_poll) > 1731 rc = stabilizedPoll(file, iterations, interval_ts, 10); > 1732 else > 1733 rc = stabilizedMtime(file, iterations, interval_ts, 10); > 1734 > 1735 if (rc < 0) > 1736 return 1; > 1737 if (rc == 0) { > 1738 eprintf("Could not detect stabilization, waiting 10 seconds.\n"); > 1739 sleep(10); > 1740 } > 1741 return 0; > 1742 } > 1743 > 1744 static int > 1745 readlinkCommand(char * cmd, char * end) > 1746 { > 1747 char * path; > 1748 char * buf, * respath, * fullpath = NULL; > 1749 struct stat sb; > 1750 int rc = 0; > 1751 > 1752 if (!(cmd = getArg(cmd, end, &path))) { > 1753 eprintf("readlink: file expected\n"); > 1754 return 1; > 1755 } > 1756 > 1757 if (lstat(path, &sb) == -1) { > 1758 eprintf("unable to stat %s: %m\n", path); > 1759 return 1; > 1760 } > 1761 > 1762 if (!S_ISLNK(sb.st_mode)) { > 1763 printf("%s\n", path); > 1764 return 0; > 1765 } > 1766 > 1767 buf = readlinka(path); > 1768 if (buf == NULL) { > 1769 eprintf("error readlink %s: %m\n", path); > 1770 return 1; > 1771 } > 1772 > 1773 /* symlink is absolute */ > 1774 if (buf[0] == '/') { > 1775 printf("%s\n", buf); > 1776 return 0; > 1777 } > 1778 > 1779 /* nope, need to handle the relative symlink case too */ > 1780 respath = strrchr(path, '/'); > 1781 if (respath) { > 1782 *respath = '\0'; > 1783 } > 1784 > 1785 asprintfa(&fullpath, "%s/%s", path, buf); > 1786 /* and normalize it */ > 1787 respath = NULL; > 1788 respath = canonicalize_file_name(fullpath); > 1789 if (respath == NULL) { > 1790 eprintf("error resolving symbolic link %s: %m\n", fullpath); > 1791 return 1; > 1792 } > 1793 > 1794 printf("%s\n", respath); > 1795 free(respath); > 1796 return rc; > 1797 } > 1798 > 1799 static int > 1800 doFind(char * dirName, char * name, mode_t mask) > 1801 { > 1802 struct stat sb; > 1803 DIR * dir; > 1804 struct dirent * d; > 1805 char * strBuf = alloca(strlen(dirName) + 1024); > 1806 > 1807 if (!(dir = opendir(dirName))) { > 1808 eprintf("error opening %s: %m\n", dirName); > 1809 return 0; > 1810 } > 1811 > 1812 errno = 0; > 1813 while ((d = readdir(dir))) { > 1814 errno = 0; > 1815 > 1816 strcpy(strBuf, dirName); > 1817 strcat(strBuf, "/"); > 1818 strcat(strBuf, d->d_name); > 1819 > 1820 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) { > 1821 errno = 0; > 1822 continue; > 1823 } > 1824 > 1825 if (lstat(strBuf, &sb)) { > 1826 eprintf("failed to stat %s: %m\n", strBuf); > 1827 errno = 0; > 1828 continue; > 1829 } > 1830 > 1831 if (!name || !strcmp(d->d_name, name)) { > 1832 if (mask == 0 || (sb.st_mode & mask) == mask) > 1833 printf("%s\n", strBuf); > 1834 } > 1835 > 1836 if (S_ISDIR(sb.st_mode)) > 1837 doFind(strBuf, name, mask); > 1838 } > 1839 > 1840 if (errno) { > 1841 closedir(dir); > 1842 eprintf("error reading from %s: %m\n", dirName); > 1843 return 1; > 1844 } > 1845 > 1846 closedir(dir); > 1847 > 1848 return 0; > 1849 } > 1850 > 1851 static int > 1852 findCommand(char * cmd, char * end) > 1853 { > 1854 char * dir; > 1855 char * name = NULL; > 1856 char * type = NULL; > 1857 mode_t mode = 0; > 1858 > 1859 if (!(cmd = getArg(cmd, end, &dir))) { > 1860 dir = strdupa("."); > 1861 } else { > 1862 if (!strcmp(dir, "-type")) { > 1863 char *t; > 1864 if (!cmd) > 1865 goto error; > 1866 if (!(cmd = getArg(cmd, end, &type))) > 1867 goto error; > 1868 for (t=type; t && *t; t++) { > 1869 if (*t != 'd') { > 1870 eprintf("find: error: unknown type '%c'\n", *t); > 1871 goto error; > 1872 } > 1873 } > 1874 mode = S_IFDIR; > 1875 if (!(cmd = getArg(cmd, end, &dir))) > 1876 dir = strdup("."); > 1877 } > 1878 if ((cmd = getArg(cmd, end, &name))) { > 1879 if (strcmp(name, "-name")) > 1880 goto error; > 1881 if (!(cmd = getArg(cmd, end, &name))) > 1882 goto error; > 1883 } > 1884 } > 1885 > 1886 return doFind(dir, name, mode); > 1887 error: > 1888 eprintf("usage: find [-type type] [path [-name file]]\n"); > 1889 return 1; > 1890 } > 1891 > 1892 static int > 1893 mknodCommand(char * cmd, char * end) > 1894 { > 1895 char * path, * type; > 1896 char * majorStr, * minorStr; > 1897 int major; > 1898 int minor; > 1899 char * chptr; > 1900 mode_t mode; > 1901 > 1902 cmd = getArg(cmd, end, &path); > 1903 if (!path) > 1904 goto err; > 1905 > 1906 cmd = getArg(cmd, end, &type); > 1907 if (!type) > 1908 goto err; > 1909 > 1910 cmd = getArg(cmd, end, &majorStr); > 1911 if (!majorStr) > 1912 goto err; > 1913 > 1914 cmd = getArg(cmd, end, &minorStr); > 1915 if (!minorStr) { > 1916 err: > 1917 eprintf("mknod: usage mknod <path> [c|b] <major> <minor>\n"); > 1918 return 1; > 1919 } > 1920 > 1921 if (!strcmp(type, "b")) { > 1922 mode = S_IFBLK; > 1923 } else if (!strcmp(type, "c")) { > 1924 mode = S_IFCHR; > 1925 } else { > 1926 eprintf("mknod: invalid type\n"); > 1927 return 1; > 1928 } > 1929 > 1930 major = strtol(majorStr, &chptr, 10); > 1931 if (*chptr) { > 1932 eprintf("invalid major number\n"); > 1933 return 1; > 1934 } > 1935 > 1936 minor = strtol(minorStr, &chptr, 10); > 1937 if (*chptr) { > 1938 eprintf("invalid minor number\n"); > 1939 return 1; > 1940 } > 1941 > 1942 if (smartmknod(path, mode | 0600, makedev(major, minor))) { > 1943 eprintf("mknod: failed to create %s: %m\n", path); > 1944 return 1; > 1945 } > 1946 > 1947 return 0; > 1948 } > 1949 > 1950 static int > 1951 dmCommand(char *cmd, char *end) > 1952 { > 1953 char *action = NULL; > 1954 char *name = NULL; > 1955 > 1956 cmd = getArg(cmd, end, &action); > 1957 if (!cmd) > 1958 goto usage; > 1959 > 1960 if (!strcmp(action, "create")) { > 1961 long long start, length; > 1962 char *type = NULL, *params = NULL; > 1963 char *c = NULL; > 1964 char *uuid = NULL; > 1965 > 1966 cmd = getArg(cmd, end, &name); > 1967 if (!cmd) > 1968 goto usage; > 1969 > 1970 cmd = getArg(cmd, end, &uuid); > 1971 if (!cmd) > 1972 goto usage; > 1973 > 1974 if (!strcmp(uuid, "--uuid")) { > 1975 if (!(cmd = getArg(cmd, end, &uuid))) { > 1976 eprintf("dm create: missing uuid argument\n"); > 1977 return 1; > 1978 } > 1979 > 1980 cmd = getArg(cmd, end, ¶ms); > 1981 if (!cmd) > 1982 goto usage; > 1983 } else { > 1984 params = uuid; > 1985 uuid = NULL; > 1986 } > 1987 > 1988 errno = 0; > 1989 start = strtoll(params, NULL, 0); > 1990 if (errno) > 1991 goto usage; > 1992 > 1993 cmd = getArg(cmd, end, ¶ms); > 1994 if (!cmd) > 1995 goto usage; > 1996 errno = 0; > 1997 length = strtoll(params, NULL, 0); > 1998 if (errno) > 1999 goto usage; > 2000 > 2001 cmd = getArg(cmd, end, &type); > 2002 if (!cmd) > 2003 goto usage; > 2004 > 2005 params = cmd; > 2006 c = strchr(params, '\n'); > 2007 if (c) > 2008 *c = '\0'; > 2009 if (nashDmCreate(name, uuid, start, length, type, params)) > 2010 return 0; > 2011 if (c) > 2012 *c = '\n'; > 2013 return 1; > 2014 } else if (!strcmp(action, "remove")) { > 2015 cmd = getArg(cmd, end, &name); > 2016 if (!cmd) > 2017 goto usage; > 2018 > 2019 if (nashDmRemove(name)) > 2020 return 0; > 2021 } else if (!strcmp(action, "partadd")) { > 2022 cmd = getArg(cmd, end, &name); > 2023 if (!cmd) > 2024 goto usage; > 2025 > 2026 if (nashDmCreatePartitions(_nash_context, name)) > 2027 return 0; > 2028 return 1; > 2029 } else if (!strcmp(action, "get_uuid")) { > 2030 char *uuid; > 2031 > 2032 cmd = getArg(cmd, end, &name); > 2033 if (!cmd) > 2034 goto usage; > 2035 > 2036 uuid = nashDmGetUUID(name); > 2037 if (uuid) { > 2038 printf("%s\n", uuid); > 2039 free(uuid); > 2040 return 0; > 2041 } > 2042 return 1; > 2043 } else if (!strcmp(action, "list")) { > 2044 const char **names = NULL; > 2045 int m = 0, n = 0; > 2046 > 2047 names = calloc(m+1, sizeof (char *)); > 2048 while((cmd = getArg(cmd, end, &name))) { > 2049 names = realloc(names, sizeof (char *) * (m+2)); > 2050 names[m++] = strdupa(name); > 2051 names[m] = NULL; > 2052 } > 2053 > 2054 qsort(names, m, sizeof (char *), stringsort); > 2055 /* it's too bad qsort doesn't dedupe... */ > 2056 for (n = 0; n < m-1; n++) { > 2057 if (!strcmp(names[n], names[n+1])) { > 2058 memmove(names+n, names+n+1, (m - n) * sizeof (char *)); > 2059 m--; n--; > 2060 } > 2061 } > 2062 > 2063 n = nashDmListSorted(_nash_context, names); > 2064 if (names) > 2065 free(names); > 2066 if (n) > 2067 return 0; > 2068 return 1; > 2069 } > 2070 usage: > 2071 eprintf("usage: dm create name start length type PARAMS...\n" > 2072 " dm remove name\n" > 2073 " dm partadd path\n" > 2074 " dm get_uuid path\n" > 2075 " dm list [name0] [name1] [...] [nameN]\n" > 2076 ); > 2077 return 1; > 2078 } > 2079 > 2080 static int > 2081 mkDMNodCommand(char * cmd, char * end) > 2082 { > 2083 int major = getDevNumFromProc("/proc/devices", "misc"); > 2084 int minor = getDevNumFromProc("/proc/misc", "device-mapper"); > 2085 > 2086 if ((major == -1) || (minor == -1)) { > 2087 eprintf("Unable to find device-mapper major/minor\n"); > 2088 return 1; > 2089 } > 2090 > 2091 if (!access("/dev/mapper/control", R_OK)) { > 2092 struct stat sb; > 2093 if (stat("/dev/mapper/control", &sb) == 0) { > 2094 if (S_ISCHR(sb.st_mode) && (sb.st_rdev == makedev(major, minor))) > 2095 return 0; > 2096 } > 2097 > 2098 unlink("/dev/mapper/control"); > 2099 } > 2100 > 2101 if (smartmknod("/dev/mapper/control", S_IFCHR | 0600, > 2102 makedev(major, minor))) { > 2103 eprintf("failed to create /dev/mapper/control\n"); > 2104 return 1; > 2105 } > 2106 > 2107 return 0; > 2108 } > 2109 > 2110 static int > 2111 mkblkdevsCommand(char * cmd, char * end) > 2112 { > 2113 if (cmd < end) { > 2114 eprintf("mkblkdevs: unexpected arguments\n"); > 2115 return 1; > 2116 } > 2117 > 2118 sysfs_blkdev_probe(_nash_context, "/sys/block"); > 2119 return 1; > 2120 } > 2121 > 2122 static int > 2123 rmpartsCommand(char *cmd, char *end) > 2124 { > 2125 char *devname = NULL; > 2126 > 2127 cmd = getArg(cmd, end, &devname); > 2128 if (!cmd) { > 2129 printf("usage: rmparts hda\n"); > 2130 return 1; > 2131 } > 2132 > 2133 if (nashDisablePartitions(devname) < 1) > 2134 return 1; > 2135 return 0; > 2136 } > 2137 > 2138 struct commandHandler { > 2139 char *name; > 2140 int (*fp)(char *cmd, char *end); > 2141 }; > 2142 > 2143 static const struct commandHandler *getCommandHandler(const char *name); > 2144 > 2145 static int > 2146 statusCommand(char *cmd, char *end) > 2147 { > 2148 char *si = NULL; > 2149 long i; > 2150 > 2151 cmd = getArg(cmd, end, &si); > 2152 if (!si) { > 2153 printf("%d\n", exit_status); > 2154 return exit_status; > 2155 } > 2156 > 2157 i = strtoul(si, NULL, 0); > 2158 if (i == ULONG_MAX && errno) { > 2159 eprintf("status: error: %m\n"); > 2160 return 1; > 2161 } > 2162 > 2163 return i; > 2164 } > 2165 > 2166 static int > 2167 condCommand(char *cmd, char *end) > 2168 { > 2169 char *op = NULL; > 2170 int conditional = 0; > 2171 int internal = 0; > 2172 int rc; > 2173 > 2174 while((cmd = getArg(cmd, end, &op))) { > 2175 char *stval = NULL; > 2176 unsigned long tval; > 2177 > 2178 if (!op) > 2179 return 1; > 2180 > 2181 if (op[0] != '-') > 2182 break; > 2183 > 2184 cmd = getArg(cmd, end, &stval); > 2185 if (stval) > 2186 tval = strtoul(stval, NULL, 0); > 2187 if (!stval || (tval == ULONG_MAX && errno)) { > 2188 if (errno) > 2189 eprintf("cond: error: %m\n"); > 2190 else > 2191 eprintf("cond: error: invalid value '%s' for '%s' operator\n", > 2192 stval, op); > 2193 return 1; > 2194 } > 2195 > 2196 if (!strcmp(op, "-lt")) { > 2197 if (exit_status >= tval) > 2198 return exit_status; > 2199 conditional = 1; > 2200 } else if (!strcmp(op, "-le")) { > 2201 if (exit_status > tval) > 2202 return exit_status; > 2203 conditional = 1; > 2204 } else if (!strcmp(op, "-eq") || > 2205 !strcmp(op, "-et")) { > 2206 if (exit_status != tval) > 2207 return exit_status; > 2208 conditional = 1; > 2209 } else if (!strcmp(op, "-ne")) { > 2210 if (exit_status == tval) > 2211 return exit_status; > 2212 conditional = 1; > 2213 } else if (!strcmp(op, "-ge")) { > 2214 if (exit_status < tval) > 2215 return exit_status; > 2216 conditional = 1; > 2217 } else if (!strcmp(op, "-gt")) { > 2218 if (exit_status <= tval) > 2219 return exit_status; > 2220 conditional = 1; > 2221 } > 2222 } > 2223 > 2224 if (!conditional && exit_status != 0) > 2225 return exit_status; > 2226 > 2227 if (strncmp(op, "nash-", 5)) { > 2228 char *fullPath = NULL; > 2229 > 2230 rc = searchPath(op, &fullPath); > 2231 if (rc >= 0) { > 2232 rc = otherCommand(fullPath, cmd, end, 1, 0); > 2233 free(fullPath); > 2234 return rc; > 2235 } else > 2236 internal = 1; > 2237 } else { > 2238 op += 5; > 2239 internal = 1; > 2240 } > 2241 > 2242 rc = 1; > 2243 if (internal) { > 2244 const struct commandHandler *handler; > 2245 > 2246 handler = getCommandHandler(op); > 2247 if (handler->name != NULL) > 2248 rc = (handler->fp)(cmd, end); > 2249 } > 2250 return rc; > 2251 } > 2252 > 2253 static int > 2254 networkCommand(char *cmd, char *end) > 2255 { > 2256 char *ncmd = NULL; > 2257 char c; > 2258 int rc; > 2259 size_t len; > 2260 > 2261 /* popt expects to get network --args here */ > 2262 if (!cmd || cmd >= end) > 2263 return 1; > 2264 > 2265 len = strcspn(cmd, "\n"); > 2266 c = cmd[len]; > 2267 cmd[len] = '\0'; > 2268 rc = asprintf(&ncmd, "network %s", cmd); > 2269 cmd[len] = c; > 2270 if (rc < 0) > 2271 return rc; > 2272 rc = nashNetworkCommand(ncmd); > 2273 free(ncmd); > 2274 return rc; > 2275 } > 2276 > 2277 > 2278 static int > 2279 waitdevCommand(char *cmd, char *end) > 2280 { > 2281 static struct blkent **blkents = NULL; > 2282 char *device = NULL; > 2283 int rc = 0; > 2284 > 2285 if (!(cmd = getArg(cmd, end, &device))) { > 2286 eprintf("waitdev: device expected\n"); > 2287 return 1; > 2288 } > 2289 > 2290 if (cmd < end) { > 2291 eprintf("waitdev: unexpected arguments\n"); > 2292 return 1; > 2293 } > 2294 > 2295 if (!blkents) { > 2296 int m = 0; > 2297 FILE *blktab = NULL; > 2298 > 2299 if (!(blktab = setblkent("/etc/blktab", "r"))) { > 2300 eprintf("waitdev: couldn't open /etc/blktab\n"); > 2301 return 1; > 2302 } > 2303 > 2304 blkents = calloc(m+1, sizeof (struct blkent)); > 2305 do { > 2306 struct blkent **newents = NULL; > 2307 struct blkent *be = NULL, *nbe = NULL; > 2308 > 2309 if (!(be = getblkent(blktab))) > 2310 break; > 2311 > 2312 rc = 1; > 2313 if (!(nbe = alloca(sizeof (*nbe) > 2314 + strlen(be->blk_name) + 1 > 2315 + strlen(be->blk_type) + 1 > 2316 + strlen(be->blk_opts) + 1))) > 2317 break; > 2318 > 2319 if (!(newents = realloc(blkents, sizeof (struct blkent) * (m+2)))) > 2320 break; > 2321 blkents = newents; > 2322 > 2323 memcpy(nbe, be, sizeof (*nbe)); > 2324 nbe->blk_name = (void *)nbe + sizeof(*nbe); > 2325 strcpy(nbe->blk_name, be->blk_name); > 2326 nbe->blk_type = nbe->blk_name + strlen(nbe->blk_name) + 1; > 2327 strcpy(nbe->blk_type, be->blk_type); > 2328 nbe->blk_opts = nbe->blk_type + strlen(nbe->blk_type) + 1; > 2329 strcpy(nbe->blk_opts, be->blk_opts); > 2330 blkents[m++] = nbe; > 2331 blkents[m] = NULL; > 2332 rc = 0; > 2333 } while (1); > 2334 > 2335 endblkent(blktab); > 2336 if (rc) { > 2337 if (blkents) > 2338 free(blkents); > 2339 } > 2340 } > 2341 > 2342 if (!rc && nashWaitForDevice(_nash_context, blkents, device) < 0) > 2343 rc = 1; > 2344 > 2345 return rc; > 2346 } > 2347 > 2348 static int > 2349 setQuietCommand(char * cmd, char * end) > 2350 { > 2351 char *quietcmd; > 2352 > 2353 quietcmd = getKernelArg("quiet"); > 2354 if (quietcmd) > 2355 _nash_context->reallyquiet = 1; > 2356 > 2357 quietcmd = getKernelArg("noquiet"); > 2358 if (quietcmd) > 2359 _nash_context->reallyquiet = 0; > 2360 > 2361 /* reallyquiet may be set elsewhere */ > 2362 if (_nash_context->reallyquiet) > 2363 _nash_context->quiet = 1; > 2364 > 2365 return 0; > 2366 } > 2367 > 2368 static const struct commandHandler handlers[] = { > 2369 { "access", accessCommand }, > 2370 #ifdef DEBUG > 2371 { "cat", catCommand }, > 2372 #endif > 2373 { "cond", condCommand }, > 2374 { "cp", cpCommand }, > 2375 { "dm", dmCommand }, > 2376 { "echo", echoCommand }, > 2377 { "exec", execCommand }, > 2378 { "exit", exitCommand }, > 2379 { "find", findCommand }, > 2380 { "mkblkdevs", mkblkdevsCommand }, > 2381 { "mkdir", mkdirCommand }, > 2382 { "mkdmnod", mkDMNodCommand }, > 2383 { "mknod", mknodCommand }, > 2384 { "mkrootdev", mkrootdevCommand }, > 2385 { "mount", mountCommand }, > 2386 { "network", networkCommand }, > 2387 { "hotplug", hotplugCommand }, > 2388 { "killplug", killplugCommand }, > 2389 { "losetup", losetupCommand }, > 2390 { "ln", lnCommand }, > 2391 #ifdef DEBUG > 2392 { "ls", lsCommand }, > 2393 #endif > 2394 { "raidautorun", raidautorunCommand }, > 2395 { "readlink", readlinkCommand }, > 2396 { "resume", resumeCommand }, > 2397 { "resolveDevice", resolveDeviceCommand }, > 2398 { "rmparts", rmpartsCommand }, > 2399 { "setquiet", setQuietCommand }, > 2400 { "setuproot", setuprootCommand }, > 2401 { "showlabels", showLabelsCommand }, > 2402 { "sleep", sleepCommand }, > 2403 { "stabilized", stabilizedCommand }, > 2404 { "status", statusCommand }, > 2405 { "switchroot", switchrootCommand }, > 2406 { "umount", umountCommand }, > 2407 { "waitdev", waitdevCommand }, > 2408 { NULL, }, > 2409 }; > 2410 > 2411 static const struct commandHandler * > 2412 getCommandHandler(const char *name) > 2413 { > 2414 const struct commandHandler *handler = NULL; > 2415 > 2416 for (handler = &handlers[0]; handler->name; handler++) > 2417 if (!strcmp(name, handler->name)) > 2418 return handler; > 2419 return handler; > 2420 } > 2421 > 2422 static int > 2423 runStartup(int fd, char *name) > 2424 { > 2425 char *contents; > 2426 int i; > 2427 char * start, * end; > 2428 char * chptr; > 2429 int rc; > 2430 const struct commandHandler *handler; > 2431 > 2432 i = readFD(fd, &contents); > 2433 if (i < 0) { > 2434 eprintf("Failed to read startup file %s", name); > 2435 return 1; > 2436 } > 2437 > 2438 start = contents; > 2439 while (*start) { > 2440 while (isspace(*start) && *start && (*start != '\n')) > 2441 start++; > 2442 > 2443 if (*start == '#') { > 2444 while (*start && (*start != '\n')) > 2445 start++; > 2446 if (*start == '\n') > 2447 start++; > 2448 } > 2449 > 2450 if (*start == '\n') { > 2451 start++; > 2452 continue; > 2453 } > 2454 > 2455 if (!*start) { > 2456 eprintf("(last line in %s is empty)\n", name); > 2457 continue; > 2458 } > 2459 > 2460 /* start points to the beginning of the command */ > 2461 end = start + 1; > 2462 while (*end && (*end != '\n')) > 2463 end++; > 2464 if (!*end) { > 2465 eprintf("(last line in %s missing newline -- skipping)\n", name); > 2466 start = end; > 2467 continue; > 2468 } > 2469 > 2470 /* end points to the \n at the end of the command */ > 2471 > 2472 chptr = start; > 2473 while (chptr < end && !isspace(*chptr)) > 2474 chptr++; > 2475 > 2476 i = 0; > 2477 rc = 1; > 2478 *(chptr++) = '\0'; > 2479 if (strncmp(start, "nash-", 5)) { > 2480 char *fullPath = NULL; > 2481 rc = searchPath(start, &fullPath); > 2482 if (rc >= 0) { > 2483 rc = otherCommand(fullPath, chptr, end, 1, 0); > 2484 free(fullPath); > 2485 } else > 2486 i = 1; > 2487 } else { > 2488 start += 5; > 2489 i = 1; > 2490 } > 2491 > 2492 if (i == 1) { > 2493 handler = getCommandHandler(start); > 2494 if (handler->name != NULL) > 2495 rc = (handler->fp)(chptr, end); > 2496 } > 2497 exit_status = rc; > 2498 start = end + 1; > 2499 } > 2500 > 2501 free(contents); > 2502 return rc; > 2503 } > 2504 > 2505 void delayOnSignal(int signum) { > 2506 if (ocPid != -1) > 2507 kill(ocPid, SIGSTOP); > 2508 udelay(500000); > 2509 if (ocPid != -1) > 2510 kill(ocPid, SIGCONT); > 2511 > 2512 signal(signum, delayOnSignal); > 2513 } > 2514 > 2515 static void > 2516 sendParentAlarm(nashContext *nc, int usec) > 2517 { > 2518 if (nc->hp_parent_pid != -1) > 2519 kill(nc->hp_parent_pid, SIGALRM); > 2520 } > 2521 > 2522 static void traceback(int signum) > 2523 { > 2524 void *array[20]; > 2525 size_t size; > 2526 char **strings; > 2527 size_t i; > 2528 > 2529 signal(SIGSEGV, SIG_DFL); > 2530 > 2531 size = backtrace(array, 20); > 2532 strings = backtrace_symbols(array, size); > 2533 > 2534 printf("nash received SIGSEGV! Backtrace:\n"); > 2535 for (i = 0; i < size; i++) > 2536 printf("%s\n", strings[i]); > 2537 > 2538 free(strings); > 2539 exit(1); > 2540 } > 2541 > 2542 int main(int argc, char **argv) { > 2543 int fd = 0; > 2544 char * name; > 2545 int rc; > 2546 int force = 0; > 2547 > 2548 signal(SIGSEGV, traceback); > 2549 > 2550 _nash_context = nashNewContext(); > 2551 nashSetDelayParent(_nash_context, sendParentAlarm); > 2552 > 2553 name = strrchr(argv[0], '/'); > 2554 if (!name) > 2555 name = argv[0]; > 2556 else > 2557 name++; > 2558 > 2559 if (!strcmp(name, "modprobe")) { > 2560 exit(0); > 2561 } > 2562 > 2563 _nash_context->testing = (getppid() != 0) && (getppid() != 1); > 2564 argv++, argc--; > 2565 > 2566 while (argc && **argv == '-') { > 2567 if (!strcmp(*argv, "--forcequiet")) { > 2568 force = 1; > 2569 _nash_context->quiet = 1; > 2570 argv++, argc--; > 2571 _nash_context->testing = 0; > 2572 } else if (!strcmp(*argv, "--force")) { > 2573 force = 1; > 2574 argv++, argc--; > 2575 _nash_context->testing = 0; > 2576 } else if (!strcmp(*argv, "--quiet")) { > 2577 _nash_context->quiet = 1; > 2578 argv++, argc--; > 2579 } else if (!strcmp(*argv, "--reallyquiet")) { > 2580 _nash_context->reallyquiet = 1; > 2581 argv++, argc--; > 2582 } else { > 2583 eprintf("unknown argument %s\n", *argv); > 2584 nashFreeContext(_nash_context); > 2585 return 1; > 2586 } > 2587 } > 2588 > 2589 if (force) > 2590 qprintf("(forcing normal run)\n"); > 2591 > 2592 if (_nash_context->testing) > 2593 qprintf("(running in test mode).\n"); > 2594 > 2595 qprintf("Red Hat nash version %s starting\n", VERSION); > 2596 > 2597 if (*argv) { > 2598 fd = open(*argv, O_RDONLY, 0); > 2599 if (fd < 0) { > 2600 eprintf("nash: cannot open %s: %m\n", *argv); > 2601 nashFreeContext(_nash_context); > 2602 exit(1); > 2603 } > 2604 } > 2605 > 2606 signal(SIGALRM, delayOnSignal); > 2607 > 2608 /* runStartup closes fd */ > 2609 rc = runStartup(fd, *argv); > 2610 > 2611 nashHotplugKill(_nash_context); > 2612 nashFreeContext(_nash_context); > 2613 return rc; > 2614 } > 2615 > 2616 /* > 2617 * vim:ts=8:sw=4:sts=4:et > 2618 */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 220687
: 144328