| /* |
| * Copyright 1996-2004 by Hans Reiser, licensing governed by |
| * reiserfsprogs/README |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| # include <config.h> |
| #endif |
| |
| #include "util/device.h" |
| #include "util/print.h" |
| #include "util/mntent.h" |
| #include "misc/device.h" |
| #include "misc/types.h" |
| #include "misc/misc.h" |
| #include "reiserfs/print.h" |
| |
| #include <linux/hdreg.h> |
| #include <sys/ioctl.h> |
| #include <sys/stat.h> |
| #include <mntent.h> |
| #include <unistd.h> |
| #include <signal.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <utime.h> |
| #include <assert.h> |
| |
| #define reiserfs_confirm(force) \ |
| if (force < 1) {\ |
| /* avoid formatting it without being forced */\ |
| reiserfs_warning (stderr, "Use -f to force over\n");\ |
| return 0;\ |
| }\ |
| if (force < 2) {\ |
| if (!util_user_confirmed (stderr, "Continue (y/n):", "y\n"))\ |
| return 0;\ |
| }\ |
| |
| /* 0 - dma is not supported, scsi or regular file */ |
| /* 1 - xt drive */ |
| /* 2 - ide drive */ |
| static void get_dma_support(util_device_dma_t *dma_info, struct stat *st){ |
| if (S_ISREG(st->st_mode)) |
| st->st_rdev = st->st_dev; |
| |
| if (IDE_DISK_MAJOR(major(st->st_rdev))) { |
| dma_info->support_type = 2; |
| return; |
| } |
| |
| #ifdef XT_DISK_MAJOR |
| if (major(st->st_rdev) == XT_DISK_MAJOR) { |
| dma_info->support_type = 1; |
| return; |
| } |
| #endif |
| dma_info->support_type = 0; |
| } |
| |
| /* |
| * Return values: |
| * 0 - ok; |
| * 1 - preparation cannot be done |
| * -1 - preparation failed |
| */ |
| |
| int util_device_dma_prep(util_device_dma_t *dma_info) { |
| struct stat st; |
| char buf[4096]; |
| dev_t rdev; |
| int rem; |
| int res; |
| |
| #ifndef HDIO_GET_DMA |
| return -1; |
| #endif |
| |
| if (fstat(dma_info->fd, &st)) |
| misc_die("stat on device failed\n"); |
| |
| get_dma_support(dma_info, &st); |
| |
| /* dma should be supported */ |
| if (dma_info->support_type == 0) |
| return 1; |
| |
| if (dma_info->support_type == 1) |
| return 0; |
| |
| rdev = dma_info->st_rdev = st.st_rdev; |
| |
| /* If it is the whole device? no preparation needed then. */ |
| if ((rem = (minor(rdev) % 64)) == 0) |
| return 0; |
| |
| dma_info->st_rdev -= rem; |
| |
| strcpy(buf, "/dev"); |
| |
| if ((res = misc_dir_walk(buf, misc_device_rdev_match, &dma_info->st_rdev)) <= 0) { |
| dma_info->st_rdev += rem; |
| dma_info->support_type = 1; |
| return res; |
| } |
| |
| /* Matched block device file found. Open it. */ |
| dma_info->fd = open(buf, O_RDONLY |
| #if defined(O_LARGEFILE) |
| | O_LARGEFILE |
| #endif |
| ); |
| |
| return 0; |
| } |
| |
| static int is_dma_on (int fd) { |
| #ifdef HDIO_GET_DMA |
| static long parm; |
| if (ioctl(fd, HDIO_GET_DMA, &parm)) |
| return -1; |
| else |
| return parm; |
| #endif |
| return 0; |
| } |
| |
| |
| static __u64 dma_speed(int fd, int support_type) { |
| static struct hd_driveid id; |
| __u64 speed = 0; |
| |
| if (support_type != 2) |
| return 0; |
| |
| #ifdef HDIO_OBSOLETE_IDENTITY |
| if (!ioctl(fd, HDIO_GET_IDENTITY, &id) || |
| !ioctl(fd, HDIO_OBSOLETE_IDENTITY)) { |
| #else |
| if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) { |
| #endif |
| speed |= (__u64)id.dma_1word & ~(__u64)0xff; |
| speed |= ((__u64)id.dma_mword & ~(__u64)0xff) << 16; |
| speed |= ((__u64)id.dma_ultra & ~(__u64)0xff) << 32; |
| } else if (errno == -ENOMSG) |
| return -1; |
| else |
| return -1; |
| |
| return speed; |
| } |
| |
| int util_device_get_dma(util_device_dma_t *dma_info) { |
| if ((dma_info->dma = is_dma_on(dma_info->fd)) == -1) |
| return -1; |
| if ((dma_info->speed = dma_speed(dma_info->fd, dma_info->support_type)) == (__u64)-1) |
| return -1; |
| return 0; |
| } |
| |
| void util_device_dma_fini(int fd, util_device_dma_t *dma_info) { |
| signal(SIGALRM, SIG_IGN); |
| if (dma_info->fd && fd != dma_info->fd) |
| close(dma_info->fd); |
| } |
| |
| FILE * util_file_open (char * filename, char * option) |
| { |
| FILE * fp = fopen (filename, option); |
| if (!fp) { |
| reiserfs_warning (stderr, "util_file_open: could not " |
| "open file %s\n", filename); |
| return 0; |
| } |
| reiserfs_warning (stderr, "Temp file opened by fsck: " |
| "\"%s\" .. \n", filename); |
| return fp; |
| } |
| |
| /* we only can use a file for filesystem or journal if it is either not |
| mounted block device or regular file and we are forced to use it */ |
| int util_device_formatable (char * device_name, int force) |
| { |
| mode_t mode; |
| dev_t rdev; |
| |
| if (util_device_mounted(device_name) > 0) { |
| /* device looks mounted */ |
| reiserfs_warning (stderr, "'%s' looks mounted.", device_name); |
| reiserfs_confirm (force); |
| } |
| |
| mode = misc_device_mode(device_name); |
| rdev = misc_device_rdev(device_name); |
| |
| if (!S_ISBLK (mode)) { |
| /* file is not a block device */ |
| reiserfs_warning (stderr, "%s is not a block special device\n", device_name); |
| reiserfs_confirm (force); |
| } else { |
| if ((IDE_DISK_MAJOR (major(rdev)) && minor(rdev) % 64 == 0) || |
| (SCSI_BLK_MAJOR (major(rdev)) && minor(rdev) % 16 == 0)) { |
| /* /dev/hda or similar */ |
| reiserfs_warning (stderr, "%s is entire device, not just one partition!\n", |
| device_name); |
| reiserfs_confirm (force); |
| } |
| } |
| |
| return 1; |
| } |
| |
| int util_root_mounted(char *device) { |
| struct stat rootst, devst; |
| |
| assert(device != NULL); |
| |
| if (stat("/", &rootst) != 0) |
| return -1; |
| |
| if (stat(device, &devst) != 0) |
| return -1; |
| |
| if (!S_ISBLK(devst.st_mode) || |
| devst.st_rdev != rootst.st_dev) |
| return 0; |
| |
| return 1; |
| } |
| |
| int util_device_mounted(char *device) { |
| struct mntent *mnt; |
| |
| /* Check for the "/" first to avoid any possible problem with |
| reflecting the root fs info in mtab files. */ |
| if (util_root_mounted(device) == 1) { |
| return util_file_ro("/") ? MF_RO : MF_RW; |
| } |
| |
| /* Lookup the mount entry. */ |
| if ((mnt = util_mntent(device)) == NULL) { |
| return MF_NOT_MOUNTED; |
| } else if (mnt == INVAL_PTR) { |
| return 0; |
| } |
| |
| return hasmntopt(mnt, MNTOPT_RO) ? MF_RO : MF_RW; |
| } |
| |
| int util_file_ro(char *file) { |
| if (utime(file, 0) == -1) { |
| if (errno == EROFS) |
| return 1; |
| } |
| |
| return 0; |
| } |
| |