blob: 31186cea2056bc4f2d4589c5fcb7fffcf002126c [file] [log] [blame] [raw]
/* A part of the Native C Library for Windows NT
Copyright 2007-2015 PC GO Ld.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
#include <windows.h>
#include <nt.h>
#include <sys/stat.h>
#include <pathname.h>
#include <errno.h>
#include <stdio.h>
#include <ntstatus.h>
int mkdir(const char *pathname, mode_t mode) {
if(!pathname) {
errno = EFAULT;
return -1;
}
if(!*pathname) {
errno = ENOENT;
return -1;
}
if(*pathname != '/') {
errno = ENOSYS;
return -1;
}
if(!pathname[1]) {
// mkdir / ??
errno = EEXIST;
return -1;
}
UNICODE_STRING ntpathname;
if(!RtlCreateUnicodeStringFromAsciiz(&ntpathname, pathname)) {
errno = ENOMEM;
return -1;
}
if(ntpathname.Buffer[ntpathname.Length / sizeof(wchar_t) - 1] == L'/') {
ntpathname.Buffer[ntpathname.Length / sizeof(wchar_t) - 1] = 0;
ntpathname.Length -= sizeof(wchar_t);
ntpathname.MaximumLength -= sizeof(wchar_t);
}
PATHNAME_UNIX2NT_UTF16_STRUCT(ntpathname);
void *handle;
OBJECT_ATTRIBUTES object_attrib = { sizeof(OBJECT_ATTRIBUTES), NULL, &ntpathname, OBJ_PERMANENT, NULL, NULL };
// Try to create a directory object first
long int status = NtCreateDirectoryObject(&handle, 0, &object_attrib);
//printf("nativelibc debug: mkdir: status = 0x%lx\n", status);
if(status != STATUS_OBJECT_TYPE_MISMATCH) {
RtlFreeUnicodeString(&ntpathname);
if(status >= 0) NtClose(handle);
return __set_errno_from_ntstatus(status) ? -1 : 0;
}
// Try to create a directory file in a regular file system
unsigned long int file_access = SYNCHRONIZE;
unsigned long int file_attrib = 0;
unsigned long int file_share = 0;
unsigned long int file_create_disposition = FILE_CREATE;
unsigned long int file_create_options = FILE_DIRECTORY_FILE;
IO_STATUS_BLOCK io_status;
object_attrib.Attributes = 0;
switch(mode & (S_IREAD | S_IWRITE | S_IEXEC)) {
case 0: // XXX
case S_IREAD:
file_attrib |= FILE_ATTRIBUTE_READONLY;
break;
case S_IWRITE: // XXX
case S_IREAD | S_IWRITE:
file_attrib |= FILE_ATTRIBUTE_NORMAL;
break;
case S_IEXEC:
//file_access |= FILE_TRAVERSE;
file_attrib |= FILE_ATTRIBUTE_READONLY; // ?
break;
case S_IREAD | S_IEXEC:
//file_access |= FILE_LIST_DIRECTORY;
file_attrib |= FILE_ATTRIBUTE_READONLY;
break;
case S_IREAD | S_IWRITE | S_IEXEC:
//file_access |= FILE_LIST_DIRECTORY;
case S_IWRITE | S_IEXEC:
//file_access |= FILE_TRAVERSE;
file_attrib |= FILE_ATTRIBUTE_NORMAL;
break;
default:
puts(__FILE__": Unexpected code path");
abort();
}
status = NtCreateFile(&handle, file_access, &object_attrib, &io_status, NULL, file_attrib, file_share, file_create_disposition, file_create_options, NULL, 0);
//printf("nativelibc debug: mkdir: status = 0x%lx\n", status);
RtlFreeUnicodeString(&ntpathname);
if(status >= 0) NtClose(handle);
return __set_errno_from_ntstatus(status) ? -1 : 0;
}