OSDN Git Service

* fhandler_dsp.cc (fhandler_dev_dsp::Audio_out::init): Fix non-ISO
[pf3gnuchains/sourceware.git] / winsup / cygwin / fhandler_floppy.cc
1 /* fhandler_floppy.cc.  See fhandler.h for a description of the
2    fhandler classes.
3
4    Copyright 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include <sys/termios.h>
14 #include <unistd.h>
15 #include <winioctl.h>
16 #include <asm/socket.h>
17 #include <cygwin/hdreg.h>
18 #include <cygwin/fs.h>
19 #include "security.h"
20 #include "path.h"
21 #include "fhandler.h"
22 #include "cygerrno.h"
23
24 /**********************************************************************/
25 /* fhandler_dev_floppy */
26
27 int
28 fhandler_dev_floppy::is_eom (int win_error)
29 {
30   int ret = (win_error == ERROR_INVALID_PARAMETER);
31   if (ret)
32     debug_printf ("end of medium");
33   return ret;
34 }
35
36 int
37 fhandler_dev_floppy::is_eof (int)
38 {
39   int ret = 0;
40   if (ret)
41     debug_printf ("end of file");
42   return ret;
43 }
44
45 fhandler_dev_floppy::fhandler_dev_floppy ()
46   : fhandler_dev_raw ()
47 {
48 }
49
50 int
51 fhandler_dev_floppy::open (int flags, mode_t)
52 {
53   /* The correct size of the buffer would be 512 bytes,
54    * which is the atomic size, supported by WinNT.
55    * Unfortunately, the performance is worse than
56    * access to file system on same device!
57    * Setting buffer size to a relatively big value
58    * increases performance by means.
59    * The new ioctl call with 'rdevio.h' header file
60    * supports changing this value.
61    *
62    * Let's be smart: Let's take a multiplier of typical tar
63    * and cpio buffer sizes by default!
64   */
65   devbufsiz = 61440L; /* 512L; */
66   return fhandler_dev_raw::open (flags);
67 }
68
69 _off64_t
70 fhandler_dev_floppy::lseek (_off64_t offset, int whence)
71 {
72   char buf[512];
73   _off64_t drive_size = 0;
74   _off64_t lloffset = offset;
75   _off64_t current_position;
76   _off64_t sector_aligned_offset;
77   _off64_t bytes_left;
78   DWORD low;
79   LONG high = 0;
80
81   DISK_GEOMETRY di;
82   PARTITION_INFORMATION pi;
83   DWORD bytes_read;
84
85   if (!DeviceIoControl (get_handle (),
86                           IOCTL_DISK_GET_DRIVE_GEOMETRY,
87                           NULL, 0,
88                           &di, sizeof (di),
89                           &bytes_read, NULL))
90     {
91       __seterrno ();
92       return -1;
93     }
94   debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)",
95                  di.Cylinders.LowPart,
96                  di.TracksPerCylinder,
97                  di.SectorsPerTrack,
98                  di.BytesPerSector);
99   if (DeviceIoControl (get_handle (),
100                          IOCTL_DISK_GET_PARTITION_INFO,
101                          NULL, 0,
102                          &pi, sizeof (pi),
103                          &bytes_read, NULL))
104     {
105       debug_printf ("partition info: %ld (%ld)",
106                       pi.StartingOffset.LowPart,
107                       pi.PartitionLength.LowPart);
108       drive_size = pi.PartitionLength.QuadPart;
109     }
110   else
111     {
112       drive_size = di.Cylinders.QuadPart * di.TracksPerCylinder *
113                    di.SectorsPerTrack * di.BytesPerSector;
114     }
115   debug_printf ("drive size: %ld", drive_size);
116
117   if (whence == SEEK_END && drive_size > 0)
118     {
119       lloffset = offset + drive_size;
120       whence = SEEK_SET;
121     }
122
123   if (whence == SEEK_CUR)
124     {
125       low = SetFilePointer (get_handle (), 0, &high, FILE_CURRENT);
126       if (low == INVALID_SET_FILE_POINTER && GetLastError ())
127         {
128           __seterrno ();
129           return -1;
130         }
131       current_position = low + ((_off64_t) high << 32);
132       /* devbufend and devbufstart are always 0 when writing. */
133       current_position -= devbufend - devbufstart;
134
135       lloffset += current_position;
136       whence = SEEK_SET;
137     }
138
139   if (lloffset < 0 ||
140       drive_size > 0 && lloffset > drive_size)
141     {
142       set_errno (EINVAL);
143       return -1;
144     }
145
146   /* FIXME: sector can possibly be not 512 bytes long */
147   sector_aligned_offset = (lloffset / 512) * 512;
148   bytes_left = lloffset - sector_aligned_offset;
149
150   if (whence == SEEK_SET)
151     {
152       /* Invalidate buffer. */
153       devbufstart = devbufend = 0;
154
155       low = sector_aligned_offset & UINT32_MAX;
156       high = sector_aligned_offset >> 32;
157       if (SetFilePointer (get_handle (), low, &high, FILE_BEGIN)
158           == INVALID_SET_FILE_POINTER && GetLastError ())
159         {
160           __seterrno ();
161           return -1;
162         }
163
164       eom_detected (false);
165       size_t len = bytes_left;
166       raw_read (buf, len);
167       return sector_aligned_offset + bytes_left;
168     }
169
170   set_errno (EINVAL);
171   return -1;
172 }
173
174 int
175 fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf)
176 {
177   DISK_GEOMETRY di;
178   PARTITION_INFORMATION pi;
179   DWORD bytes_read;
180   _off64_t drive_size = 0;
181   _off64_t start = 0;
182   switch (cmd)
183     {
184     case HDIO_GETGEO:
185       {
186         debug_printf ("HDIO_GETGEO");
187         if (!DeviceIoControl (get_handle (),
188                               IOCTL_DISK_GET_DRIVE_GEOMETRY,
189                               NULL, 0,
190                               &di, sizeof (di),
191                               &bytes_read, NULL))
192           {
193             __seterrno ();
194             return -1;
195           }
196         debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)",
197                       di.Cylinders.LowPart,
198                       di.TracksPerCylinder,
199                       di.SectorsPerTrack,
200                       di.BytesPerSector);
201         if (DeviceIoControl (get_handle (),
202                              IOCTL_DISK_GET_PARTITION_INFO,
203                              NULL, 0,
204                              &pi, sizeof (pi),
205                              &bytes_read, NULL))
206           {
207             debug_printf ("partition info: %ld (%ld)",
208                           pi.StartingOffset.LowPart,
209                           pi.PartitionLength.LowPart);
210             start = pi.StartingOffset.QuadPart >> 9ULL;
211           }
212         struct hd_geometry *geo = (struct hd_geometry *) buf;
213         geo->heads = di.TracksPerCylinder;
214         geo->sectors = di.SectorsPerTrack;
215         geo->cylinders = di.Cylinders.LowPart;
216         geo->start = start;
217         return 0;
218       }
219     case BLKGETSIZE:
220     case BLKGETSIZE64:
221       {
222         debug_printf ("BLKGETSIZE");
223         if (!DeviceIoControl (get_handle (),
224                               IOCTL_DISK_GET_DRIVE_GEOMETRY,
225                               NULL, 0,
226                               &di, sizeof (di),
227                               &bytes_read, NULL))
228           {
229             __seterrno ();
230             return -1;
231           }
232         debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)",
233                       di.Cylinders.LowPart,
234                       di.TracksPerCylinder,
235                       di.SectorsPerTrack,
236                       di.BytesPerSector);
237         if (DeviceIoControl (get_handle (),
238                              IOCTL_DISK_GET_PARTITION_INFO,
239                              NULL, 0,
240                              &pi, sizeof (pi),
241                              &bytes_read, NULL))
242           {
243             debug_printf ("partition info: %ld (%ld)",
244                           pi.StartingOffset.LowPart,
245                           pi.PartitionLength.LowPart);
246             drive_size = pi.PartitionLength.QuadPart;
247           }
248         else
249           {
250             drive_size = di.Cylinders.QuadPart * di.TracksPerCylinder *
251                          di.SectorsPerTrack * di.BytesPerSector;
252           }
253         if (cmd == BLKGETSIZE)
254           *(long *)buf = drive_size >> 9UL;
255         else
256           *(_off64_t *)buf = drive_size;
257         return 0;
258       }
259     case BLKRRPART:
260       {
261         debug_printf ("BLKRRPART");
262         if (!DeviceIoControl (get_handle (),
263                               IOCTL_DISK_UPDATE_DRIVE_SIZE,
264                               NULL, 0,
265                               &di, sizeof (di),
266                               &bytes_read, NULL))
267           {
268             __seterrno ();
269             return -1;
270           }
271         return 0;
272       }
273     case BLKSSZGET:
274       {
275         debug_printf ("BLKSSZGET");
276         if (!DeviceIoControl (get_handle (),
277                               IOCTL_DISK_GET_DRIVE_GEOMETRY,
278                               NULL, 0,
279                               &di, sizeof (di),
280                               &bytes_read, NULL))
281           {
282             __seterrno ();
283             return -1;
284           }
285         debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)",
286                       di.Cylinders.LowPart,
287                       di.TracksPerCylinder,
288                       di.SectorsPerTrack,
289                       di.BytesPerSector);
290         *(int *)buf = di.BytesPerSector;
291         return 0;
292       }
293     default:
294       return fhandler_dev_raw::ioctl (cmd, buf);
295     }
296 }
297