xref: /onnv-gate/usr/src/grub/grub-0.97/lib/device.c (revision 8044:b3af80bbf173)
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, &sector_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