/* ----------------------------------------------------------------------- *
*
* Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
- * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ * 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
#include <linux/hdreg.h> /* Hard disk geometry */
#define statfs _kernel_statfs /* HACK to deal with broken 2.4 distros */
#include <linux/fs.h> /* FIGETBSZ, FIBMAP */
+#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES */
+#ifndef FAT_IOCTL_SET_ATTRIBUTES
+# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, uint32_t)
+#endif
#undef statfs
+#undef SECTOR_SIZE /* Garbage from <linux/msdos_fs.h> */
#include "ext2_fs.h"
#include "btrfs.h"
/* Global option handling */
/* Global fs_type for handling fat, ext2/3/4 and btrfs */
-#define EXT2 1
-#define BTRFS 2
-#define VFAT 3
-int fs_type;
+static enum filesystem {
+ NONE,
+ EXT2,
+ BTRFS,
+ VFAT,
+} fs_type;
const char *program;
}
/*
+ * Set and clear file attributes
+ */
+static void clear_attributes(int fd)
+{
+ struct stat st;
+
+ if (!fstat(fd, &st)) {
+ switch (fs_type) {
+ case EXT2:
+ {
+ int flags;
+
+ if (!ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) {
+ flags &= ~EXT2_IMMUTABLE_FL;
+ ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
+ }
+ break;
+ }
+ case VFAT:
+ {
+ uint32_t attr = 0x00; /* Clear all attributes */
+ ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
+ break;
+ }
+ default:
+ break;
+ }
+ fchmod(fd, st.st_mode | S_IWUSR);
+ }
+}
+
+static void set_attributes(int fd)
+{
+ struct stat st;
+
+ if (!fstat(fd, &st)) {
+ fchmod(fd, st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH));
+ switch (fs_type) {
+ case EXT2:
+ {
+ int flags;
+
+ if (st.st_uid == 0 && !ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) {
+ flags |= EXT2_IMMUTABLE_FL;
+ ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
+ }
+ break;
+ }
+ case VFAT:
+ {
+ uint32_t attr = 0x07; /* Hidden+System+Readonly */
+ ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+/*
* Produce file map
*/
int sectmap(int fd, uint32_t * sectors, int nsectors)
int fd = -1;
struct stat st, xst;
int err = 0;
- int flags, nflags;
if (fs_type == BTRFS) { /* btrfs "extlinux.sys" is in 64k blank area */
if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE,
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);
+ clear_attributes(fd);
/* Need to re-open read-write */
close(fd);
}
sync();
-
- if (!(st.st_mode & S_IWUSR))
- fchmod(fd, st.st_mode);
-
- if (nflags != flags)
- ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
+ set_attributes(fd);
}
}
int ext2_fat_install_file(const char *path, int devfd, struct stat *rst)
{
char *file;
- int fd = -1, dirfd = -1, flags;
- struct stat st;
+ int fd = -1, dirfd = -1;
int modbytes;
asprintf(&file, "%s%sextlinux.sys",
perror(file);
goto bail;
}
- } else if (fs_type == EXT2) {
- /* 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);
- }
+ } else {
+ clear_attributes(fd);
}
close(fd);
/* 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);
- }
- }
+ set_attributes(fd);
if (fstat(fd, rst)) {
perror(file);