Initial commit of visual studio 9 git build superproject.
[git-build-vc9.git] / tcrt / src / unistd.cpp
blobdd6f8d3b1799f27a35eaabe2c28cee02ccf4214c
1 /*=============================================================================
2 unistd.cpp :
4 Copyright © 2008 Bruno Santos <nayart3@gmail.com>
5 =============================================================================*/
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <fcntl.h>
11 #include <errno.h>
12 #include "winnt.h"
13 #include "utils.h"
14 #include "Ws2_32.h"
16 ///////////////////////////////////////////////////////////////////////////////
17 namespace {
18 unsigned int get_disposition(int oflags)
20 if (oflags & O_CREAT)
21 if (oflags & O_EXCL)
22 return CREATE_NEW;
23 else if (oflags & O_TRUNC)
24 return CREATE_ALWAYS;
25 else
26 return OPEN_ALWAYS;
28 else
29 if (oflags & O_TRUNC)
30 return TRUNCATE_EXISTING;
31 else
32 return OPEN_EXISTING;
35 HANDLE sys_open(const char* filename, int oflags, mode_t mode)
37 tcrt::buffer<wchar_t> wname;
38 HANDLE handle;
39 size_t len;
41 DWORD access = 0;
42 if (oflags & O_RDONLY)
43 access |= GENERIC_READ;
44 if (oflags & O_WRONLY)
45 access |= GENERIC_WRITE;
47 DWORD flags = 0;
48 if (oflags & O_SYMLINK)
49 flags |= FILE_FLAG_OPEN_REPARSE_POINT;
50 if ((oflags & O_CREAT) && !(mode & S_IWUSR))
51 flags |= FILE_ATTRIBUTE_READONLY;
52 if (!(oflags & O_BINARY))
53 flags |= FILE_FLAG_BACKUP_SEMANTICS;
54 if (oflags & O_DELETE) {
55 access |= DELETE | FILE_WRITE_ATTRIBUTES;
56 //flags |= FILE_FLAG_DELETE_ON_CLOSE;
59 len = strlen(filename) + 1;
60 if (!wname.resize(len))
61 return NULL;
62 tcrt_utf8_to_utf16(filename, len, wname.get(), len);
63 handle = CreateFileW(wname.get(), access,
64 FILE_SHARE_READ | FILE_SHARE_WRITE,
65 NULL, get_disposition(oflags), flags, NULL);
66 if (handle == INVALID_HANDLE_VALUE) {
67 tcrt_set_errno_win32();
68 return NULL;
70 LARGE_INTEGER off = { 0 };
71 if ((oflags & O_APPEND) && !SetFilePointerEx(handle, off, NULL, FILE_END)) {
72 tcrt_set_errno_win32();
73 CloseHandle(handle);
74 return NULL;
77 return handle;
80 ssize_t sys_console_read(HANDLE handle, void* buf, size_t bufsize)
82 tcrt::buffer<wchar_t> wbuf;
83 DWORD rd;
85 __debugbreak();
86 if (!wbuf.resize(bufsize))
87 return -1;
89 if (!ReadConsoleW(handle, wbuf.get(), bufsize * sizeof(wchar_t), &rd, NULL)) {
90 tcrt_set_errno_win32();
91 return -1;
94 return tcrt_utf16_to_utf8(wbuf.get(), rd, (char*) buf, bufsize);
97 ssize_t sys_console_write(HANDLE handle, const void* buf, size_t bufsize)
99 tcrt::buffer<wchar_t> wbuf;
100 DWORD written;
102 if (!wbuf.resize(bufsize))
103 return -1;
105 bufsize = tcrt_utf8_to_utf16((char*) buf, bufsize, wbuf.get(), wbuf.length());
106 if (!WriteConsoleW(handle, wbuf.get(), truncate_cast<DWORD>(bufsize), &written, NULL)) {
107 tcrt_set_errno_win32();
108 return -1;
110 return written;
113 static ssize_t sys_read(HANDLE handle, void *buf, size_t bufsize, off_t* offset)
115 IO_STATUS_BLOCK iostatus;
116 NTSTATUS ntstatus;
118 ntstatus = NtReadFile( handle,
119 NULL,
120 NULL,
121 NULL,
122 &iostatus,
123 buf,
124 truncate_cast<ULONG>(bufsize),
125 (LARGE_INTEGER*) offset,
126 NULL);
127 if (ntstatus == STATUS_END_OF_FILE) {
128 return 0;
130 } else if (!NTSUCCESS(ntstatus)) {
131 //tcrt_set_errno_winnt(ntstatus);
132 __debugbreak();
133 return -1;
135 return iostatus.Information;
138 static ssize_t sys_write(HANDLE handle, const void *buf, size_t bufsize, off_t* offset)
140 IO_STATUS_BLOCK iostatus;
141 NTSTATUS ntstatus;
143 ntstatus = NtWriteFile( handle,
144 NULL,
145 NULL,
146 NULL,
147 &iostatus,
148 buf,
149 truncate_cast<ULONG>(bufsize),
150 (LARGE_INTEGER*) offset,
151 NULL);
152 if (!NTSUCCESS(ntstatus)) {
153 //tcrt_set_errno_winnt(ntstatus);
154 __debugbreak();
155 return -1;
157 return iostatus.Information;
160 } /* namespace */
162 int open(const char *filename, int oflags, ...)
164 HANDLE handle;
165 va_list args;
166 mode_t mode;
168 va_start(args, oflags);
169 mode = va_arg(args, int);
170 va_end(args);
172 if (!strcmp(filename, "/dev/null"))
173 filename = "NUL";
175 handle = sys_open(filename, oflags, mode);
176 if (!handle) {
177 return -1;
179 } else if ((size_t) handle > FOPEN_MAX) {
180 CloseHandle(handle);
181 errno = ENFILE;
182 return -1;
184 } else if ((size_t) handle < 3) {
185 __debugbreak();
187 return (int) handle;
190 int close(int fildes)
192 HANDLE handle = tcrt::fildes_to_handle(fildes);
194 if (fildes < 3)
195 SetStdHandle(STD_INPUT_HANDLE - fildes, NULL);
197 if (tcrt::is_socket_fildes(fildes)) {
198 if (Ws2_Close(handle)) {
199 errno = Ws2_GetLastError();
200 return -1;
203 } else {
204 if (!CloseHandle(handle)) {
205 tcrt_set_errno_win32();
206 return -1;
209 return 0;
212 int fcntl(int fildes, int cmd, ...)
214 if (cmd == F_GETFD || cmd == F_SETFD)
215 return 0;
217 errno = ENOSYS;
218 return -1;
221 int dup(int fildes)
223 HANDLE process;
224 HANDLE oldh;
225 HANDLE newh;
226 bool is_sock;
228 oldh = tcrt::fildes_to_handle(fildes);
229 is_sock = tcrt::is_socket_fildes(fildes);
230 if (!is_sock) {
231 process = GetCurrentProcess();
232 if (!DuplicateHandle(process, oldh, process, &newh, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
233 tcrt_set_errno_win32();
234 return -1;
236 } else {
237 WSAPROTOCOL_INFOW pinfo;
239 if (Ws2_Duplicate(oldh, GetCurrentProcessId(), &pinfo)) {
240 errno = Ws2_GetLastError();
241 return -1;
243 newh = Ws2_Socket(0, 0, 0, &pinfo, NULL, 0x01);
244 if (newh == INVALID_HANDLE_VALUE) {
245 errno = Ws2_GetLastError();
246 return -1;
249 if ((size_t) newh > FOPEN_MAX) {
250 if (!is_sock)
251 CloseHandle(newh);
252 else
253 Ws2_Close(newh);
254 errno = ENFILE;
255 return -1;
257 return (int) newh | ((is_sock) ? SOCKET_FILDES : 0);
260 ssize_t read(int fildes, void *buf, size_t bufsize)
262 HANDLE handle = tcrt::fildes_to_handle(fildes);
264 if (tcrt::is_console_handle(handle))
265 return sys_console_read(handle, buf, bufsize);
267 if (tcrt::is_socket_fildes(fildes))
268 return recv(fildes, buf, bufsize, 0);
270 return sys_read(handle, buf, bufsize, NULL);
274 ssize_t pread(int fildes, void *buf, size_t bufsize, off_t offset)
276 HANDLE handle = tcrt::fildes_to_handle(fildes);
278 if (tcrt::is_console_handle(handle))
279 return sys_console_read(handle, buf, bufsize);
281 return sys_read(handle, buf, bufsize, &offset);
284 ssize_t write(int fildes, const void *buf, size_t bufsize)
286 HANDLE handle = tcrt::fildes_to_handle(fildes);
288 if (tcrt::is_console_handle(handle))
289 return sys_console_write(handle, buf, bufsize);
291 if (tcrt::is_socket_fildes(fildes))
292 return send(fildes, buf, bufsize, 0);
294 return sys_write(handle, buf, bufsize, NULL);
297 ssize_t pwrite(int fildes, const void *buf, size_t bufsize, off_t offset)
299 HANDLE handle = tcrt::fildes_to_handle(fildes);
301 if (tcrt::is_console_handle(handle))
302 return sys_console_write(handle, buf, bufsize);
304 return sys_write(tcrt::fildes_to_handle(fildes), buf, bufsize, &offset);
307 int isatty(int fildes)
309 if (!tcrt::is_console_handle(tcrt::fildes_to_handle(fildes)))
310 return 0;
312 return 1;
315 int fsync(int fildes)
317 if (!FlushFileBuffers(tcrt::fildes_to_handle(fildes))) {
318 tcrt_set_errno_win32();
319 return -1;
321 return 0;
324 int ftruncate(int fildes, off_t length)
326 FILE_END_OF_FILE_INFO eof;
328 __debugbreak();
329 eof.EndOfFile.QuadPart = length;
330 if (!SetFileInformationByHandle(tcrt::fildes_to_handle(fildes), FileEndOfFileInfo, &eof, sizeof(eof))) {
331 tcrt_set_errno_win32();
332 return -1;
334 return 0;
337 off_t lseek(int fildes, off_t offset, int whence)
339 LARGE_INTEGER off;
341 TCRT_STATIC_ASSERT(SEEK_SET == FILE_BEGIN);
342 TCRT_STATIC_ASSERT(SEEK_CUR == FILE_CURRENT);
343 TCRT_STATIC_ASSERT(SEEK_END == FILE_END);
345 off.QuadPart = offset;
346 if (!SetFilePointerEx(tcrt::fildes_to_handle(fildes), off, &off, whence)) {
347 tcrt_set_errno_win32();
348 return -1;
350 return off.QuadPart;
353 ///////////////////////////////////////////////////////////////////////////////
354 int access(const char* path, int amode)
356 struct stat st;
358 if ( ((amode & (R_OK | W_OK | X_OK)) && (amode & F_OK))
359 || (amode & ~(R_OK | W_OK | X_OK | F_OK))
360 || !amode) {
361 errno = EINVAL;
362 return -1;
365 if (stat(path, &st)) {
366 if ((errno == ENOENT) && (amode & F_OK))
367 errno = EACCES;
368 return -1;
370 if ((amode & W_OK) && !(st.st_mode & S_IWUSR)) {
371 errno = EACCES;
372 return -1;
375 return 0;
378 int chdir(const char* path)
380 tcrt::buffer<wchar_t> wpath;
382 if (!wpath.resize(strlen(path) + 1))
383 return 1;
385 tcrt::utf8_to_utf16(path, wpath.length(), wpath.get(), wpath.length());
386 if (!SetCurrentDirectoryW(wpath.get())) {
387 tcrt_set_errno_win32();
388 return -1;
390 return 0;
393 int execv(const char* path, const char* argv[])
395 __debugbreak();
396 errno = ENOSYS;
397 return -1;
400 int execl(const char* path, const char* arg0, ... /*, (char *)0 */)
402 __debugbreak();
403 errno = ENOSYS;
404 return -1;
407 int execlp(const char* file, const char* arg0, ... /*, (char *)0 */)
409 __debugbreak();
410 errno = ENOSYS;
411 return -1;
414 int execvp(const char* file, char* const argv[])
416 __debugbreak();
417 errno = ENOSYS;
418 return -1;
421 pid_t fork(void)
423 __debugbreak();
424 errno = ENOSYS;
425 return -1;
428 char* getcwd(char* buf, size_t size)
430 tcrt::buffer<wchar_t> name;
431 DWORD len = size - 1;
433 if (!size) {
434 errno = EINVAL;
435 return NULL;
438 if (!name.resize(len))
439 return NULL;
440 len = GetCurrentDirectoryW(len, name.get());
441 if (!len) {
442 __debugbreak();
443 } else if (len > (size - 1)
444 || !WideCharToMultiByte(CP_UTF8, 0, name.get(), len + 1, buf, size, NULL, NULL)) {
445 errno = ERANGE;
446 buf = NULL;
448 return buf;
451 int getpagesize(void)
453 SYSTEM_INFO sysinfo;
455 GetSystemInfo(&sysinfo);
456 return sysinfo.dwAllocationGranularity;
459 pid_t getpid(void)
461 return GetCurrentProcessId();
464 uid_t getuid(void)
466 __debugbreak();
467 errno = ENOSYS;
468 return -1;
471 int pipe(int fildes[2])
473 HANDLE handle[2];
475 if (!CreatePipe(handle + 0, handle + 1, NULL, 0)) {
476 tcrt_set_errno_win32();
477 return -1;
479 if ((size_t) handle[0] > FOPEN_MAX || (size_t) handle[1] > FOPEN_MAX) {
480 CloseHandle(handle[0]);
481 CloseHandle(handle[1]);
482 errno = ENFILE;
483 return -1;
485 fildes[0] = (int) handle[0];
486 fildes[1] = (int) handle[1];
487 return 0;
490 int rmdir(const char* path)
492 tcrt::buffer<wchar_t> wpath;
494 if (!wpath.resize(strlen(path) + 1))
495 return -1;
497 tcrt::utf8_to_utf16(path, wpath.length(), wpath.get(), wpath.length());
498 if (!RemoveDirectoryW(wpath.get())) {
499 tcrt_set_errno_win32();
500 return -1;
502 return 0;
505 unsigned sleep(unsigned seconds)
507 Sleep(seconds * 1000);
508 return 0;
511 int symlink(const char *path1, const char *path2)
513 errno = ENOSYS;
514 return -1;
517 int readlink(const char* path, char* buf, size_t bufsize)
519 errno = ENOSYS;
520 return -1;
523 int link(const char* oldpath, const char* newpath)
525 tcrt::buffer<wchar_t> woldpath;
526 tcrt::buffer<wchar_t> wnewpath;
528 if (!woldpath.resize(strlen(oldpath) + 1))
529 return 1;
530 if (!wnewpath.resize(strlen(newpath) + 1))
531 return 1;
533 tcrt::utf8_to_utf16(oldpath, woldpath.length(), woldpath.get(), woldpath.length());
534 tcrt::utf8_to_utf16(newpath, wnewpath.length(), wnewpath.get(), wnewpath.length());
535 if (!CreateHardLinkW(wnewpath.get(), woldpath.get(), NULL)) {
536 tcrt_set_errno_win32();
537 return -1;
539 return 0;
542 int unlink(const char* path)
544 FILE_DISPOSITION_INFO del = { TRUE };
545 FILE_BASIC_INFO binfo;
546 HANDLE fh;
548 fh = sys_open(path, O_BINARY | O_SYMLINK | O_DELETE, 0);
549 if (!fh)
550 return -1;
551 if (!SetFileInformationByHandle(fh, FileDispositionInfo, &del, sizeof(del))) {
552 GetFileInformationByHandleEx(fh, FileBasicInfo, &binfo, sizeof(binfo));
553 binfo.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
554 SetFileInformationByHandle(fh, FileBasicInfo, &binfo, sizeof(binfo));
555 if (!SetFileInformationByHandle(fh, FileDispositionInfo, &del, sizeof(del))) {
556 CloseHandle(fh);
557 tcrt_set_errno_win32();
558 return -1;
561 CloseHandle(fh);
562 return 0;
565 // EOF ////////////////////////////////////////////////////////////////////////