summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux/latest/extlinux/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux/latest/extlinux/main.c')
-rwxr-xr-xcontrib/syslinux/latest/extlinux/main.c856
1 files changed, 0 insertions, 856 deletions
diff --git a/contrib/syslinux/latest/extlinux/main.c b/contrib/syslinux/latest/extlinux/main.c
deleted file mode 100755
index 30422c2..0000000
--- a/contrib/syslinux/latest/extlinux/main.c
+++ /dev/null
@@ -1,856 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
- * Boston MA 02111-1307, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * extlinux.c
- *
- * Install the syslinux boot block on an fat, ext2/3/4 and btrfs filesystem
- */
-
-#define _GNU_SOURCE /* Enable everything */
-#include <inttypes.h>
-/* This is needed to deal with the kernel headers imported into glibc 3.3.3. */
-typedef uint64_t u64;
-#include <alloca.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-#ifndef __KLIBC__
-#include <mntent.h>
-#endif
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <sysexits.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/mount.h>
-#include <sys/vfs.h>
-
-#include "linuxioctl.h"
-
-#include "btrfs.h"
-#include "fat.h"
-#include "../version.h"
-#include "syslxint.h"
-#include "syslxcom.h" /* common functions shared with extlinux and syslinux */
-#include "setadv.h"
-#include "syslxopt.h" /* unified options */
-
-#ifdef DEBUG
-# define dprintf printf
-#else
-# define dprintf(...) ((void)0)
-#endif
-
-#ifndef EXT2_SUPER_OFFSET
-#define EXT2_SUPER_OFFSET 1024
-#endif
-
-/* the btrfs partition first 64K blank area is used to store boot sector and
- boot image, the boot sector is from 0~512, the boot image starts after */
-#define BTRFS_BOOTSECT_AREA 65536
-#define BTRFS_EXTLINUX_OFFSET SECTOR_SIZE
-#define BTRFS_SUBVOL_OPT "subvol="
-#define BTRFS_SUBVOL_MAX 256 /* By btrfs specification */
-static char subvol[BTRFS_SUBVOL_MAX];
-
-#define BTRFS_ADV_OFFSET (BTRFS_BOOTSECT_AREA - 2 * ADV_SIZE)
-
-/*
- * Get the size of a block device
- */
-uint64_t get_size(int devfd)
-{
- uint64_t bytes;
- uint32_t sects;
- struct stat st;
-
-#ifdef BLKGETSIZE64
- if (!ioctl(devfd, BLKGETSIZE64, &bytes))
- return bytes;
-#endif
- if (!ioctl(devfd, BLKGETSIZE, &sects))
- return (uint64_t) sects << 9;
- else if (!fstat(devfd, &st) && st.st_size)
- return st.st_size;
- else
- return 0;
-}
-
-/*
- * Get device geometry and partition offset
- */
-struct geometry_table {
- uint64_t bytes;
- struct hd_geometry g;
-};
-
-static int sysfs_get_offset(int devfd, unsigned long *start)
-{
- struct stat st;
- char sysfs_name[128];
- FILE *f;
- int rv;
-
- if (fstat(devfd, &st))
- return -1;
-
- if ((size_t)snprintf(sysfs_name, sizeof sysfs_name,
- "/sys/dev/block/%u:%u/start",
- major(st.st_dev), minor(st.st_dev))
- >= sizeof sysfs_name)
- return -1;
-
- f = fopen(sysfs_name, "r");
- if (!f)
- return -1;
-
- rv = fscanf(f, "%lu", start);
- fclose(f);
-
- return (rv == 1) ? 0 : -1;
-}
-
-/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry
- (x/64/32) is the final fallback. I don't know what LS-240 has
- as its geometry, since I don't have one and don't know anyone that does,
- and Google wasn't helpful... */
-static const struct geometry_table standard_geometries[] = {
- {360 * 1024, {2, 9, 40, 0}},
- {720 * 1024, {2, 9, 80, 0}},
- {1200 * 1024, {2, 15, 80, 0}},
- {1440 * 1024, {2, 18, 80, 0}},
- {1680 * 1024, {2, 21, 80, 0}},
- {1722 * 1024, {2, 21, 80, 0}},
- {2880 * 1024, {2, 36, 80, 0}},
- {3840 * 1024, {2, 48, 80, 0}},
- {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */
- {0, {0, 0, 0, 0}}
-};
-
-int get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
-{
- struct floppy_struct fd_str;
- struct loop_info li;
- struct loop_info64 li64;
- const struct geometry_table *gp;
- int rv = 0;
-
- memset(geo, 0, sizeof *geo);
-
- if (!ioctl(devfd, HDIO_GETGEO, &geo)) {
- goto ok;
- } 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;
- goto ok;
- }
-
- /* 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);
- goto ok;
- }
- }
-
- /* 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);
- rv = 1; /* Suboptimal result */
- }
-
-ok:
- /* If this is a loopback device, try to set the start */
- if (!ioctl(devfd, LOOP_GET_STATUS64, &li64))
- geo->start = li64.lo_offset >> SECTOR_SHIFT;
- else if (!ioctl(devfd, LOOP_GET_STATUS, &li))
- geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT;
- else if (!sysfs_get_offset(devfd, &geo->start)) {
- /* OK */
- }
-
- return rv;
-}
-
-/*
- * 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.
- *
- * Returns the number of modified bytes in the boot file.
- */
-int patch_file_and_bootblock(int fd, const char *dir, int devfd)
-{
- struct stat dirst, xdst;
- struct hd_geometry geo;
- sector_t *sectp;
- uint64_t totalbytes, totalsectors;
- int nsect;
- struct boot_sector *sbs;
- char *dirpath, *subpath, *xdirpath, *xsubpath;
- int rv;
-
- dirpath = realpath(dir, NULL);
- if (!dirpath || stat(dir, &dirst)) {
- perror("accessing install directory");
- exit(255); /* This should never happen */
- }
-
- if (lstat(dirpath, &xdst) ||
- dirst.st_ino != xdst.st_ino ||
- dirst.st_dev != xdst.st_dev) {
- perror("realpath returned nonsense");
- exit(255);
- }
-
- subpath = strchr(dirpath, '\0');
- for (;;) {
- if (*subpath == '/') {
- if (subpath > dirpath) {
- *subpath = '\0';
- xsubpath = subpath+1;
- xdirpath = dirpath;
- } else {
- xsubpath = subpath;
- xdirpath = "/";
- }
- if (lstat(xdirpath, &xdst) || dirst.st_dev != xdst.st_dev) {
- subpath = strchr(subpath+1, '/');
- if (!subpath)
- subpath = "/"; /* It's the root of the filesystem */
- break;
- }
- *subpath = '/';
- }
-
- if (subpath == dirpath)
- break;
-
- subpath--;
- }
-
- /* Now subpath should contain the path relative to the fs base */
- dprintf("subpath = %s\n", subpath);
-
- 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);
-
- sbs = (struct boot_sector *)syslinux_bootsect;
-
- totalsectors = totalbytes >> SECTOR_SHIFT;
- if (totalsectors >= 65536) {
- set_16(&sbs->bsSectors, 0);
- } else {
- set_16(&sbs->bsSectors, totalsectors);
- }
- set_32(&sbs->bsHugeSectors, totalsectors);
-
- set_16(&sbs->bsBytesPerSec, SECTOR_SIZE);
- set_16(&sbs->bsSecPerTrack, geo.sectors);
- set_16(&sbs->bsHeads, geo.heads);
- set_32(&sbs->bsHiddenSecs, geo.start);
-
- /* Construct the boot file map */
-
- dprintf("directory inode = %lu\n", (unsigned long)dirst.st_ino);
- nsect = (boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
- nsect += 2; /* Two sectors for the ADV */
- sectp = alloca(sizeof(sector_t) * nsect);
- if (fs_type == EXT2 || fs_type == VFAT) {
- if (sectmap(fd, sectp, nsect)) {
- perror("bmap");
- exit(1);
- }
- } else if (fs_type == BTRFS) {
- int i;
- sector_t *sp = sectp;
-
- for (i = 0; i < nsect - 2; i++)
- *sp++ = BTRFS_EXTLINUX_OFFSET/SECTOR_SIZE + i;
- for (i = 0; i < 2; i++)
- *sp++ = BTRFS_ADV_OFFSET/SECTOR_SIZE + i;
- }
-
- /* Create the modified image in memory */
- rv = syslinux_patch(sectp, nsect, opt.stupid_mode,
- opt.raid_mode, subpath, subvol);
-
- free(dirpath);
- return rv;
-}
-
-/*
- * Install the boot block on the specified device.
- * Must be run AFTER install_file()!
- */
-int install_bootblock(int fd, const char *device)
-{
- struct ext2_super_block sb;
- struct btrfs_super_block sb2;
- struct boot_sector sb3;
- bool ok = false;
-
- if (fs_type == EXT2) {
- if (xpread(fd, &sb, sizeof sb, EXT2_SUPER_OFFSET) != sizeof sb) {
- perror("reading superblock");
- return 1;
- }
- if (sb.s_magic == EXT2_SUPER_MAGIC)
- ok = true;
- } else if (fs_type == BTRFS) {
- if (xpread(fd, &sb2, sizeof sb2, BTRFS_SUPER_INFO_OFFSET)
- != sizeof sb2) {
- perror("reading superblock");
- return 1;
- }
- if (sb2.magic == *(u64 *)BTRFS_MAGIC)
- ok = true;
- } else if (fs_type == VFAT) {
- if (xpread(fd, &sb3, sizeof sb3, 0) != sizeof sb3) {
- perror("reading fat superblock");
- return 1;
- }
- if (sb3.bsResSectors && sb3.bsFATs &&
- (strstr(sb3.bs16.FileSysType, "FAT") ||
- strstr(sb3.bs32.FileSysType, "FAT")))
- ok = true;
- }
- if (!ok) {
- fprintf(stderr, "no fat, ext2/3/4 or btrfs superblock found on %s\n",
- device);
- return 1;
- }
- if (fs_type == VFAT) {
- struct boot_sector *sbs = (struct boot_sector *)syslinux_bootsect;
- if (xpwrite(fd, &sbs->bsHead, bsHeadLen, 0) != bsHeadLen ||
- xpwrite(fd, &sbs->bsCode, bsCodeLen,
- offsetof(struct boot_sector, bsCode)) != bsCodeLen) {
- perror("writing fat bootblock");
- return 1;
- }
- } else {
- if (xpwrite(fd, syslinux_bootsect, syslinux_bootsect_len, 0)
- != syslinux_bootsect_len) {
- perror("writing bootblock");
- return 1;
- }
- }
-
- return 0;
-}
-
-int ext2_fat_install_file(const char *path, int devfd, struct stat *rst)
-{
- char *file, *oldfile;
- int fd = -1, dirfd = -1;
- int modbytes;
- int r1, r2;
-
- r1 = asprintf(&file, "%s%sldlinux.sys",
- path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
- r2 = asprintf(&oldfile, "%s%sextlinux.sys",
- path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
- if (r1 < 0 || !file || r2 < 0 || !oldfile) {
- 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 {
- clear_attributes(fd);
- }
- close(fd);
-
- fd = open(file, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
- 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 ||
- xpwrite(fd, syslinux_adv, 2 * ADV_SIZE,
- boot_image_len) != 2 * ADV_SIZE) {
- fprintf(stderr, "%s: write failure on %s\n", program, file);
- goto bail;
- }
-
- /* Map the file, and patch the initial sector accordingly */
- modbytes = patch_file_and_bootblock(fd, path, devfd);
-
- /* Write the patch area again - this relies on the file being
- overwritten in place! */
- if (xpwrite(fd, boot_image, modbytes, 0) != modbytes) {
- 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 */
- set_attributes(fd);
-
- if (fstat(fd, rst)) {
- perror(file);
- goto bail;
- }
-
- close(dirfd);
- close(fd);
-
- /* Look if we have the old filename */
- fd = open(oldfile, O_RDONLY);
- if (fd >= 0) {
- clear_attributes(fd);
- close(fd);
- unlink(oldfile);
- }
-
- free(file);
- free(oldfile);
- return 0;
-
-bail:
- if (dirfd >= 0)
- close(dirfd);
- if (fd >= 0)
- close(fd);
-
- free(file);
- free(oldfile);
- return 1;
-}
-
-/* btrfs has to install the ldlinux.sys in the first 64K blank area, which
- is not managered by btrfs tree, so actually this is not installed as files.
- since the cow feature of btrfs will move the ldlinux.sys every where */
-int btrfs_install_file(const char *path, int devfd, struct stat *rst)
-{
- patch_file_and_bootblock(-1, path, devfd);
- if (xpwrite(devfd, boot_image, boot_image_len, BTRFS_EXTLINUX_OFFSET)
- != boot_image_len) {
- perror("writing bootblock");
- return 1;
- }
- dprintf("write boot_image to 0x%x\n", BTRFS_EXTLINUX_OFFSET);
- if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE, BTRFS_ADV_OFFSET)
- != 2 * ADV_SIZE) {
- perror("writing adv");
- return 1;
- }
- dprintf("write adv to 0x%x\n", BTRFS_ADV_OFFSET);
- if (stat(path, rst)) {
- perror(path);
- return 1;
- }
- return 0;
-}
-
-int install_file(const char *path, int devfd, struct stat *rst)
-{
- if (fs_type == EXT2 || fs_type == VFAT)
- return ext2_fat_install_file(path, devfd, rst);
- else if (fs_type == BTRFS)
- return btrfs_install_file(path, devfd, rst);
- return 1;
-}
-
-/*
- * SYSLINUX installs the string 'SYSLINUX' at offset 3 in the boot
- * sector; this is consistent with FAT filesystems. Earlier versions
- * would install the string "EXTLINUX" instead, handle both.
- */
-int already_installed(int devfd)
-{
- char buffer[8];
-
- xpread(devfd, buffer, 8, 3);
- return !memcmp(buffer, "SYSLINUX", 8) || !memcmp(buffer, "EXTLINUX", 8);
-}
-
-#ifdef __KLIBC__
-static char devname_buf[64];
-
-static void device_cleanup(void)
-{
- unlink(devname_buf);
-}
-#endif
-
-/* Verify that a device fd and a pathname agree.
- Return 0 on valid, -1 on error. */
-static int validate_device(const char *path, int devfd)
-{
- struct stat pst, dst;
- struct statfs sfs;
-
- if (stat(path, &pst) || fstat(devfd, &dst) || statfs(path, &sfs))
- return -1;
- /* btrfs st_dev is not matched with mnt st_rdev, it is a known issue */
- if (fs_type == BTRFS && sfs.f_type == BTRFS_SUPER_MAGIC)
- return 0;
- return (pst.st_dev == dst.st_rdev) ? 0 : -1;
-}
-
-#ifndef __KLIBC__
-static const char *find_device(const char *mtab_file, dev_t dev)
-{
- struct mntent *mnt;
- struct stat dst;
- FILE *mtab;
- const char *devname = NULL;
- bool done;
-
- mtab = setmntent(mtab_file, "r");
- if (!mtab)
- return NULL;
-
- done = false;
- while ((mnt = getmntent(mtab))) {
- /* btrfs st_dev is not matched with mnt st_rdev, it is a known issue */
- switch (fs_type) {
- case BTRFS:
- if (!strcmp(mnt->mnt_type, "btrfs") &&
- !stat(mnt->mnt_dir, &dst) &&
- dst.st_dev == dev) {
- char *opt = strstr(mnt->mnt_opts, BTRFS_SUBVOL_OPT);
-
- if (opt) {
- if (!subvol[0]) {
- char *tmp;
-
- strcpy(subvol, opt + sizeof(BTRFS_SUBVOL_OPT) - 1);
- tmp = strchr(subvol, 32);
- if (tmp)
- *tmp = '\0';
- }
- break; /* should break and let upper layer try again */
- } else
- done = true;
- }
- break;
- case EXT2:
- if ((!strcmp(mnt->mnt_type, "ext2") ||
- !strcmp(mnt->mnt_type, "ext3") ||
- !strcmp(mnt->mnt_type, "ext4")) &&
- !stat(mnt->mnt_fsname, &dst) &&
- dst.st_rdev == dev) {
- done = true;
- break;
- }
- case VFAT:
- if ((!strcmp(mnt->mnt_type, "vfat")) &&
- !stat(mnt->mnt_fsname, &dst) &&
- dst.st_rdev == dev) {
- done = true;
- break;
- }
- case NONE:
- break;
- }
- if (done) {
- devname = strdup(mnt->mnt_fsname);
- break;
- }
- }
- endmntent(mtab);
-
- return devname;
-}
-#endif
-
-static const char *get_devname(const char *path)
-{
- const char *devname = NULL;
- struct stat st;
- struct statfs sfs;
-
- if (stat(path, &st) || !S_ISDIR(st.st_mode)) {
- fprintf(stderr, "%s: Not a directory: %s\n", program, path);
- return devname;
- }
- if (statfs(path, &sfs)) {
- fprintf(stderr, "%s: statfs %s: %s\n", program, path, strerror(errno));
- return devname;
- }
-#ifdef __KLIBC__
-
- /* klibc doesn't have getmntent and friends; instead, just create
- a new device with the appropriate device type */
- snprintf(devname_buf, sizeof devname_buf, "/tmp/dev-%u:%u",
- major(st.st_dev), minor(st.st_dev));
-
- if (mknod(devname_buf, S_IFBLK | 0600, st.st_dev)) {
- fprintf(stderr, "%s: cannot create device %s\n", program, devname);
- return devname;
- }
-
- atexit(device_cleanup); /* unlink the device node on exit */
- devname = devname_buf;
-
-#else
-
- /* check /etc/mtab first, since btrfs subvol info is only in here */
- devname = find_device("/etc/mtab", st.st_dev);
- if (subvol[0] && !devname) { /* we just find it is a btrfs subvol */
- char parent[256];
- char *tmp;
-
- strcpy(parent, path);
- tmp = strrchr(parent, '/');
- if (tmp) {
- *tmp = '\0';
- fprintf(stderr, "%s is subvol, try its parent dir %s\n", path, parent);
- devname = get_devname(parent);
- } else
- devname = NULL;
- }
- if (!devname) {
- /* Didn't find it in /etc/mtab, try /proc/mounts */
- devname = find_device("/proc/mounts", st.st_dev);
- }
- if (!devname) {
- fprintf(stderr, "%s: cannot find device for path %s\n", program, path);
- return devname;
- }
-
- fprintf(stderr, "%s is device %s\n", path, devname);
-#endif
- return devname;
-}
-
-static int open_device(const char *path, struct stat *st, const char **_devname)
-{
- int devfd;
- const char *devname = NULL;
- struct statfs sfs;
-
- if (st)
- if (stat(path, st) || !S_ISDIR(st->st_mode)) {
- fprintf(stderr, "%s: Not a directory: %s\n", program, path);
- return -1;
- }
-
- if (statfs(path, &sfs)) {
- fprintf(stderr, "%s: statfs %s: %s\n", program, path, strerror(errno));
- return -1;
- }
- if (sfs.f_type == EXT2_SUPER_MAGIC)
- fs_type = EXT2;
- else if (sfs.f_type == BTRFS_SUPER_MAGIC)
- fs_type = BTRFS;
- else if (sfs.f_type == MSDOS_SUPER_MAGIC)
- fs_type = VFAT;
-
- if (!fs_type) {
- fprintf(stderr, "%s: not a fat, ext2/3/4 or btrfs filesystem: %s\n",
- program, path);
- return -1;
- }
-
- devfd = -1;
- devname = get_devname(path);
- if (_devname)
- *_devname = devname;
-
- if ((devfd = open(devname, O_RDWR | O_SYNC)) < 0) {
- fprintf(stderr, "%s: cannot open device %s\n", program, devname);
- return -1;
- }
-
- /* Verify that the device we opened is the device intended */
- if (validate_device(path, devfd)) {
- fprintf(stderr, "%s: path %s doesn't match device %s\n",
- program, path, devname);
- close(devfd);
- return -1;
- }
- return devfd;
-}
-
-static int btrfs_read_adv(int devfd)
-{
- if (xpread(devfd, syslinux_adv, 2 * ADV_SIZE, BTRFS_ADV_OFFSET)
- != 2 * ADV_SIZE)
- return -1;
-
- return syslinux_validate_adv(syslinux_adv) ? 1 : 0;
-}
-
-static int ext_read_adv(const char *path, int devfd, const char **namep)
-{
- int err;
- const char *name;
-
- if (fs_type == BTRFS) {
- /* btrfs "ldlinux.sys" is in 64k blank area */
- return btrfs_read_adv(devfd);
- } else {
- err = read_adv(path, name = "ldlinux.sys");
- if (err == 2) /* ldlinux.sys does not exist */
- err = read_adv(path, name = "extlinux.sys");
- if (namep)
- *namep = name;
- return err;
- }
-}
-
-static int ext_write_adv(const char *path, const char *cfg, int devfd)
-{
- if (fs_type == BTRFS) { /* btrfs "ldlinux.sys" is in 64k blank area */
- if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE,
- BTRFS_ADV_OFFSET) != 2 * ADV_SIZE) {
- perror("writing adv");
- return 1;
- }
- return 0;
- }
- return write_adv(path, cfg);
-}
-
-int install_loader(const char *path, int update_only)
-{
- struct stat st, fst;
- int devfd, rv;
- const char *devname;
-
- devfd = open_device(path, &st, &devname);
- if (devfd < 0)
- return 1;
-
- if (update_only && !already_installed(devfd)) {
- fprintf(stderr, "%s: no previous syslinux boot sector found\n",
- program);
- close(devfd);
- return 1;
- }
-
- /* Read a pre-existing ADV, if already installed */
- if (opt.reset_adv) {
- syslinux_reset_adv(syslinux_adv);
- } else if (ext_read_adv(path, devfd, NULL) < 0) {
- close(devfd);
- return 1;
- }
-
- if (modify_adv() < 0) {
- close(devfd);
- return 1;
- }
-
- /* Install ldlinux.sys */
- if (install_file(path, devfd, &fst)) {
- close(devfd);
- return 1;
- }
- if (fst.st_dev != st.st_dev) {
- fprintf(stderr, "%s: file system changed under us - aborting!\n",
- program);
- close(devfd);
- return 1;
- }
-
- sync();
- rv = install_bootblock(devfd, devname);
- close(devfd);
- sync();
-
- return rv;
-}
-
-/*
- * Modify the ADV of an existing installation
- */
-int modify_existing_adv(const char *path)
-{
- const char *filename;
- int devfd;
-
- devfd = open_device(path, NULL, NULL);
- if (devfd < 0)
- return 1;
-
- if (opt.reset_adv)
- syslinux_reset_adv(syslinux_adv);
- else if (ext_read_adv(path, devfd, &filename) < 0) {
- close(devfd);
- return 1;
- }
- if (modify_adv() < 0) {
- close(devfd);
- return 1;
- }
- if (ext_write_adv(path, filename, devfd) < 0) {
- close(devfd);
- return 1;
- }
- close(devfd);
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- parse_options(argc, argv, MODE_EXTLINUX);
-
- if (!opt.directory || opt.install_mbr || opt.activate_partition)
- usage(EX_USAGE, 0);
-
- if (opt.update_only == -1) {
- if (opt.reset_adv || opt.set_once || opt.menu_save)
- return modify_existing_adv(opt.directory);
- else
- usage(EX_USAGE, MODE_EXTLINUX);
- }
-
- return install_loader(opt.directory, opt.update_only);
-}