summaryrefslogtreecommitdiffstats
path: root/extlinux
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-05-29 15:16:22 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-05-29 15:16:22 -0700
commit5e6aef0b866b1e5c1c458cc8ca2a52092928fb0d (patch)
treed88795d0d3aba72776a20bf8ee4c8778815df3d0 /extlinux
parentdcd9ae222c665a56a57a560be62b407a04573e13 (diff)
parent8833b1c37f7ecfa41e0e2c26e72c2913d5eba969 (diff)
downloadsyslinux-5e6aef0b866b1e5c1c458cc8ca2a52092928fb0d.tar.gz
syslinux-5e6aef0b866b1e5c1c458cc8ca2a52092928fb0d.tar.xz
syslinux-5e6aef0b866b1e5c1c458cc8ca2a52092928fb0d.zip
Merge branch 'master' into core32
Conflicts: com32/include/netinet/in.h com32/include/sys/cpu.h dos/argv.c dos/malloc.c dos/syslinux.c extlinux/main.c libinstaller/setadv.c libinstaller/syslinux.h libinstaller/syslxint.h libinstaller/syslxmod.c linux/syslinux.c mtools/syslinux.c win32/syslinux.c Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'extlinux')
-rw-r--r--extlinux/ext2_fs.h341
-rw-r--r--extlinux/main.c1360
2 files changed, 838 insertions, 863 deletions
diff --git a/extlinux/ext2_fs.h b/extlinux/ext2_fs.h
index c0eeb7b7..1351d8cd 100644
--- a/extlinux/ext2_fs.h
+++ b/extlinux/ext2_fs.h
@@ -51,9 +51,8 @@
printk (f, ## a); \
}
#else
-# define ext2_debug(f, a...) /**/
+# define ext2_debug(f, a...) /**/
#endif
-
/*
* Special inode numbers
*/
@@ -63,20 +62,16 @@
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
-
/* First non-reserved inode for old ext2 filesystems */
#define EXT2_GOOD_OLD_FIRST_INO 11
-
/*
* The second extended file system magic number
*/
#define EXT2_SUPER_MAGIC 0xEF53
-
/*
* Maximal count of links to a file
*/
#define EXT2_LINK_MAX 32000
-
/*
* Macro-instructions used to manage several block sizes
*/
@@ -93,7 +88,6 @@
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_FIRST_INO : \
(s)->s_first_ino)
-
/*
* Macro-instructions used to manage fragments
*/
@@ -102,42 +96,38 @@
#define EXT2_MIN_FRAG_LOG_SIZE 10
# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
-
/*
* ACL structures
*/
-struct ext2_acl_header /* Header of Access Control Lists */
-{
- __u32 aclh_size;
- __u32 aclh_file_count;
- __u32 aclh_acle_count;
- __u32 aclh_first_acle;
+ struct ext2_acl_header { /* Header of Access Control Lists */
+ __u32 aclh_size;
+ __u32 aclh_file_count;
+ __u32 aclh_acle_count;
+ __u32 aclh_first_acle;
};
-struct ext2_acl_entry /* Access Control List Entry */
-{
- __u32 acle_size;
- __u16 acle_perms; /* Access permissions */
- __u16 acle_type; /* Type of entry */
- __u16 acle_tag; /* User or group identity */
- __u16 acle_pad1;
- __u32 acle_next; /* Pointer on next entry for the */
- /* same inode or on next free entry */
+struct ext2_acl_entry { /* Access Control List Entry */
+ __u32 acle_size;
+ __u16 acle_perms; /* Access permissions */
+ __u16 acle_type; /* Type of entry */
+ __u16 acle_tag; /* User or group identity */
+ __u16 acle_pad1;
+ __u32 acle_next; /* Pointer on next entry for the */
+ /* same inode or on next free entry */
};
/*
* Structure of a blocks group descriptor
*/
-struct ext2_group_desc
-{
- __u32 bg_block_bitmap; /* Blocks bitmap block */
- __u32 bg_inode_bitmap; /* Inodes bitmap block */
- __u32 bg_inode_table; /* Inodes table block */
- __u16 bg_free_blocks_count; /* Free blocks count */
- __u16 bg_free_inodes_count; /* Free inodes count */
- __u16 bg_used_dirs_count; /* Directories count */
- __u16 bg_pad;
- __u32 bg_reserved[3];
+struct ext2_group_desc {
+ __u32 bg_block_bitmap; /* Blocks bitmap block */
+ __u32 bg_inode_bitmap; /* Inodes bitmap block */
+ __u32 bg_inode_table; /* Inodes table block */
+ __u16 bg_free_blocks_count; /* Free blocks count */
+ __u16 bg_free_inodes_count; /* Free inodes count */
+ __u16 bg_used_dirs_count; /* Directories count */
+ __u16 bg_pad;
+ __u32 bg_reserved[3];
};
/*
@@ -159,25 +149,25 @@ struct ext2_group_desc
/*
* Inode flags
*/
-#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
-#define EXT2_UNRM_FL 0x00000002 /* Undelete */
-#define EXT2_COMPR_FL 0x00000004 /* Compress file */
-#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
-#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
-#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
-#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
-#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
+#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
+#define EXT2_UNRM_FL 0x00000002 /* Undelete */
+#define EXT2_COMPR_FL 0x00000004 /* Compress file */
+#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
+#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
+#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
+#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
+#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
/* Reserved for compression usage... */
#define EXT2_DIRTY_FL 0x00000100
-#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
-#define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */
-#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
+#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
+#define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */
+#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
/* End compression flags --- maybe not all used */
-#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
-#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
+#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
+#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
-#define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */
-#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
+#define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
/*
* ioctl commands
@@ -191,57 +181,57 @@ struct ext2_group_desc
* Structure of an inode on the disk
*/
struct ext2_inode {
- __u16 i_mode; /* File mode */
- __u16 i_uid; /* Low 16 bits of Owner Uid */
- __u32 i_size; /* Size in bytes */
- __u32 i_atime; /* Access time */
- __u32 i_ctime; /* Creation time */
- __u32 i_mtime; /* Modification time */
- __u32 i_dtime; /* Deletion Time */
- __u16 i_gid; /* Low 16 bits of Group Id */
- __u16 i_links_count; /* Links count */
- __u32 i_blocks; /* Blocks count */
- __u32 i_flags; /* File flags */
- union {
- struct {
- __u32 l_i_reserved1;
- } linux1;
- struct {
- __u32 h_i_translator;
- } hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
- } osd1; /* OS dependent 1 */
- __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
- __u32 i_generation; /* File version (for NFS) */
- __u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
- __u32 i_faddr; /* Fragment address */
- union {
- struct {
- __u8 l_i_frag; /* Fragment number */
- __u8 l_i_fsize; /* Fragment size */
- __u16 i_pad1;
- __u16 l_i_uid_high; /* these 2 fields */
- __u16 l_i_gid_high; /* were reserved2[0] */
- __u32 l_i_reserved2;
- } linux2;
- struct {
- __u8 h_i_frag; /* Fragment number */
- __u8 h_i_fsize; /* Fragment size */
- __u16 h_i_mode_high;
- __u16 h_i_uid_high;
- __u16 h_i_gid_high;
- __u32 h_i_author;
- } hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
- } osd2; /* OS dependent 2 */
+ __u16 i_mode; /* File mode */
+ __u16 i_uid; /* Low 16 bits of Owner Uid */
+ __u32 i_size; /* Size in bytes */
+ __u32 i_atime; /* Access time */
+ __u32 i_ctime; /* Creation time */
+ __u32 i_mtime; /* Modification time */
+ __u32 i_dtime; /* Deletion Time */
+ __u16 i_gid; /* Low 16 bits of Group Id */
+ __u16 i_links_count; /* Links count */
+ __u32 i_blocks; /* Blocks count */
+ __u32 i_flags; /* File flags */
+ union {
+ struct {
+ __u32 l_i_reserved1;
+ } linux1;
+ struct {
+ __u32 h_i_translator;
+ } hurd1;
+ struct {
+ __u32 m_i_reserved1;
+ } masix1;
+ } osd1; /* OS dependent 1 */
+ __u32 i_block[EXT2_N_BLOCKS]; /* Pointers to blocks */
+ __u32 i_generation; /* File version (for NFS) */
+ __u32 i_file_acl; /* File ACL */
+ __u32 i_dir_acl; /* Directory ACL */
+ __u32 i_faddr; /* Fragment address */
+ union {
+ struct {
+ __u8 l_i_frag; /* Fragment number */
+ __u8 l_i_fsize; /* Fragment size */
+ __u16 i_pad1;
+ __u16 l_i_uid_high; /* these 2 fields */
+ __u16 l_i_gid_high; /* were reserved2[0] */
+ __u32 l_i_reserved2;
+ } linux2;
+ struct {
+ __u8 h_i_frag; /* Fragment number */
+ __u8 h_i_fsize; /* Fragment size */
+ __u16 h_i_mode_high;
+ __u16 h_i_uid_high;
+ __u16 h_i_gid_high;
+ __u32 h_i_author;
+ } hurd2;
+ struct {
+ __u8 m_i_frag; /* Fragment number */
+ __u8 m_i_fsize; /* Fragment size */
+ __u16 m_pad1;
+ __u32 m_i_reserved2[2];
+ } masix2;
+ } osd2; /* OS dependent 2 */
};
#define i_size_high i_dir_acl
@@ -289,7 +279,7 @@ struct ext2_inode {
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
-#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
+#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
@@ -313,62 +303,62 @@ struct ext2_inode {
* Structure of the super block
*/
struct ext2_super_block {
- __u32 s_inodes_count; /* Inodes count */
- __u32 s_blocks_count; /* Blocks count */
- __u32 s_r_blocks_count; /* Reserved blocks count */
- __u32 s_free_blocks_count; /* Free blocks count */
- __u32 s_free_inodes_count; /* Free inodes count */
- __u32 s_first_data_block; /* First Data Block */
- __u32 s_log_block_size; /* Block size */
- __s32 s_log_frag_size; /* Fragment size */
- __u32 s_blocks_per_group; /* # Blocks per group */
- __u32 s_frags_per_group; /* # Fragments per group */
- __u32 s_inodes_per_group; /* # Inodes per group */
- __u32 s_mtime; /* Mount time */
- __u32 s_wtime; /* Write time */
- __u16 s_mnt_count; /* Mount count */
- __s16 s_max_mnt_count; /* Maximal mount count */
- __u16 s_magic; /* Magic signature */
- __u16 s_state; /* File system state */
- __u16 s_errors; /* Behaviour when detecting errors */
- __u16 s_minor_rev_level; /* minor revision level */
- __u32 s_lastcheck; /* time of last check */
- __u32 s_checkinterval; /* max. time between checks */
- __u32 s_creator_os; /* OS */
- __u32 s_rev_level; /* Revision level */
- __u16 s_def_resuid; /* Default uid for reserved blocks */
- __u16 s_def_resgid; /* Default gid for reserved blocks */
- /*
- * These fields are for EXT2_DYNAMIC_REV superblocks only.
- *
- * Note: the difference between the compatible feature set and
- * the incompatible feature set is that if there is a bit set
- * in the incompatible feature set that the kernel doesn't
- * know about, it should refuse to mount the filesystem.
- *
- * e2fsck's requirements are more strict; if it doesn't know
- * about a feature in either the compatible or incompatible
- * feature set, it must abort and not try to meddle with
- * things it doesn't understand...
- */
- __u32 s_first_ino; /* First non-reserved inode */
- __u16 s_inode_size; /* size of inode structure */
- __u16 s_block_group_nr; /* block group # of this superblock */
- __u32 s_feature_compat; /* compatible feature set */
- __u32 s_feature_incompat; /* incompatible feature set */
- __u32 s_feature_ro_compat; /* readonly-compatible feature set */
- __u8 s_uuid[16]; /* 128-bit uuid for volume */
- char s_volume_name[16]; /* volume name */
- char s_last_mounted[64]; /* directory where last mounted */
- __u32 s_algorithm_usage_bitmap; /* For compression */
- /*
- * Performance hints. Directory preallocation should only
- * happen if the EXT2_COMPAT_PREALLOC flag is on.
- */
- __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
- __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
- __u16 s_padding1;
- __u32 s_reserved[204]; /* Padding to the end of the block */
+ __u32 s_inodes_count; /* Inodes count */
+ __u32 s_blocks_count; /* Blocks count */
+ __u32 s_r_blocks_count; /* Reserved blocks count */
+ __u32 s_free_blocks_count; /* Free blocks count */
+ __u32 s_free_inodes_count; /* Free inodes count */
+ __u32 s_first_data_block; /* First Data Block */
+ __u32 s_log_block_size; /* Block size */
+ __s32 s_log_frag_size; /* Fragment size */
+ __u32 s_blocks_per_group; /* # Blocks per group */
+ __u32 s_frags_per_group; /* # Fragments per group */
+ __u32 s_inodes_per_group; /* # Inodes per group */
+ __u32 s_mtime; /* Mount time */
+ __u32 s_wtime; /* Write time */
+ __u16 s_mnt_count; /* Mount count */
+ __s16 s_max_mnt_count; /* Maximal mount count */
+ __u16 s_magic; /* Magic signature */
+ __u16 s_state; /* File system state */
+ __u16 s_errors; /* Behaviour when detecting errors */
+ __u16 s_minor_rev_level; /* minor revision level */
+ __u32 s_lastcheck; /* time of last check */
+ __u32 s_checkinterval; /* max. time between checks */
+ __u32 s_creator_os; /* OS */
+ __u32 s_rev_level; /* Revision level */
+ __u16 s_def_resuid; /* Default uid for reserved blocks */
+ __u16 s_def_resgid; /* Default gid for reserved blocks */
+ /*
+ * These fields are for EXT2_DYNAMIC_REV superblocks only.
+ *
+ * Note: the difference between the compatible feature set and
+ * the incompatible feature set is that if there is a bit set
+ * in the incompatible feature set that the kernel doesn't
+ * know about, it should refuse to mount the filesystem.
+ *
+ * e2fsck's requirements are more strict; if it doesn't know
+ * about a feature in either the compatible or incompatible
+ * feature set, it must abort and not try to meddle with
+ * things it doesn't understand...
+ */
+ __u32 s_first_ino; /* First non-reserved inode */
+ __u16 s_inode_size; /* size of inode structure */
+ __u16 s_block_group_nr; /* block group # of this superblock */
+ __u32 s_feature_compat; /* compatible feature set */
+ __u32 s_feature_incompat; /* incompatible feature set */
+ __u32 s_feature_ro_compat; /* readonly-compatible feature set */
+ __u8 s_uuid[16]; /* 128-bit uuid for volume */
+ char s_volume_name[16]; /* volume name */
+ char s_last_mounted[64]; /* directory where last mounted */
+ __u32 s_algorithm_usage_bitmap; /* For compression */
+ /*
+ * Performance hints. Directory preallocation should only
+ * happen if the EXT2_COMPAT_PREALLOC flag is on.
+ */
+ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate */
+ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
+ __u16 s_padding1;
+ __u32 s_reserved[204]; /* Padding to the end of the block */
};
/* Assume that user mode programs are passing in an ext2fs superblock, not
@@ -458,10 +448,10 @@ struct ext2_super_block {
#define EXT2_NAME_LEN 255
struct ext2_dir_entry {
- __u32 inode; /* Inode number */
- __u16 rec_len; /* Directory entry length */
- __u16 name_len; /* Name length */
- char name[EXT2_NAME_LEN]; /* File name */
+ __u32 inode; /* Inode number */
+ __u16 rec_len; /* Directory entry length */
+ __u16 name_len; /* Name length */
+ char name[EXT2_NAME_LEN]; /* File name */
};
/*
@@ -471,11 +461,11 @@ struct ext2_dir_entry {
* file_type field.
*/
struct ext2_dir_entry_2 {
- __u32 inode; /* Inode number */
- __u16 rec_len; /* Directory entry length */
- __u8 name_len; /* Name length */
- __u8 file_type;
- char name[EXT2_NAME_LEN]; /* File name */
+ __u32 inode; /* Inode number */
+ __u16 rec_len; /* Directory entry length */
+ __u8 name_len; /* Name length */
+ __u8 file_type;
+ char name[EXT2_NAME_LEN]; /* File name */
};
/*
@@ -483,15 +473,15 @@ struct ext2_dir_entry_2 {
* other bits are reserved for now.
*/
enum {
- EXT2_FT_UNKNOWN,
- EXT2_FT_REG_FILE,
- EXT2_FT_DIR,
- EXT2_FT_CHRDEV,
- EXT2_FT_BLKDEV,
- EXT2_FT_FIFO,
- EXT2_FT_SOCK,
- EXT2_FT_SYMLINK,
- EXT2_FT_MAX
+ EXT2_FT_UNKNOWN,
+ EXT2_FT_REG_FILE,
+ EXT2_FT_DIR,
+ EXT2_FT_CHRDEV,
+ EXT2_FT_BLKDEV,
+ EXT2_FT_FIFO,
+ EXT2_FT_SOCK,
+ EXT2_FT_SYMLINK,
+ EXT2_FT_MAX
};
/*
@@ -504,5 +494,4 @@ enum {
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
-
-#endif /* _LINUX_EXT2_FS_H */
+#endif /* _LINUX_EXT2_FS_H */
diff --git a/extlinux/main.c b/extlinux/main.c
index c4ccd538..940f2f18 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -61,67 +61,62 @@ const char *program;
/* These are the options we can set and their values */
struct my_options {
- unsigned int sectors;
- unsigned int heads;
- int raid_mode;
- int stupid_mode;
- int reset_adv;
- const char *set_once;
+ unsigned int sectors;
+ unsigned int heads;
+ int raid_mode;
+ int stupid_mode;
+ int reset_adv;
+ const char *set_once;
} opt = {
- .sectors = 0,
- .heads = 0,
- .raid_mode = 0,
- .stupid_mode = 0,
- .reset_adv = 0,
- .set_once = NULL,
-};
+.sectors = 0,.heads = 0,.raid_mode = 0,.stupid_mode = 0,.reset_adv =
+ 0,.set_once = NULL,};
-static void __attribute__((noreturn)) usage(int rv)
+static void __attribute__ ((noreturn)) usage(int rv)
{
- fprintf(stderr,
- "Usage: %s [options] directory\n"
- " --install -i Install over the current bootsector\n"
- " --update -U Update a previous EXTLINUX installation\n"
- " --zip -z Force zipdrive geometry (-H 64 -S 32)\n"
- " --sectors=# -S Force the number of sectors per track\n"
- " --heads=# -H Force number of heads\n"
- " --stupid -s Slow, safe and stupid mode\n"
- " --raid -r Fall back to the next device on boot failure\n"
- " --once=... -o Execute a command once upon boot\n"
- " --clear-once -O Clear the boot-once command\n"
- " --reset-adv Reset auxilliary data\n"
- "\n"
- " Note: geometry is determined at boot time for devices which\n"
- " are considered hard disks by the BIOS. Unfortunately, this is\n"
- " not possible for devices which are considered floppy disks,\n"
- " which includes zipdisks and LS-120 superfloppies.\n"
- "\n"
- " The -z option is useful for USB devices which are considered\n"
- " hard disks by some BIOSes and zipdrives by other BIOSes.\n",
- program);
-
- exit(rv);
+ fprintf(stderr,
+ "Usage: %s [options] directory\n"
+ " --install -i Install over the current bootsector\n"
+ " --update -U Update a previous EXTLINUX installation\n"
+ " --zip -z Force zipdrive geometry (-H 64 -S 32)\n"
+ " --sectors=# -S Force the number of sectors per track\n"
+ " --heads=# -H Force number of heads\n"
+ " --stupid -s Slow, safe and stupid mode\n"
+ " --raid -r Fall back to the next device on boot failure\n"
+ " --once=... -o Execute a command once upon boot\n"
+ " --clear-once -O Clear the boot-once command\n"
+ " --reset-adv Reset auxilliary data\n"
+ "\n"
+ " Note: geometry is determined at boot time for devices which\n"
+ " are considered hard disks by the BIOS. Unfortunately, this is\n"
+ " not possible for devices which are considered floppy disks,\n"
+ " which includes zipdisks and LS-120 superfloppies.\n"
+ "\n"
+ " The -z option is useful for USB devices which are considered\n"
+ " hard disks by some BIOSes and zipdrives by other BIOSes.\n",
+ program);
+
+ exit(rv);
}
enum long_only_opt {
- OPT_NONE,
- OPT_RESET_ADV,
+ OPT_NONE,
+ OPT_RESET_ADV,
};
static const struct option long_options[] = {
- { "install", 0, NULL, 'i' },
- { "update", 0, NULL, 'U' },
- { "zipdrive", 0, NULL, 'z' },
- { "sectors", 1, NULL, 'S' },
- { "stupid", 0, NULL, 's' },
- { "heads", 1, NULL, 'H' },
- { "raid-mode", 0, NULL, 'r' },
- { "version", 0, NULL, 'v' },
- { "help", 0, NULL, 'h' },
- { "once", 1, NULL, 'o' },
- { "clear-once", 0, NULL, 'O' },
- { "reset-adv", 0, NULL, OPT_RESET_ADV },
- { 0, 0, 0, 0 }
+ {"install", 0, NULL, 'i'},
+ {"update", 0, NULL, 'U'},
+ {"zipdrive", 0, NULL, 'z'},
+ {"sectors", 1, NULL, 'S'},
+ {"stupid", 0, NULL, 's'},
+ {"heads", 1, NULL, 'H'},
+ {"raid-mode", 0, NULL, 'r'},
+ {"version", 0, NULL, 'v'},
+ {"help", 0, NULL, 'h'},
+ {"once", 1, NULL, 'o'},
+ {"clear-once", 0, NULL, 'O'},
+ {"reset-adv", 0, NULL, OPT_RESET_ADV},
+ {0, 0, 0, 0}
};
static const char short_options[] = "iUuzS:H:rvho:O";
@@ -141,7 +136,7 @@ const char *program;
* Boot block
*/
extern unsigned char extlinux_bootsect[];
-extern unsigned int extlinux_bootsect_len;
+extern unsigned int extlinux_bootsect_len;
#define boot_block extlinux_bootsect
#define boot_block_len extlinux_bootsect_len
@@ -149,17 +144,17 @@ extern unsigned int extlinux_bootsect_len;
* Image file
*/
extern unsigned char extlinux_image[];
-extern unsigned int extlinux_image_len;
+extern unsigned int extlinux_image_len;
#define boot_image extlinux_image
#define boot_image_len extlinux_image_len
/*
* Common abort function
*/
-void __attribute__((noreturn)) die(const char *msg)
+void __attribute__ ((noreturn)) die(const char *msg)
{
- fputs(msg, stderr);
- exit(1);
+ fputs(msg, stderr);
+ exit(1);
}
/*
@@ -167,94 +162,93 @@ void __attribute__((noreturn)) die(const char *msg)
*/
ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
{
- char *bufp = (char *)buf;
- ssize_t rv;
- ssize_t done = 0;
-
- while ( count ) {
- rv = pread(fd, bufp, count, offset);
- if ( rv == 0 ) {
- die("short read");
- } else if ( rv == -1 ) {
- if ( errno == EINTR ) {
- continue;
- } else {
- die(strerror(errno));
- }
- } else {
- bufp += rv;
- offset += rv;
- done += rv;
- count -= rv;
+ char *bufp = (char *)buf;
+ ssize_t rv;
+ ssize_t done = 0;
+
+ while (count) {
+ rv = pread(fd, bufp, count, offset);
+ if (rv == 0) {
+ die("short read");
+ } else if (rv == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ die(strerror(errno));
+ }
+ } else {
+ bufp += rv;
+ offset += rv;
+ done += rv;
+ count -= rv;
+ }
}
- }
- return done;
+ return done;
}
ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
{
- const char *bufp = (const char *)buf;
- ssize_t rv;
- ssize_t done = 0;
-
- while ( count ) {
- rv = pwrite(fd, bufp, count, offset);
- if ( rv == 0 ) {
- die("short write");
- } else if ( rv == -1 ) {
- if ( errno == EINTR ) {
- continue;
- } else {
- die(strerror(errno));
- }
- } else {
- bufp += rv;
- offset += rv;
- done += rv;
- count -= rv;
+ const char *bufp = (const char *)buf;
+ ssize_t rv;
+ ssize_t done = 0;
+
+ while (count) {
+ rv = pwrite(fd, bufp, count, offset);
+ if (rv == 0) {
+ die("short write");
+ } else if (rv == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ die(strerror(errno));
+ }
+ } else {
+ bufp += rv;
+ offset += rv;
+ done += rv;
+ count -= rv;
+ }
}
- }
- return done;
+ return done;
}
/*
* Produce file map
*/
-int
-sectmap(int fd, uint32_t *sectors, int nsectors)
+int sectmap(int fd, uint32_t * sectors, int nsectors)
{
- unsigned int blksize, blk, nblk;
- unsigned int i;
+ unsigned int blksize, blk, nblk;
+ unsigned int i;
- /* Get block size */
- if ( ioctl(fd, FIGETBSZ, &blksize) )
- return -1;
+ /* Get block size */
+ if (ioctl(fd, FIGETBSZ, &blksize))
+ return -1;
- /* Number of sectors per block */
- blksize >>= SECTOR_SHIFT;
+ /* Number of sectors per block */
+ blksize >>= SECTOR_SHIFT;
- nblk = 0;
- while ( nsectors ) {
+ nblk = 0;
+ while (nsectors) {
- blk = nblk++;
- dprintf("querying block %u\n", blk);
- if ( ioctl(fd, FIBMAP, &blk) )
- return -1;
+ blk = nblk++;
+ dprintf("querying block %u\n", blk);
+ if (ioctl(fd, FIBMAP, &blk))
+ return -1;
- blk *= blksize;
- for ( i = 0 ; i < blksize ; i++ ) {
- if ( !nsectors )
- return 0;
+ blk *= blksize;
+ for (i = 0; i < blksize; i++) {
+ if (!nsectors)
+ return 0;
- dprintf("Sector: %10u\n", blk);
- *sectors++ = blk++;
- nsectors--;
+ dprintf("Sector: %10u\n", blk);
+ *sectors++ = blk++;
+ nsectors--;
+ }
}
- }
- return 0;
+ return 0;
}
/*
@@ -262,29 +256,28 @@ sectmap(int fd, uint32_t *sectors, int nsectors)
*/
uint64_t get_size(int devfd)
{
- uint64_t bytes;
- uint32_t sects;
- struct stat st;
+ uint64_t bytes;
+ uint32_t sects;
+ struct stat st;
#ifdef BLKGETSIZE64
- if ( !ioctl(devfd, BLKGETSIZE64, &bytes) )
- return bytes;
+ 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;
+ 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;
+ uint64_t bytes;
+ struct hd_geometry g;
};
/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry
@@ -292,59 +285,59 @@ struct geometry_table {
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} }
+ {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)
+int get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
{
- struct floppy_struct fd_str;
- const struct geometry_table *gp;
+ struct floppy_struct fd_str;
+ const struct geometry_table *gp;
- memset(geo, 0, sizeof *geo);
+ memset(geo, 0, sizeof *geo);
- 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;
- }
+ 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. 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. */
+ /* 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;
+ 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);
+ 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;
+ return 1;
}
/*
@@ -352,106 +345,105 @@ get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
* Map the file and put the map in the boot sector and file.
* Stick the "current directory" inode number into the file.
*/
-void
-patch_file_and_bootblock(int fd, int dirfd, int devfd)
+void patch_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;
- uint32_t *wp;
- struct boot_sector *bs;
- struct patch_area *patcharea;
- int i, dw, nptrs;
- 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);
-
- bs = (struct boot_sector *)boot_block;
-
- totalsectors = totalbytes >> SECTOR_SHIFT;
- if ( totalsectors >= 65536 ) {
- set_16(&bs->bsSectors, 0);
- } else {
- set_16(&bs->bsSectors, totalsectors);
- }
- set_32(&bs->bsHugeSectors, totalsectors);
-
- set_16(&bs->bsBytesPerSec, SECTOR_SIZE);
- set_16(&bs->bsSecPerTrack, geo.sectors);
- set_16(&bs->bsHeads, geo.heads);
- set_32(&bs->bsHiddenSecs, geo.start);
-
- /* If we're in RAID mode then patch the appropriate instruction;
- either way write the proper boot signature */
- i = get_16(&bs->bsSignature);
- if (opt.raid_mode)
- set_16((uint16_t *)(boot_block+i), 0x18CD); /* INT 18h */
-
- set_16(&bs->bsSignature, 0xAA55);
-
- /* Construct the boot file */
-
- 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(uint32_t)*nsect);
- if ( sectmap(fd, sectp, nsect) ) {
- perror("bmap");
- exit(1);
- }
+ struct stat dirst;
+ struct hd_geometry geo;
+ uint32_t *sectp;
+ uint64_t totalbytes, totalsectors;
+ int nsect;
+ uint32_t *wp;
+ struct boot_sector *bs;
+ struct patch_area *patcharea;
+ int i, dw, nptrs;
+ 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;
- /* First sector need pointer in boot sector */
- set_32(&bs->NextSector, *sectp++);
+ /* 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);
- /* Stupid mode? */
- if (opt.stupid_mode)
- set_16(&bs->MaxTransfer, 1);
+ bs = (struct boot_sector *)boot_block;
- /* Search for LDLINUX_MAGIC to find the patch area */
- for (wp = (uint32_t *)boot_image; get_32(wp) != LDLINUX_MAGIC; wp++);
- patcharea = (struct patch_area *)wp;
+ totalsectors = totalbytes >> SECTOR_SHIFT;
+ if (totalsectors >= 65536) {
+ set_16(&bs->bsSectors, 0);
+ } else {
+ set_16(&bs->bsSectors, totalsectors);
+ }
+ set_32(&bs->bsHugeSectors, totalsectors);
+
+ set_16(&bs->bsBytesPerSec, SECTOR_SIZE);
+ set_16(&bs->bsSecPerTrack, geo.sectors);
+ set_16(&bs->bsHeads, geo.heads);
+ set_32(&bs->bsHiddenSecs, geo.start);
+
+ /* If we're in RAID mode then patch the appropriate instruction;
+ either way write the proper boot signature */
+ i = get_16(&bs->bsSignature);
+ if (opt.raid_mode)
+ set_16((uint16_t *) (boot_block + i), 0x18CD); /* INT 18h */
+
+ set_16(&bs->bsSignature, 0xAA55);
+
+ /* Construct the boot file */
+
+ 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(uint32_t) * nsect);
+ if (sectmap(fd, sectp, nsect)) {
+ perror("bmap");
+ exit(1);
+ }
+
+ /* First sector need pointer in boot sector */
+ set_32(&bs->NextSector, *sectp++);
- /* Set up the totals */
- dw = boot_image_len >> 2; /* COMPLETE dwords, excluding ADV */
- set_16(&patcharea->data_sectors, nsect-2); /* -2 for the ADVs */
- set_16(&patcharea->adv_sectors, 2);
- set_32(&patcharea->dwords, dw);
- set_32(&patcharea->currentdir, dirst.st_ino);
+ /* Stupid mode? */
+ if (opt.stupid_mode)
+ set_16(&bs->MaxTransfer, 1);
- /* Set the sector pointers */
- wp = (uint32_t *)((char *)boot_image+get_16(&patcharea->secptroffset));
- nptrs = get_16(&patcharea->secptrcnt);
+ /* Search for LDLINUX_MAGIC to find the patch area */
+ for (wp = (uint32_t *) boot_image; get_32(wp) != LDLINUX_MAGIC; wp++) ;
+ patcharea = (struct patch_area *)wp;
- memset(wp, 0, nptrs*4);
- while ( nsect-- )
- set_32(wp++, *sectp++);
+ /* Set up the totals */
+ dw = boot_image_len >> 2; /* COMPLETE dwords, excluding ADV */
+ set_16(&patcharea->data_sectors, nsect - 2); /* -2 for the ADVs */
+ set_16(&patcharea->adv_sectors, 2);
+ set_32(&patcharea->dwords, dw);
+ set_32(&patcharea->currentdir, dirst.st_ino);
- /* Now produce a checksum */
- set_32(&patcharea->checksum, 0);
+ /* Set the sector pointers */
+ wp = (uint32_t *) ((char *)boot_image + get_16(&patcharea->secptroffset));
+ nptrs = get_16(&patcharea->secptrcnt);
- csum = LDLINUX_MAGIC;
- for (i = 0, wp = (uint32_t *)boot_image; i < dw; i++, wp++)
- csum -= get_32(wp); /* Negative checksum */
+ memset(wp, 0, nptrs * 4);
+ while (nsect--)
+ set_32(wp++, *sectp++);
- set_32(&patcharea->checksum, csum);
+ /* Now produce a checksum */
+ set_32(&patcharea->checksum, 0);
+
+ csum = LDLINUX_MAGIC;
+ for (i = 0, wp = (uint32_t *) boot_image; i < dw; i++, wp++)
+ csum -= get_32(wp); /* Negative checksum */
+
+ set_32(&patcharea->checksum, csum);
}
/*
@@ -459,139 +451,135 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
* Returns -1 on fatal errors, 0 if ADV is okay, and 1 if no valid
* ADV was found.
*/
-int
-read_adv(const char *path)
+int read_adv(const char *path)
{
- char *file;
- int fd = -1;
- struct stat st;
- int err = 0;
-
- asprintf(&file, "%s%sextlinux.sys",
- path,
- path[0] && path[strlen(path)-1] == '/' ? "" : "/");
-
- if ( !file ) {
- perror(program);
- return -1;
- }
-
- fd = open(file, O_RDONLY);
- if ( fd < 0 ) {
- if ( errno != ENOENT ) {
- err = -1;
+ char *file;
+ int fd = -1;
+ struct stat st;
+ int err = 0;
+
+ asprintf(&file, "%s%sextlinux.sys",
+ path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+
+ if (!file) {
+ perror(program);
+ return -1;
+ }
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ if (errno != ENOENT) {
+ err = -1;
+ } else {
+ syslinux_reset_adv(syslinux_adv);
+ }
+ } else if (fstat(fd, &st)) {
+ err = -1;
+ } else if (st.st_size < 2 * ADV_SIZE) {
+ /* Too small to be useful */
+ syslinux_reset_adv(syslinux_adv);
+ err = 0; /* Nothing to read... */
+ } else if (xpread(fd, syslinux_adv, 2 * ADV_SIZE,
+ st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
+ err = -1;
} else {
- syslinux_reset_adv(syslinux_adv);
- }
- } else if (fstat(fd, &st)) {
- err = -1;
- } else if (st.st_size < 2*ADV_SIZE) {
- /* Too small to be useful */
- syslinux_reset_adv(syslinux_adv);
- err = 0; /* Nothing to read... */
- } else if (xpread(fd, syslinux_adv, 2*ADV_SIZE,
- st.st_size-2*ADV_SIZE) != 2*ADV_SIZE) {
- err = -1;
- } else {
- /* We got it... maybe? */
- err = syslinux_validate_adv(syslinux_adv) ? 1 : 0;
- }
-
- if (err < 0)
- perror(file);
-
- if (fd >= 0)
- close(fd);
- if (file)
- free(file);
+ /* We got it... maybe? */
+ err = syslinux_validate_adv(syslinux_adv) ? 1 : 0;
+ }
- return err;
+ if (err < 0)
+ perror(file);
+
+ if (fd >= 0)
+ close(fd);
+ if (file)
+ free(file);
+
+ return err;
}
/*
* Update the ADV in an existing installation.
*/
-int
-write_adv(const char *path)
+int write_adv(const char *path)
{
- unsigned char advtmp[2*ADV_SIZE];
- char *file;
- int fd = -1;
- struct stat st, xst;
- int err = 0;
- int flags, nflags;
-
- asprintf(&file, "%s%sextlinux.sys",
- path,
- path[0] && path[strlen(path)-1] == '/' ? "" : "/");
-
- if ( !file ) {
- perror(program);
- return -1;
- }
-
- fd = open(file, O_RDONLY);
- if ( fd < 0 ) {
- err = -1;
- } else if (fstat(fd, &st)) {
- err = -1;
- } else if (st.st_size < 2*ADV_SIZE) {
- /* Too small to be useful */
- err = -2;
- } else if (xpread(fd, advtmp, 2*ADV_SIZE,
- st.st_size-2*ADV_SIZE) != 2*ADV_SIZE) {
- err = -1;
- } else {
- /* We got it... maybe? */
- err = syslinux_validate_adv(advtmp) ? -2 : 0;
- if (!err) {
- /* Got a good one, write our own ADV here */
- if (!ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) {
- nflags = flags & ~EXT2_IMMUTABLE_FL;
- if (nflags != flags)
- ioctl(fd, EXT2_IOC_SETFLAGS, &nflags);
- }
- if (!(st.st_mode & S_IWUSR))
- fchmod(fd, st.st_mode | S_IWUSR);
-
- /* Need to re-open read-write */
- close(fd);
- fd = open(file, O_RDWR|O_SYNC);
- if (fd < 0) {
+ unsigned char advtmp[2 * ADV_SIZE];
+ char *file;
+ int fd = -1;
+ struct stat st, xst;
+ int err = 0;
+ int flags, nflags;
+
+ asprintf(&file, "%s%sextlinux.sys",
+ path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+
+ if (!file) {
+ perror(program);
+ return -1;
+ }
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
err = -1;
- } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino ||
- xst.st_dev != st.st_dev || xst.st_size != st.st_size) {
- fprintf(stderr, "%s: race condition on write\n", file);
+ } else if (fstat(fd, &st)) {
+ err = -1;
+ } else if (st.st_size < 2 * ADV_SIZE) {
+ /* Too small to be useful */
err = -2;
- }
- /* Write our own version ... */
- if (xpwrite(fd, syslinux_adv, 2*ADV_SIZE,
- st.st_size-2*ADV_SIZE) != 2*ADV_SIZE) {
+ } else if (xpread(fd, advtmp, 2 * ADV_SIZE,
+ st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
err = -1;
- }
-
- sync();
-
- if (!(st.st_mode & S_IWUSR))
- fchmod(fd, st.st_mode);
-
- if (nflags != flags)
- ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
+ } else {
+ /* We got it... maybe? */
+ err = syslinux_validate_adv(advtmp) ? -2 : 0;
+ if (!err) {
+ /* Got a good one, write our own ADV here */
+ if (!ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) {
+ nflags = flags & ~EXT2_IMMUTABLE_FL;
+ if (nflags != flags)
+ ioctl(fd, EXT2_IOC_SETFLAGS, &nflags);
+ }
+ if (!(st.st_mode & S_IWUSR))
+ fchmod(fd, st.st_mode | S_IWUSR);
+
+ /* Need to re-open read-write */
+ close(fd);
+ fd = open(file, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ err = -1;
+ } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino ||
+ xst.st_dev != st.st_dev || xst.st_size != st.st_size) {
+ fprintf(stderr, "%s: race condition on write\n", file);
+ err = -2;
+ }
+ /* Write our own version ... */
+ if (xpwrite(fd, syslinux_adv, 2 * ADV_SIZE,
+ st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
+ err = -1;
+ }
+
+ sync();
+
+ if (!(st.st_mode & S_IWUSR))
+ fchmod(fd, st.st_mode);
+
+ if (nflags != flags)
+ ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
+ }
}
- }
- if (err == -2)
- fprintf(stderr, "%s: cannot write auxilliary data (need --update)?\n",
- file);
- else if (err == -1)
- perror(file);
+ if (err == -2)
+ fprintf(stderr, "%s: cannot write auxilliary data (need --update)?\n",
+ file);
+ else if (err == -1)
+ perror(file);
- if (fd >= 0)
- close(fd);
- if (file)
- free(file);
+ if (fd >= 0)
+ close(fd);
+ if (file)
+ free(file);
- return err;
+ return err;
}
/*
@@ -599,153 +587,151 @@ write_adv(const char *path)
*/
int modify_adv(void)
{
- int rv = 0;
-
- if (opt.set_once) {
- if (syslinux_setadv(ADV_BOOTONCE, strlen(opt.set_once), opt.set_once)) {
- fprintf(stderr, "%s: not enough space for boot-once command\n", program);
- rv = -1;
+ int rv = 0;
+
+ if (opt.set_once) {
+ if (syslinux_setadv(ADV_BOOTONCE, strlen(opt.set_once), opt.set_once)) {
+ fprintf(stderr, "%s: not enough space for boot-once command\n",
+ program);
+ rv = -1;
+ }
}
- }
- return rv;
+ return rv;
}
/*
* Install the boot block on the specified device.
* Must be run AFTER install_file()!
*/
-int
-install_bootblock(int fd, const char *device)
+int install_bootblock(int fd, const char *device)
{
- struct ext2_super_block sb;
+ struct ext2_super_block sb;
- if ( xpread(fd, &sb, sizeof sb, EXT2_SUPER_OFFSET) != sizeof sb ) {
- perror("reading superblock");
- return 1;
- }
+ 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 (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;
- }
+ if (xpwrite(fd, boot_block, boot_block_len, 0) != boot_block_len) {
+ perror("writing bootblock");
+ return 1;
+ }
- return 0;
+ return 0;
}
-int
-install_file(const char *path, int devfd, struct stat *rst)
+int install_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|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 */
- patch_file_and_bootblock(fd, dirfd, devfd);
-
- /* Write the first sector again - this relies on the file being
- overwritten in place! */
- if ( xpwrite(fd, boot_image, SECTOR_SIZE, 0) != SECTOR_SIZE ) {
- 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 )
+ 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 | 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 */
+ patch_file_and_bootblock(fd, dirfd, devfd);
+
+ /* Write the first sector again - this relies on the file being
+ overwritten in place! */
+ if (xpwrite(fd, boot_image, SECTOR_SIZE, 0) != SECTOR_SIZE) {
+ 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);
- if ( fd >= 0 )
close(fd);
+ return 0;
- return 1;
+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. */
-int
-already_installed(int devfd)
+int already_installed(int devfd)
{
- char buffer[8];
+ char buffer[8];
- xpread(devfd, buffer, 8, 3);
- return !memcmp(buffer, "EXTLINUX", 8);
+ xpread(devfd, buffer, 8, 3);
+ return !memcmp(buffer, "EXTLINUX", 8);
}
-
#ifdef __KLIBC__
static char devname_buf[64];
static void device_cleanup(void)
{
- unlink(devname_buf);
+ unlink(devname_buf);
}
#endif
@@ -753,237 +739,237 @@ static void device_cleanup(void)
Return 0 on valid, -1 on error. */
static int validate_device(const char *path, int devfd)
{
- struct stat pst, dst;
+ struct stat pst, dst;
- if (stat(path, &pst) || fstat(devfd, &dst))
- return -1;
+ if (stat(path, &pst) || fstat(devfd, &dst))
+ return -1;
- return (pst.st_dev == dst.st_rdev) ? 0 : -1;
+ 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;
-
- mtab = setmntent(mtab_file, "r");
- if (!mtab)
- return NULL;
-
- while ( (mnt = getmntent(mtab)) ) {
- if ( (!strcmp(mnt->mnt_type, "ext2") ||
- !strcmp(mnt->mnt_type, "ext3")) &&
- !stat(mnt->mnt_fsname, &dst) && dst.st_rdev == dev ) {
- devname = strdup(mnt->mnt_fsname);
- break;
- }
- }
- endmntent(mtab);
-
- return devname;
+ struct mntent *mnt;
+ struct stat dst;
+ FILE *mtab;
+ const char *devname = NULL;
+
+ mtab = setmntent(mtab_file, "r");
+ if (!mtab)
+ return NULL;
+
+ while ((mnt = getmntent(mtab))) {
+ if ((!strcmp(mnt->mnt_type, "ext2") ||
+ !strcmp(mnt->mnt_type, "ext3")) &&
+ !stat(mnt->mnt_fsname, &dst) && dst.st_rdev == dev) {
+ devname = strdup(mnt->mnt_fsname);
+ break;
+ }
+ }
+ endmntent(mtab);
+
+ return devname;
}
#endif
-int
-install_loader(const char *path, int update_only)
+int install_loader(const char *path, int update_only)
{
- struct stat st, fst;
- int devfd, rv;
- const char *devname = NULL;
- struct statfs sfs;
-
- if ( stat(path, &st) || !S_ISDIR(st.st_mode) ) {
- fprintf(stderr, "%s: Not a directory: %s\n", program, path);
- return 1;
- }
+ struct stat st, fst;
+ int devfd, rv;
+ const char *devname = NULL;
+ struct statfs sfs;
+
+ 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 (statfs(path, &sfs)) {
+ fprintf(stderr, "%s: statfs %s: %s\n", program, path, strerror(errno));
+ return 1;
+ }
- if ( sfs.f_type != EXT2_SUPER_MAGIC ) {
- fprintf(stderr, "%s: not an ext2/ext3 filesystem: %s\n", program, path);
- return 1;
- }
+ if (sfs.f_type != EXT2_SUPER_MAGIC) {
+ fprintf(stderr, "%s: not an ext2/ext3 filesystem: %s\n", program, path);
+ return 1;
+ }
- devfd = -1;
+ devfd = -1;
#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));
+ /* 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 1;
- }
+ if (mknod(devname_buf, S_IFBLK | 0600, st.st_dev)) {
+ fprintf(stderr, "%s: cannot create device %s\n", program, devname);
+ return 1;
+ }
- atexit(device_cleanup); /* unlink the device node on exit */
- devname = devname_buf;
+ atexit(device_cleanup); /* unlink the device node on exit */
+ devname = devname_buf;
#else
- devname = find_device("/proc/mounts", st.st_dev);
- if (!devname) {
- /* Didn't find it in /proc/mounts, try /etc/mtab */
- devname = find_device("/etc/mtab", st.st_dev);
- }
- if (!devname) {
- fprintf(stderr, "%s: cannot find device for path %s\n", program, path);
- return 1;
- }
+ devname = find_device("/proc/mounts", st.st_dev);
+ if (!devname) {
+ /* Didn't find it in /proc/mounts, try /etc/mtab */
+ devname = find_device("/etc/mtab", st.st_dev);
+ }
+ 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);
+ fprintf(stderr, "%s is device %s\n", path, devname);
#endif
- if ( (devfd = open(devname, O_RDWR|O_SYNC)) < 0 ) {
- fprintf(stderr, "%s: cannot open device %s\n", program, devname);
- return 1;
- }
+ 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);
- 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);
+ return 1;
+ }
- if ( update_only && !already_installed(devfd) ) {
- fprintf(stderr, "%s: no previous extlinux boot sector found\n", program);
- return 1;
- }
+ if (update_only && !already_installed(devfd)) {
+ fprintf(stderr, "%s: no previous extlinux boot sector found\n",
+ program);
+ return 1;
+ }
- /* Read a pre-existing ADV, if already installed */
- if (opt.reset_adv)
- syslinux_reset_adv(syslinux_adv);
- else if (read_adv(path) < 0)
- return 1;
+ /* Read a pre-existing ADV, if already installed */
+ if (opt.reset_adv)
+ syslinux_reset_adv(syslinux_adv);
+ else if (read_adv(path) < 0)
+ return 1;
- if (modify_adv() < 0)
- return 1;
+ if (modify_adv() < 0)
+ return 1;
- /* Install extlinux.sys */
- if (install_file(path, devfd, &fst))
- return 1;
+ /* Install extlinux.sys */
+ if (install_file(path, devfd, &fst))
+ return 1;
- if ( fst.st_dev != st.st_dev ) {
- fprintf(stderr, "%s: file system changed under us - aborting!\n",
- program);
- return 1;
- }
+ 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, devname);
- close(devfd);
- sync();
+ sync();
+ rv = install_bootblock(devfd, devname);
+ close(devfd);
+ sync();
- return rv;
+ return rv;
}
/*
* Modify the ADV of an existing installation
*/
-int
-modify_existing_adv(const char *path)
+int modify_existing_adv(const char *path)
{
- if (opt.reset_adv)
- syslinux_reset_adv(syslinux_adv);
- else if (read_adv(path) < 0)
- return 1;
+ if (opt.reset_adv)
+ syslinux_reset_adv(syslinux_adv);
+ else if (read_adv(path) < 0)
+ return 1;
- if (modify_adv() < 0)
- return 1;
+ if (modify_adv() < 0)
+ return 1;
- if (write_adv(path) < 0)
- return 1;
+ if (write_adv(path) < 0)
+ return 1;
- return 0;
+ return 0;
}
-int
-main(int argc, char *argv[])
+int main(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 'r':
- opt.raid_mode = 1;
- break;
- case 's':
- opt.stupid_mode = 1;
- break;
- case 'i':
- update_only = 0;
- break;
- case 'u':
- case 'U':
- update_only = 1;
- break;
- case 'h':
- usage(0);
- break;
- case 'o':
- opt.set_once = optarg;
- break;
- case 'O':
- opt.set_once = "";
- break;
- case OPT_RESET_ADV:
- opt.reset_adv = 1;
- break;
- case 'v':
- fputs("extlinux " VERSION_STR
- " Copyright 1994-" YEAR_STR " H. Peter Anvin \n", stderr);
- exit(0);
- default:
- usage(EX_USAGE);
- }
- }
-
- directory = argv[optind];
-
- if ( !directory )
- usage(EX_USAGE);
-
- if ( update_only == -1 ) {
- if (opt.reset_adv || opt.set_once) {
- return modify_existing_adv(directory);
- } else {
- usage(EX_USAGE);
+ 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 'r':
+ opt.raid_mode = 1;
+ break;
+ case 's':
+ opt.stupid_mode = 1;
+ break;
+ case 'i':
+ update_only = 0;
+ break;
+ case 'u':
+ case 'U':
+ update_only = 1;
+ break;
+ case 'h':
+ usage(0);
+ break;
+ case 'o':
+ opt.set_once = optarg;
+ break;
+ case 'O':
+ opt.set_once = "";
+ break;
+ case OPT_RESET_ADV:
+ opt.reset_adv = 1;
+ break;
+ case 'v':
+ fputs("extlinux " VERSION_STR
+ " Copyright 1994-" YEAR_STR " H. Peter Anvin \n", stderr);
+ exit(0);
+ default:
+ usage(EX_USAGE);
+ }
+ }
+
+ directory = argv[optind];
+
+ if (!directory)
+ usage(EX_USAGE);
+
+ if (update_only == -1) {
+ if (opt.reset_adv || opt.set_once) {
+ return modify_existing_adv(directory);
+ } else {
+ usage(EX_USAGE);
+ }
}
- }
- return install_loader(directory, update_only);
+ return install_loader(directory, update_only);
}