blob: d89d81a5c905e8853e1752fa0ad55415404c4280 [file] [log] [blame] [raw]
#include <windows.h>
#include <nt.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdarg.h>
//#include <errno.h>
#include <pathname.h>
#include <assert.h>
#include <stdio.h> // For debug messages
int vopen(const char *pathname, int flags, va_list ap) {
unsigned long int fileaccess;
switch(flags & (O_RDONLY | O_WRONLY | O_RDWR)) {
case O_RDONLY:
fileaccess = GENERIC_READ;
break;
case O_WRONLY:
fileaccess = GENERIC_WRITE;
break;
case O_RDWR:
fileaccess = GENERIC_READ | GENERIC_WRITE;
break;
default:
//errno = EINVAL;
return -1;
}
if(flags & O_APPEND) {
if(!(fileaccess & GENERIC_WRITE)) {
//errno = EINVAL;
return -1;
}
fileaccess = FILE_APPEND_DATA;
}
if(/*(flags & O_SYNC) || */!(flags & O_NONBLOCK)) fileaccess |= SYNCHRONIZE;
unsigned long int file_create_disposition;
switch(flags & (O_CREAT | O_EXCL | O_TRUNC)) {
case 0:
case O_EXCL: // O_EXCL without O_CREAT: ignored
// Open file if it exist, or fail if not
file_create_disposition = FILE_OPEN;
break;
case O_CREAT:
// Open file if it exist, or create it if not
file_create_disposition = FILE_OPEN_IF;
break;
case O_CREAT | O_EXCL:
case O_CREAT | O_TRUNC | O_EXCL:
// Create file if it not exist, otherwise fail
file_create_disposition = FILE_CREATE;
break;
case O_TRUNC:
case O_TRUNC | O_EXCL: // O_EXCL without O_CREAT: ignored
// Open and truncate file if it exist, or fail if not
file_create_disposition = FILE_OVERWRITE;
break;
case O_CREAT | O_TRUNC:
// Open and truncate file if it exist, or create it if not
file_create_disposition = FILE_OVERWRITE_IF;
break;
default:
/* this can't happen ... all cases are covered */
assert(!flags);
return -1;
}
unsigned long int fileshare = FILE_SHARE_READ | FILE_SHARE_DELETE;
unsigned long int fileattrib = 0;
if(flags & O_CREAT) {
int pmode = va_arg(ap, int);
if((pmode & S_IWRITE) != S_IWRITE) fileattrib |= FILE_ATTRIBUTE_READONLY;
}
if(!fileattrib) fileattrib = FILE_ATTRIBUTE_NORMAL;
unsigned long int file_create_options = 0;
if(!(flags & O_NONBLOCK)) {
if(flags & O_ASYNC) file_create_options |= FILE_SYNCHRONOUS_IO_ALERT;
else file_create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
}
if(flags & O_DIRECTORY) {
//int access = fileaccess;
fileaccess = SYNCHRONIZE;
//if(access & GENERIC_READ) fileaccess |= FILE_READ_ATTRIBUTES;
//if(access & GENERIC_WRITE) fileaccess |= FILE_WRITE_ATTRIBUTES;
file_create_options |= FILE_DIRECTORY_FILE;
} else file_create_options |= FILE_NON_DIRECTORY_FILE;
if(flags & O_RANDOM) file_create_options |= FILE_RANDOM_ACCESS;
else if(flags & O_SEQUENTIAL) file_create_options |= FILE_SEQUENTIAL_ONLY;
if(flags & O_TEMPORARY) file_create_options |= FILE_DELETE_ON_CLOSE;
if(flags & O_DIRECT) file_create_options |= FILE_NO_INTERMEDIATE_BUFFERING;
UNICODE_STRING ntpathname;
RtlCreateUnicodeStringFromAsciiz(&ntpathname, pathname);
PATHNAME_UNIX2NT_UTF16_STRUCT(ntpathname);
OBJECT_ATTRIBUTES objectattrib = { sizeof(OBJECT_ATTRIBUTES), NULL, &ntpathname, 0, NULL, NULL };
void *r;
IO_STATUS_BLOCK io_status;
long int status = NtCreateFile(&r, fileaccess, &objectattrib, &io_status, NULL, fileattrib, fileshare, file_create_disposition, file_create_options, NULL, 0);
printf("nativelibc debug: open: status = 0x%lx\n", status);
//return ntstatus_to_errno(status) ? -1 : (int)r;
return status ? -1 : (int)r; // TODO: implemente the errno
}
int open(const char *pathname, int flags, ...) {
va_list ap;
va_start(ap, flags);
int r = vopen(pathname, flags, ap);
va_end(ap);
return r;
}