/* open.c (rsxnt) -- Copyright (c) 1996-1997 Rainer Schnitker */

#include "rsxnt.h"
#include <string.h>

int __open (const char * name, int flags, unsigned long size)
{
    static SECURITY_ATTRIBUTES defsec =
	{ sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
    EMXPROCESS *p = _rsxnt_get_process_ptr();
    char fname[512];
    HANDLE h;
    DWORD access_mode;
    DWORD share_mode;
    DWORD create_mode;
    DWORD attrflags;

    if (lstrcmp (name, "/dev/null") == 0)
	lstrcpy (fname, "nul");
    else if (lstrcmp (name, "/dev/tty") == 0)
	lstrcpy (fname, "con");
    else if (strncmp (name, "/pipe/", 6) == 0 || strncmp (name, "\\pipe\\", 6) == 0) {
	memcpy (fname, "\\\\.\\pipe\\", 9);
	lstrcpy (fname + 9, name + 6);
    } else
	_rsxnt_truncate_name (fname, name);

    if (p->bConsoleApp)
	OemToChar(fname, fname);

    /* create flags */
    attrflags = (flags >> 8) & 0xff;
    if (p->umask_bits & 0200)
	attrflags |= 1;

    if (flags & _SO_SYNC)
	attrflags |= FILE_FLAG_WRITE_THROUGH;
    else if (attrflags == 0)
	attrflags = FILE_ATTRIBUTE_NORMAL;

    if (flags & _SO_NOINHERIT)
	defsec.bInheritHandle = FALSE;
    else
	defsec.bInheritHandle = TRUE;

    /* access mode */
    switch (flags & 3) {
	case 0:
	    access_mode = GENERIC_READ;
	    break;
	case 1:
	    access_mode = GENERIC_WRITE;
	    break;
	default: /* 2 */
	    access_mode = GENERIC_READ | GENERIC_WRITE;
	    break;
    }

    if (flags & _SO_CREAT) {
	share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
    } else {
	switch ((flags >> 5) & 3) {
	    case 0: /* comapible */
	    case 4: /* DENYNONE */
		share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
		break;
	    case 2: /* DENYWRITE */
		share_mode = FILE_SHARE_READ;
		break;
	    case 3: /* DENYWRITE */
		share_mode = FILE_SHARE_WRITE;
		break;
	    default: /* DENYALL */
		share_mode = 0;
		break;
	}
    }

    if (flags & _SO_CREAT) {	    /* create files */
	if (flags & _SO_EXCL)
	    create_mode = CREATE_NEW;
	else if (flags & _SO_TRUNC)
	    create_mode = CREATE_ALWAYS;
	else
	    create_mode =  OPEN_ALWAYS;
    }
    else if (flags & _SO_TRUNC)     /* open files */
	create_mode = TRUNCATE_EXISTING;
    else
	create_mode = OPEN_EXISTING;

    if ((h = CreateFile(fname,
	    access_mode, share_mode,
	    &defsec, create_mode, attrflags, NULL)) == INVALID_HANDLE_VALUE)
	return _rsxnt_get_last_errno();
    else {
	int fd = _rsxnt_get_new_file(p);

	if (fd < 0) {
	    CloseHandle(h);
	    return _rsxnt_errno(EMFILE);
	}
	p->file[fd].f_handle = h;
	p->file[fd].f_mode = _rsxnt_get_ht_type(h);
	p->file[fd].f_flags = 0;
	_rsxnt_check_console_handle(p, fd);
	return (fd);
    }
}

/*

CREATE: Bitfields for file attributes:

Bit(s)	Description
 0	read-only
 1	hidden
 2	system
 3	volume label (ignored)
 4	reserved, must be zero (directory)
 5	archive bit
 7	if set, file is shareable under Novell NetWare


OPEN:	Bitfields for access and sharing modes:

Bit(s)	Description	(Table 0585)
 2-0	access mode
	000 read only
	001 write only
	010 read/write
	011 (DOS 5+ internal) passed to redirector on EXEC to allow
		case-sensitive filenames
 3	reserved (0)
 6-4	sharing mode (DOS 3+) (see #0586)
	000 compatibility mode
	001 "DENYALL" prohiboth read and write access by others
	010 "DENYWRITE" prohiwrite access by others
	011 "DENYREAD" prohiread access by others
	100 "DENYNONE" allow full access by others
	111 network FCB (only available during server call)
 7	inheritance
	if set, file is private to current process and will not be inherited
	  by child processes
*/
