1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6 #include <stdio.h>
7 #include <io.h>
8 #include <errno.h>
9 #include <windows.h>
10 #include <internal.h>
11
12 struct oserr_map {
13 unsigned long oscode; /* OS values */
14 int errnocode; /* System V codes */
15 };
16
17 typedef union doubleint {
18 __int64 bigint;
19 struct {
20 unsigned long lowerhalf;
21 long upperhalf;
22 } twoints;
23 } DINT;
24
25 #define _IOYOURBUF 0x0100
26 #define _IOSETVBUF 0x0400
27 #define _IOFEOF 0x0800
28 #define _IOFLRTN 0x1000
29 #define _IOCTRLZ 0x2000
30 #define _IOCOMMIT 0x4000
31
32 /* General use macros */
33
34 #define inuse(s) ((s)->_flag & (_IOREAD|_IOWRT|_IORW))
35 #define mbuf(s) ((s)->_flag & _IOMYBUF)
36 #define nbuf(s) ((s)->_flag & _IONBF)
37 #define ybuf(s) ((s)->_flag & _IOYOURBUF)
38 #define bigbuf(s) ((s)->_flag & (_IOMYBUF|_IOYOURBUF))
39 #define anybuf(s) ((s)->_flag & (_IOMYBUF|_IONBF|_IOYOURBUF))
40
41 #define _INTERNAL_BUFSIZ 4096
42 #define _SMALL_BUFSIZ 512
43
44 #define FOPEN 0x01 /* file handle open */
45 #define FEOFLAG 0x02 /* end of file has been encountered */
46 #define FCRLF 0x04 /* CR-LF across read buffer (in text mode) */
47 #define FPIPE 0x08 /* file handle refers to a pipe */
48 #define FNOINHERIT 0x10 /* file handle opened _O_NOINHERIT */
49 #define FAPPEND 0x20 /* file handle opened O_APPEND */
50 #define FDEV 0x40 /* file handle refers to device */
51 #define FTEXT 0x80 /* file handle is in text mode */
52
53 static struct oserr_map local_errtab[] = {
54 { ERROR_INVALID_FUNCTION, EINVAL }, { ERROR_FILE_NOT_FOUND, ENOENT },
55 { ERROR_PATH_NOT_FOUND, ENOENT }, { ERROR_TOO_MANY_OPEN_FILES, EMFILE },
56 { ERROR_ACCESS_DENIED, EACCES }, { ERROR_INVALID_HANDLE, EBADF },
57 { ERROR_ARENA_TRASHED, ENOMEM }, { ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
58 { ERROR_INVALID_BLOCK, ENOMEM }, { ERROR_BAD_ENVIRONMENT, E2BIG },
59 { ERROR_BAD_FORMAT, ENOEXEC }, { ERROR_INVALID_ACCESS, EINVAL },
60 { ERROR_INVALID_DATA, EINVAL }, { ERROR_INVALID_DRIVE, ENOENT },
61 { ERROR_CURRENT_DIRECTORY, EACCES }, { ERROR_NOT_SAME_DEVICE, EXDEV },
62 { ERROR_NO_MORE_FILES, ENOENT }, { ERROR_LOCK_VIOLATION, EACCES },
63 { ERROR_BAD_NETPATH, ENOENT }, { ERROR_NETWORK_ACCESS_DENIED, EACCES },
64 { ERROR_BAD_NET_NAME, ENOENT }, { ERROR_FILE_EXISTS, EEXIST },
65 { ERROR_CANNOT_MAKE, EACCES }, { ERROR_FAIL_I24, EACCES },
66 { ERROR_INVALID_PARAMETER, EINVAL }, { ERROR_NO_PROC_SLOTS, EAGAIN },
67 { ERROR_DRIVE_LOCKED, EACCES }, { ERROR_BROKEN_PIPE, EPIPE },
68 { ERROR_DISK_FULL, ENOSPC }, { ERROR_INVALID_TARGET_HANDLE, EBADF },
69 { ERROR_INVALID_HANDLE, EINVAL }, { ERROR_WAIT_NO_CHILDREN, ECHILD },
70 { ERROR_CHILD_NOT_COMPLETE, ECHILD }, { ERROR_DIRECT_ACCESS_HANDLE, EBADF },
71 { ERROR_NEGATIVE_SEEK, EINVAL }, { ERROR_SEEK_ON_DEVICE, EACCES },
72 { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, { ERROR_NOT_LOCKED, EACCES },
73 { ERROR_BAD_PATHNAME, ENOENT }, { ERROR_MAX_THRDS_REACHED, EAGAIN },
74 { ERROR_LOCK_FAILED, EACCES }, { ERROR_ALREADY_EXISTS, EEXIST },
75 { ERROR_FILENAME_EXCED_RANGE, ENOENT }, { ERROR_NESTING_NOT_ALLOWED, EAGAIN },
76 { ERROR_NOT_ENOUGH_QUOTA, ENOMEM }, { 0, -1 }
77 };
78
79 void mingw_dosmaperr (unsigned long oserrno);
80
fseeko64(FILE * stream,_off64_t offset,int whence)81 int fseeko64 (FILE* stream, _off64_t offset, int whence)
82 {
83 fpos_t pos;
84 if (whence == SEEK_CUR)
85 {
86 /* If stream is invalid, fgetpos sets errno. */
87 if (fgetpos (stream, &pos))
88 return (-1);
89 pos += (fpos_t) offset;
90 }
91 else if (whence == SEEK_END)
92 {
93 /* If writing, we need to flush before getting file length. */
94 fflush (stream);
95 pos = (fpos_t) (_filelengthi64 (_fileno (stream)) + offset);
96 }
97 else if (whence == SEEK_SET)
98 pos = (fpos_t) offset;
99 else
100 {
101 errno = EINVAL;
102 return (-1);
103 }
104 return fsetpos (stream, &pos);
105 }
106
mingw_dosmaperr(unsigned long oserrno)107 void mingw_dosmaperr (unsigned long oserrno)
108 {
109 size_t i;
110
111 _doserrno = oserrno; /* set _doserrno */
112 /* check the table for the OS error code */
113 i = 0;
114 do {
115 if (oserrno == local_errtab[i].oscode)
116 {
117 errno = local_errtab[i].errnocode;
118 return;
119 }
120 } while (local_errtab[++i].errnocode != -1);
121 if (oserrno >= ERROR_WRITE_PROTECT && oserrno <= ERROR_SHARING_BUFFER_EXCEEDED)
122 errno = EACCES;
123 else if (oserrno >= ERROR_INVALID_STARTING_CODESEG && oserrno <= ERROR_INFLOOP_IN_RELOC_CHAIN)
124 errno = ENOEXEC;
125 else
126 errno = EINVAL;
127 }
128