VirtualBox

Changeset 2416 in kBuild for trunk/src/kash


Ignore:
Timestamp:
Sep 14, 2010 12:30:30 AM (15 years ago)
Author:
bird
Message:

kash: implemented opendir/readdir/closedir for windows (NT). Fixed windows forking.

Location:
trunk/src/kash
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kash/miscbltin.c

    r2290 r2416  
    108108        }
    109109
    110         if (prompt && isatty(0)) {
     110        if (prompt && shfile_isatty(&psh->fdtab, 0)) {
    111111                out2str(psh, prompt);
    112112                output_flushall(psh);
  • trunk/src/kash/shfile.c

    r2413 r2416  
    3939#  define PIPE_BUF 512
    4040# endif
     41# include <ntstatus.h>
     42# define WIN32_NO_STATUS
    4143# include <Windows.h>
     44# if !defined(_WIN32_WINNT)
     45#  define _WIN32_WINNT 0x0502 /* Windows Server 2003 */
     46# endif
     47# include <winternl.h> //NTSTATUS
    4248#else
    4349# include <unistd.h>
     
    8692
    8793# define MY_ObjectBasicInformation 0
    88 typedef LONG (NTAPI * PFN_NtQueryObject)(HANDLE, int, void *, size_t, size_t *);
    89 
    90 typedef struct MY_OBJECT_BASIC_INFORMATION
     94# define MY_FileNamesInformation 12
     95
     96typedef struct
    9197{
    9298    ULONG           Attributes;
     
    103109} MY_OBJECT_BASIC_INFORMATION;
    104110
     111#if 0
     112typedef struct
     113{
     114    union
     115    {
     116        LONG    Status;
     117        PVOID   Pointer;
     118    };
     119    ULONG_PTR   Information;
     120} MY_IO_STATUS_BLOCK;
     121#else
     122typedef IO_STATUS_BLOCK MY_IO_STATUS_BLOCK;
     123#endif
     124typedef MY_IO_STATUS_BLOCK *PMY_IO_STATUS_BLOCK;
     125
     126typedef struct
     127{
     128    ULONG   NextEntryOffset;
     129    ULONG   FileIndex;
     130    ULONG   FileNameLength;
     131    WCHAR   FileName[1];
     132} MY_FILE_NAMES_INFORMATION, *PMY_FILE_NAMES_INFORMATION;
     133
     134typedef NTSTATUS (NTAPI * PFN_NtQueryObject)(HANDLE, int, void *, size_t, size_t *);
     135typedef NTSTATUS (NTAPI * PFN_NtQueryDirectoryFile)(HANDLE, HANDLE, void *,  void *, PMY_IO_STATUS_BLOCK, void *,
     136                                                    ULONG, int, int, PUNICODE_STRING, int);
     137typedef NTSTATUS (NTAPI * PFN_RtlUnicodeStringToAnsiString)(PANSI_STRING, PCUNICODE_STRING, int);
     138
     139
     140#endif /* K_OS_WINDOWS */
     141
     142
     143/*******************************************************************************
     144*   Global Variables                                                           *
     145*******************************************************************************/
     146#if K_OS == K_OS_WINDOWS
     147static int                              g_shfile_globals_initialized = 0;
     148static PFN_NtQueryObject                g_pfnNtQueryObject = NULL;
     149static PFN_NtQueryDirectoryFile         g_pfnNtQueryDirectoryFile = NULL;
     150static PFN_RtlUnicodeStringToAnsiString g_pfnRtlUnicodeStringToAnsiString = NULL;
    105151#endif /* K_OS_WINDOWS */
    106152
     
    387433}
    388434
     435/**
     436 * Converts an NT status code to errno,
     437 * assigning it to errno.
     438 *
     439 * @returns -1
     440 * @param   rcNt        The NT status code.
     441 */
     442static int shfile_nt2errno(NTSTATUS rcNt)
     443{
     444    switch (rcNt)
     445    {
     446        default:                            errno = EINVAL; break;
     447    }
     448    return -1;
     449}
     450
    389451DWORD shfile_query_handle_access_mask(HANDLE h, PACCESS_MASK pMask)
    390452{
    391     static PFN_NtQueryObject        s_pfnNtQueryObject = NULL;
    392453    MY_OBJECT_BASIC_INFORMATION     BasicInfo;
    393     LONG                            Status;
    394 
    395     if (!s_pfnNtQueryObject)
    396     {
    397         s_pfnNtQueryObject = (PFN_NtQueryObject)GetProcAddress(GetModuleHandle("NTDLL"), "NtQueryObject");
    398         if (!s_pfnNtQueryObject)
    399             return ERROR_NOT_SUPPORTED;
    400     }
    401 
    402     Status = s_pfnNtQueryObject(h, MY_ObjectBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
    403     if (Status >= 0)
     454    NTSTATUS                        rcNt;
     455
     456    if (!g_pfnNtQueryObject)
     457        return ERROR_NOT_SUPPORTED;
     458
     459    rcNt = g_pfnNtQueryObject(h, MY_ObjectBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
     460    if (rcNt >= 0)
    404461    {
    405462        *pMask = BasicInfo.GrantedAccess;
    406463        return NO_ERROR;
    407464    }
    408     if (Status != STATUS_INVALID_HANDLE)
     465    if (rcNt != STATUS_INVALID_HANDLE)
    409466        return ERROR_GEN_FAILURE;
    410467    return ERROR_INVALID_HANDLE;
     
    414471
    415472#endif /* SHFILE_IN_USE */
     473
     474/**
     475 * Initializes the global variables in this file.
     476 */
     477static void shfile_init_globals(void)
     478{
     479#if K_OS == K_OS_WINDOWS
     480    if (!g_shfile_globals_initialized)
     481    {
     482        HMODULE hNtDll = GetModuleHandle("NTDLL");
     483        g_pfnNtQueryObject                = (PFN_NtQueryObject)       GetProcAddress(hNtDll, "NtQueryObject");
     484        g_pfnNtQueryDirectoryFile         = (PFN_NtQueryDirectoryFile)GetProcAddress(hNtDll, "NtQueryDirectoryFile");
     485        g_pfnRtlUnicodeStringToAnsiString = (PFN_RtlUnicodeStringToAnsiString)GetProcAddress(hNtDll, "RtlUnicodeStringToAnsiString");
     486        if (   !g_pfnRtlUnicodeStringToAnsiString
     487            || !g_pfnNtQueryDirectoryFile)
     488        {
     489            /* fatal error */
     490        }
     491        g_shfile_globals_initialized = 1;
     492    }
     493#endif
     494}
    416495
    417496/**
     
    426505{
    427506    int rc;
     507
     508    shfile_init_globals();
    428509
    429510    pfdtab->cwd  = NULL;
     
    14171498
    14181499
     1500
    14191501shdir *shfile_opendir(shfdtab *pfdtab, const char *dir)
    14201502{
    14211503#ifdef SHFILE_IN_USE
    1422     errno = ENOSYS;
    1423     return NULL;
     1504    shdir  *pdir = NULL;
     1505
     1506    if (g_pfnNtQueryDirectoryFile)
     1507    {
     1508        char abspath[SHFILE_MAX_PATH];
     1509        if (shfile_make_path(pfdtab, dir, &abspath[0]) == 0)
     1510        {
     1511            HANDLE              hFile;
     1512            SECURITY_ATTRIBUTES SecurityAttributes;
     1513
     1514            SecurityAttributes.nLength = sizeof(SecurityAttributes);
     1515            SecurityAttributes.lpSecurityDescriptor = NULL;
     1516            SecurityAttributes.bInheritHandle = FALSE;
     1517
     1518            hFile = CreateFileA(abspath,
     1519                                GENERIC_READ,
     1520                                FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
     1521                                &SecurityAttributes,
     1522                                OPEN_ALWAYS,
     1523                                FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS,
     1524                                NULL /* hTemplateFile */);
     1525            if (hFile != INVALID_HANDLE_VALUE)
     1526            {
     1527                pdir = (shdir *)sh_malloc(shthread_get_shell(), sizeof(*pdir));
     1528                if (pdir)
     1529                {
     1530                    pdir->pfdtab = pfdtab;
     1531                    pdir->native = hFile;
     1532                    pdir->off    = ~(size_t)0;
     1533                }
     1534                else
     1535                    CloseHandle(hFile);
     1536            }
     1537            else
     1538                shfile_dos2errno(GetLastError());
     1539        }
     1540    }
     1541    else
     1542        errno = ENOSYS;
     1543    return pdir;
    14241544#else
    14251545    return (shdir *)opendir(dir);
     
    14301550{
    14311551#ifdef SHFILE_IN_USE
    1432     errno = ENOSYS;
     1552    if (pdir)
     1553    {
     1554        NTSTATUS rcNt;
     1555
     1556        if (   pdir->off == ~(size_t)0
     1557            || pdir->off + sizeof(MY_FILE_NAMES_INFORMATION) >= pdir->cb)
     1558        {
     1559            MY_IO_STATUS_BLOCK Ios;
     1560
     1561            memset(&Ios, 0, sizeof(Ios));
     1562            rcNt = g_pfnNtQueryDirectoryFile(pdir->native,
     1563                                             NULL /*Event*/,
     1564                                             NULL /*ApcRoutine*/,
     1565                                             NULL /*ApcContext*/,
     1566                                             &Ios,
     1567                                             &pdir->buf[0],
     1568                                             sizeof(pdir->buf),
     1569                                             MY_FileNamesInformation,
     1570                                             FALSE /*ReturnSingleEntry*/,
     1571                                             NULL /*FileName*/,
     1572                                             pdir->off == ~(size_t)0 /*RestartScan*/);
     1573            if (rcNt >= 0 && rcNt != STATUS_PENDING)
     1574            {
     1575                pdir->cb  = Ios.Information;
     1576                pdir->off = 0;
     1577            }
     1578            else if (rcNt == STATUS_NO_MORE_FILES)
     1579                errno = 0; /* wrong? */
     1580            else
     1581                shfile_nt2errno(rcNt);
     1582        }
     1583
     1584        if (   pdir->off != ~(size_t)0
     1585            && pdir->off + sizeof(MY_FILE_NAMES_INFORMATION) <= pdir->cb)
     1586        {
     1587            PMY_FILE_NAMES_INFORMATION  pcur = (PMY_FILE_NAMES_INFORMATION)&pdir->buf[pdir->off];
     1588            ANSI_STRING                 astr;
     1589            UNICODE_STRING              ustr;
     1590
     1591            astr.Length = astr.MaximumLength = sizeof(pdir->ent.name);
     1592            astr.Buffer = &pdir->ent.name[0];
     1593
     1594            ustr.Length = ustr.MaximumLength = pcur->FileNameLength < ~(USHORT)0 ? (USHORT)pcur->FileNameLength : ~(USHORT)0;
     1595            ustr.Buffer = &pcur->FileName[0];
     1596
     1597            rcNt = g_pfnRtlUnicodeStringToAnsiString(&astr, &ustr, 0/*AllocateDestinationString*/);
     1598            if (rcNt < 0)
     1599                sprintf(pdir->ent.name, "conversion-failed-%08x-rcNt=%08x-len=%u",
     1600                        pcur->FileIndex, rcNt, pcur->FileNameLength);
     1601            if (pcur->NextEntryOffset)
     1602                pdir->off += pcur->NextEntryOffset;
     1603            else
     1604                pdir->off = pdir->cb;
     1605            return &pdir->ent;
     1606        }
     1607    }
     1608    else
     1609        errno = EINVAL;
    14331610    return NULL;
    14341611#else
     
    14411618{
    14421619#ifdef SHFILE_IN_USE
    1443     errno = ENOSYS;
     1620    if (pdir)
     1621    {
     1622        CloseHandle(pdir->native);
     1623        pdir->pfdtab = NULL;
     1624        pdir->native = INVALID_HANDLE_VALUE;
     1625        sh_free(shthread_get_shell(), pdir);
     1626    }
     1627    else
     1628        errno = EINVAL;
    14441629#else
    14451630    closedir((DIR *)pdir);
  • trunk/src/kash/shfile.h

    r2415 r2416  
    173173typedef struct shdir
    174174{
    175     shfdtab    *pshfdtab;
     175    shfdtab    *pfdtab;
    176176    void       *native;
    177177    shdirent    ent;
     178#if K_OS == K_OS_WINDOWS
     179    size_t      off;
     180    size_t      cb;
     181    char        buf[32768 - sizeof(void *) * 2 - sizeof(shdirent) * 2];
     182#endif
    178183} shdir;
    179184
  • trunk/src/kash/shfork-win.c

    r2377 r2416  
    66#include <string.h>
    77#include <locale.h>
     8#include <assert.h>
    89#include "shinstance.h"
    910#include <Windows.h>
     
    2930
    3031/* in shforkA-win.asm: */
     32extern pid_t shfork_do_it(shinstance *psh);
    3133extern void shfork_resume(void *cur, void *base, void *limit);
    3234
     
    3436void *shfork_maybe_forked(int argc, char **argv, char **envp);
    3537extern int shfork_body(shinstance *psh, void *stack_ptr);
    36 
    37 
    38 /***
     38extern void init_syntax(void);
     39
     40
     41/**
    3942 * Called by shforkA-win.asm to check whether we're a forked child
    4043 * process or not.
     
    6467    {
    6568        char *stack;
    66         shheap_init();
    67         stack = (char *)sh_malloc(NULL, SHFORK_STACK_SIZE) + SHFORK_STACK_SIZE;
    68         g_stack_base = stack + SHFORK_STACK_SIZE;
    69         g_stack_limit = stack;
     69        shheap_init(NULL);
     70        g_stack_limit = stack = (char *)sh_malloc(NULL, SHFORK_STACK_SIZE);
     71        g_stack_base = stack += SHFORK_STACK_SIZE;
    7072        return stack;
    7173    }
     
    8385    g_stack_base  = shfork_string_to_ptr(argv[5], argv[0], "--stack-base");
    8486    g_stack_limit = shfork_string_to_ptr(argv[7], argv[0], "--stack-limit");
     87    assert((uintptr_t)stack_ptr < (uintptr_t)g_stack_base);
     88    assert((uintptr_t)stack_ptr > (uintptr_t)g_stack_limit);
    8589
    8690    /*
     
    137141}
    138142
    139 /***
     143/**
     144 * Do the fork.
     145 * @returns same as fork().
     146 * @param   psh             The shell that's forking.
     147 */
     148int shfork_do(shinstance *psh)
     149{
     150    /* save globals */
     151    void *pheap_head = shheap_get_head();
     152    pid_t pid = shfork_do_it(psh);
     153    if (pid == 0)
     154    {
     155        /* reinit stuff, only the heap is copied! */
     156        shthread_set_shell(psh);
     157        shheap_init(pheap_head);
     158        setlocale(LC_ALL, "");
     159        init_syntax();
     160    }
     161    return pid;
     162}
     163
     164/**
    140165 * Create the child process making sure it inherits all our handles,
    141166 * copy of the forkable heap and kick it off.
     
    156181    DWORD cch;
    157182    int rc = 0;
     183
     184    assert((uintptr_t)stack_ptr < (uintptr_t)g_stack_base);
     185    assert((uintptr_t)stack_ptr > (uintptr_t)g_stack_limit);
    158186
    159187    /*
     
    178206                       stack_ptr, g_stack_base, g_stack_limit);
    179207        szCmdLine[cch+1] = '\0';
     208        TRACE2((NULL, "shfork_body: szCmdLine=%s\n", szCmdLine));
    180209
    181210        memset(&StrtInfo, '\0', sizeof(StrtInfo)); /* just in case. */
  • trunk/src/kash/shforkA-win.asm

    r2413 r2416  
    121121        mov     r8,  [rbp - 18h]        ; envp
    122122
    123         lea     rsp, [eax - 40h]        ; Switch!
     123        lea     rsp, [rax - 40h]        ; Switch!
    124124%else
    125125        mov     [esp + 18h], eax
  • trunk/src/kash/shheap.c

    r2413 r2416  
    123123
    124124
    125 int shheap_init(void)
     125int shheap_init(void *phead)
    126126{
    127127    int rc;
     
    129129    SHHEAP_ASSERT(SHHEAP_ALIGN(sizeof(shmemhdr)) == sizeof(shmemhdr));
    130130    rc = shmtx_init(&g_sh_heap_mtx);
     131    g_sh_heap = (shmemchunk *)phead; /* non-zero on fork() */
    131132#else
    132133    rc = 0;
     
    138139
    139140# if K_OS == K_OS_WINDOWS
     141
     142/**
     143 * Get the head so the child can pass it to shheap_init() after fork().
     144 *
     145 * @returns g_sh_heap.
     146 */
     147void *shheap_get_head(void)
     148{
     149    return g_sh_heap;
     150}
     151
    140152/**
    141153 * Copies the heap into the child process.
     
    180192    return -1;
    181193}
    182 # endif
    183 
     194
     195# endif /* K_OS == K_OS_WINDOWS */
    184196
    185197/**
  • trunk/src/kash/shheap.h

    r2413 r2416  
    3232
    3333/* heap */
    34 int shheap_init(void);
     34int shheap_init(void *phead);
     35void *shheap_get_head(void);
    3536int shheap_fork_copy_to_child(void *);
    3637
  • trunk/src/kash/shinstance.c

    r2413 r2416  
    4242#if K_OS == K_OS_WINDOWS
    4343# include <Windows.h>
    44 extern pid_t shfork_do_it(shinstance *psh); /* shforkA-win.asm */
     44extern pid_t shfork_do(shinstance *psh); /* shforkA-win.asm */
    4545#endif
    4646
     
    898898
    899899#if K_OS == K_OS_WINDOWS //&& defined(SH_FORKED_MODE)
    900     pid = shfork_do_it(psh);
    901     if (pid == 0)
    902         shthread_set_shell(psh);
     900    pid = shfork_do(psh);
    903901
    904902#elif defined(SH_FORKED_MODE)
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette