/* * Copyright 1996-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #ifdef HAVE_CONFIG_H # include #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 #include #include #include #include #include #include #include #include #include #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; }