Cygwin: strptime: add release note
[newlib-cygwin.git] / winsup / cygwin / devices.in
bloba86e5015f28ee6266eb5f23a75aa0540ef654646
1 %import {
2 #include "winsup.h"
3 #include "devices.h"
4 #include "sys/cygwin.h"
5 #include "tty.h"
6 #include "pinfo.h"
7 #include "shared_info.h"
8 #include "path.h"
9 #include "fhandler.h"
10 #include "ntdll.h"
11 #include "dtable.h"
12 #include "cygheap.h"
14 typedef const _device *KR_device_t;
16 %type KR_device_t
17 %local {
19 static int
20 exists_internal (const device&)
22   return false;
25 static int
26 exists (const device&)
28   return true;
31 /* Check existence of POSIX devices backed by real NT devices. */
32 static int
33 exists_ntdev (const device& dev)
35   WCHAR wpath[MAX_PATH];
36   UNICODE_STRING upath;
37   OBJECT_ATTRIBUTES attr;
38   HANDLE h;
39   NTSTATUS status;
41   sys_mbstowcs (wpath, MAX_PATH, dev.native ());
42   RtlInitUnicodeString (&upath, wpath);
43   InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
44   /* Except for the serial IO devices, the native paths are
45      direct device paths, not symlinks, so every status code
46      except for "NOT_FOUND" means the device exists. */
47   status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY, &attr);
48   switch (status)
49     {
50     case STATUS_OBJECT_NAME_NOT_FOUND:
51     case STATUS_OBJECT_PATH_NOT_FOUND:
52       return false;
53     case STATUS_SUCCESS:
54       NtClose (h);
55     default:
56       break;
57     }
58   return true;
61 /* Don't list via readdir but allow as a direct reference. */
62 static int
63 exists_ntdev_silent (const device& dev)
65   return exists_ntdev (dev) ? -1 : false;
68 static int
69 exists_console (const device& dev)
71   fh_devices devn = *const_cast<device *> (&dev);
72   switch (devn)
73     {
74     case FH_CONSOLE:
75     case FH_CONIN:
76     case FH_CONOUT:
77       return cygheap && cygheap->ctty && cygheap->ctty->is_console ()
78         && fhandler_console::exists ();
79     default:
80       if (dev.get_minor () < MAX_CONS_DEV)
81         {
82           unsigned long bitmask = fhandler_console::console_unit (CONS_LIST_USED);
83           return !!(bitmask & (1UL << dev.get_minor ()));
84         }
85       return false;
86     }
89 static int
90 exists_pty (const device& dev)
92   /* Only existing slave ptys. */
93   return cygwin_shared->tty.connect (dev.get_minor ()) != -1;
96 const _device dev_cygdrive_storage =
97   {"/cygdrive", {FH_CYGDRIVE}, "", exists};
99 const _device dev_fs_storage =
100   {"", {FH_FS}, "", exists};
102 const _device dev_dev_disk_storage =
103   {"", {FH_DEV_DISK}, "", exists};
105 const _device dev_proc_storage =
106   {"", {FH_PROC}, "", exists};
108 const _device dev_procnet_storage =
109   {"", {FH_PROCNET}, "", exists};
111 const _device dev_procsys_storage =
112   {"", {FH_PROCSYS}, "", exists};
114 const _device dev_procsysvipc_storage =
115   {"", {FH_PROCSYSVIPC}, "", exists};
117 const _device dev_netdrive_storage =
118   {"", {FH_NETDRIVE}, "", exists};
120 const _device dev_registry_storage =
121   {"", {FH_REGISTRY}, "", exists_internal};
123 const _device dev_piper_storage =
124   {"", {FH_PIPER}, "", exists_internal};
126 const _device dev_pipew_storage =
127   {"", {FH_PIPEW}, "", exists_internal};
129 const _device dev_signalfd_storage =
130   {"", {FH_SIGNALFD}, "", exists_internal};
132 const _device dev_timerfd_storage =
133   {"", {FH_TIMERFD}, "", exists_internal};
135 const _device dev_mqueue_storage =
136   {"", {FH_MQUEUE}, "", exists_internal};
138 const _device dev_socket_storage =
139   {"", {FH_SOCKET}, "", exists_internal};
141 const _device dev_af_inet_storage =
142   {"", {FH_INET}, "", exists_internal};
144 const _device dev_af_unix_storage =
145   {"", {FH_UNIX}, "", exists_internal};
147 const _device dev_af_local_storage =
148   {"", {FH_LOCAL}, "", exists_internal};
150 const _device dev_bad_storage =
151   {"", {FH_NADA}, "", exists_internal};
153 const _device dev_error_storage =
154   {"", {FH_ERROR}, "", exists_internal};
156 #define BRACK(x) {devn: x}
157 %storage_here
159 /* Internal devices below are prefixed with a ":".  This moves them out of
160    the POSIX namespace.  */
162 "/dev", BRACK(FH_DEV), "", exists, S_IFDIR
163 "/dev/disk", BRACK(FH_DEV_DISK), "", exists, S_IFDIR
164 "/dev/tty", BRACK(FH_TTY), "/dev/tty", exists, S_IFCHR
165 "/dev/pty%(0-127)d", BRACK(FHDEV(DEV_PTYS_MAJOR, {$1})), "/dev/pty{$1}", exists_pty, S_IFCHR, =ptys_dev
166 ":ptym%(0-127)d", BRACK(FHDEV(DEV_PTYM_MAJOR, {$1})), "/dev/ptym{$1}", exists_internal, S_IFCHR, =ptym_dev
167 "/dev/cons%(0-127)d", BRACK(FHDEV(DEV_CONS_MAJOR, {$1})), "/dev/cons{$1}", exists_console, S_IFCHR, =cons_dev
168 "/dev/console", BRACK(FH_CONSOLE), "/dev/console", exists_console, S_IFCHR, =console_dev
169 "/dev/ptmx", BRACK(FH_PTMX), "/dev/ptmx", exists, S_IFCHR
170 "/dev/windows", BRACK(FH_WINDOWS), "\\Device\\Null", exists_ntdev, S_IFCHR
171 "/dev/mixer", BRACK(FH_OSS_MIXER), "\\Device\\Null", exists_ntdev, S_IFCHR
172 "/dev/dsp", BRACK(FH_OSS_DSP), "\\Device\\Null", exists_ntdev, S_IFCHR
173 "/dev/conin", BRACK(FH_CONIN), "/dev/conin", exists_console, S_IFCHR
174 "/dev/conout", BRACK(FH_CONOUT), "/dev/conout", exists_console, S_IFCHR
175 "/dev/null", BRACK(FH_NULL), "\\Device\\Null", exists_ntdev, S_IFCHR
176 "/dev/zero", BRACK(FH_ZERO), "\\Device\\Null", exists_ntdev, S_IFCHR
177 "/dev/full", BRACK(FH_FULL), "\\Device\\Null", exists_ntdev, S_IFCHR
178 "/dev/random", BRACK(FH_RANDOM), "\\Device\\Null", exists_ntdev, S_IFCHR
179 "/dev/urandom", BRACK(FH_URANDOM), "\\Device\\Null", exists_ntdev, S_IFCHR, =urandom_dev
180 "/dev/clipboard", BRACK(FH_CLIPBOARD), "\\Device\\Null", exists_ntdev, S_IFCHR
181 "/dev/com%(1-16)d", BRACK(FHDEV(DEV_SERIAL_MAJOR, {$1 - 1})), "\\??\\COM{$1}", exists_ntdev_silent, S_IFCHR
182 "/dev/ttyS%(0-127)d", BRACK(FHDEV(DEV_SERIAL_MAJOR, {$1})), "\\??\\COM{$1 + 1}", exists_ntdev, S_IFCHR
183 ":pipe", BRACK(FH_PIPE), "/dev/pipe", exists_internal, S_IFCHR
184 ":fifo", BRACK(FH_FIFO), "/dev/fifo", exists_internal, S_IFCHR
185 "/dev/st%(0-127)d", BRACK(FHDEV(DEV_TAPE_MAJOR, {$1})), "\\Device\\Tape{$1}", exists_ntdev, S_IFCHR
186 "/dev/nst%(0-127)d", BRACK(FHDEV(DEV_TAPE_MAJOR, {$1 + 128})), "\\Device\\Tape{$1}", exists_ntdev, S_IFCHR
187 "/dev/fd%(0-15)d", BRACK(FHDEV(DEV_FLOPPY_MAJOR, {$1})), "\\Device\\Floppy{$1}", exists_ntdev, S_IFBLK
188 "/dev/scd%(0-15)d", BRACK(FHDEV(DEV_CDROM_MAJOR, {$1})), "\\Device\\CdRom{$1}", exists_ntdev, S_IFBLK
189 "/dev/sr%(0-15)d", BRACK(FHDEV(DEV_CDROM_MAJOR, {$1})), "\\Device\\CdRom{$1}", exists_ntdev, S_IFBLK
190 "/dev/fd", BRACK(FH_DEV_FD), "/proc/self/fd", exists, S_IFLNK
191 "/dev/stdin", BRACK(FH_DEV_FD), "/proc/self/fd/0", exists, S_IFLNK
192 "/dev/stdout", BRACK(FH_DEV_FD), "/proc/self/fd/1", exists, S_IFLNK
193 "/dev/stderr", BRACK(FH_DEV_FD), "/proc/self/fd/2", exists, S_IFLNK
194 %other  {return NULL;}
196 #undef BRACK
198 const _device *dev_storage_end = dev_storage
199                                 + (sizeof dev_storage / sizeof dev_storage[0]);
201 /* Convert disk/partition to major/minor */
202 static void
203 conv_dp_to_mm (int drive, int part, _major_t &major, _minor_t &minor)
205   if (part >= 16)
206     {
207       major = DEV_SD_HIGHPART_START + drive / 5;
208       drive %= 5;
209       minor = (part - 16) + 48 * drive;
210       return;
211     }
212   if (drive < ('q' - 'a'))      /* /dev/sda -to- /dev/sdp */
213     major = DEV_SD_MAJOR;
214   else if (drive < 32)          /* /dev/sdq -to- /dev/sdaf */
215     {
216       major = DEV_SD1_MAJOR;
217       drive -= 'q' - 'a';
218     }
219   else if (drive < 48)          /* /dev/sdag -to- /dev/sdav */
220     {
221       major = DEV_SD2_MAJOR;
222       drive -= 32;
223     }
224   else if (drive < 64)          /* /dev/sdaw -to- /dev/sdbl */
225     {
226       major = DEV_SD3_MAJOR;
227       drive -= 48;
228     }
229   else if (drive < 80)          /* /dev/sdbm -to- /dev/sdcb */
230     {
231       major = DEV_SD4_MAJOR;
232       drive -= 64;
233     }
234   else if (drive < 96)          /* /dev/sdcc -to- /dev/sdcr */
235     {
236       major = DEV_SD5_MAJOR;
237       drive -= 80;
238     }
239   else if (drive < 112)         /* /dev/sdcs -to- /dev/sddh */
240     {
241       major = DEV_SD6_MAJOR;
242       drive -= 96;
243     }
244   /* NOTE: This will cause multiple /dev/sddx entries in
245            /proc/partitions if there are more than 128 devices */
246   else                          /* /dev/sddi -to- /dev/sddx */
247     {
248       major = DEV_SD7_MAJOR;
249       drive -= 112;
250     }
251   minor = part + (drive * 16);
254 #define DISK_PREFIX     "/dev/sd"
255 #define DP_LEN          (sizeof (DISK_PREFIX) - 1)
257 static const char *hd_pattern = "\\Device\\Harddisk%u\\Partition%u";
259 void
260 device::parse (const char *s)
262   size_t len = strlen (s);
263   const _device *dev = KR_find_keyword (s, len);
265   if (!dev)
266     {
267       /* /dev/sd* devices have 8192 entries, given that we support 128 disks
268          with up to 64 partitions.  Handling them with shilka raises the size
269          of devices.o from ~250K to ~2 Megs.  So we handle them here manually
270          to save this space. */
271       int drive = 0, part = 0;
272       const char *pos = s + DP_LEN;
274       /* Generic check for /dev/sd[a-z] prefix */
275       if (len <= DP_LEN || strncmp (s, DISK_PREFIX, DP_LEN)
276           || pos[0] < 'a' || pos[0] > 'z')
277         goto no_disk;
279       /* /dev/sdd[a-x]? */
280       if (pos[0] == 'd' && pos[1] >= 'a' && pos[1] <= 'x')
281         {
282           drive = 104 + (pos[1] - 'a');
283           ++pos;
284         }
285       /* /dev/sd[a-c][a-z]? */
286       else if (pos[0] <= 'c' && pos[1] >= 'a' && pos[1] <= 'z')
287         {
288           drive = 26 + (pos[0] - 'a') * 26 + (pos[1] - 'a');
289           ++pos;
290         }
291       else
292         drive = (pos[0] - 'a');
293       /* Check next position in string for partition number. */
294       ++pos;
295       /* No partition number, equivalent to Windows partition 0. */
296       if (!pos[0])
297         ;
298       /* First digit must not be 0. */
299       else if (pos[0] < '1' || pos[0] > '9')
300         goto no_disk;
301       else if (!pos[1])
302         part = (pos[0] - '0');
303       else if (pos[1] < '0' || pos[1] > '9' || pos[2] != '\0')
304         goto no_disk;
305       else
306         {
307           part = (pos[0] - '0') * 10 + (pos[1] - '0');
308           if (part > 63)
309             goto no_disk;
310         }
311       char buf[sizeof *hd_pattern + 32];
312       __small_sprintf (buf, hd_pattern, drive, part);
313       native (buf, false);
314       if (exists_ntdev (*this))
315         {
316           name (s, true);
317           conv_dp_to_mm (drive, part, d.major, d.minor);
318           native (buf, true);
319           exists_func = exists_ntdev;
320           _mode = S_IFBLK;
321           lives_in_dev = dev_on_fs = false;
322           return;
323         }
324 no_disk:
325       *this = *fs_dev;
326     }
327   else
328     *this = *dev;
331 void
332 device::init ()
334   /* nothing to do... yet */
337 void
338 device::parse (_major_t major, _minor_t minor)
340   dev_t devn = FHDEV (major, minor);
342   d.devn = 0;
344   for (const _device *devidx = dev_storage; devidx < dev_storage_end; devidx++)
345     if (devidx->d.devn == devn)
346       {
347         *this = *devidx;
348         break;
349       }
351   if (!*this)
352     d.devn = FHDEV (major, minor);
355 void
356 device::parse (dev_t dev)
358   parse (_major (dev), _minor (dev));
361 void
362 device::parsedisk (int drive, int part)
364   char buf[sizeof ("/dev/sddx63")], *bp;
366   conv_dp_to_mm (drive, part, d.major, d.minor);
367   bp = stpcpy (buf, "/dev/sd");
368   if (drive >= 26)
369     {
370       drive -= 26;
371       *bp++ = drive / 26 + 'a';
372       drive %= 26;
373     }
374   *bp++ = drive + 'a';
375   if (part)
376     {
377       if (part >= 10)
378         {
379           *bp++ = part / 10 + '0';
380           part %= 10;
381         }
382       *bp++ = part + '0';
383     }
384   *bp = '\0';
385   name (buf, true);