xref: /onnv-gate/usr/src/grub/grub-0.97/lib/device.c (revision 9768:c62013fcda99)
18044SWilliam.Kucharski@Sun.COM /* device.c - Some helper functions for OS devices and BIOS drives */
28044SWilliam.Kucharski@Sun.COM /*
38044SWilliam.Kucharski@Sun.COM  *  GRUB  --  GRand Unified Bootloader
48044SWilliam.Kucharski@Sun.COM  *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005  Free Software Foundation, Inc.
58044SWilliam.Kucharski@Sun.COM  *
68044SWilliam.Kucharski@Sun.COM  *  This program is free software; you can redistribute it and/or modify
78044SWilliam.Kucharski@Sun.COM  *  it under the terms of the GNU General Public License as published by
88044SWilliam.Kucharski@Sun.COM  *  the Free Software Foundation; either version 2 of the License, or
98044SWilliam.Kucharski@Sun.COM  *  (at your option) any later version.
108044SWilliam.Kucharski@Sun.COM  *
118044SWilliam.Kucharski@Sun.COM  *  This program is distributed in the hope that it will be useful,
128044SWilliam.Kucharski@Sun.COM  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
138044SWilliam.Kucharski@Sun.COM  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
148044SWilliam.Kucharski@Sun.COM  *  GNU General Public License for more details.
158044SWilliam.Kucharski@Sun.COM  *
168044SWilliam.Kucharski@Sun.COM  *  You should have received a copy of the GNU General Public License
178044SWilliam.Kucharski@Sun.COM  *  along with this program; if not, write to the Free Software
188044SWilliam.Kucharski@Sun.COM  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
198044SWilliam.Kucharski@Sun.COM  */
208044SWilliam.Kucharski@Sun.COM 
218044SWilliam.Kucharski@Sun.COM /* Try to use glibc's transparant LFS support. */
228044SWilliam.Kucharski@Sun.COM #define _LARGEFILE_SOURCE       1
238044SWilliam.Kucharski@Sun.COM /* lseek becomes synonymous with lseek64.  */
248044SWilliam.Kucharski@Sun.COM #define _FILE_OFFSET_BITS       64
258044SWilliam.Kucharski@Sun.COM 
268044SWilliam.Kucharski@Sun.COM #include <stdio.h>
278044SWilliam.Kucharski@Sun.COM #include <stdlib.h>
288044SWilliam.Kucharski@Sun.COM #include <string.h>
298044SWilliam.Kucharski@Sun.COM #include <ctype.h>
308044SWilliam.Kucharski@Sun.COM #include <assert.h>
318044SWilliam.Kucharski@Sun.COM #include <unistd.h>
328044SWilliam.Kucharski@Sun.COM #include <sys/types.h>
338044SWilliam.Kucharski@Sun.COM #include <sys/stat.h>
348044SWilliam.Kucharski@Sun.COM #include <fcntl.h>
358044SWilliam.Kucharski@Sun.COM #include <errno.h>
368044SWilliam.Kucharski@Sun.COM #include <limits.h>
378044SWilliam.Kucharski@Sun.COM #include <stdarg.h>
388044SWilliam.Kucharski@Sun.COM 
398044SWilliam.Kucharski@Sun.COM #ifdef __linux__
408044SWilliam.Kucharski@Sun.COM # if !defined(__GLIBC__) || \
418044SWilliam.Kucharski@Sun.COM         ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
428044SWilliam.Kucharski@Sun.COM /* Maybe libc doesn't have large file support.  */
438044SWilliam.Kucharski@Sun.COM #  include <linux/unistd.h>     /* _llseek */
448044SWilliam.Kucharski@Sun.COM # endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
458044SWilliam.Kucharski@Sun.COM # include <sys/ioctl.h>		/* ioctl */
468044SWilliam.Kucharski@Sun.COM # ifndef HDIO_GETGEO
478044SWilliam.Kucharski@Sun.COM #  define HDIO_GETGEO	0x0301	/* get device geometry */
488044SWilliam.Kucharski@Sun.COM /* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
498044SWilliam.Kucharski@Sun.COM    defined.  */
508044SWilliam.Kucharski@Sun.COM struct hd_geometry
518044SWilliam.Kucharski@Sun.COM {
528044SWilliam.Kucharski@Sun.COM   unsigned char heads;
538044SWilliam.Kucharski@Sun.COM   unsigned char sectors;
548044SWilliam.Kucharski@Sun.COM   unsigned short cylinders;
558044SWilliam.Kucharski@Sun.COM   unsigned long start;
568044SWilliam.Kucharski@Sun.COM };
578044SWilliam.Kucharski@Sun.COM # endif /* ! HDIO_GETGEO */
588044SWilliam.Kucharski@Sun.COM # ifndef FLOPPY_MAJOR
598044SWilliam.Kucharski@Sun.COM #  define FLOPPY_MAJOR	2	/* the major number for floppy */
608044SWilliam.Kucharski@Sun.COM # endif /* ! FLOPPY_MAJOR */
618044SWilliam.Kucharski@Sun.COM # ifndef MAJOR
628044SWilliam.Kucharski@Sun.COM #  define MAJOR(dev)	\
638044SWilliam.Kucharski@Sun.COM   ({ \
648044SWilliam.Kucharski@Sun.COM      unsigned long long __dev = (dev); \
658044SWilliam.Kucharski@Sun.COM      (unsigned) ((__dev >> 8) & 0xfff) \
668044SWilliam.Kucharski@Sun.COM                  | ((unsigned int) (__dev >> 32) & ~0xfff); \
678044SWilliam.Kucharski@Sun.COM   })
688044SWilliam.Kucharski@Sun.COM # endif /* ! MAJOR */
698044SWilliam.Kucharski@Sun.COM # ifndef CDROM_GET_CAPABILITY
708044SWilliam.Kucharski@Sun.COM #  define CDROM_GET_CAPABILITY	0x5331	/* get capabilities */
718044SWilliam.Kucharski@Sun.COM # endif /* ! CDROM_GET_CAPABILITY */
728044SWilliam.Kucharski@Sun.COM # ifndef BLKGETSIZE
738044SWilliam.Kucharski@Sun.COM #  define BLKGETSIZE	_IO(0x12,96)	/* return device size */
748044SWilliam.Kucharski@Sun.COM # endif /* ! BLKGETSIZE */
758044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */
768044SWilliam.Kucharski@Sun.COM 
778044SWilliam.Kucharski@Sun.COM /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
788044SWilliam.Kucharski@Sun.COM    kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */
798044SWilliam.Kucharski@Sun.COM #if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__)
808044SWilliam.Kucharski@Sun.COM # define __FreeBSD_kernel__
818044SWilliam.Kucharski@Sun.COM #endif
828044SWilliam.Kucharski@Sun.COM #ifdef __FreeBSD_kernel__
838044SWilliam.Kucharski@Sun.COM   /* Obtain version of kFreeBSD headers */
848044SWilliam.Kucharski@Sun.COM # include <osreldate.h>
858044SWilliam.Kucharski@Sun.COM # ifndef __FreeBSD_kernel_version
868044SWilliam.Kucharski@Sun.COM #  define __FreeBSD_kernel_version __FreeBSD_version
878044SWilliam.Kucharski@Sun.COM # endif
888044SWilliam.Kucharski@Sun.COM 
898044SWilliam.Kucharski@Sun.COM   /* Runtime detection of kernel */
908044SWilliam.Kucharski@Sun.COM # include <sys/utsname.h>
918044SWilliam.Kucharski@Sun.COM int
get_kfreebsd_version()928044SWilliam.Kucharski@Sun.COM get_kfreebsd_version ()
938044SWilliam.Kucharski@Sun.COM {
948044SWilliam.Kucharski@Sun.COM   struct utsname uts;
958044SWilliam.Kucharski@Sun.COM   int major; int minor, v[2];
968044SWilliam.Kucharski@Sun.COM 
978044SWilliam.Kucharski@Sun.COM   uname (&uts);
988044SWilliam.Kucharski@Sun.COM   sscanf (uts.release, "%d.%d", &major, &minor);
998044SWilliam.Kucharski@Sun.COM 
1008044SWilliam.Kucharski@Sun.COM   if (major >= 9)
1018044SWilliam.Kucharski@Sun.COM     major = 9;
1028044SWilliam.Kucharski@Sun.COM   if (major >= 5)
1038044SWilliam.Kucharski@Sun.COM     {
1048044SWilliam.Kucharski@Sun.COM       v[0] = minor/10; v[1] = minor%10;
1058044SWilliam.Kucharski@Sun.COM     }
1068044SWilliam.Kucharski@Sun.COM   else
1078044SWilliam.Kucharski@Sun.COM     {
1088044SWilliam.Kucharski@Sun.COM       v[0] = minor%10; v[1] = minor/10;
1098044SWilliam.Kucharski@Sun.COM     }
1108044SWilliam.Kucharski@Sun.COM   return major*100000+v[0]*10000+v[1]*1000;
1118044SWilliam.Kucharski@Sun.COM }
1128044SWilliam.Kucharski@Sun.COM #endif /* __FreeBSD_kernel__ */
1138044SWilliam.Kucharski@Sun.COM 
1148044SWilliam.Kucharski@Sun.COM #if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
1158044SWilliam.Kucharski@Sun.COM # include <sys/ioctl.h>		/* ioctl */
1168044SWilliam.Kucharski@Sun.COM # include <sys/disklabel.h>
1178044SWilliam.Kucharski@Sun.COM # include <sys/cdio.h>		/* CDIOCCLRDEBUG */
1188044SWilliam.Kucharski@Sun.COM # if defined(__FreeBSD_kernel__)
1198044SWilliam.Kucharski@Sun.COM #  include <sys/param.h>
1208044SWilliam.Kucharski@Sun.COM #  if __FreeBSD_kernel_version >= 500040
1218044SWilliam.Kucharski@Sun.COM #   include <sys/disk.h>
1228044SWilliam.Kucharski@Sun.COM #  endif
1238044SWilliam.Kucharski@Sun.COM # endif /* __FreeBSD_kernel__ */
1248044SWilliam.Kucharski@Sun.COM #endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
1258044SWilliam.Kucharski@Sun.COM 
1268044SWilliam.Kucharski@Sun.COM #if defined(__sun)
1278044SWilliam.Kucharski@Sun.COM # include <sys/dkio.h>
1288044SWilliam.Kucharski@Sun.COM #endif /* __sun */
1298044SWilliam.Kucharski@Sun.COM 
1308044SWilliam.Kucharski@Sun.COM #ifdef HAVE_OPENDISK
1318044SWilliam.Kucharski@Sun.COM # include <util.h>
1328044SWilliam.Kucharski@Sun.COM #endif /* HAVE_OPENDISK */
1338044SWilliam.Kucharski@Sun.COM 
1348044SWilliam.Kucharski@Sun.COM #define WITHOUT_LIBC_STUBS	1
1358044SWilliam.Kucharski@Sun.COM #include <shared.h>
1368044SWilliam.Kucharski@Sun.COM #include <device.h>
1378044SWilliam.Kucharski@Sun.COM 
1388044SWilliam.Kucharski@Sun.COM /* Get the geometry of a drive DRIVE.  */
1398044SWilliam.Kucharski@Sun.COM void
get_drive_geometry(struct geometry * geom,char ** map,int drive)1408044SWilliam.Kucharski@Sun.COM get_drive_geometry (struct geometry *geom, char **map, int drive)
1418044SWilliam.Kucharski@Sun.COM {
1428044SWilliam.Kucharski@Sun.COM   int fd;
1438044SWilliam.Kucharski@Sun.COM 
1448044SWilliam.Kucharski@Sun.COM   if (geom->flags == -1)
1458044SWilliam.Kucharski@Sun.COM     {
1468044SWilliam.Kucharski@Sun.COM       fd = open (map[drive], O_RDONLY);
1478044SWilliam.Kucharski@Sun.COM       assert (fd >= 0);
1488044SWilliam.Kucharski@Sun.COM     }
1498044SWilliam.Kucharski@Sun.COM   else
1508044SWilliam.Kucharski@Sun.COM     fd = geom->flags;
1518044SWilliam.Kucharski@Sun.COM 
1528044SWilliam.Kucharski@Sun.COM   /* XXX This is the default size.  */
1538044SWilliam.Kucharski@Sun.COM   geom->sector_size = SECTOR_SIZE;
1548044SWilliam.Kucharski@Sun.COM 
1558044SWilliam.Kucharski@Sun.COM #if defined(__linux__)
1568044SWilliam.Kucharski@Sun.COM   /* Linux */
1578044SWilliam.Kucharski@Sun.COM   {
1588044SWilliam.Kucharski@Sun.COM     struct hd_geometry hdg;
1598044SWilliam.Kucharski@Sun.COM     unsigned long nr;
1608044SWilliam.Kucharski@Sun.COM 
1618044SWilliam.Kucharski@Sun.COM     if (ioctl (fd, HDIO_GETGEO, &hdg))
1628044SWilliam.Kucharski@Sun.COM       goto fail;
1638044SWilliam.Kucharski@Sun.COM 
1648044SWilliam.Kucharski@Sun.COM     if (ioctl (fd, BLKGETSIZE, &nr))
1658044SWilliam.Kucharski@Sun.COM       goto fail;
1668044SWilliam.Kucharski@Sun.COM 
1678044SWilliam.Kucharski@Sun.COM     /* Got the geometry, so save it. */
1688044SWilliam.Kucharski@Sun.COM     geom->cylinders = hdg.cylinders;
1698044SWilliam.Kucharski@Sun.COM     geom->heads = hdg.heads;
1708044SWilliam.Kucharski@Sun.COM     geom->sectors = hdg.sectors;
1718044SWilliam.Kucharski@Sun.COM     geom->total_sectors = nr;
1728044SWilliam.Kucharski@Sun.COM 
1738044SWilliam.Kucharski@Sun.COM     goto success;
1748044SWilliam.Kucharski@Sun.COM   }
1758044SWilliam.Kucharski@Sun.COM 
1768044SWilliam.Kucharski@Sun.COM #elif defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
1778044SWilliam.Kucharski@Sun.COM # if defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version >= 500040
1788044SWilliam.Kucharski@Sun.COM   /* kFreeBSD version 5 or later */
1798044SWilliam.Kucharski@Sun.COM   if (get_kfreebsd_version () >= 500040)
1808044SWilliam.Kucharski@Sun.COM   {
1818044SWilliam.Kucharski@Sun.COM     unsigned int sector_size;
1828044SWilliam.Kucharski@Sun.COM     off_t media_size;
1838044SWilliam.Kucharski@Sun.COM     unsigned int tmp;
1848044SWilliam.Kucharski@Sun.COM 
1858044SWilliam.Kucharski@Sun.COM     if(ioctl (fd, DIOCGSECTORSIZE, &sector_size) != 0)
1868044SWilliam.Kucharski@Sun.COM       sector_size = 512;
1878044SWilliam.Kucharski@Sun.COM 
1888044SWilliam.Kucharski@Sun.COM     if (ioctl (fd, DIOCGMEDIASIZE, &media_size) != 0)
1898044SWilliam.Kucharski@Sun.COM       goto fail;
1908044SWilliam.Kucharski@Sun.COM 
1918044SWilliam.Kucharski@Sun.COM     geom->total_sectors = media_size / sector_size;
1928044SWilliam.Kucharski@Sun.COM 
1938044SWilliam.Kucharski@Sun.COM     if (ioctl (fd, DIOCGFWSECTORS, &tmp) == 0)
1948044SWilliam.Kucharski@Sun.COM       geom->sectors = tmp;
1958044SWilliam.Kucharski@Sun.COM     else
1968044SWilliam.Kucharski@Sun.COM       geom->sectors = 63;
1978044SWilliam.Kucharski@Sun.COM     if (ioctl (fd, DIOCGFWHEADS, &tmp) == 0)
1988044SWilliam.Kucharski@Sun.COM       geom->heads = tmp;
1998044SWilliam.Kucharski@Sun.COM     else if (geom->total_sectors <= 63 * 1 * 1024)
2008044SWilliam.Kucharski@Sun.COM       geom->heads = 1;
2018044SWilliam.Kucharski@Sun.COM     else if (geom->total_sectors <= 63 * 16 * 1024)
2028044SWilliam.Kucharski@Sun.COM       geom->heads = 16;
2038044SWilliam.Kucharski@Sun.COM     else
2048044SWilliam.Kucharski@Sun.COM       geom->heads = 255;
2058044SWilliam.Kucharski@Sun.COM 
2068044SWilliam.Kucharski@Sun.COM     geom->cylinders = (geom->total_sectors
2078044SWilliam.Kucharski@Sun.COM 			   / geom->heads
2088044SWilliam.Kucharski@Sun.COM 			   / geom->sectors);
2098044SWilliam.Kucharski@Sun.COM 
2108044SWilliam.Kucharski@Sun.COM     goto success;
2118044SWilliam.Kucharski@Sun.COM   }
2128044SWilliam.Kucharski@Sun.COM   else
2138044SWilliam.Kucharski@Sun.COM #endif /* defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version >= 500040 */
2148044SWilliam.Kucharski@Sun.COM 
2158044SWilliam.Kucharski@Sun.COM   /* kFreeBSD < 5, NetBSD or OpenBSD */
2168044SWilliam.Kucharski@Sun.COM   {
2178044SWilliam.Kucharski@Sun.COM     struct disklabel hdg;
2188044SWilliam.Kucharski@Sun.COM     if (ioctl (fd, DIOCGDINFO, &hdg))
2198044SWilliam.Kucharski@Sun.COM       goto fail;
2208044SWilliam.Kucharski@Sun.COM 
2218044SWilliam.Kucharski@Sun.COM     geom->cylinders = hdg.d_ncylinders;
2228044SWilliam.Kucharski@Sun.COM     geom->heads = hdg.d_ntracks;
2238044SWilliam.Kucharski@Sun.COM     geom->sectors = hdg.d_nsectors;
2248044SWilliam.Kucharski@Sun.COM     geom->total_sectors = hdg.d_secperunit;
2258044SWilliam.Kucharski@Sun.COM 
2268044SWilliam.Kucharski@Sun.COM     goto success;
2278044SWilliam.Kucharski@Sun.COM   }
2288044SWilliam.Kucharski@Sun.COM 
2298044SWilliam.Kucharski@Sun.COM #elif defined(__sun)
2308044SWilliam.Kucharski@Sun.COM   /* Solaris */
2318044SWilliam.Kucharski@Sun.COM   {
2328044SWilliam.Kucharski@Sun.COM     struct dk_geom dkg;
2338044SWilliam.Kucharski@Sun.COM 
2348044SWilliam.Kucharski@Sun.COM     if (ioctl(fd, DKIOCG_PHYGEOM, &dkg))
2358044SWilliam.Kucharski@Sun.COM       goto fail;
2368044SWilliam.Kucharski@Sun.COM     geom->cylinders = dkg.dkg_ncyl;
2378044SWilliam.Kucharski@Sun.COM     geom->heads = dkg.dkg_nhead;
2388044SWilliam.Kucharski@Sun.COM     geom->sectors = dkg.dkg_nsect;
239*9768SShidokht.Yadegari@Sun.COM     geom->total_sectors = (unsigned long long)dkg.dkg_ncyl * dkg.dkg_nhead
240*9768SShidokht.Yadegari@Sun.COM 	* dkg.dkg_nsect;
2418044SWilliam.Kucharski@Sun.COM 
2428044SWilliam.Kucharski@Sun.COM     goto success;
2438044SWilliam.Kucharski@Sun.COM   }
2448044SWilliam.Kucharski@Sun.COM 
2458044SWilliam.Kucharski@Sun.COM #else
2468044SWilliam.Kucharski@Sun.COM   /* Notably, defined(__GNU__) */
2478044SWilliam.Kucharski@Sun.COM # warning "Automatic detection of geometries will be performed only \
2488044SWilliam.Kucharski@Sun.COM partially. This is not fatal."
2498044SWilliam.Kucharski@Sun.COM #endif
2508044SWilliam.Kucharski@Sun.COM 
2518044SWilliam.Kucharski@Sun.COM  fail:
2528044SWilliam.Kucharski@Sun.COM   {
2538044SWilliam.Kucharski@Sun.COM     struct stat st;
2548044SWilliam.Kucharski@Sun.COM 
2558044SWilliam.Kucharski@Sun.COM     /* FIXME: It would be nice to somehow compute fake C/H/S settings,
2568044SWilliam.Kucharski@Sun.COM        given a proper st_blocks size. */
2578044SWilliam.Kucharski@Sun.COM     if (drive & 0x80)
2588044SWilliam.Kucharski@Sun.COM       {
2598044SWilliam.Kucharski@Sun.COM 	geom->cylinders = DEFAULT_HD_CYLINDERS;
2608044SWilliam.Kucharski@Sun.COM 	geom->heads = DEFAULT_HD_HEADS;
2618044SWilliam.Kucharski@Sun.COM 	geom->sectors = DEFAULT_HD_SECTORS;
2628044SWilliam.Kucharski@Sun.COM       }
2638044SWilliam.Kucharski@Sun.COM     else
2648044SWilliam.Kucharski@Sun.COM       {
2658044SWilliam.Kucharski@Sun.COM 	geom->cylinders = DEFAULT_FD_CYLINDERS;
2668044SWilliam.Kucharski@Sun.COM 	geom->heads = DEFAULT_FD_HEADS;
2678044SWilliam.Kucharski@Sun.COM 	geom->sectors = DEFAULT_FD_SECTORS;
2688044SWilliam.Kucharski@Sun.COM       }
2698044SWilliam.Kucharski@Sun.COM 
2708044SWilliam.Kucharski@Sun.COM     /* Set the total sectors properly, if we can. */
2718044SWilliam.Kucharski@Sun.COM     if (! fstat (fd, &st) && st.st_blocks)
2728044SWilliam.Kucharski@Sun.COM       geom->total_sectors = st.st_blocks >> SECTOR_BITS;
2738044SWilliam.Kucharski@Sun.COM     else
274*9768SShidokht.Yadegari@Sun.COM       geom->total_sectors = (unsigned long long)geom->cylinders *
275*9768SShidokht.Yadegari@Sun.COM 	geom->heads * geom->sectors;
2768044SWilliam.Kucharski@Sun.COM   }
2778044SWilliam.Kucharski@Sun.COM 
2788044SWilliam.Kucharski@Sun.COM  success:
2798044SWilliam.Kucharski@Sun.COM   if (geom->flags == -1)
2808044SWilliam.Kucharski@Sun.COM     close (fd);
2818044SWilliam.Kucharski@Sun.COM }
2828044SWilliam.Kucharski@Sun.COM 
2838044SWilliam.Kucharski@Sun.COM #ifdef __linux__
2848044SWilliam.Kucharski@Sun.COM /* Check if we have devfs support.  */
2858044SWilliam.Kucharski@Sun.COM static int
have_devfs(void)2868044SWilliam.Kucharski@Sun.COM have_devfs (void)
2878044SWilliam.Kucharski@Sun.COM {
2888044SWilliam.Kucharski@Sun.COM   static int dev_devfsd_exists = -1;
2898044SWilliam.Kucharski@Sun.COM 
2908044SWilliam.Kucharski@Sun.COM   if (dev_devfsd_exists < 0)
2918044SWilliam.Kucharski@Sun.COM     {
2928044SWilliam.Kucharski@Sun.COM       struct stat st;
2938044SWilliam.Kucharski@Sun.COM 
2948044SWilliam.Kucharski@Sun.COM       dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0;
2958044SWilliam.Kucharski@Sun.COM     }
2968044SWilliam.Kucharski@Sun.COM 
2978044SWilliam.Kucharski@Sun.COM   return dev_devfsd_exists;
2988044SWilliam.Kucharski@Sun.COM }
2998044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */
3008044SWilliam.Kucharski@Sun.COM 
3018044SWilliam.Kucharski@Sun.COM /* These three functions are quite different among OSes.  */
3028044SWilliam.Kucharski@Sun.COM static void
get_floppy_disk_name(char * name,int unit)3038044SWilliam.Kucharski@Sun.COM get_floppy_disk_name (char *name, int unit)
3048044SWilliam.Kucharski@Sun.COM {
3058044SWilliam.Kucharski@Sun.COM #if defined(__linux__)
3068044SWilliam.Kucharski@Sun.COM   /* GNU/Linux */
3078044SWilliam.Kucharski@Sun.COM   if (have_devfs ())
3088044SWilliam.Kucharski@Sun.COM     sprintf (name, "/dev/floppy/%d", unit);
3098044SWilliam.Kucharski@Sun.COM   else
3108044SWilliam.Kucharski@Sun.COM     sprintf (name, "/dev/fd%d", unit);
3118044SWilliam.Kucharski@Sun.COM #elif defined(__GNU__)
3128044SWilliam.Kucharski@Sun.COM   /* GNU/Hurd */
3138044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/fd%d", unit);
3148044SWilliam.Kucharski@Sun.COM #elif defined(__FreeBSD_kernel__)
3158044SWilliam.Kucharski@Sun.COM   /* kFreeBSD */
3168044SWilliam.Kucharski@Sun.COM   if (get_kfreebsd_version () >= 400000)
3178044SWilliam.Kucharski@Sun.COM     sprintf (name, "/dev/fd%d", unit);
3188044SWilliam.Kucharski@Sun.COM   else
3198044SWilliam.Kucharski@Sun.COM     sprintf (name, "/dev/rfd%d", unit);
3208044SWilliam.Kucharski@Sun.COM #elif defined(__NetBSD__)
3218044SWilliam.Kucharski@Sun.COM   /* NetBSD */
3228044SWilliam.Kucharski@Sun.COM   /* opendisk() doesn't work for floppies.  */
3238044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/rfd%da", unit);
3248044SWilliam.Kucharski@Sun.COM #elif defined(__OpenBSD__)
3258044SWilliam.Kucharski@Sun.COM   /* OpenBSD */
3268044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/rfd%dc", unit);
3278044SWilliam.Kucharski@Sun.COM #elif defined(__QNXNTO__)
3288044SWilliam.Kucharski@Sun.COM   /* QNX RTP */
3298044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/fd%d", unit);
3308044SWilliam.Kucharski@Sun.COM #elif defined(__sun)
3318044SWilliam.Kucharski@Sun.COM   /* Solaris */
3328044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/rdiskette%d", unit);
3338044SWilliam.Kucharski@Sun.COM #else
3348044SWilliam.Kucharski@Sun.COM # warning "BIOS floppy drives cannot be guessed in your operating system."
3358044SWilliam.Kucharski@Sun.COM   /* Set NAME to a bogus string.  */
3368044SWilliam.Kucharski@Sun.COM   *name = 0;
3378044SWilliam.Kucharski@Sun.COM #endif
3388044SWilliam.Kucharski@Sun.COM }
3398044SWilliam.Kucharski@Sun.COM 
3408044SWilliam.Kucharski@Sun.COM static void
get_ide_disk_name(char * name,int unit)3418044SWilliam.Kucharski@Sun.COM get_ide_disk_name (char *name, int unit)
3428044SWilliam.Kucharski@Sun.COM {
3438044SWilliam.Kucharski@Sun.COM #if defined(__linux__)
3448044SWilliam.Kucharski@Sun.COM   /* GNU/Linux */
3458044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/hd%c", unit + 'a');
3468044SWilliam.Kucharski@Sun.COM #elif defined(__GNU__)
3478044SWilliam.Kucharski@Sun.COM   /* GNU/Hurd */
3488044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/hd%d", unit);
3498044SWilliam.Kucharski@Sun.COM #elif defined(__FreeBSD_kernel__)
3508044SWilliam.Kucharski@Sun.COM   /* kFreeBSD */
3518044SWilliam.Kucharski@Sun.COM   if (get_kfreebsd_version () >= 400000)
3528044SWilliam.Kucharski@Sun.COM     sprintf (name, "/dev/ad%d", unit);
3538044SWilliam.Kucharski@Sun.COM   else
3548044SWilliam.Kucharski@Sun.COM     sprintf (name, "/dev/rwd%d", unit);
3558044SWilliam.Kucharski@Sun.COM #elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
3568044SWilliam.Kucharski@Sun.COM   /* NetBSD */
3578044SWilliam.Kucharski@Sun.COM   char shortname[16];
3588044SWilliam.Kucharski@Sun.COM   int fd;
3598044SWilliam.Kucharski@Sun.COM 
3608044SWilliam.Kucharski@Sun.COM   sprintf (shortname, "wd%d", unit);
3618044SWilliam.Kucharski@Sun.COM   fd = opendisk (shortname, O_RDONLY, name,
3628044SWilliam.Kucharski@Sun.COM 		 16,	/* length of NAME */
3638044SWilliam.Kucharski@Sun.COM 		 0	/* char device */
3648044SWilliam.Kucharski@Sun.COM 		 );
3658044SWilliam.Kucharski@Sun.COM   close (fd);
3668044SWilliam.Kucharski@Sun.COM #elif defined(__OpenBSD__)
3678044SWilliam.Kucharski@Sun.COM   /* OpenBSD */
3688044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/rwd%dc", unit);
3698044SWilliam.Kucharski@Sun.COM #elif defined(__QNXNTO__)
3708044SWilliam.Kucharski@Sun.COM   /* QNX RTP */
3718044SWilliam.Kucharski@Sun.COM   /* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
3728044SWilliam.Kucharski@Sun.COM      contain SCSI disks.  */
3738044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/hd%d", unit);
3748044SWilliam.Kucharski@Sun.COM #elif defined(__sun)
3758044SWilliam.Kucharski@Sun.COM   *name = 0;		/* FIXME */
3768044SWilliam.Kucharski@Sun.COM #else
3778044SWilliam.Kucharski@Sun.COM # warning "BIOS IDE drives cannot be guessed in your operating system."
3788044SWilliam.Kucharski@Sun.COM   /* Set NAME to a bogus string.  */
3798044SWilliam.Kucharski@Sun.COM   *name = 0;
3808044SWilliam.Kucharski@Sun.COM #endif
3818044SWilliam.Kucharski@Sun.COM }
3828044SWilliam.Kucharski@Sun.COM 
3838044SWilliam.Kucharski@Sun.COM static void
get_scsi_disk_name(char * name,int unit)3848044SWilliam.Kucharski@Sun.COM get_scsi_disk_name (char *name, int unit)
3858044SWilliam.Kucharski@Sun.COM {
3868044SWilliam.Kucharski@Sun.COM #if defined(__linux__)
3878044SWilliam.Kucharski@Sun.COM   /* GNU/Linux */
3888044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/sd%c", unit + 'a');
3898044SWilliam.Kucharski@Sun.COM #elif defined(__GNU__)
3908044SWilliam.Kucharski@Sun.COM   /* GNU/Hurd */
3918044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/sd%d", unit);
3928044SWilliam.Kucharski@Sun.COM #elif defined(__FreeBSD_kernel__)
3938044SWilliam.Kucharski@Sun.COM   /* kFreeBSD */
3948044SWilliam.Kucharski@Sun.COM   if (get_kfreebsd_version () >= 400000)
3958044SWilliam.Kucharski@Sun.COM     sprintf (name, "/dev/da%d", unit);
3968044SWilliam.Kucharski@Sun.COM   else
3978044SWilliam.Kucharski@Sun.COM     sprintf (name, "/dev/rda%d", unit);
3988044SWilliam.Kucharski@Sun.COM #elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
3998044SWilliam.Kucharski@Sun.COM   /* NetBSD */
4008044SWilliam.Kucharski@Sun.COM   char shortname[16];
4018044SWilliam.Kucharski@Sun.COM   int fd;
4028044SWilliam.Kucharski@Sun.COM 
4038044SWilliam.Kucharski@Sun.COM   sprintf (shortname, "sd%d", unit);
4048044SWilliam.Kucharski@Sun.COM   fd = opendisk (shortname, O_RDONLY, name,
4058044SWilliam.Kucharski@Sun.COM 		 16,	/* length of NAME */
4068044SWilliam.Kucharski@Sun.COM 		 0	/* char device */
4078044SWilliam.Kucharski@Sun.COM 		 );
4088044SWilliam.Kucharski@Sun.COM   close (fd);
4098044SWilliam.Kucharski@Sun.COM #elif defined(__OpenBSD__)
4108044SWilliam.Kucharski@Sun.COM   /* OpenBSD */
4118044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/rsd%dc", unit);
4128044SWilliam.Kucharski@Sun.COM #elif defined(__QNXNTO__)
4138044SWilliam.Kucharski@Sun.COM   /* QNX RTP */
4148044SWilliam.Kucharski@Sun.COM   /* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
4158044SWilliam.Kucharski@Sun.COM      disable the detection of SCSI disks here.  */
4168044SWilliam.Kucharski@Sun.COM   *name = 0;
4178044SWilliam.Kucharski@Sun.COM #elif defined(__sun)
4188044SWilliam.Kucharski@Sun.COM   *name = 0;		/* FIXME */
4198044SWilliam.Kucharski@Sun.COM #else
4208044SWilliam.Kucharski@Sun.COM # warning "BIOS SCSI drives cannot be guessed in your operating system."
4218044SWilliam.Kucharski@Sun.COM   /* Set NAME to a bogus string.  */
4228044SWilliam.Kucharski@Sun.COM   *name = 0;
4238044SWilliam.Kucharski@Sun.COM #endif
4248044SWilliam.Kucharski@Sun.COM }
4258044SWilliam.Kucharski@Sun.COM 
4268044SWilliam.Kucharski@Sun.COM #ifdef __linux__
4278044SWilliam.Kucharski@Sun.COM static void
get_dac960_disk_name(char * name,int controller,int drive)4288044SWilliam.Kucharski@Sun.COM get_dac960_disk_name (char *name, int controller, int drive)
4298044SWilliam.Kucharski@Sun.COM {
4308044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/rd/c%dd%d", controller, drive);
4318044SWilliam.Kucharski@Sun.COM }
4328044SWilliam.Kucharski@Sun.COM 
4338044SWilliam.Kucharski@Sun.COM static void
get_ataraid_disk_name(char * name,int unit)4348044SWilliam.Kucharski@Sun.COM get_ataraid_disk_name (char *name, int unit)
4358044SWilliam.Kucharski@Sun.COM {
4368044SWilliam.Kucharski@Sun.COM   sprintf (name, "/dev/ataraid/d%c", unit + '0');
4378044SWilliam.Kucharski@Sun.COM }
4388044SWilliam.Kucharski@Sun.COM #endif
4398044SWilliam.Kucharski@Sun.COM 
4408044SWilliam.Kucharski@Sun.COM /* Check if DEVICE can be read. If an error occurs, return zero,
4418044SWilliam.Kucharski@Sun.COM    otherwise return non-zero.  */
4428044SWilliam.Kucharski@Sun.COM int
check_device(const char * device)4438044SWilliam.Kucharski@Sun.COM check_device (const char *device)
4448044SWilliam.Kucharski@Sun.COM {
4458044SWilliam.Kucharski@Sun.COM   char buf[512];
4468044SWilliam.Kucharski@Sun.COM   FILE *fp;
4478044SWilliam.Kucharski@Sun.COM 
4488044SWilliam.Kucharski@Sun.COM   /* If DEVICE is empty, just return 1.  */
4498044SWilliam.Kucharski@Sun.COM   if (*device == 0)
4508044SWilliam.Kucharski@Sun.COM     return 1;
4518044SWilliam.Kucharski@Sun.COM 
4528044SWilliam.Kucharski@Sun.COM   fp = fopen (device, "r");
4538044SWilliam.Kucharski@Sun.COM   if (! fp)
4548044SWilliam.Kucharski@Sun.COM     {
4558044SWilliam.Kucharski@Sun.COM       switch (errno)
4568044SWilliam.Kucharski@Sun.COM 	{
4578044SWilliam.Kucharski@Sun.COM #ifdef ENOMEDIUM
4588044SWilliam.Kucharski@Sun.COM 	case ENOMEDIUM:
4598044SWilliam.Kucharski@Sun.COM # if 0
4608044SWilliam.Kucharski@Sun.COM 	  /* At the moment, this finds only CDROMs, which can't be
4618044SWilliam.Kucharski@Sun.COM 	     read anyway, so leave it out. Code should be
4628044SWilliam.Kucharski@Sun.COM 	     reactivated if `removable disks' and CDROMs are
4638044SWilliam.Kucharski@Sun.COM 	     supported.  */
4648044SWilliam.Kucharski@Sun.COM 	  /* Accept it, it may be inserted.  */
4658044SWilliam.Kucharski@Sun.COM 	  return 1;
4668044SWilliam.Kucharski@Sun.COM # endif
4678044SWilliam.Kucharski@Sun.COM 	  break;
4688044SWilliam.Kucharski@Sun.COM #endif /* ENOMEDIUM */
4698044SWilliam.Kucharski@Sun.COM 	default:
4708044SWilliam.Kucharski@Sun.COM 	  /* Break case and leave.  */
4718044SWilliam.Kucharski@Sun.COM 	  break;
4728044SWilliam.Kucharski@Sun.COM 	}
4738044SWilliam.Kucharski@Sun.COM       /* Error opening the device.  */
4748044SWilliam.Kucharski@Sun.COM       return 0;
4758044SWilliam.Kucharski@Sun.COM     }
4768044SWilliam.Kucharski@Sun.COM 
4778044SWilliam.Kucharski@Sun.COM   /* Make sure CD-ROMs don't get assigned a BIOS disk number
4788044SWilliam.Kucharski@Sun.COM      before SCSI disks!  */
4798044SWilliam.Kucharski@Sun.COM #ifdef __linux__
4808044SWilliam.Kucharski@Sun.COM # ifdef CDROM_GET_CAPABILITY
4818044SWilliam.Kucharski@Sun.COM   if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0)
4828044SWilliam.Kucharski@Sun.COM     return 0;
4838044SWilliam.Kucharski@Sun.COM # else /* ! CDROM_GET_CAPABILITY */
4848044SWilliam.Kucharski@Sun.COM   /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl.  */
4858044SWilliam.Kucharski@Sun.COM   {
4868044SWilliam.Kucharski@Sun.COM     struct hd_geometry hdg;
4878044SWilliam.Kucharski@Sun.COM     struct stat st;
4888044SWilliam.Kucharski@Sun.COM 
4898044SWilliam.Kucharski@Sun.COM     if (fstat (fileno (fp), &st))
4908044SWilliam.Kucharski@Sun.COM       return 0;
4918044SWilliam.Kucharski@Sun.COM 
4928044SWilliam.Kucharski@Sun.COM     /* If it is a block device and isn't a floppy, check if HDIO_GETGEO
4938044SWilliam.Kucharski@Sun.COM        succeeds.  */
4948044SWilliam.Kucharski@Sun.COM     if (S_ISBLK (st.st_mode)
4958044SWilliam.Kucharski@Sun.COM 	&& MAJOR (st.st_rdev) != FLOPPY_MAJOR
4968044SWilliam.Kucharski@Sun.COM 	&& ioctl (fileno (fp), HDIO_GETGEO, &hdg))
4978044SWilliam.Kucharski@Sun.COM       return 0;
4988044SWilliam.Kucharski@Sun.COM   }
4998044SWilliam.Kucharski@Sun.COM # endif /* ! CDROM_GET_CAPABILITY */
5008044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */
5018044SWilliam.Kucharski@Sun.COM 
5028044SWilliam.Kucharski@Sun.COM #if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
5038044SWilliam.Kucharski@Sun.COM # ifdef CDIOCCLRDEBUG
5048044SWilliam.Kucharski@Sun.COM   if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
5058044SWilliam.Kucharski@Sun.COM     return 0;
5068044SWilliam.Kucharski@Sun.COM # endif /* CDIOCCLRDEBUG */
5078044SWilliam.Kucharski@Sun.COM #endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
5088044SWilliam.Kucharski@Sun.COM 
5098044SWilliam.Kucharski@Sun.COM   /* Attempt to read the first sector.  */
5108044SWilliam.Kucharski@Sun.COM   if (fread (buf, 1, 512, fp) != 512)
5118044SWilliam.Kucharski@Sun.COM     {
5128044SWilliam.Kucharski@Sun.COM       fclose (fp);
5138044SWilliam.Kucharski@Sun.COM       return 0;
5148044SWilliam.Kucharski@Sun.COM     }
5158044SWilliam.Kucharski@Sun.COM 
5168044SWilliam.Kucharski@Sun.COM   fclose (fp);
5178044SWilliam.Kucharski@Sun.COM   return 1;
5188044SWilliam.Kucharski@Sun.COM }
5198044SWilliam.Kucharski@Sun.COM 
5208044SWilliam.Kucharski@Sun.COM /* Read mapping information from FP, and write it to MAP.  */
5218044SWilliam.Kucharski@Sun.COM static int
read_device_map(FILE * fp,char ** map,const char * map_file)5228044SWilliam.Kucharski@Sun.COM read_device_map (FILE *fp, char **map, const char *map_file)
5238044SWilliam.Kucharski@Sun.COM {
5248044SWilliam.Kucharski@Sun.COM   auto void show_error (int no, const char *msg);
5258044SWilliam.Kucharski@Sun.COM   auto void show_warning (int no, const char *msg, ...);
5268044SWilliam.Kucharski@Sun.COM 
5278044SWilliam.Kucharski@Sun.COM   auto void show_error (int no, const char *msg)
5288044SWilliam.Kucharski@Sun.COM     {
5298044SWilliam.Kucharski@Sun.COM       fprintf (stderr, "%s:%d: error: %s\n", map_file, no, msg);
5308044SWilliam.Kucharski@Sun.COM     }
5318044SWilliam.Kucharski@Sun.COM 
5328044SWilliam.Kucharski@Sun.COM   auto void show_warning (int no, const char *msg, ...)
5338044SWilliam.Kucharski@Sun.COM     {
5348044SWilliam.Kucharski@Sun.COM       va_list ap;
5358044SWilliam.Kucharski@Sun.COM 
5368044SWilliam.Kucharski@Sun.COM       va_start (ap, msg);
5378044SWilliam.Kucharski@Sun.COM       fprintf (stderr, "%s:%d: warning: ", map_file, no);
5388044SWilliam.Kucharski@Sun.COM       vfprintf (stderr, msg, ap);
5398044SWilliam.Kucharski@Sun.COM       va_end (ap);
5408044SWilliam.Kucharski@Sun.COM     }
5418044SWilliam.Kucharski@Sun.COM 
5428044SWilliam.Kucharski@Sun.COM   /* If there is the device map file, use the data in it instead of
5438044SWilliam.Kucharski@Sun.COM      probing devices.  */
5448044SWilliam.Kucharski@Sun.COM   char buf[1024];		/* XXX */
5458044SWilliam.Kucharski@Sun.COM   int line_number = 0;
5468044SWilliam.Kucharski@Sun.COM 
5478044SWilliam.Kucharski@Sun.COM   while (fgets (buf, sizeof (buf), fp))
5488044SWilliam.Kucharski@Sun.COM     {
5498044SWilliam.Kucharski@Sun.COM       char *ptr, *eptr;
5508044SWilliam.Kucharski@Sun.COM       int drive;
5518044SWilliam.Kucharski@Sun.COM       int is_floppy = 0;
5528044SWilliam.Kucharski@Sun.COM 
5538044SWilliam.Kucharski@Sun.COM       /* Increase the number of lines.  */
5548044SWilliam.Kucharski@Sun.COM       line_number++;
5558044SWilliam.Kucharski@Sun.COM 
5568044SWilliam.Kucharski@Sun.COM       /* If the first character is '#', skip it.  */
5578044SWilliam.Kucharski@Sun.COM       if (buf[0] == '#')
5588044SWilliam.Kucharski@Sun.COM 	continue;
5598044SWilliam.Kucharski@Sun.COM 
5608044SWilliam.Kucharski@Sun.COM       ptr = buf;
5618044SWilliam.Kucharski@Sun.COM       /* Skip leading spaces.  */
5628044SWilliam.Kucharski@Sun.COM       while (*ptr && isspace (*ptr))
5638044SWilliam.Kucharski@Sun.COM 	ptr++;
5648044SWilliam.Kucharski@Sun.COM 
5658044SWilliam.Kucharski@Sun.COM       /* Skip empty lines.  */
5668044SWilliam.Kucharski@Sun.COM       if (! *ptr)
5678044SWilliam.Kucharski@Sun.COM 	continue;
5688044SWilliam.Kucharski@Sun.COM 
5698044SWilliam.Kucharski@Sun.COM       if (*ptr != '(')
5708044SWilliam.Kucharski@Sun.COM 	{
5718044SWilliam.Kucharski@Sun.COM 	  show_error (line_number, "No open parenthesis found");
5728044SWilliam.Kucharski@Sun.COM 	  return 0;
5738044SWilliam.Kucharski@Sun.COM 	}
5748044SWilliam.Kucharski@Sun.COM 
5758044SWilliam.Kucharski@Sun.COM       ptr++;
5768044SWilliam.Kucharski@Sun.COM       if ((*ptr != 'f' && *ptr != 'h') || *(ptr + 1) != 'd')
5778044SWilliam.Kucharski@Sun.COM 	{
5788044SWilliam.Kucharski@Sun.COM 	  show_error (line_number, "Bad drive name");
5798044SWilliam.Kucharski@Sun.COM 	  return 0;
5808044SWilliam.Kucharski@Sun.COM 	}
5818044SWilliam.Kucharski@Sun.COM 
5828044SWilliam.Kucharski@Sun.COM       if (*ptr == 'f')
5838044SWilliam.Kucharski@Sun.COM 	is_floppy = 1;
5848044SWilliam.Kucharski@Sun.COM 
5858044SWilliam.Kucharski@Sun.COM       ptr += 2;
5868044SWilliam.Kucharski@Sun.COM       drive = strtoul (ptr, &ptr, 10);
5878044SWilliam.Kucharski@Sun.COM       if (drive < 0)
5888044SWilliam.Kucharski@Sun.COM 	{
5898044SWilliam.Kucharski@Sun.COM 	  show_error (line_number, "Bad device number");
5908044SWilliam.Kucharski@Sun.COM 	  return 0;
5918044SWilliam.Kucharski@Sun.COM 	}
5928044SWilliam.Kucharski@Sun.COM       else if (drive > 127)
5938044SWilliam.Kucharski@Sun.COM 	{
5948044SWilliam.Kucharski@Sun.COM 	  show_warning (line_number,
5958044SWilliam.Kucharski@Sun.COM 			"Ignoring %cd%d due to a BIOS limitation",
5968044SWilliam.Kucharski@Sun.COM 			is_floppy ? 'f' : 'h', drive);
5978044SWilliam.Kucharski@Sun.COM 	  continue;
5988044SWilliam.Kucharski@Sun.COM 	}
5998044SWilliam.Kucharski@Sun.COM 
6008044SWilliam.Kucharski@Sun.COM       if (! is_floppy)
6018044SWilliam.Kucharski@Sun.COM 	drive += 0x80;
6028044SWilliam.Kucharski@Sun.COM 
6038044SWilliam.Kucharski@Sun.COM       if (*ptr != ')')
6048044SWilliam.Kucharski@Sun.COM 	{
6058044SWilliam.Kucharski@Sun.COM 	  show_error (line_number, "No close parenthesis found");
6068044SWilliam.Kucharski@Sun.COM 	  return 0;
6078044SWilliam.Kucharski@Sun.COM 	}
6088044SWilliam.Kucharski@Sun.COM 
6098044SWilliam.Kucharski@Sun.COM       ptr++;
6108044SWilliam.Kucharski@Sun.COM       /* Skip spaces.  */
6118044SWilliam.Kucharski@Sun.COM       while (*ptr && isspace (*ptr))
6128044SWilliam.Kucharski@Sun.COM 	ptr++;
6138044SWilliam.Kucharski@Sun.COM 
6148044SWilliam.Kucharski@Sun.COM       if (! *ptr)
6158044SWilliam.Kucharski@Sun.COM 	{
6168044SWilliam.Kucharski@Sun.COM 	  show_error (line_number, "No filename found");
6178044SWilliam.Kucharski@Sun.COM 	  return 0;
6188044SWilliam.Kucharski@Sun.COM 	}
6198044SWilliam.Kucharski@Sun.COM 
6208044SWilliam.Kucharski@Sun.COM       /* Terminate the filename.  */
6218044SWilliam.Kucharski@Sun.COM       eptr = ptr;
6228044SWilliam.Kucharski@Sun.COM       while (*eptr && ! isspace (*eptr))
6238044SWilliam.Kucharski@Sun.COM 	eptr++;
6248044SWilliam.Kucharski@Sun.COM       *eptr = 0;
6258044SWilliam.Kucharski@Sun.COM 
6268044SWilliam.Kucharski@Sun.COM       /* Multiple entries for a given drive is not allowed.  */
6278044SWilliam.Kucharski@Sun.COM       if (map[drive])
6288044SWilliam.Kucharski@Sun.COM 	{
6298044SWilliam.Kucharski@Sun.COM 	  show_error (line_number, "Duplicated entry found");
6308044SWilliam.Kucharski@Sun.COM 	  return 0;
6318044SWilliam.Kucharski@Sun.COM 	}
6328044SWilliam.Kucharski@Sun.COM 
6338044SWilliam.Kucharski@Sun.COM       map[drive] = strdup (ptr);
6348044SWilliam.Kucharski@Sun.COM       assert (map[drive]);
6358044SWilliam.Kucharski@Sun.COM     }
6368044SWilliam.Kucharski@Sun.COM 
6378044SWilliam.Kucharski@Sun.COM   return 1;
6388044SWilliam.Kucharski@Sun.COM }
6398044SWilliam.Kucharski@Sun.COM 
6408044SWilliam.Kucharski@Sun.COM /* Initialize the device map MAP. *MAP will be allocated from the heap
6418044SWilliam.Kucharski@Sun.COM    space. If MAP_FILE is not NULL, then read mappings from the file
6428044SWilliam.Kucharski@Sun.COM    MAP_FILE if it exists, otherwise, write guessed mappings to the file.
6438044SWilliam.Kucharski@Sun.COM    FLOPPY_DISKS is the number of floppy disk drives which will be probed.
6448044SWilliam.Kucharski@Sun.COM    If it is zero, don't probe any floppy at all. If it is one, probe one
6458044SWilliam.Kucharski@Sun.COM    floppy. If it is two, probe two floppies. And so on.  */
6468044SWilliam.Kucharski@Sun.COM int
init_device_map(char *** map,const char * map_file,int floppy_disks)6478044SWilliam.Kucharski@Sun.COM init_device_map (char ***map, const char *map_file, int floppy_disks)
6488044SWilliam.Kucharski@Sun.COM {
6498044SWilliam.Kucharski@Sun.COM   int i;
6508044SWilliam.Kucharski@Sun.COM   int num_hd = 0;
6518044SWilliam.Kucharski@Sun.COM   FILE *fp = 0;
6528044SWilliam.Kucharski@Sun.COM 
6538044SWilliam.Kucharski@Sun.COM   assert (map);
6548044SWilliam.Kucharski@Sun.COM   assert (*map == 0);
6558044SWilliam.Kucharski@Sun.COM   *map = malloc (NUM_DISKS * sizeof (char *));
6568044SWilliam.Kucharski@Sun.COM   assert (*map);
6578044SWilliam.Kucharski@Sun.COM 
6588044SWilliam.Kucharski@Sun.COM   /* Probe devices for creating the device map.  */
6598044SWilliam.Kucharski@Sun.COM 
6608044SWilliam.Kucharski@Sun.COM   /* Initialize DEVICE_MAP.  */
6618044SWilliam.Kucharski@Sun.COM   for (i = 0; i < NUM_DISKS; i++)
6628044SWilliam.Kucharski@Sun.COM     (*map)[i] = 0;
6638044SWilliam.Kucharski@Sun.COM 
6648044SWilliam.Kucharski@Sun.COM   if (map_file)
6658044SWilliam.Kucharski@Sun.COM     {
6668044SWilliam.Kucharski@Sun.COM       /* Open the device map file.  */
6678044SWilliam.Kucharski@Sun.COM       fp = fopen (map_file, "r");
6688044SWilliam.Kucharski@Sun.COM       if (fp)
6698044SWilliam.Kucharski@Sun.COM 	{
6708044SWilliam.Kucharski@Sun.COM 	  int ret;
6718044SWilliam.Kucharski@Sun.COM 
6728044SWilliam.Kucharski@Sun.COM 	  ret = read_device_map (fp, *map, map_file);
6738044SWilliam.Kucharski@Sun.COM 	  fclose (fp);
6748044SWilliam.Kucharski@Sun.COM 	  return ret;
6758044SWilliam.Kucharski@Sun.COM 	}
6768044SWilliam.Kucharski@Sun.COM     }
6778044SWilliam.Kucharski@Sun.COM 
6788044SWilliam.Kucharski@Sun.COM   /* Print something so that the user does not think GRUB has been
6798044SWilliam.Kucharski@Sun.COM      crashed.  */
6808044SWilliam.Kucharski@Sun.COM   fprintf (stderr,
6818044SWilliam.Kucharski@Sun.COM 	   "Probing devices to guess BIOS drives. "
6828044SWilliam.Kucharski@Sun.COM 	   "This may take a long time.\n");
6838044SWilliam.Kucharski@Sun.COM 
6848044SWilliam.Kucharski@Sun.COM   if (map_file)
6858044SWilliam.Kucharski@Sun.COM     /* Try to open the device map file to write the probed data.  */
6868044SWilliam.Kucharski@Sun.COM     fp = fopen (map_file, "w");
6878044SWilliam.Kucharski@Sun.COM 
6888044SWilliam.Kucharski@Sun.COM   /* Floppies.  */
6898044SWilliam.Kucharski@Sun.COM   for (i = 0; i < floppy_disks; i++)
6908044SWilliam.Kucharski@Sun.COM     {
6918044SWilliam.Kucharski@Sun.COM       char name[16];
6928044SWilliam.Kucharski@Sun.COM 
6938044SWilliam.Kucharski@Sun.COM       get_floppy_disk_name (name, i);
6948044SWilliam.Kucharski@Sun.COM       /* In floppies, write the map, whether check_device succeeds
6958044SWilliam.Kucharski@Sun.COM 	 or not, because the user just does not insert floppies.  */
6968044SWilliam.Kucharski@Sun.COM       if (fp)
6978044SWilliam.Kucharski@Sun.COM 	fprintf (fp, "(fd%d)\t%s\n", i, name);
6988044SWilliam.Kucharski@Sun.COM 
6998044SWilliam.Kucharski@Sun.COM       if (check_device (name))
7008044SWilliam.Kucharski@Sun.COM 	{
7018044SWilliam.Kucharski@Sun.COM 	  (*map)[i] = strdup (name);
7028044SWilliam.Kucharski@Sun.COM 	  assert ((*map)[i]);
7038044SWilliam.Kucharski@Sun.COM 	}
7048044SWilliam.Kucharski@Sun.COM     }
7058044SWilliam.Kucharski@Sun.COM 
7068044SWilliam.Kucharski@Sun.COM #ifdef __linux__
7078044SWilliam.Kucharski@Sun.COM   if (have_devfs ())
7088044SWilliam.Kucharski@Sun.COM     {
7098044SWilliam.Kucharski@Sun.COM       while (1)
7108044SWilliam.Kucharski@Sun.COM 	{
7118044SWilliam.Kucharski@Sun.COM 	  char discn[32];
7128044SWilliam.Kucharski@Sun.COM 	  char name[PATH_MAX];
7138044SWilliam.Kucharski@Sun.COM 	  struct stat st;
7148044SWilliam.Kucharski@Sun.COM 
7158044SWilliam.Kucharski@Sun.COM 	  /* Linux creates symlinks "/dev/discs/discN" for convenience.
7168044SWilliam.Kucharski@Sun.COM 	     The way to number disks is the same as GRUB's.  */
7178044SWilliam.Kucharski@Sun.COM 	  sprintf (discn, "/dev/discs/disc%d", num_hd);
7188044SWilliam.Kucharski@Sun.COM 	  if (stat (discn, &st) < 0)
7198044SWilliam.Kucharski@Sun.COM 	    break;
7208044SWilliam.Kucharski@Sun.COM 
7218044SWilliam.Kucharski@Sun.COM 	  if (realpath (discn, name))
7228044SWilliam.Kucharski@Sun.COM 	    {
7238044SWilliam.Kucharski@Sun.COM 	      strcat (name, "/disc");
7248044SWilliam.Kucharski@Sun.COM 	      (*map)[num_hd + 0x80] = strdup (name);
7258044SWilliam.Kucharski@Sun.COM 	      assert ((*map)[num_hd + 0x80]);
7268044SWilliam.Kucharski@Sun.COM 
7278044SWilliam.Kucharski@Sun.COM 	      /* If the device map file is opened, write the map.  */
7288044SWilliam.Kucharski@Sun.COM 	      if (fp)
7298044SWilliam.Kucharski@Sun.COM 		fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
7308044SWilliam.Kucharski@Sun.COM 	    }
7318044SWilliam.Kucharski@Sun.COM 
7328044SWilliam.Kucharski@Sun.COM 	  num_hd++;
7338044SWilliam.Kucharski@Sun.COM 	}
7348044SWilliam.Kucharski@Sun.COM 
7358044SWilliam.Kucharski@Sun.COM       /* OK, close the device map file if opened.  */
7368044SWilliam.Kucharski@Sun.COM       if (fp)
7378044SWilliam.Kucharski@Sun.COM 	fclose (fp);
7388044SWilliam.Kucharski@Sun.COM 
7398044SWilliam.Kucharski@Sun.COM       return 1;
7408044SWilliam.Kucharski@Sun.COM     }
7418044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */
7428044SWilliam.Kucharski@Sun.COM 
7438044SWilliam.Kucharski@Sun.COM   /* IDE disks.  */
7448044SWilliam.Kucharski@Sun.COM   for (i = 0; i < 8; i++)
7458044SWilliam.Kucharski@Sun.COM     {
7468044SWilliam.Kucharski@Sun.COM       char name[16];
7478044SWilliam.Kucharski@Sun.COM 
7488044SWilliam.Kucharski@Sun.COM       get_ide_disk_name (name, i);
7498044SWilliam.Kucharski@Sun.COM       if (check_device (name))
7508044SWilliam.Kucharski@Sun.COM 	{
7518044SWilliam.Kucharski@Sun.COM 	  (*map)[num_hd + 0x80] = strdup (name);
7528044SWilliam.Kucharski@Sun.COM 	  assert ((*map)[num_hd + 0x80]);
7538044SWilliam.Kucharski@Sun.COM 
7548044SWilliam.Kucharski@Sun.COM 	  /* If the device map file is opened, write the map.  */
7558044SWilliam.Kucharski@Sun.COM 	  if (fp)
7568044SWilliam.Kucharski@Sun.COM 	    fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
7578044SWilliam.Kucharski@Sun.COM 
7588044SWilliam.Kucharski@Sun.COM 	  num_hd++;
7598044SWilliam.Kucharski@Sun.COM 	}
7608044SWilliam.Kucharski@Sun.COM     }
7618044SWilliam.Kucharski@Sun.COM 
7628044SWilliam.Kucharski@Sun.COM #ifdef __linux__
7638044SWilliam.Kucharski@Sun.COM   /* ATARAID disks.  */
7648044SWilliam.Kucharski@Sun.COM   for (i = 0; i < 8; i++)
7658044SWilliam.Kucharski@Sun.COM     {
7668044SWilliam.Kucharski@Sun.COM       char name[20];
7678044SWilliam.Kucharski@Sun.COM 
7688044SWilliam.Kucharski@Sun.COM       get_ataraid_disk_name (name, i);
7698044SWilliam.Kucharski@Sun.COM       if (check_device (name))
7708044SWilliam.Kucharski@Sun.COM         {
7718044SWilliam.Kucharski@Sun.COM           (*map)[num_hd + 0x80] = strdup (name);
7728044SWilliam.Kucharski@Sun.COM           assert ((*map)[num_hd + 0x80]);
7738044SWilliam.Kucharski@Sun.COM 
7748044SWilliam.Kucharski@Sun.COM           /* If the device map file is opened, write the map.  */
7758044SWilliam.Kucharski@Sun.COM           if (fp)
7768044SWilliam.Kucharski@Sun.COM             fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
7778044SWilliam.Kucharski@Sun.COM 
7788044SWilliam.Kucharski@Sun.COM           num_hd++;
7798044SWilliam.Kucharski@Sun.COM         }
7808044SWilliam.Kucharski@Sun.COM     }
7818044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */
7828044SWilliam.Kucharski@Sun.COM 
7838044SWilliam.Kucharski@Sun.COM   /* The rest is SCSI disks.  */
7848044SWilliam.Kucharski@Sun.COM   for (i = 0; i < 16; i++)
7858044SWilliam.Kucharski@Sun.COM     {
7868044SWilliam.Kucharski@Sun.COM       char name[16];
7878044SWilliam.Kucharski@Sun.COM 
7888044SWilliam.Kucharski@Sun.COM       get_scsi_disk_name (name, i);
7898044SWilliam.Kucharski@Sun.COM       if (check_device (name))
7908044SWilliam.Kucharski@Sun.COM 	{
7918044SWilliam.Kucharski@Sun.COM 	  (*map)[num_hd + 0x80] = strdup (name);
7928044SWilliam.Kucharski@Sun.COM 	  assert ((*map)[num_hd + 0x80]);
7938044SWilliam.Kucharski@Sun.COM 
7948044SWilliam.Kucharski@Sun.COM 	  /* If the device map file is opened, write the map.  */
7958044SWilliam.Kucharski@Sun.COM 	  if (fp)
7968044SWilliam.Kucharski@Sun.COM 	    fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
7978044SWilliam.Kucharski@Sun.COM 
7988044SWilliam.Kucharski@Sun.COM 	  num_hd++;
7998044SWilliam.Kucharski@Sun.COM 	}
8008044SWilliam.Kucharski@Sun.COM     }
8018044SWilliam.Kucharski@Sun.COM 
8028044SWilliam.Kucharski@Sun.COM #ifdef __linux__
8038044SWilliam.Kucharski@Sun.COM   /* This is for DAC960 - we have
8048044SWilliam.Kucharski@Sun.COM      /dev/rd/c<controller>d<logical drive>p<partition>.
8058044SWilliam.Kucharski@Sun.COM 
8068044SWilliam.Kucharski@Sun.COM      DAC960 driver currently supports up to 8 controllers, 32 logical
8078044SWilliam.Kucharski@Sun.COM      drives, and 7 partitions.  */
8088044SWilliam.Kucharski@Sun.COM   {
8098044SWilliam.Kucharski@Sun.COM     int controller, drive;
8108044SWilliam.Kucharski@Sun.COM 
8118044SWilliam.Kucharski@Sun.COM     for (controller = 0; controller < 8; controller++)
8128044SWilliam.Kucharski@Sun.COM       {
8138044SWilliam.Kucharski@Sun.COM 	for (drive = 0; drive < 15; drive++)
8148044SWilliam.Kucharski@Sun.COM 	  {
8158044SWilliam.Kucharski@Sun.COM 	    char name[24];
8168044SWilliam.Kucharski@Sun.COM 
8178044SWilliam.Kucharski@Sun.COM 	    get_dac960_disk_name (name, controller, drive);
8188044SWilliam.Kucharski@Sun.COM 	    if (check_device (name))
8198044SWilliam.Kucharski@Sun.COM 	      {
8208044SWilliam.Kucharski@Sun.COM 		(*map)[num_hd + 0x80] = strdup (name);
8218044SWilliam.Kucharski@Sun.COM 		assert ((*map)[num_hd + 0x80]);
8228044SWilliam.Kucharski@Sun.COM 
8238044SWilliam.Kucharski@Sun.COM 		/* If the device map file is opened, write the map.  */
8248044SWilliam.Kucharski@Sun.COM 		if (fp)
8258044SWilliam.Kucharski@Sun.COM 		  fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
8268044SWilliam.Kucharski@Sun.COM 
8278044SWilliam.Kucharski@Sun.COM 		num_hd++;
8288044SWilliam.Kucharski@Sun.COM 	      }
8298044SWilliam.Kucharski@Sun.COM 	  }
8308044SWilliam.Kucharski@Sun.COM       }
8318044SWilliam.Kucharski@Sun.COM   }
8328044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */
8338044SWilliam.Kucharski@Sun.COM 
8348044SWilliam.Kucharski@Sun.COM   /* OK, close the device map file if opened.  */
8358044SWilliam.Kucharski@Sun.COM   if (fp)
8368044SWilliam.Kucharski@Sun.COM     fclose (fp);
8378044SWilliam.Kucharski@Sun.COM 
8388044SWilliam.Kucharski@Sun.COM   return 1;
8398044SWilliam.Kucharski@Sun.COM }
8408044SWilliam.Kucharski@Sun.COM 
8418044SWilliam.Kucharski@Sun.COM /* Restore the memory consumed for MAP.  */
8428044SWilliam.Kucharski@Sun.COM void
restore_device_map(char ** map)8438044SWilliam.Kucharski@Sun.COM restore_device_map (char **map)
8448044SWilliam.Kucharski@Sun.COM {
8458044SWilliam.Kucharski@Sun.COM   int i;
8468044SWilliam.Kucharski@Sun.COM 
8478044SWilliam.Kucharski@Sun.COM   for (i = 0; i < NUM_DISKS; i++)
8488044SWilliam.Kucharski@Sun.COM     if (map[i])
8498044SWilliam.Kucharski@Sun.COM       free (map[i]);
8508044SWilliam.Kucharski@Sun.COM 
8518044SWilliam.Kucharski@Sun.COM   free (map);
8528044SWilliam.Kucharski@Sun.COM }
8538044SWilliam.Kucharski@Sun.COM 
8548044SWilliam.Kucharski@Sun.COM #ifdef __linux__
8558044SWilliam.Kucharski@Sun.COM /* Linux-only functions, because Linux has a bug that the disk cache for
8568044SWilliam.Kucharski@Sun.COM    a whole disk is not consistent with the one for a partition of the
8578044SWilliam.Kucharski@Sun.COM    disk.  */
8588044SWilliam.Kucharski@Sun.COM int
is_disk_device(char ** map,int drive)8598044SWilliam.Kucharski@Sun.COM is_disk_device (char **map, int drive)
8608044SWilliam.Kucharski@Sun.COM {
8618044SWilliam.Kucharski@Sun.COM   struct stat st;
8628044SWilliam.Kucharski@Sun.COM 
8638044SWilliam.Kucharski@Sun.COM   assert (map[drive] != 0);
8648044SWilliam.Kucharski@Sun.COM   assert (stat (map[drive], &st) == 0);
8658044SWilliam.Kucharski@Sun.COM   /* For now, disk devices under Linux are all block devices.  */
8668044SWilliam.Kucharski@Sun.COM   return S_ISBLK (st.st_mode);
8678044SWilliam.Kucharski@Sun.COM }
8688044SWilliam.Kucharski@Sun.COM 
8698044SWilliam.Kucharski@Sun.COM int
write_to_partition(char ** map,int drive,int partition,int sector,int size,const char * buf)8708044SWilliam.Kucharski@Sun.COM write_to_partition (char **map, int drive, int partition,
8718044SWilliam.Kucharski@Sun.COM 		    int sector, int size, const char *buf)
8728044SWilliam.Kucharski@Sun.COM {
8738044SWilliam.Kucharski@Sun.COM   char dev[PATH_MAX];	/* XXX */
8748044SWilliam.Kucharski@Sun.COM   int fd;
8758044SWilliam.Kucharski@Sun.COM 
8768044SWilliam.Kucharski@Sun.COM   if ((partition & 0x00FF00) != 0x00FF00)
8778044SWilliam.Kucharski@Sun.COM     {
8788044SWilliam.Kucharski@Sun.COM       /* If the partition is a BSD partition, it is difficult to
8798044SWilliam.Kucharski@Sun.COM 	 obtain the representation in Linux. So don't support that.  */
8808044SWilliam.Kucharski@Sun.COM       errnum = ERR_DEV_VALUES;
8818044SWilliam.Kucharski@Sun.COM       return 1;
8828044SWilliam.Kucharski@Sun.COM     }
8838044SWilliam.Kucharski@Sun.COM 
8848044SWilliam.Kucharski@Sun.COM   assert (map[drive] != 0);
8858044SWilliam.Kucharski@Sun.COM 
8868044SWilliam.Kucharski@Sun.COM   strcpy (dev, map[drive]);
8878044SWilliam.Kucharski@Sun.COM   if (have_devfs ())
8888044SWilliam.Kucharski@Sun.COM     {
8898044SWilliam.Kucharski@Sun.COM       if (strcmp (dev + strlen(dev) - 5, "/disc") == 0)
8908044SWilliam.Kucharski@Sun.COM 	strcpy (dev + strlen(dev) - 5, "/part");
8918044SWilliam.Kucharski@Sun.COM     }
8928044SWilliam.Kucharski@Sun.COM   sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1);
8938044SWilliam.Kucharski@Sun.COM 
8948044SWilliam.Kucharski@Sun.COM   /* Open the partition.  */
8958044SWilliam.Kucharski@Sun.COM   fd = open (dev, O_RDWR);
8968044SWilliam.Kucharski@Sun.COM   if (fd < 0)
8978044SWilliam.Kucharski@Sun.COM     {
8988044SWilliam.Kucharski@Sun.COM       errnum = ERR_NO_PART;
8998044SWilliam.Kucharski@Sun.COM       return 0;
9008044SWilliam.Kucharski@Sun.COM     }
9018044SWilliam.Kucharski@Sun.COM 
9028044SWilliam.Kucharski@Sun.COM #if defined(__linux__) && (!defined(__GLIBC__) || \
9038044SWilliam.Kucharski@Sun.COM         ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
9048044SWilliam.Kucharski@Sun.COM   /* Maybe libc doesn't have large file support.  */
9058044SWilliam.Kucharski@Sun.COM   {
9068044SWilliam.Kucharski@Sun.COM     loff_t offset, result;
9078044SWilliam.Kucharski@Sun.COM     static int _llseek (uint filedes, ulong hi, ulong lo,
9088044SWilliam.Kucharski@Sun.COM                         loff_t *res, uint wh);
9098044SWilliam.Kucharski@Sun.COM     _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
9108044SWilliam.Kucharski@Sun.COM                loff_t *, res, uint, wh);
9118044SWilliam.Kucharski@Sun.COM 
9128044SWilliam.Kucharski@Sun.COM     offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
9138044SWilliam.Kucharski@Sun.COM     if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
9148044SWilliam.Kucharski@Sun.COM       {
9158044SWilliam.Kucharski@Sun.COM 	errnum = ERR_DEV_VALUES;
9168044SWilliam.Kucharski@Sun.COM 	return 0;
9178044SWilliam.Kucharski@Sun.COM       }
9188044SWilliam.Kucharski@Sun.COM   }
9198044SWilliam.Kucharski@Sun.COM #else
9208044SWilliam.Kucharski@Sun.COM   {
9218044SWilliam.Kucharski@Sun.COM     off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
9228044SWilliam.Kucharski@Sun.COM 
9238044SWilliam.Kucharski@Sun.COM     if (lseek (fd, offset, SEEK_SET) != offset)
9248044SWilliam.Kucharski@Sun.COM       {
9258044SWilliam.Kucharski@Sun.COM 	errnum = ERR_DEV_VALUES;
9268044SWilliam.Kucharski@Sun.COM 	return 0;
9278044SWilliam.Kucharski@Sun.COM       }
9288044SWilliam.Kucharski@Sun.COM   }
9298044SWilliam.Kucharski@Sun.COM #endif
9308044SWilliam.Kucharski@Sun.COM 
9318044SWilliam.Kucharski@Sun.COM   if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE))
9328044SWilliam.Kucharski@Sun.COM     {
9338044SWilliam.Kucharski@Sun.COM       close (fd);
9348044SWilliam.Kucharski@Sun.COM       errnum = ERR_WRITE;
9358044SWilliam.Kucharski@Sun.COM       return 0;
9368044SWilliam.Kucharski@Sun.COM     }
9378044SWilliam.Kucharski@Sun.COM 
9388044SWilliam.Kucharski@Sun.COM   sync ();	/* Paranoia.  */
9398044SWilliam.Kucharski@Sun.COM   close (fd);
9408044SWilliam.Kucharski@Sun.COM 
9418044SWilliam.Kucharski@Sun.COM   return 1;
9428044SWilliam.Kucharski@Sun.COM }
9438044SWilliam.Kucharski@Sun.COM #endif /* __linux__ */
944