⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 extlinux.c

📁 linux内核
💻 C
📖 第 1 页 / 共 2 页
字号:
  if ( !ioctl(devfd, HDIO_GETGEO, &geo) ) {    return 0;  } else if ( !ioctl(devfd, FDGETPRM, &fd_str) ) {    geo->heads     = fd_str.head;    geo->sectors   = fd_str.sect;    geo->cylinders = fd_str.track;    geo->start     = 0;    return 0;  }   /* Didn't work.  Let's see if this is one of the standard geometries */  for ( gp = standard_geometries ; gp->bytes ; gp++ ) {    if ( gp->bytes == totalbytes ) {      memcpy(geo, &gp->g, sizeof *geo);      return 0;    }  }  /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is     what zipdisks use, so this would help if someone has a USB key that     they're booting in USB-ZIP mode. */  geo->heads     = opt.heads ?: 64;  geo->sectors   = opt.sectors ?: 32;  geo->cylinders = totalbytes/(geo->heads*geo->sectors << SECTOR_SHIFT);  geo->start     = 0;  if ( !opt.sectors && !opt.heads )    fprintf(stderr, "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n"	    "         (on hard disks, this is usually harmless.)\n",	    geo->heads, geo->sectors);  return 1;}/* * Query the device geometry and put it into the boot sector. * Map the file and put the map in the boot sector and file. * Stick the "current directory" inode number into the file. */voidpatch_file_and_bootblock(int fd, int dirfd, int devfd){  struct stat dirst;  struct hd_geometry geo;  uint32_t *sectp;  uint64_t totalbytes, totalsectors;  int nsect;  unsigned char *p, *patcharea;  int i, dw;  uint32_t csum;  if ( fstat(dirfd, &dirst) ) {    perror("fstat dirfd");    exit(255);			/* This should never happen */  }  totalbytes = get_size(devfd);  get_geometry(devfd, totalbytes, &geo);  if ( opt.heads )    geo.heads = opt.heads;  if ( opt.sectors )    geo.sectors = opt.sectors;  /* Patch this into a fake FAT superblock.  This isn't because     FAT is a good format in any way, it's because it lets the     early bootstrap share code with the FAT version. */  dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);  totalsectors = totalbytes >> SECTOR_SHIFT;  if ( totalsectors >= 65536 ) {    set_16(boot_block+bsSectors, 0);  } else {    set_16(boot_block+bsSectors, totalsectors);  }  set_32(boot_block+bsHugeSectors, totalsectors);  set_16(boot_block+bsBytesPerSec, SECTOR_SIZE);  set_16(boot_block+bsSecPerTrack, geo.sectors);  set_16(boot_block+bsHeads, geo.heads);  set_32(boot_block+bsHiddenSecs, geo.start);  /* Construct the boot file */  dprintf("directory inode = %lu\n", (unsigned long) dirst.st_ino);  nsect = (boot_image_len+SECTOR_SIZE-1) >> SECTOR_SHIFT;  sectp = alloca(sizeof(uint32_t)*nsect);  if ( sectmap(fd, sectp, nsect) ) {    perror("bmap");    exit(1);  }  /* First sector need pointer in boot sector */  set_32(boot_block+0x1F8, *sectp++);  nsect--;    /* Search for LDLINUX_MAGIC to find the patch area */  for ( p = boot_image ; get_32(p) != LDLINUX_MAGIC ; p += 4 );  patcharea = p+8;    /* Set up the totals */  dw = boot_image_len >> 2; /* COMPLETE dwords! */  set_16(patcharea, dw);  set_16(patcharea+2, nsect);	/* Does not include the first sector! */  set_32(patcharea+8, dirst.st_ino); /* "Current" directory */    /* Set the sector pointers */  p = patcharea+12;    memset(p, 0, 64*4);  while ( nsect-- ) {    set_32(p, *sectp++);    p += 4;  }    /* Now produce a checksum */  set_32(patcharea+4, 0);  csum = LDLINUX_MAGIC;  for ( i = 0, p = boot_image ; i < dw ; i++, p += 4 )    csum -= get_32(p);		/* Negative checksum */    set_32(patcharea+4, csum);}/* * Install the boot block on the specified device. * Must be run AFTER install_file()! */intinstall_bootblock(int fd, const char *device){  struct ext2_super_block sb;  if ( xpread(fd, &sb, sizeof sb, EXT2_SUPER_OFFSET) != sizeof sb ) {    perror("reading superblock");    return 1;  }  if ( sb.s_magic != EXT2_SUPER_MAGIC ) {    fprintf(stderr, "no ext2/ext3 superblock found on %s\n", device);    return 1;  }    if ( xpwrite(fd, boot_block, boot_block_len, 0) != boot_block_len ) {    perror("writing bootblock");    return 1;  }  return 0;}intinstall_file(const char *path, int devfd, struct stat *rst){  char *file;  int fd = -1, dirfd = -1, flags;  struct stat st;  asprintf(&file, "%s%sextlinux.sys",	   path,	   path[0] && path[strlen(path)-1] == '/' ? "" : "/");  if ( !file ) {    perror(program);    return 1;  }  dirfd = open(path, O_RDONLY|O_DIRECTORY);  if ( dirfd < 0 ) {    perror(path);    goto bail;  }      fd = open(file, O_RDONLY);  if ( fd < 0 ) {    if ( errno != ENOENT ) {      perror(file);      goto bail;    }  } else {    /* If file exist, remove the immutable flag and set u+w mode */    if ( !ioctl(fd, EXT2_IOC_GETFLAGS, &flags) ) {      flags &= ~EXT2_IMMUTABLE_FL;      ioctl(fd, EXT2_IOC_SETFLAGS, &flags);    }    if ( !fstat(fd, &st) ) {      fchmod(fd, st.st_mode | S_IWUSR);    }  }  close(fd);  fd = open(file, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IRGRP|S_IROTH);  if ( fd < 0 ) {    perror(file);    goto bail;  }    /* Write it the first time */  if ( xpwrite(fd, boot_image, boot_image_len, 0) != boot_image_len ) {    fprintf(stderr, "%s: write failure on %s\n", program, file);    goto bail;  }  /* Map the file, and patch the initial sector accordingly */  patch_file_and_bootblock(fd, dirfd, devfd);  /* Write it again - this relies on the file being overwritten in place! */  if ( xpwrite(fd, boot_image, boot_image_len, 0) != boot_image_len ) {    fprintf(stderr, "%s: write failure on %s\n", program, file);    goto bail;  }  /* Attempt to set immutable flag and remove all write access */  /* Only set immutable flag if file is owned by root */  if ( !fstat(fd, &st) ) {    fchmod(fd, st.st_mode & (S_IRUSR|S_IRGRP|S_IROTH));    if ( st.st_uid == 0 && !ioctl(fd, EXT2_IOC_GETFLAGS, &flags) ) {      flags |= EXT2_IMMUTABLE_FL;      ioctl(fd, EXT2_IOC_SETFLAGS, &flags);    }  }  if ( fstat(fd, rst) ) {    perror(file);    goto bail;  }  close(dirfd);  close(fd);  return 0; bail:  if ( dirfd >= 0 )    close(dirfd);  if ( fd >= 0 )    close(fd);  return 1;}/* EXTLINUX installs the string 'EXTLINUX' at offset 3 in the boot   sector; this is consistent with FAT filesystems. */intalready_installed(int devfd){  char buffer[8];  xpread(devfd, buffer, 8, 3);  return !memcmp(buffer, "EXTLINUX", 8);}intinstall_loader(const char *path, int update_only){  struct stat st, dst, fst;  struct mntent *mnt = NULL;  int devfd, rv;  FILE *mtab;  const char *devname = NULL;  if ( stat(path, &st) || !S_ISDIR(st.st_mode) ) {    fprintf(stderr, "%s: Not a directory: %s\n", program, path);    return 1;  }    devfd = -1;  if ( (mtab = setmntent("/proc/mounts", "r")) ) {    while ( (mnt = getmntent(mtab)) ) {      if ( (!strcmp(mnt->mnt_type, "ext2") ||	    !strcmp(mnt->mnt_type, "ext3")) &&	   !stat(mnt->mnt_fsname, &dst) &&	   dst.st_rdev == st.st_dev ) {	devname = mnt->mnt_fsname;	break;      }    }  }  if ( !devname ) {    /* Didn't find it in /proc/mounts, try /etc/mtab */    if ( (mtab = setmntent("/etc/mtab", "r")) ) {      while ( (mnt = getmntent(mtab)) ) {	devname = mnt->mnt_fsname;	break;      }    }  }  if ( !devname ) {    fprintf(stderr, "%s: cannot find device for path %s\n", program, path);    return 1;  }  fprintf(stderr, "%s is device %s\n", path, devname);  if ( (devfd = open(devname, O_RDWR|O_SYNC)) < 0 ) {    fprintf(stderr, "%s: cannot open device %s\n", program, devname);    return 1;  }    if ( update_only && !already_installed(devfd) ) {    fprintf(stderr, "%s: no previous extlinux boot sector found\n", program);    return 1;  }	      install_file(path, devfd, &fst);  if ( fst.st_dev != st.st_dev ) {    fprintf(stderr, "%s: file system changed under us - aborting!\n",	    program);    return 1;  }  sync();  rv = install_bootblock(devfd, mnt->mnt_fsname);  close(devfd);  sync();  endmntent(mtab);  if ( rv ) return rv;  return 0;}intmain(int argc, char *argv[]){  int o;  const char *directory;  int update_only = -1;  program = argv[0];  while ( (o = getopt_long(argc, argv, short_options,			     long_options, NULL)) != EOF ) {    switch ( o ) {    case 'z':      opt.heads = 64;      opt.sectors = 32;      break;    case 'S':      opt.sectors = strtoul(optarg, NULL, 0);      if ( opt.sectors < 1 || opt.sectors > 63 ) {	fprintf(stderr, "%s: invalid number of sectors: %u (must be 1-63)\n",		program, opt.sectors);	exit(EX_USAGE);      }      break;    case 'H':      opt.heads = strtoul(optarg, NULL, 0);      if ( opt.heads < 1 || opt.heads > 256 ) {	fprintf(stderr, "%s: invalid number of heads: %u (must be 1-256)\n",		program, opt.heads);	exit(EX_USAGE);      }      break;    case 'i':      update_only = 0;      break;    case 'u':    case 'U':      update_only = 1;      break;    case 'h':      usage(0);      break;    case 'v':      fputs("extlinux " VERSION "\n", stderr);      exit(0);    default:      fprintf(stderr, "%s: Unknown option: %c\n", program, optopt);      exit(EX_USAGE);    }  }  directory = argv[optind];  if ( !directory )    usage(EX_USAGE);  if ( update_only == -1 ) {    fprintf(stderr, "%s: warning: a future version will require --install or --update\n",	    program);    update_only = 0;  }  return install_loader(directory, update_only);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -