1*8044SWilliam.Kucharski@Sun.COM /* device.c - Some helper functions for OS devices and BIOS drives */ 2*8044SWilliam.Kucharski@Sun.COM /* 3*8044SWilliam.Kucharski@Sun.COM * GRUB -- GRand Unified Bootloader 4*8044SWilliam.Kucharski@Sun.COM * Copyright (C) 1999,2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc. 5*8044SWilliam.Kucharski@Sun.COM * 6*8044SWilliam.Kucharski@Sun.COM * This program is free software; you can redistribute it and/or modify 7*8044SWilliam.Kucharski@Sun.COM * it under the terms of the GNU General Public License as published by 8*8044SWilliam.Kucharski@Sun.COM * the Free Software Foundation; either version 2 of the License, or 9*8044SWilliam.Kucharski@Sun.COM * (at your option) any later version. 10*8044SWilliam.Kucharski@Sun.COM * 11*8044SWilliam.Kucharski@Sun.COM * This program is distributed in the hope that it will be useful, 12*8044SWilliam.Kucharski@Sun.COM * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*8044SWilliam.Kucharski@Sun.COM * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*8044SWilliam.Kucharski@Sun.COM * GNU General Public License for more details. 15*8044SWilliam.Kucharski@Sun.COM * 16*8044SWilliam.Kucharski@Sun.COM * You should have received a copy of the GNU General Public License 17*8044SWilliam.Kucharski@Sun.COM * along with this program; if not, write to the Free Software 18*8044SWilliam.Kucharski@Sun.COM * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*8044SWilliam.Kucharski@Sun.COM */ 20*8044SWilliam.Kucharski@Sun.COM 21*8044SWilliam.Kucharski@Sun.COM /* Try to use glibc's transparant LFS support. */ 22*8044SWilliam.Kucharski@Sun.COM #define _LARGEFILE_SOURCE 1 23*8044SWilliam.Kucharski@Sun.COM /* lseek becomes synonymous with lseek64. */ 24*8044SWilliam.Kucharski@Sun.COM #define _FILE_OFFSET_BITS 64 25*8044SWilliam.Kucharski@Sun.COM 26*8044SWilliam.Kucharski@Sun.COM #include <stdio.h> 27*8044SWilliam.Kucharski@Sun.COM #include <stdlib.h> 28*8044SWilliam.Kucharski@Sun.COM #include <string.h> 29*8044SWilliam.Kucharski@Sun.COM #include <ctype.h> 30*8044SWilliam.Kucharski@Sun.COM #include <assert.h> 31*8044SWilliam.Kucharski@Sun.COM #include <unistd.h> 32*8044SWilliam.Kucharski@Sun.COM #include <sys/types.h> 33*8044SWilliam.Kucharski@Sun.COM #include <sys/stat.h> 34*8044SWilliam.Kucharski@Sun.COM #include <fcntl.h> 35*8044SWilliam.Kucharski@Sun.COM #include <errno.h> 36*8044SWilliam.Kucharski@Sun.COM #include <limits.h> 37*8044SWilliam.Kucharski@Sun.COM #include <stdarg.h> 38*8044SWilliam.Kucharski@Sun.COM 39*8044SWilliam.Kucharski@Sun.COM #ifdef __linux__ 40*8044SWilliam.Kucharski@Sun.COM # if !defined(__GLIBC__) || \ 41*8044SWilliam.Kucharski@Sun.COM ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) 42*8044SWilliam.Kucharski@Sun.COM /* Maybe libc doesn't have large file support. */ 43*8044SWilliam.Kucharski@Sun.COM # include <linux/unistd.h> /* _llseek */ 44*8044SWilliam.Kucharski@Sun.COM # endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */ 45*8044SWilliam.Kucharski@Sun.COM # include <sys/ioctl.h> /* ioctl */ 46*8044SWilliam.Kucharski@Sun.COM # ifndef HDIO_GETGEO 47*8044SWilliam.Kucharski@Sun.COM # define HDIO_GETGEO 0x0301 /* get device geometry */ 48*8044SWilliam.Kucharski@Sun.COM /* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is 49*8044SWilliam.Kucharski@Sun.COM defined. */ 50*8044SWilliam.Kucharski@Sun.COM struct hd_geometry 51*8044SWilliam.Kucharski@Sun.COM { 52*8044SWilliam.Kucharski@Sun.COM unsigned char heads; 53*8044SWilliam.Kucharski@Sun.COM unsigned char sectors; 54*8044SWilliam.Kucharski@Sun.COM unsigned short cylinders; 55*8044SWilliam.Kucharski@Sun.COM unsigned long start; 56*8044SWilliam.Kucharski@Sun.COM }; 57*8044SWilliam.Kucharski@Sun.COM # endif /* ! HDIO_GETGEO */ 58*8044SWilliam.Kucharski@Sun.COM # ifndef FLOPPY_MAJOR 59*8044SWilliam.Kucharski@Sun.COM # define FLOPPY_MAJOR 2 /* the major number for floppy */ 60*8044SWilliam.Kucharski@Sun.COM # endif /* ! FLOPPY_MAJOR */ 61*8044SWilliam.Kucharski@Sun.COM # ifndef MAJOR 62*8044SWilliam.Kucharski@Sun.COM # define MAJOR(dev) \ 63*8044SWilliam.Kucharski@Sun.COM ({ \ 64*8044SWilliam.Kucharski@Sun.COM unsigned long long __dev = (dev); \ 65*8044SWilliam.Kucharski@Sun.COM (unsigned) ((__dev >> 8) & 0xfff) \ 66*8044SWilliam.Kucharski@Sun.COM | ((unsigned int) (__dev >> 32) & ~0xfff); \ 67*8044SWilliam.Kucharski@Sun.COM }) 68*8044SWilliam.Kucharski@Sun.COM # endif /* ! MAJOR */ 69*8044SWilliam.Kucharski@Sun.COM # ifndef CDROM_GET_CAPABILITY 70*8044SWilliam.Kucharski@Sun.COM # define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */ 71*8044SWilliam.Kucharski@Sun.COM # endif /* ! CDROM_GET_CAPABILITY */ 72*8044SWilliam.Kucharski@Sun.COM # ifndef BLKGETSIZE 73*8044SWilliam.Kucharski@Sun.COM # define BLKGETSIZE _IO(0x12,96) /* return device size */ 74*8044SWilliam.Kucharski@Sun.COM # endif /* ! BLKGETSIZE */ 75*8044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */ 76*8044SWilliam.Kucharski@Sun.COM 77*8044SWilliam.Kucharski@Sun.COM /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with 78*8044SWilliam.Kucharski@Sun.COM kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */ 79*8044SWilliam.Kucharski@Sun.COM #if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__) 80*8044SWilliam.Kucharski@Sun.COM # define __FreeBSD_kernel__ 81*8044SWilliam.Kucharski@Sun.COM #endif 82*8044SWilliam.Kucharski@Sun.COM #ifdef __FreeBSD_kernel__ 83*8044SWilliam.Kucharski@Sun.COM /* Obtain version of kFreeBSD headers */ 84*8044SWilliam.Kucharski@Sun.COM # include <osreldate.h> 85*8044SWilliam.Kucharski@Sun.COM # ifndef __FreeBSD_kernel_version 86*8044SWilliam.Kucharski@Sun.COM # define __FreeBSD_kernel_version __FreeBSD_version 87*8044SWilliam.Kucharski@Sun.COM # endif 88*8044SWilliam.Kucharski@Sun.COM 89*8044SWilliam.Kucharski@Sun.COM /* Runtime detection of kernel */ 90*8044SWilliam.Kucharski@Sun.COM # include <sys/utsname.h> 91*8044SWilliam.Kucharski@Sun.COM int 92*8044SWilliam.Kucharski@Sun.COM get_kfreebsd_version () 93*8044SWilliam.Kucharski@Sun.COM { 94*8044SWilliam.Kucharski@Sun.COM struct utsname uts; 95*8044SWilliam.Kucharski@Sun.COM int major; int minor, v[2]; 96*8044SWilliam.Kucharski@Sun.COM 97*8044SWilliam.Kucharski@Sun.COM uname (&uts); 98*8044SWilliam.Kucharski@Sun.COM sscanf (uts.release, "%d.%d", &major, &minor); 99*8044SWilliam.Kucharski@Sun.COM 100*8044SWilliam.Kucharski@Sun.COM if (major >= 9) 101*8044SWilliam.Kucharski@Sun.COM major = 9; 102*8044SWilliam.Kucharski@Sun.COM if (major >= 5) 103*8044SWilliam.Kucharski@Sun.COM { 104*8044SWilliam.Kucharski@Sun.COM v[0] = minor/10; v[1] = minor%10; 105*8044SWilliam.Kucharski@Sun.COM } 106*8044SWilliam.Kucharski@Sun.COM else 107*8044SWilliam.Kucharski@Sun.COM { 108*8044SWilliam.Kucharski@Sun.COM v[0] = minor%10; v[1] = minor/10; 109*8044SWilliam.Kucharski@Sun.COM } 110*8044SWilliam.Kucharski@Sun.COM return major*100000+v[0]*10000+v[1]*1000; 111*8044SWilliam.Kucharski@Sun.COM } 112*8044SWilliam.Kucharski@Sun.COM #endif /* __FreeBSD_kernel__ */ 113*8044SWilliam.Kucharski@Sun.COM 114*8044SWilliam.Kucharski@Sun.COM #if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) 115*8044SWilliam.Kucharski@Sun.COM # include <sys/ioctl.h> /* ioctl */ 116*8044SWilliam.Kucharski@Sun.COM # include <sys/disklabel.h> 117*8044SWilliam.Kucharski@Sun.COM # include <sys/cdio.h> /* CDIOCCLRDEBUG */ 118*8044SWilliam.Kucharski@Sun.COM # if defined(__FreeBSD_kernel__) 119*8044SWilliam.Kucharski@Sun.COM # include <sys/param.h> 120*8044SWilliam.Kucharski@Sun.COM # if __FreeBSD_kernel_version >= 500040 121*8044SWilliam.Kucharski@Sun.COM # include <sys/disk.h> 122*8044SWilliam.Kucharski@Sun.COM # endif 123*8044SWilliam.Kucharski@Sun.COM # endif /* __FreeBSD_kernel__ */ 124*8044SWilliam.Kucharski@Sun.COM #endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */ 125*8044SWilliam.Kucharski@Sun.COM 126*8044SWilliam.Kucharski@Sun.COM #if defined(__sun) 127*8044SWilliam.Kucharski@Sun.COM # include <sys/dkio.h> 128*8044SWilliam.Kucharski@Sun.COM #endif /* __sun */ 129*8044SWilliam.Kucharski@Sun.COM 130*8044SWilliam.Kucharski@Sun.COM #ifdef HAVE_OPENDISK 131*8044SWilliam.Kucharski@Sun.COM # include <util.h> 132*8044SWilliam.Kucharski@Sun.COM #endif /* HAVE_OPENDISK */ 133*8044SWilliam.Kucharski@Sun.COM 134*8044SWilliam.Kucharski@Sun.COM #define WITHOUT_LIBC_STUBS 1 135*8044SWilliam.Kucharski@Sun.COM #include <shared.h> 136*8044SWilliam.Kucharski@Sun.COM #include <device.h> 137*8044SWilliam.Kucharski@Sun.COM 138*8044SWilliam.Kucharski@Sun.COM /* Get the geometry of a drive DRIVE. */ 139*8044SWilliam.Kucharski@Sun.COM void 140*8044SWilliam.Kucharski@Sun.COM get_drive_geometry (struct geometry *geom, char **map, int drive) 141*8044SWilliam.Kucharski@Sun.COM { 142*8044SWilliam.Kucharski@Sun.COM int fd; 143*8044SWilliam.Kucharski@Sun.COM 144*8044SWilliam.Kucharski@Sun.COM if (geom->flags == -1) 145*8044SWilliam.Kucharski@Sun.COM { 146*8044SWilliam.Kucharski@Sun.COM fd = open (map[drive], O_RDONLY); 147*8044SWilliam.Kucharski@Sun.COM assert (fd >= 0); 148*8044SWilliam.Kucharski@Sun.COM } 149*8044SWilliam.Kucharski@Sun.COM else 150*8044SWilliam.Kucharski@Sun.COM fd = geom->flags; 151*8044SWilliam.Kucharski@Sun.COM 152*8044SWilliam.Kucharski@Sun.COM /* XXX This is the default size. */ 153*8044SWilliam.Kucharski@Sun.COM geom->sector_size = SECTOR_SIZE; 154*8044SWilliam.Kucharski@Sun.COM 155*8044SWilliam.Kucharski@Sun.COM #if defined(__linux__) 156*8044SWilliam.Kucharski@Sun.COM /* Linux */ 157*8044SWilliam.Kucharski@Sun.COM { 158*8044SWilliam.Kucharski@Sun.COM struct hd_geometry hdg; 159*8044SWilliam.Kucharski@Sun.COM unsigned long nr; 160*8044SWilliam.Kucharski@Sun.COM 161*8044SWilliam.Kucharski@Sun.COM if (ioctl (fd, HDIO_GETGEO, &hdg)) 162*8044SWilliam.Kucharski@Sun.COM goto fail; 163*8044SWilliam.Kucharski@Sun.COM 164*8044SWilliam.Kucharski@Sun.COM if (ioctl (fd, BLKGETSIZE, &nr)) 165*8044SWilliam.Kucharski@Sun.COM goto fail; 166*8044SWilliam.Kucharski@Sun.COM 167*8044SWilliam.Kucharski@Sun.COM /* Got the geometry, so save it. */ 168*8044SWilliam.Kucharski@Sun.COM geom->cylinders = hdg.cylinders; 169*8044SWilliam.Kucharski@Sun.COM geom->heads = hdg.heads; 170*8044SWilliam.Kucharski@Sun.COM geom->sectors = hdg.sectors; 171*8044SWilliam.Kucharski@Sun.COM geom->total_sectors = nr; 172*8044SWilliam.Kucharski@Sun.COM 173*8044SWilliam.Kucharski@Sun.COM goto success; 174*8044SWilliam.Kucharski@Sun.COM } 175*8044SWilliam.Kucharski@Sun.COM 176*8044SWilliam.Kucharski@Sun.COM #elif defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) 177*8044SWilliam.Kucharski@Sun.COM # if defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version >= 500040 178*8044SWilliam.Kucharski@Sun.COM /* kFreeBSD version 5 or later */ 179*8044SWilliam.Kucharski@Sun.COM if (get_kfreebsd_version () >= 500040) 180*8044SWilliam.Kucharski@Sun.COM { 181*8044SWilliam.Kucharski@Sun.COM unsigned int sector_size; 182*8044SWilliam.Kucharski@Sun.COM off_t media_size; 183*8044SWilliam.Kucharski@Sun.COM unsigned int tmp; 184*8044SWilliam.Kucharski@Sun.COM 185*8044SWilliam.Kucharski@Sun.COM if(ioctl (fd, DIOCGSECTORSIZE, §or_size) != 0) 186*8044SWilliam.Kucharski@Sun.COM sector_size = 512; 187*8044SWilliam.Kucharski@Sun.COM 188*8044SWilliam.Kucharski@Sun.COM if (ioctl (fd, DIOCGMEDIASIZE, &media_size) != 0) 189*8044SWilliam.Kucharski@Sun.COM goto fail; 190*8044SWilliam.Kucharski@Sun.COM 191*8044SWilliam.Kucharski@Sun.COM geom->total_sectors = media_size / sector_size; 192*8044SWilliam.Kucharski@Sun.COM 193*8044SWilliam.Kucharski@Sun.COM if (ioctl (fd, DIOCGFWSECTORS, &tmp) == 0) 194*8044SWilliam.Kucharski@Sun.COM geom->sectors = tmp; 195*8044SWilliam.Kucharski@Sun.COM else 196*8044SWilliam.Kucharski@Sun.COM geom->sectors = 63; 197*8044SWilliam.Kucharski@Sun.COM if (ioctl (fd, DIOCGFWHEADS, &tmp) == 0) 198*8044SWilliam.Kucharski@Sun.COM geom->heads = tmp; 199*8044SWilliam.Kucharski@Sun.COM else if (geom->total_sectors <= 63 * 1 * 1024) 200*8044SWilliam.Kucharski@Sun.COM geom->heads = 1; 201*8044SWilliam.Kucharski@Sun.COM else if (geom->total_sectors <= 63 * 16 * 1024) 202*8044SWilliam.Kucharski@Sun.COM geom->heads = 16; 203*8044SWilliam.Kucharski@Sun.COM else 204*8044SWilliam.Kucharski@Sun.COM geom->heads = 255; 205*8044SWilliam.Kucharski@Sun.COM 206*8044SWilliam.Kucharski@Sun.COM geom->cylinders = (geom->total_sectors 207*8044SWilliam.Kucharski@Sun.COM / geom->heads 208*8044SWilliam.Kucharski@Sun.COM / geom->sectors); 209*8044SWilliam.Kucharski@Sun.COM 210*8044SWilliam.Kucharski@Sun.COM goto success; 211*8044SWilliam.Kucharski@Sun.COM } 212*8044SWilliam.Kucharski@Sun.COM else 213*8044SWilliam.Kucharski@Sun.COM #endif /* defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version >= 500040 */ 214*8044SWilliam.Kucharski@Sun.COM 215*8044SWilliam.Kucharski@Sun.COM /* kFreeBSD < 5, NetBSD or OpenBSD */ 216*8044SWilliam.Kucharski@Sun.COM { 217*8044SWilliam.Kucharski@Sun.COM struct disklabel hdg; 218*8044SWilliam.Kucharski@Sun.COM if (ioctl (fd, DIOCGDINFO, &hdg)) 219*8044SWilliam.Kucharski@Sun.COM goto fail; 220*8044SWilliam.Kucharski@Sun.COM 221*8044SWilliam.Kucharski@Sun.COM geom->cylinders = hdg.d_ncylinders; 222*8044SWilliam.Kucharski@Sun.COM geom->heads = hdg.d_ntracks; 223*8044SWilliam.Kucharski@Sun.COM geom->sectors = hdg.d_nsectors; 224*8044SWilliam.Kucharski@Sun.COM geom->total_sectors = hdg.d_secperunit; 225*8044SWilliam.Kucharski@Sun.COM 226*8044SWilliam.Kucharski@Sun.COM goto success; 227*8044SWilliam.Kucharski@Sun.COM } 228*8044SWilliam.Kucharski@Sun.COM 229*8044SWilliam.Kucharski@Sun.COM #elif defined(__sun) 230*8044SWilliam.Kucharski@Sun.COM /* Solaris */ 231*8044SWilliam.Kucharski@Sun.COM { 232*8044SWilliam.Kucharski@Sun.COM struct dk_geom dkg; 233*8044SWilliam.Kucharski@Sun.COM 234*8044SWilliam.Kucharski@Sun.COM if (ioctl(fd, DKIOCG_PHYGEOM, &dkg)) 235*8044SWilliam.Kucharski@Sun.COM goto fail; 236*8044SWilliam.Kucharski@Sun.COM geom->cylinders = dkg.dkg_ncyl; 237*8044SWilliam.Kucharski@Sun.COM geom->heads = dkg.dkg_nhead; 238*8044SWilliam.Kucharski@Sun.COM geom->sectors = dkg.dkg_nsect; 239*8044SWilliam.Kucharski@Sun.COM geom->total_sectors = dkg.dkg_ncyl * dkg.dkg_nhead * dkg.dkg_nsect; 240*8044SWilliam.Kucharski@Sun.COM 241*8044SWilliam.Kucharski@Sun.COM goto success; 242*8044SWilliam.Kucharski@Sun.COM } 243*8044SWilliam.Kucharski@Sun.COM 244*8044SWilliam.Kucharski@Sun.COM #else 245*8044SWilliam.Kucharski@Sun.COM /* Notably, defined(__GNU__) */ 246*8044SWilliam.Kucharski@Sun.COM # warning "Automatic detection of geometries will be performed only \ 247*8044SWilliam.Kucharski@Sun.COM partially. This is not fatal." 248*8044SWilliam.Kucharski@Sun.COM #endif 249*8044SWilliam.Kucharski@Sun.COM 250*8044SWilliam.Kucharski@Sun.COM fail: 251*8044SWilliam.Kucharski@Sun.COM { 252*8044SWilliam.Kucharski@Sun.COM struct stat st; 253*8044SWilliam.Kucharski@Sun.COM 254*8044SWilliam.Kucharski@Sun.COM /* FIXME: It would be nice to somehow compute fake C/H/S settings, 255*8044SWilliam.Kucharski@Sun.COM given a proper st_blocks size. */ 256*8044SWilliam.Kucharski@Sun.COM if (drive & 0x80) 257*8044SWilliam.Kucharski@Sun.COM { 258*8044SWilliam.Kucharski@Sun.COM geom->cylinders = DEFAULT_HD_CYLINDERS; 259*8044SWilliam.Kucharski@Sun.COM geom->heads = DEFAULT_HD_HEADS; 260*8044SWilliam.Kucharski@Sun.COM geom->sectors = DEFAULT_HD_SECTORS; 261*8044SWilliam.Kucharski@Sun.COM } 262*8044SWilliam.Kucharski@Sun.COM else 263*8044SWilliam.Kucharski@Sun.COM { 264*8044SWilliam.Kucharski@Sun.COM geom->cylinders = DEFAULT_FD_CYLINDERS; 265*8044SWilliam.Kucharski@Sun.COM geom->heads = DEFAULT_FD_HEADS; 266*8044SWilliam.Kucharski@Sun.COM geom->sectors = DEFAULT_FD_SECTORS; 267*8044SWilliam.Kucharski@Sun.COM } 268*8044SWilliam.Kucharski@Sun.COM 269*8044SWilliam.Kucharski@Sun.COM /* Set the total sectors properly, if we can. */ 270*8044SWilliam.Kucharski@Sun.COM if (! fstat (fd, &st) && st.st_blocks) 271*8044SWilliam.Kucharski@Sun.COM geom->total_sectors = st.st_blocks >> SECTOR_BITS; 272*8044SWilliam.Kucharski@Sun.COM else 273*8044SWilliam.Kucharski@Sun.COM geom->total_sectors = geom->cylinders * geom->heads * geom->sectors; 274*8044SWilliam.Kucharski@Sun.COM } 275*8044SWilliam.Kucharski@Sun.COM 276*8044SWilliam.Kucharski@Sun.COM success: 277*8044SWilliam.Kucharski@Sun.COM if (geom->flags == -1) 278*8044SWilliam.Kucharski@Sun.COM close (fd); 279*8044SWilliam.Kucharski@Sun.COM } 280*8044SWilliam.Kucharski@Sun.COM 281*8044SWilliam.Kucharski@Sun.COM #ifdef __linux__ 282*8044SWilliam.Kucharski@Sun.COM /* Check if we have devfs support. */ 283*8044SWilliam.Kucharski@Sun.COM static int 284*8044SWilliam.Kucharski@Sun.COM have_devfs (void) 285*8044SWilliam.Kucharski@Sun.COM { 286*8044SWilliam.Kucharski@Sun.COM static int dev_devfsd_exists = -1; 287*8044SWilliam.Kucharski@Sun.COM 288*8044SWilliam.Kucharski@Sun.COM if (dev_devfsd_exists < 0) 289*8044SWilliam.Kucharski@Sun.COM { 290*8044SWilliam.Kucharski@Sun.COM struct stat st; 291*8044SWilliam.Kucharski@Sun.COM 292*8044SWilliam.Kucharski@Sun.COM dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0; 293*8044SWilliam.Kucharski@Sun.COM } 294*8044SWilliam.Kucharski@Sun.COM 295*8044SWilliam.Kucharski@Sun.COM return dev_devfsd_exists; 296*8044SWilliam.Kucharski@Sun.COM } 297*8044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */ 298*8044SWilliam.Kucharski@Sun.COM 299*8044SWilliam.Kucharski@Sun.COM /* These three functions are quite different among OSes. */ 300*8044SWilliam.Kucharski@Sun.COM static void 301*8044SWilliam.Kucharski@Sun.COM get_floppy_disk_name (char *name, int unit) 302*8044SWilliam.Kucharski@Sun.COM { 303*8044SWilliam.Kucharski@Sun.COM #if defined(__linux__) 304*8044SWilliam.Kucharski@Sun.COM /* GNU/Linux */ 305*8044SWilliam.Kucharski@Sun.COM if (have_devfs ()) 306*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/floppy/%d", unit); 307*8044SWilliam.Kucharski@Sun.COM else 308*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/fd%d", unit); 309*8044SWilliam.Kucharski@Sun.COM #elif defined(__GNU__) 310*8044SWilliam.Kucharski@Sun.COM /* GNU/Hurd */ 311*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/fd%d", unit); 312*8044SWilliam.Kucharski@Sun.COM #elif defined(__FreeBSD_kernel__) 313*8044SWilliam.Kucharski@Sun.COM /* kFreeBSD */ 314*8044SWilliam.Kucharski@Sun.COM if (get_kfreebsd_version () >= 400000) 315*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/fd%d", unit); 316*8044SWilliam.Kucharski@Sun.COM else 317*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rfd%d", unit); 318*8044SWilliam.Kucharski@Sun.COM #elif defined(__NetBSD__) 319*8044SWilliam.Kucharski@Sun.COM /* NetBSD */ 320*8044SWilliam.Kucharski@Sun.COM /* opendisk() doesn't work for floppies. */ 321*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rfd%da", unit); 322*8044SWilliam.Kucharski@Sun.COM #elif defined(__OpenBSD__) 323*8044SWilliam.Kucharski@Sun.COM /* OpenBSD */ 324*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rfd%dc", unit); 325*8044SWilliam.Kucharski@Sun.COM #elif defined(__QNXNTO__) 326*8044SWilliam.Kucharski@Sun.COM /* QNX RTP */ 327*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/fd%d", unit); 328*8044SWilliam.Kucharski@Sun.COM #elif defined(__sun) 329*8044SWilliam.Kucharski@Sun.COM /* Solaris */ 330*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rdiskette%d", unit); 331*8044SWilliam.Kucharski@Sun.COM #else 332*8044SWilliam.Kucharski@Sun.COM # warning "BIOS floppy drives cannot be guessed in your operating system." 333*8044SWilliam.Kucharski@Sun.COM /* Set NAME to a bogus string. */ 334*8044SWilliam.Kucharski@Sun.COM *name = 0; 335*8044SWilliam.Kucharski@Sun.COM #endif 336*8044SWilliam.Kucharski@Sun.COM } 337*8044SWilliam.Kucharski@Sun.COM 338*8044SWilliam.Kucharski@Sun.COM static void 339*8044SWilliam.Kucharski@Sun.COM get_ide_disk_name (char *name, int unit) 340*8044SWilliam.Kucharski@Sun.COM { 341*8044SWilliam.Kucharski@Sun.COM #if defined(__linux__) 342*8044SWilliam.Kucharski@Sun.COM /* GNU/Linux */ 343*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/hd%c", unit + 'a'); 344*8044SWilliam.Kucharski@Sun.COM #elif defined(__GNU__) 345*8044SWilliam.Kucharski@Sun.COM /* GNU/Hurd */ 346*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/hd%d", unit); 347*8044SWilliam.Kucharski@Sun.COM #elif defined(__FreeBSD_kernel__) 348*8044SWilliam.Kucharski@Sun.COM /* kFreeBSD */ 349*8044SWilliam.Kucharski@Sun.COM if (get_kfreebsd_version () >= 400000) 350*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/ad%d", unit); 351*8044SWilliam.Kucharski@Sun.COM else 352*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rwd%d", unit); 353*8044SWilliam.Kucharski@Sun.COM #elif defined(__NetBSD__) && defined(HAVE_OPENDISK) 354*8044SWilliam.Kucharski@Sun.COM /* NetBSD */ 355*8044SWilliam.Kucharski@Sun.COM char shortname[16]; 356*8044SWilliam.Kucharski@Sun.COM int fd; 357*8044SWilliam.Kucharski@Sun.COM 358*8044SWilliam.Kucharski@Sun.COM sprintf (shortname, "wd%d", unit); 359*8044SWilliam.Kucharski@Sun.COM fd = opendisk (shortname, O_RDONLY, name, 360*8044SWilliam.Kucharski@Sun.COM 16, /* length of NAME */ 361*8044SWilliam.Kucharski@Sun.COM 0 /* char device */ 362*8044SWilliam.Kucharski@Sun.COM ); 363*8044SWilliam.Kucharski@Sun.COM close (fd); 364*8044SWilliam.Kucharski@Sun.COM #elif defined(__OpenBSD__) 365*8044SWilliam.Kucharski@Sun.COM /* OpenBSD */ 366*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rwd%dc", unit); 367*8044SWilliam.Kucharski@Sun.COM #elif defined(__QNXNTO__) 368*8044SWilliam.Kucharski@Sun.COM /* QNX RTP */ 369*8044SWilliam.Kucharski@Sun.COM /* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could 370*8044SWilliam.Kucharski@Sun.COM contain SCSI disks. */ 371*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/hd%d", unit); 372*8044SWilliam.Kucharski@Sun.COM #elif defined(__sun) 373*8044SWilliam.Kucharski@Sun.COM *name = 0; /* FIXME */ 374*8044SWilliam.Kucharski@Sun.COM #else 375*8044SWilliam.Kucharski@Sun.COM # warning "BIOS IDE drives cannot be guessed in your operating system." 376*8044SWilliam.Kucharski@Sun.COM /* Set NAME to a bogus string. */ 377*8044SWilliam.Kucharski@Sun.COM *name = 0; 378*8044SWilliam.Kucharski@Sun.COM #endif 379*8044SWilliam.Kucharski@Sun.COM } 380*8044SWilliam.Kucharski@Sun.COM 381*8044SWilliam.Kucharski@Sun.COM static void 382*8044SWilliam.Kucharski@Sun.COM get_scsi_disk_name (char *name, int unit) 383*8044SWilliam.Kucharski@Sun.COM { 384*8044SWilliam.Kucharski@Sun.COM #if defined(__linux__) 385*8044SWilliam.Kucharski@Sun.COM /* GNU/Linux */ 386*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/sd%c", unit + 'a'); 387*8044SWilliam.Kucharski@Sun.COM #elif defined(__GNU__) 388*8044SWilliam.Kucharski@Sun.COM /* GNU/Hurd */ 389*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/sd%d", unit); 390*8044SWilliam.Kucharski@Sun.COM #elif defined(__FreeBSD_kernel__) 391*8044SWilliam.Kucharski@Sun.COM /* kFreeBSD */ 392*8044SWilliam.Kucharski@Sun.COM if (get_kfreebsd_version () >= 400000) 393*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/da%d", unit); 394*8044SWilliam.Kucharski@Sun.COM else 395*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rda%d", unit); 396*8044SWilliam.Kucharski@Sun.COM #elif defined(__NetBSD__) && defined(HAVE_OPENDISK) 397*8044SWilliam.Kucharski@Sun.COM /* NetBSD */ 398*8044SWilliam.Kucharski@Sun.COM char shortname[16]; 399*8044SWilliam.Kucharski@Sun.COM int fd; 400*8044SWilliam.Kucharski@Sun.COM 401*8044SWilliam.Kucharski@Sun.COM sprintf (shortname, "sd%d", unit); 402*8044SWilliam.Kucharski@Sun.COM fd = opendisk (shortname, O_RDONLY, name, 403*8044SWilliam.Kucharski@Sun.COM 16, /* length of NAME */ 404*8044SWilliam.Kucharski@Sun.COM 0 /* char device */ 405*8044SWilliam.Kucharski@Sun.COM ); 406*8044SWilliam.Kucharski@Sun.COM close (fd); 407*8044SWilliam.Kucharski@Sun.COM #elif defined(__OpenBSD__) 408*8044SWilliam.Kucharski@Sun.COM /* OpenBSD */ 409*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rsd%dc", unit); 410*8044SWilliam.Kucharski@Sun.COM #elif defined(__QNXNTO__) 411*8044SWilliam.Kucharski@Sun.COM /* QNX RTP */ 412*8044SWilliam.Kucharski@Sun.COM /* QNX RTP doesn't distinguish SCSI from IDE, so it is better to 413*8044SWilliam.Kucharski@Sun.COM disable the detection of SCSI disks here. */ 414*8044SWilliam.Kucharski@Sun.COM *name = 0; 415*8044SWilliam.Kucharski@Sun.COM #elif defined(__sun) 416*8044SWilliam.Kucharski@Sun.COM *name = 0; /* FIXME */ 417*8044SWilliam.Kucharski@Sun.COM #else 418*8044SWilliam.Kucharski@Sun.COM # warning "BIOS SCSI drives cannot be guessed in your operating system." 419*8044SWilliam.Kucharski@Sun.COM /* Set NAME to a bogus string. */ 420*8044SWilliam.Kucharski@Sun.COM *name = 0; 421*8044SWilliam.Kucharski@Sun.COM #endif 422*8044SWilliam.Kucharski@Sun.COM } 423*8044SWilliam.Kucharski@Sun.COM 424*8044SWilliam.Kucharski@Sun.COM #ifdef __linux__ 425*8044SWilliam.Kucharski@Sun.COM static void 426*8044SWilliam.Kucharski@Sun.COM get_dac960_disk_name (char *name, int controller, int drive) 427*8044SWilliam.Kucharski@Sun.COM { 428*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/rd/c%dd%d", controller, drive); 429*8044SWilliam.Kucharski@Sun.COM } 430*8044SWilliam.Kucharski@Sun.COM 431*8044SWilliam.Kucharski@Sun.COM static void 432*8044SWilliam.Kucharski@Sun.COM get_ataraid_disk_name (char *name, int unit) 433*8044SWilliam.Kucharski@Sun.COM { 434*8044SWilliam.Kucharski@Sun.COM sprintf (name, "/dev/ataraid/d%c", unit + '0'); 435*8044SWilliam.Kucharski@Sun.COM } 436*8044SWilliam.Kucharski@Sun.COM #endif 437*8044SWilliam.Kucharski@Sun.COM 438*8044SWilliam.Kucharski@Sun.COM /* Check if DEVICE can be read. If an error occurs, return zero, 439*8044SWilliam.Kucharski@Sun.COM otherwise return non-zero. */ 440*8044SWilliam.Kucharski@Sun.COM int 441*8044SWilliam.Kucharski@Sun.COM check_device (const char *device) 442*8044SWilliam.Kucharski@Sun.COM { 443*8044SWilliam.Kucharski@Sun.COM char buf[512]; 444*8044SWilliam.Kucharski@Sun.COM FILE *fp; 445*8044SWilliam.Kucharski@Sun.COM 446*8044SWilliam.Kucharski@Sun.COM /* If DEVICE is empty, just return 1. */ 447*8044SWilliam.Kucharski@Sun.COM if (*device == 0) 448*8044SWilliam.Kucharski@Sun.COM return 1; 449*8044SWilliam.Kucharski@Sun.COM 450*8044SWilliam.Kucharski@Sun.COM fp = fopen (device, "r"); 451*8044SWilliam.Kucharski@Sun.COM if (! fp) 452*8044SWilliam.Kucharski@Sun.COM { 453*8044SWilliam.Kucharski@Sun.COM switch (errno) 454*8044SWilliam.Kucharski@Sun.COM { 455*8044SWilliam.Kucharski@Sun.COM #ifdef ENOMEDIUM 456*8044SWilliam.Kucharski@Sun.COM case ENOMEDIUM: 457*8044SWilliam.Kucharski@Sun.COM # if 0 458*8044SWilliam.Kucharski@Sun.COM /* At the moment, this finds only CDROMs, which can't be 459*8044SWilliam.Kucharski@Sun.COM read anyway, so leave it out. Code should be 460*8044SWilliam.Kucharski@Sun.COM reactivated if `removable disks' and CDROMs are 461*8044SWilliam.Kucharski@Sun.COM supported. */ 462*8044SWilliam.Kucharski@Sun.COM /* Accept it, it may be inserted. */ 463*8044SWilliam.Kucharski@Sun.COM return 1; 464*8044SWilliam.Kucharski@Sun.COM # endif 465*8044SWilliam.Kucharski@Sun.COM break; 466*8044SWilliam.Kucharski@Sun.COM #endif /* ENOMEDIUM */ 467*8044SWilliam.Kucharski@Sun.COM default: 468*8044SWilliam.Kucharski@Sun.COM /* Break case and leave. */ 469*8044SWilliam.Kucharski@Sun.COM break; 470*8044SWilliam.Kucharski@Sun.COM } 471*8044SWilliam.Kucharski@Sun.COM /* Error opening the device. */ 472*8044SWilliam.Kucharski@Sun.COM return 0; 473*8044SWilliam.Kucharski@Sun.COM } 474*8044SWilliam.Kucharski@Sun.COM 475*8044SWilliam.Kucharski@Sun.COM /* Make sure CD-ROMs don't get assigned a BIOS disk number 476*8044SWilliam.Kucharski@Sun.COM before SCSI disks! */ 477*8044SWilliam.Kucharski@Sun.COM #ifdef __linux__ 478*8044SWilliam.Kucharski@Sun.COM # ifdef CDROM_GET_CAPABILITY 479*8044SWilliam.Kucharski@Sun.COM if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0) 480*8044SWilliam.Kucharski@Sun.COM return 0; 481*8044SWilliam.Kucharski@Sun.COM # else /* ! CDROM_GET_CAPABILITY */ 482*8044SWilliam.Kucharski@Sun.COM /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */ 483*8044SWilliam.Kucharski@Sun.COM { 484*8044SWilliam.Kucharski@Sun.COM struct hd_geometry hdg; 485*8044SWilliam.Kucharski@Sun.COM struct stat st; 486*8044SWilliam.Kucharski@Sun.COM 487*8044SWilliam.Kucharski@Sun.COM if (fstat (fileno (fp), &st)) 488*8044SWilliam.Kucharski@Sun.COM return 0; 489*8044SWilliam.Kucharski@Sun.COM 490*8044SWilliam.Kucharski@Sun.COM /* If it is a block device and isn't a floppy, check if HDIO_GETGEO 491*8044SWilliam.Kucharski@Sun.COM succeeds. */ 492*8044SWilliam.Kucharski@Sun.COM if (S_ISBLK (st.st_mode) 493*8044SWilliam.Kucharski@Sun.COM && MAJOR (st.st_rdev) != FLOPPY_MAJOR 494*8044SWilliam.Kucharski@Sun.COM && ioctl (fileno (fp), HDIO_GETGEO, &hdg)) 495*8044SWilliam.Kucharski@Sun.COM return 0; 496*8044SWilliam.Kucharski@Sun.COM } 497*8044SWilliam.Kucharski@Sun.COM # endif /* ! CDROM_GET_CAPABILITY */ 498*8044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */ 499*8044SWilliam.Kucharski@Sun.COM 500*8044SWilliam.Kucharski@Sun.COM #if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) 501*8044SWilliam.Kucharski@Sun.COM # ifdef CDIOCCLRDEBUG 502*8044SWilliam.Kucharski@Sun.COM if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0) 503*8044SWilliam.Kucharski@Sun.COM return 0; 504*8044SWilliam.Kucharski@Sun.COM # endif /* CDIOCCLRDEBUG */ 505*8044SWilliam.Kucharski@Sun.COM #endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */ 506*8044SWilliam.Kucharski@Sun.COM 507*8044SWilliam.Kucharski@Sun.COM /* Attempt to read the first sector. */ 508*8044SWilliam.Kucharski@Sun.COM if (fread (buf, 1, 512, fp) != 512) 509*8044SWilliam.Kucharski@Sun.COM { 510*8044SWilliam.Kucharski@Sun.COM fclose (fp); 511*8044SWilliam.Kucharski@Sun.COM return 0; 512*8044SWilliam.Kucharski@Sun.COM } 513*8044SWilliam.Kucharski@Sun.COM 514*8044SWilliam.Kucharski@Sun.COM fclose (fp); 515*8044SWilliam.Kucharski@Sun.COM return 1; 516*8044SWilliam.Kucharski@Sun.COM } 517*8044SWilliam.Kucharski@Sun.COM 518*8044SWilliam.Kucharski@Sun.COM /* Read mapping information from FP, and write it to MAP. */ 519*8044SWilliam.Kucharski@Sun.COM static int 520*8044SWilliam.Kucharski@Sun.COM read_device_map (FILE *fp, char **map, const char *map_file) 521*8044SWilliam.Kucharski@Sun.COM { 522*8044SWilliam.Kucharski@Sun.COM auto void show_error (int no, const char *msg); 523*8044SWilliam.Kucharski@Sun.COM auto void show_warning (int no, const char *msg, ...); 524*8044SWilliam.Kucharski@Sun.COM 525*8044SWilliam.Kucharski@Sun.COM auto void show_error (int no, const char *msg) 526*8044SWilliam.Kucharski@Sun.COM { 527*8044SWilliam.Kucharski@Sun.COM fprintf (stderr, "%s:%d: error: %s\n", map_file, no, msg); 528*8044SWilliam.Kucharski@Sun.COM } 529*8044SWilliam.Kucharski@Sun.COM 530*8044SWilliam.Kucharski@Sun.COM auto void show_warning (int no, const char *msg, ...) 531*8044SWilliam.Kucharski@Sun.COM { 532*8044SWilliam.Kucharski@Sun.COM va_list ap; 533*8044SWilliam.Kucharski@Sun.COM 534*8044SWilliam.Kucharski@Sun.COM va_start (ap, msg); 535*8044SWilliam.Kucharski@Sun.COM fprintf (stderr, "%s:%d: warning: ", map_file, no); 536*8044SWilliam.Kucharski@Sun.COM vfprintf (stderr, msg, ap); 537*8044SWilliam.Kucharski@Sun.COM va_end (ap); 538*8044SWilliam.Kucharski@Sun.COM } 539*8044SWilliam.Kucharski@Sun.COM 540*8044SWilliam.Kucharski@Sun.COM /* If there is the device map file, use the data in it instead of 541*8044SWilliam.Kucharski@Sun.COM probing devices. */ 542*8044SWilliam.Kucharski@Sun.COM char buf[1024]; /* XXX */ 543*8044SWilliam.Kucharski@Sun.COM int line_number = 0; 544*8044SWilliam.Kucharski@Sun.COM 545*8044SWilliam.Kucharski@Sun.COM while (fgets (buf, sizeof (buf), fp)) 546*8044SWilliam.Kucharski@Sun.COM { 547*8044SWilliam.Kucharski@Sun.COM char *ptr, *eptr; 548*8044SWilliam.Kucharski@Sun.COM int drive; 549*8044SWilliam.Kucharski@Sun.COM int is_floppy = 0; 550*8044SWilliam.Kucharski@Sun.COM 551*8044SWilliam.Kucharski@Sun.COM /* Increase the number of lines. */ 552*8044SWilliam.Kucharski@Sun.COM line_number++; 553*8044SWilliam.Kucharski@Sun.COM 554*8044SWilliam.Kucharski@Sun.COM /* If the first character is '#', skip it. */ 555*8044SWilliam.Kucharski@Sun.COM if (buf[0] == '#') 556*8044SWilliam.Kucharski@Sun.COM continue; 557*8044SWilliam.Kucharski@Sun.COM 558*8044SWilliam.Kucharski@Sun.COM ptr = buf; 559*8044SWilliam.Kucharski@Sun.COM /* Skip leading spaces. */ 560*8044SWilliam.Kucharski@Sun.COM while (*ptr && isspace (*ptr)) 561*8044SWilliam.Kucharski@Sun.COM ptr++; 562*8044SWilliam.Kucharski@Sun.COM 563*8044SWilliam.Kucharski@Sun.COM /* Skip empty lines. */ 564*8044SWilliam.Kucharski@Sun.COM if (! *ptr) 565*8044SWilliam.Kucharski@Sun.COM continue; 566*8044SWilliam.Kucharski@Sun.COM 567*8044SWilliam.Kucharski@Sun.COM if (*ptr != '(') 568*8044SWilliam.Kucharski@Sun.COM { 569*8044SWilliam.Kucharski@Sun.COM show_error (line_number, "No open parenthesis found"); 570*8044SWilliam.Kucharski@Sun.COM return 0; 571*8044SWilliam.Kucharski@Sun.COM } 572*8044SWilliam.Kucharski@Sun.COM 573*8044SWilliam.Kucharski@Sun.COM ptr++; 574*8044SWilliam.Kucharski@Sun.COM if ((*ptr != 'f' && *ptr != 'h') || *(ptr + 1) != 'd') 575*8044SWilliam.Kucharski@Sun.COM { 576*8044SWilliam.Kucharski@Sun.COM show_error (line_number, "Bad drive name"); 577*8044SWilliam.Kucharski@Sun.COM return 0; 578*8044SWilliam.Kucharski@Sun.COM } 579*8044SWilliam.Kucharski@Sun.COM 580*8044SWilliam.Kucharski@Sun.COM if (*ptr == 'f') 581*8044SWilliam.Kucharski@Sun.COM is_floppy = 1; 582*8044SWilliam.Kucharski@Sun.COM 583*8044SWilliam.Kucharski@Sun.COM ptr += 2; 584*8044SWilliam.Kucharski@Sun.COM drive = strtoul (ptr, &ptr, 10); 585*8044SWilliam.Kucharski@Sun.COM if (drive < 0) 586*8044SWilliam.Kucharski@Sun.COM { 587*8044SWilliam.Kucharski@Sun.COM show_error (line_number, "Bad device number"); 588*8044SWilliam.Kucharski@Sun.COM return 0; 589*8044SWilliam.Kucharski@Sun.COM } 590*8044SWilliam.Kucharski@Sun.COM else if (drive > 127) 591*8044SWilliam.Kucharski@Sun.COM { 592*8044SWilliam.Kucharski@Sun.COM show_warning (line_number, 593*8044SWilliam.Kucharski@Sun.COM "Ignoring %cd%d due to a BIOS limitation", 594*8044SWilliam.Kucharski@Sun.COM is_floppy ? 'f' : 'h', drive); 595*8044SWilliam.Kucharski@Sun.COM continue; 596*8044SWilliam.Kucharski@Sun.COM } 597*8044SWilliam.Kucharski@Sun.COM 598*8044SWilliam.Kucharski@Sun.COM if (! is_floppy) 599*8044SWilliam.Kucharski@Sun.COM drive += 0x80; 600*8044SWilliam.Kucharski@Sun.COM 601*8044SWilliam.Kucharski@Sun.COM if (*ptr != ')') 602*8044SWilliam.Kucharski@Sun.COM { 603*8044SWilliam.Kucharski@Sun.COM show_error (line_number, "No close parenthesis found"); 604*8044SWilliam.Kucharski@Sun.COM return 0; 605*8044SWilliam.Kucharski@Sun.COM } 606*8044SWilliam.Kucharski@Sun.COM 607*8044SWilliam.Kucharski@Sun.COM ptr++; 608*8044SWilliam.Kucharski@Sun.COM /* Skip spaces. */ 609*8044SWilliam.Kucharski@Sun.COM while (*ptr && isspace (*ptr)) 610*8044SWilliam.Kucharski@Sun.COM ptr++; 611*8044SWilliam.Kucharski@Sun.COM 612*8044SWilliam.Kucharski@Sun.COM if (! *ptr) 613*8044SWilliam.Kucharski@Sun.COM { 614*8044SWilliam.Kucharski@Sun.COM show_error (line_number, "No filename found"); 615*8044SWilliam.Kucharski@Sun.COM return 0; 616*8044SWilliam.Kucharski@Sun.COM } 617*8044SWilliam.Kucharski@Sun.COM 618*8044SWilliam.Kucharski@Sun.COM /* Terminate the filename. */ 619*8044SWilliam.Kucharski@Sun.COM eptr = ptr; 620*8044SWilliam.Kucharski@Sun.COM while (*eptr && ! isspace (*eptr)) 621*8044SWilliam.Kucharski@Sun.COM eptr++; 622*8044SWilliam.Kucharski@Sun.COM *eptr = 0; 623*8044SWilliam.Kucharski@Sun.COM 624*8044SWilliam.Kucharski@Sun.COM /* Multiple entries for a given drive is not allowed. */ 625*8044SWilliam.Kucharski@Sun.COM if (map[drive]) 626*8044SWilliam.Kucharski@Sun.COM { 627*8044SWilliam.Kucharski@Sun.COM show_error (line_number, "Duplicated entry found"); 628*8044SWilliam.Kucharski@Sun.COM return 0; 629*8044SWilliam.Kucharski@Sun.COM } 630*8044SWilliam.Kucharski@Sun.COM 631*8044SWilliam.Kucharski@Sun.COM map[drive] = strdup (ptr); 632*8044SWilliam.Kucharski@Sun.COM assert (map[drive]); 633*8044SWilliam.Kucharski@Sun.COM } 634*8044SWilliam.Kucharski@Sun.COM 635*8044SWilliam.Kucharski@Sun.COM return 1; 636*8044SWilliam.Kucharski@Sun.COM } 637*8044SWilliam.Kucharski@Sun.COM 638*8044SWilliam.Kucharski@Sun.COM /* Initialize the device map MAP. *MAP will be allocated from the heap 639*8044SWilliam.Kucharski@Sun.COM space. If MAP_FILE is not NULL, then read mappings from the file 640*8044SWilliam.Kucharski@Sun.COM MAP_FILE if it exists, otherwise, write guessed mappings to the file. 641*8044SWilliam.Kucharski@Sun.COM FLOPPY_DISKS is the number of floppy disk drives which will be probed. 642*8044SWilliam.Kucharski@Sun.COM If it is zero, don't probe any floppy at all. If it is one, probe one 643*8044SWilliam.Kucharski@Sun.COM floppy. If it is two, probe two floppies. And so on. */ 644*8044SWilliam.Kucharski@Sun.COM int 645*8044SWilliam.Kucharski@Sun.COM init_device_map (char ***map, const char *map_file, int floppy_disks) 646*8044SWilliam.Kucharski@Sun.COM { 647*8044SWilliam.Kucharski@Sun.COM int i; 648*8044SWilliam.Kucharski@Sun.COM int num_hd = 0; 649*8044SWilliam.Kucharski@Sun.COM FILE *fp = 0; 650*8044SWilliam.Kucharski@Sun.COM 651*8044SWilliam.Kucharski@Sun.COM assert (map); 652*8044SWilliam.Kucharski@Sun.COM assert (*map == 0); 653*8044SWilliam.Kucharski@Sun.COM *map = malloc (NUM_DISKS * sizeof (char *)); 654*8044SWilliam.Kucharski@Sun.COM assert (*map); 655*8044SWilliam.Kucharski@Sun.COM 656*8044SWilliam.Kucharski@Sun.COM /* Probe devices for creating the device map. */ 657*8044SWilliam.Kucharski@Sun.COM 658*8044SWilliam.Kucharski@Sun.COM /* Initialize DEVICE_MAP. */ 659*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < NUM_DISKS; i++) 660*8044SWilliam.Kucharski@Sun.COM (*map)[i] = 0; 661*8044SWilliam.Kucharski@Sun.COM 662*8044SWilliam.Kucharski@Sun.COM if (map_file) 663*8044SWilliam.Kucharski@Sun.COM { 664*8044SWilliam.Kucharski@Sun.COM /* Open the device map file. */ 665*8044SWilliam.Kucharski@Sun.COM fp = fopen (map_file, "r"); 666*8044SWilliam.Kucharski@Sun.COM if (fp) 667*8044SWilliam.Kucharski@Sun.COM { 668*8044SWilliam.Kucharski@Sun.COM int ret; 669*8044SWilliam.Kucharski@Sun.COM 670*8044SWilliam.Kucharski@Sun.COM ret = read_device_map (fp, *map, map_file); 671*8044SWilliam.Kucharski@Sun.COM fclose (fp); 672*8044SWilliam.Kucharski@Sun.COM return ret; 673*8044SWilliam.Kucharski@Sun.COM } 674*8044SWilliam.Kucharski@Sun.COM } 675*8044SWilliam.Kucharski@Sun.COM 676*8044SWilliam.Kucharski@Sun.COM /* Print something so that the user does not think GRUB has been 677*8044SWilliam.Kucharski@Sun.COM crashed. */ 678*8044SWilliam.Kucharski@Sun.COM fprintf (stderr, 679*8044SWilliam.Kucharski@Sun.COM "Probing devices to guess BIOS drives. " 680*8044SWilliam.Kucharski@Sun.COM "This may take a long time.\n"); 681*8044SWilliam.Kucharski@Sun.COM 682*8044SWilliam.Kucharski@Sun.COM if (map_file) 683*8044SWilliam.Kucharski@Sun.COM /* Try to open the device map file to write the probed data. */ 684*8044SWilliam.Kucharski@Sun.COM fp = fopen (map_file, "w"); 685*8044SWilliam.Kucharski@Sun.COM 686*8044SWilliam.Kucharski@Sun.COM /* Floppies. */ 687*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < floppy_disks; i++) 688*8044SWilliam.Kucharski@Sun.COM { 689*8044SWilliam.Kucharski@Sun.COM char name[16]; 690*8044SWilliam.Kucharski@Sun.COM 691*8044SWilliam.Kucharski@Sun.COM get_floppy_disk_name (name, i); 692*8044SWilliam.Kucharski@Sun.COM /* In floppies, write the map, whether check_device succeeds 693*8044SWilliam.Kucharski@Sun.COM or not, because the user just does not insert floppies. */ 694*8044SWilliam.Kucharski@Sun.COM if (fp) 695*8044SWilliam.Kucharski@Sun.COM fprintf (fp, "(fd%d)\t%s\n", i, name); 696*8044SWilliam.Kucharski@Sun.COM 697*8044SWilliam.Kucharski@Sun.COM if (check_device (name)) 698*8044SWilliam.Kucharski@Sun.COM { 699*8044SWilliam.Kucharski@Sun.COM (*map)[i] = strdup (name); 700*8044SWilliam.Kucharski@Sun.COM assert ((*map)[i]); 701*8044SWilliam.Kucharski@Sun.COM } 702*8044SWilliam.Kucharski@Sun.COM } 703*8044SWilliam.Kucharski@Sun.COM 704*8044SWilliam.Kucharski@Sun.COM #ifdef __linux__ 705*8044SWilliam.Kucharski@Sun.COM if (have_devfs ()) 706*8044SWilliam.Kucharski@Sun.COM { 707*8044SWilliam.Kucharski@Sun.COM while (1) 708*8044SWilliam.Kucharski@Sun.COM { 709*8044SWilliam.Kucharski@Sun.COM char discn[32]; 710*8044SWilliam.Kucharski@Sun.COM char name[PATH_MAX]; 711*8044SWilliam.Kucharski@Sun.COM struct stat st; 712*8044SWilliam.Kucharski@Sun.COM 713*8044SWilliam.Kucharski@Sun.COM /* Linux creates symlinks "/dev/discs/discN" for convenience. 714*8044SWilliam.Kucharski@Sun.COM The way to number disks is the same as GRUB's. */ 715*8044SWilliam.Kucharski@Sun.COM sprintf (discn, "/dev/discs/disc%d", num_hd); 716*8044SWilliam.Kucharski@Sun.COM if (stat (discn, &st) < 0) 717*8044SWilliam.Kucharski@Sun.COM break; 718*8044SWilliam.Kucharski@Sun.COM 719*8044SWilliam.Kucharski@Sun.COM if (realpath (discn, name)) 720*8044SWilliam.Kucharski@Sun.COM { 721*8044SWilliam.Kucharski@Sun.COM strcat (name, "/disc"); 722*8044SWilliam.Kucharski@Sun.COM (*map)[num_hd + 0x80] = strdup (name); 723*8044SWilliam.Kucharski@Sun.COM assert ((*map)[num_hd + 0x80]); 724*8044SWilliam.Kucharski@Sun.COM 725*8044SWilliam.Kucharski@Sun.COM /* If the device map file is opened, write the map. */ 726*8044SWilliam.Kucharski@Sun.COM if (fp) 727*8044SWilliam.Kucharski@Sun.COM fprintf (fp, "(hd%d)\t%s\n", num_hd, name); 728*8044SWilliam.Kucharski@Sun.COM } 729*8044SWilliam.Kucharski@Sun.COM 730*8044SWilliam.Kucharski@Sun.COM num_hd++; 731*8044SWilliam.Kucharski@Sun.COM } 732*8044SWilliam.Kucharski@Sun.COM 733*8044SWilliam.Kucharski@Sun.COM /* OK, close the device map file if opened. */ 734*8044SWilliam.Kucharski@Sun.COM if (fp) 735*8044SWilliam.Kucharski@Sun.COM fclose (fp); 736*8044SWilliam.Kucharski@Sun.COM 737*8044SWilliam.Kucharski@Sun.COM return 1; 738*8044SWilliam.Kucharski@Sun.COM } 739*8044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */ 740*8044SWilliam.Kucharski@Sun.COM 741*8044SWilliam.Kucharski@Sun.COM /* IDE disks. */ 742*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < 8; i++) 743*8044SWilliam.Kucharski@Sun.COM { 744*8044SWilliam.Kucharski@Sun.COM char name[16]; 745*8044SWilliam.Kucharski@Sun.COM 746*8044SWilliam.Kucharski@Sun.COM get_ide_disk_name (name, i); 747*8044SWilliam.Kucharski@Sun.COM if (check_device (name)) 748*8044SWilliam.Kucharski@Sun.COM { 749*8044SWilliam.Kucharski@Sun.COM (*map)[num_hd + 0x80] = strdup (name); 750*8044SWilliam.Kucharski@Sun.COM assert ((*map)[num_hd + 0x80]); 751*8044SWilliam.Kucharski@Sun.COM 752*8044SWilliam.Kucharski@Sun.COM /* If the device map file is opened, write the map. */ 753*8044SWilliam.Kucharski@Sun.COM if (fp) 754*8044SWilliam.Kucharski@Sun.COM fprintf (fp, "(hd%d)\t%s\n", num_hd, name); 755*8044SWilliam.Kucharski@Sun.COM 756*8044SWilliam.Kucharski@Sun.COM num_hd++; 757*8044SWilliam.Kucharski@Sun.COM } 758*8044SWilliam.Kucharski@Sun.COM } 759*8044SWilliam.Kucharski@Sun.COM 760*8044SWilliam.Kucharski@Sun.COM #ifdef __linux__ 761*8044SWilliam.Kucharski@Sun.COM /* ATARAID disks. */ 762*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < 8; i++) 763*8044SWilliam.Kucharski@Sun.COM { 764*8044SWilliam.Kucharski@Sun.COM char name[20]; 765*8044SWilliam.Kucharski@Sun.COM 766*8044SWilliam.Kucharski@Sun.COM get_ataraid_disk_name (name, i); 767*8044SWilliam.Kucharski@Sun.COM if (check_device (name)) 768*8044SWilliam.Kucharski@Sun.COM { 769*8044SWilliam.Kucharski@Sun.COM (*map)[num_hd + 0x80] = strdup (name); 770*8044SWilliam.Kucharski@Sun.COM assert ((*map)[num_hd + 0x80]); 771*8044SWilliam.Kucharski@Sun.COM 772*8044SWilliam.Kucharski@Sun.COM /* If the device map file is opened, write the map. */ 773*8044SWilliam.Kucharski@Sun.COM if (fp) 774*8044SWilliam.Kucharski@Sun.COM fprintf (fp, "(hd%d)\t%s\n", num_hd, name); 775*8044SWilliam.Kucharski@Sun.COM 776*8044SWilliam.Kucharski@Sun.COM num_hd++; 777*8044SWilliam.Kucharski@Sun.COM } 778*8044SWilliam.Kucharski@Sun.COM } 779*8044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */ 780*8044SWilliam.Kucharski@Sun.COM 781*8044SWilliam.Kucharski@Sun.COM /* The rest is SCSI disks. */ 782*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < 16; i++) 783*8044SWilliam.Kucharski@Sun.COM { 784*8044SWilliam.Kucharski@Sun.COM char name[16]; 785*8044SWilliam.Kucharski@Sun.COM 786*8044SWilliam.Kucharski@Sun.COM get_scsi_disk_name (name, i); 787*8044SWilliam.Kucharski@Sun.COM if (check_device (name)) 788*8044SWilliam.Kucharski@Sun.COM { 789*8044SWilliam.Kucharski@Sun.COM (*map)[num_hd + 0x80] = strdup (name); 790*8044SWilliam.Kucharski@Sun.COM assert ((*map)[num_hd + 0x80]); 791*8044SWilliam.Kucharski@Sun.COM 792*8044SWilliam.Kucharski@Sun.COM /* If the device map file is opened, write the map. */ 793*8044SWilliam.Kucharski@Sun.COM if (fp) 794*8044SWilliam.Kucharski@Sun.COM fprintf (fp, "(hd%d)\t%s\n", num_hd, name); 795*8044SWilliam.Kucharski@Sun.COM 796*8044SWilliam.Kucharski@Sun.COM num_hd++; 797*8044SWilliam.Kucharski@Sun.COM } 798*8044SWilliam.Kucharski@Sun.COM } 799*8044SWilliam.Kucharski@Sun.COM 800*8044SWilliam.Kucharski@Sun.COM #ifdef __linux__ 801*8044SWilliam.Kucharski@Sun.COM /* This is for DAC960 - we have 802*8044SWilliam.Kucharski@Sun.COM /dev/rd/c<controller>d<logical drive>p<partition>. 803*8044SWilliam.Kucharski@Sun.COM 804*8044SWilliam.Kucharski@Sun.COM DAC960 driver currently supports up to 8 controllers, 32 logical 805*8044SWilliam.Kucharski@Sun.COM drives, and 7 partitions. */ 806*8044SWilliam.Kucharski@Sun.COM { 807*8044SWilliam.Kucharski@Sun.COM int controller, drive; 808*8044SWilliam.Kucharski@Sun.COM 809*8044SWilliam.Kucharski@Sun.COM for (controller = 0; controller < 8; controller++) 810*8044SWilliam.Kucharski@Sun.COM { 811*8044SWilliam.Kucharski@Sun.COM for (drive = 0; drive < 15; drive++) 812*8044SWilliam.Kucharski@Sun.COM { 813*8044SWilliam.Kucharski@Sun.COM char name[24]; 814*8044SWilliam.Kucharski@Sun.COM 815*8044SWilliam.Kucharski@Sun.COM get_dac960_disk_name (name, controller, drive); 816*8044SWilliam.Kucharski@Sun.COM if (check_device (name)) 817*8044SWilliam.Kucharski@Sun.COM { 818*8044SWilliam.Kucharski@Sun.COM (*map)[num_hd + 0x80] = strdup (name); 819*8044SWilliam.Kucharski@Sun.COM assert ((*map)[num_hd + 0x80]); 820*8044SWilliam.Kucharski@Sun.COM 821*8044SWilliam.Kucharski@Sun.COM /* If the device map file is opened, write the map. */ 822*8044SWilliam.Kucharski@Sun.COM if (fp) 823*8044SWilliam.Kucharski@Sun.COM fprintf (fp, "(hd%d)\t%s\n", num_hd, name); 824*8044SWilliam.Kucharski@Sun.COM 825*8044SWilliam.Kucharski@Sun.COM num_hd++; 826*8044SWilliam.Kucharski@Sun.COM } 827*8044SWilliam.Kucharski@Sun.COM } 828*8044SWilliam.Kucharski@Sun.COM } 829*8044SWilliam.Kucharski@Sun.COM } 830*8044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */ 831*8044SWilliam.Kucharski@Sun.COM 832*8044SWilliam.Kucharski@Sun.COM /* OK, close the device map file if opened. */ 833*8044SWilliam.Kucharski@Sun.COM if (fp) 834*8044SWilliam.Kucharski@Sun.COM fclose (fp); 835*8044SWilliam.Kucharski@Sun.COM 836*8044SWilliam.Kucharski@Sun.COM return 1; 837*8044SWilliam.Kucharski@Sun.COM } 838*8044SWilliam.Kucharski@Sun.COM 839*8044SWilliam.Kucharski@Sun.COM /* Restore the memory consumed for MAP. */ 840*8044SWilliam.Kucharski@Sun.COM void 841*8044SWilliam.Kucharski@Sun.COM restore_device_map (char **map) 842*8044SWilliam.Kucharski@Sun.COM { 843*8044SWilliam.Kucharski@Sun.COM int i; 844*8044SWilliam.Kucharski@Sun.COM 845*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < NUM_DISKS; i++) 846*8044SWilliam.Kucharski@Sun.COM if (map[i]) 847*8044SWilliam.Kucharski@Sun.COM free (map[i]); 848*8044SWilliam.Kucharski@Sun.COM 849*8044SWilliam.Kucharski@Sun.COM free (map); 850*8044SWilliam.Kucharski@Sun.COM } 851*8044SWilliam.Kucharski@Sun.COM 852*8044SWilliam.Kucharski@Sun.COM #ifdef __linux__ 853*8044SWilliam.Kucharski@Sun.COM /* Linux-only functions, because Linux has a bug that the disk cache for 854*8044SWilliam.Kucharski@Sun.COM a whole disk is not consistent with the one for a partition of the 855*8044SWilliam.Kucharski@Sun.COM disk. */ 856*8044SWilliam.Kucharski@Sun.COM int 857*8044SWilliam.Kucharski@Sun.COM is_disk_device (char **map, int drive) 858*8044SWilliam.Kucharski@Sun.COM { 859*8044SWilliam.Kucharski@Sun.COM struct stat st; 860*8044SWilliam.Kucharski@Sun.COM 861*8044SWilliam.Kucharski@Sun.COM assert (map[drive] != 0); 862*8044SWilliam.Kucharski@Sun.COM assert (stat (map[drive], &st) == 0); 863*8044SWilliam.Kucharski@Sun.COM /* For now, disk devices under Linux are all block devices. */ 864*8044SWilliam.Kucharski@Sun.COM return S_ISBLK (st.st_mode); 865*8044SWilliam.Kucharski@Sun.COM } 866*8044SWilliam.Kucharski@Sun.COM 867*8044SWilliam.Kucharski@Sun.COM int 868*8044SWilliam.Kucharski@Sun.COM write_to_partition (char **map, int drive, int partition, 869*8044SWilliam.Kucharski@Sun.COM int sector, int size, const char *buf) 870*8044SWilliam.Kucharski@Sun.COM { 871*8044SWilliam.Kucharski@Sun.COM char dev[PATH_MAX]; /* XXX */ 872*8044SWilliam.Kucharski@Sun.COM int fd; 873*8044SWilliam.Kucharski@Sun.COM 874*8044SWilliam.Kucharski@Sun.COM if ((partition & 0x00FF00) != 0x00FF00) 875*8044SWilliam.Kucharski@Sun.COM { 876*8044SWilliam.Kucharski@Sun.COM /* If the partition is a BSD partition, it is difficult to 877*8044SWilliam.Kucharski@Sun.COM obtain the representation in Linux. So don't support that. */ 878*8044SWilliam.Kucharski@Sun.COM errnum = ERR_DEV_VALUES; 879*8044SWilliam.Kucharski@Sun.COM return 1; 880*8044SWilliam.Kucharski@Sun.COM } 881*8044SWilliam.Kucharski@Sun.COM 882*8044SWilliam.Kucharski@Sun.COM assert (map[drive] != 0); 883*8044SWilliam.Kucharski@Sun.COM 884*8044SWilliam.Kucharski@Sun.COM strcpy (dev, map[drive]); 885*8044SWilliam.Kucharski@Sun.COM if (have_devfs ()) 886*8044SWilliam.Kucharski@Sun.COM { 887*8044SWilliam.Kucharski@Sun.COM if (strcmp (dev + strlen(dev) - 5, "/disc") == 0) 888*8044SWilliam.Kucharski@Sun.COM strcpy (dev + strlen(dev) - 5, "/part"); 889*8044SWilliam.Kucharski@Sun.COM } 890*8044SWilliam.Kucharski@Sun.COM sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1); 891*8044SWilliam.Kucharski@Sun.COM 892*8044SWilliam.Kucharski@Sun.COM /* Open the partition. */ 893*8044SWilliam.Kucharski@Sun.COM fd = open (dev, O_RDWR); 894*8044SWilliam.Kucharski@Sun.COM if (fd < 0) 895*8044SWilliam.Kucharski@Sun.COM { 896*8044SWilliam.Kucharski@Sun.COM errnum = ERR_NO_PART; 897*8044SWilliam.Kucharski@Sun.COM return 0; 898*8044SWilliam.Kucharski@Sun.COM } 899*8044SWilliam.Kucharski@Sun.COM 900*8044SWilliam.Kucharski@Sun.COM #if defined(__linux__) && (!defined(__GLIBC__) || \ 901*8044SWilliam.Kucharski@Sun.COM ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) 902*8044SWilliam.Kucharski@Sun.COM /* Maybe libc doesn't have large file support. */ 903*8044SWilliam.Kucharski@Sun.COM { 904*8044SWilliam.Kucharski@Sun.COM loff_t offset, result; 905*8044SWilliam.Kucharski@Sun.COM static int _llseek (uint filedes, ulong hi, ulong lo, 906*8044SWilliam.Kucharski@Sun.COM loff_t *res, uint wh); 907*8044SWilliam.Kucharski@Sun.COM _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, 908*8044SWilliam.Kucharski@Sun.COM loff_t *, res, uint, wh); 909*8044SWilliam.Kucharski@Sun.COM 910*8044SWilliam.Kucharski@Sun.COM offset = (loff_t) sector * (loff_t) SECTOR_SIZE; 911*8044SWilliam.Kucharski@Sun.COM if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) 912*8044SWilliam.Kucharski@Sun.COM { 913*8044SWilliam.Kucharski@Sun.COM errnum = ERR_DEV_VALUES; 914*8044SWilliam.Kucharski@Sun.COM return 0; 915*8044SWilliam.Kucharski@Sun.COM } 916*8044SWilliam.Kucharski@Sun.COM } 917*8044SWilliam.Kucharski@Sun.COM #else 918*8044SWilliam.Kucharski@Sun.COM { 919*8044SWilliam.Kucharski@Sun.COM off_t offset = (off_t) sector * (off_t) SECTOR_SIZE; 920*8044SWilliam.Kucharski@Sun.COM 921*8044SWilliam.Kucharski@Sun.COM if (lseek (fd, offset, SEEK_SET) != offset) 922*8044SWilliam.Kucharski@Sun.COM { 923*8044SWilliam.Kucharski@Sun.COM errnum = ERR_DEV_VALUES; 924*8044SWilliam.Kucharski@Sun.COM return 0; 925*8044SWilliam.Kucharski@Sun.COM } 926*8044SWilliam.Kucharski@Sun.COM } 927*8044SWilliam.Kucharski@Sun.COM #endif 928*8044SWilliam.Kucharski@Sun.COM 929*8044SWilliam.Kucharski@Sun.COM if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE)) 930*8044SWilliam.Kucharski@Sun.COM { 931*8044SWilliam.Kucharski@Sun.COM close (fd); 932*8044SWilliam.Kucharski@Sun.COM errnum = ERR_WRITE; 933*8044SWilliam.Kucharski@Sun.COM return 0; 934*8044SWilliam.Kucharski@Sun.COM } 935*8044SWilliam.Kucharski@Sun.COM 936*8044SWilliam.Kucharski@Sun.COM sync (); /* Paranoia. */ 937*8044SWilliam.Kucharski@Sun.COM close (fd); 938*8044SWilliam.Kucharski@Sun.COM 939*8044SWilliam.Kucharski@Sun.COM return 1; 940*8044SWilliam.Kucharski@Sun.COM } 941*8044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */ 942