VirtualBox

Changeset 2289 in kBuild for trunk/src/kash/shfile.c


Ignore:
Timestamp:
Feb 26, 2009 4:58:49 AM (16 years ago)
Author:
bird
Message:

kash: implementing shfile on top of the win32 api instead of msvcrt.

File:
1 edited

Legend:

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

    r2288 r2289  
    2929#include <stdlib.h>
    3030#include <stdio.h>
     31#include <assert.h>
    3132
    3233#if K_OS == K_OS_WINDOWS
     
    3536#  define PIPE_BUF 512
    3637# endif
     38# include <Windows.h>
    3739#else
    3840# include <unistd.h>
     
    4648
    4749
     50/*******************************************************************************
     51*   Defined Constants And Macros                                               *
     52*******************************************************************************/
     53/** @def SHFILE_IN_USE
     54 * Whether the file descriptor table stuff is actually in use or not.
     55 */
     56#if !defined(SH_PURE_STUB_MODE) \
     57 && (   K_OS == K_OS_WINDOWS \
     58     || (   !defined(SH_STUB_MODE) \
     59         && !defined(SH_FORKED_MODE)) \
     60    )
     61# define SHFILE_IN_USE
     62#endif
     63/** The max file table size. */
     64#define SHFILE_MAX          1024
     65/** The file table growth rate. */
     66#define SHFILE_GROW         64
     67/** The min native unix file descriptor. */
     68#define SHFILE_UNIX_MIN_FD  32
     69/** The path buffer size we use. */
     70#define SHFILE_MAX_PATH     4096
     71
     72/** Set errno and return. Doing a trace in debug build. */
     73#define RETURN_ERROR(rc, err, msg)  \
     74    do { \
     75        TRACE2((NULL, "%s: " ## msg ## " - returning %d / %d\n", __FUNCTION__, (rc), (err))); \
     76        errno = (err); \
     77        return (rc); \
     78    } while (0)
     79
     80
     81#ifdef SHFILE_IN_USE
     82
     83/**
     84 * Close the specified native handle.
     85 *
     86 * @param   native      The native file handle.
     87 * @param   flags       The flags in case they might come in handy later.
     88 */
     89static void shfile_native_close(intptr_t native, unsigned flags)
     90{
     91#if K_OS == K_OS_WINDOWS
     92    BOOL fRc = CloseHandle((HANDLE)native);
     93    assert(fRc); (void)fRc;
     94#else
     95    int s = errno;
     96    close(native);
     97    errno = s;
     98#endif
     99    (void)flags;
     100}
     101
     102/**
     103 * Inserts the file into the descriptor table.
     104 *
     105 * If we're out of memory and cannot extend the table, we'll close the
     106 * file, set errno to EMFILE and return -1.
     107 *
     108 * @returns The file descriptor number. -1 and errno on failure.
     109 * @param   pfdtab      The file descriptor table.
     110 * @param   native      The native file handle.
     111 * @param   flags       The flags the it was created with.
     112 * @param   fdMin       The minimum file descriptor number, pass -1 if any is ok.
     113 * @param   who         Who we're doing this for (for logging purposes).
     114 */
     115static int shfile_insert(shfdtab *pfdtab, intptr_t native, unsigned flags, int fdMin, const char *who)
     116{
     117    shmtxtmp tmp;
     118    int fd;
     119    int i;
     120
     121    /*
     122     * Fend of bad stuff.
     123     */
     124    if (fdMin >= SHFILE_MAX)
     125    {
     126        errno = EMFILE;
     127        return -1;
     128    }
     129
     130    shmtx_enter(&pfdtab->mtx, &tmp);
     131
     132    /*
     133     * Search for a fitting unused location.
     134     */
     135    fd = -1;
     136    for (i = 0; (unsigned)i < pfdtab->size; i++)
     137        if (    i >= fdMin
     138            &&  pfdtab->tab[i].fd == -1)
     139        {
     140            fd = i;
     141            break;
     142        }
     143    if (fd == -1)
     144    {
     145        /*
     146         * Grow the descriptor table.
     147         */
     148        shfile     *new_tab;
     149        int         new_size = pfdtab->size + SHFILE_GROW;
     150        while (new_size < fdMin)
     151            new_size += SHFILE_GROW;
     152        new_tab = realloc(pfdtab->tab, new_size * sizeof(shfile));
     153        if (new_tab)
     154        {
     155            fd = i = pfdtab->size;
     156            if (fd < fdMin)
     157                fd = fdMin;
     158            for (i = pfdtab->size; i < new_size; i++)
     159            {
     160                new_tab[i].fd = -1;
     161                new_tab[i].flags = 0;
     162                new_tab[i].native = -1;
     163            }
     164
     165            pfdtab->tab = new_tab;
     166            pfdtab->size = new_size;
     167        }
     168    }
     169
     170    /*
     171     * Fill in the entry if we've found one.
     172     */
     173    if (fd != -1)
     174    {
     175        pfdtab->tab[fd].fd = fd;
     176        pfdtab->tab[fd].flags = flags;
     177        pfdtab->tab[fd].cloexec = 0;
     178        pfdtab->tab[fd].native = native;
     179    }
     180    else
     181        shfile_native_close(native, flags);
     182
     183    shmtx_leave(&pfdtab->mtx, &tmp);
     184
     185    if (fd == -1)
     186        errno = EMFILE;
     187    (void)who;
     188    return fd;
     189}
     190
     191/**
     192 * Gets a file descriptor and lock the file descriptor table.
     193 *
     194 * @returns Pointer to the file and table ownership on success,
     195 *          NULL and errno set to EBADF on failure.
     196 * @param   pfdtab      The file descriptor table.
     197 * @param   fd          The file descriptor number.
     198 * @param   ptmp        See shmtx_enter.
     199 */
     200static shfile *shfile_get(shfdtab *pfdtab, int fd, shmtxtmp *ptmp)
     201{
     202    shfile *file = NULL;
     203    if (    fd >= 0
     204        &&  (unsigned)fd < pfdtab->size)
     205    {
     206        shmtx_enter(&pfdtab->mtx, ptmp);
     207        if ((unsigned)fd < pfdtab->size
     208            &&  pfdtab->tab[fd].fd != -1)
     209            file = &pfdtab->tab[fd];
     210        else
     211            shmtx_leave(&pfdtab->mtx, ptmp);
     212    }
     213    if (!file)
     214        errno = EBADF;
     215    return file;
     216}
     217
     218/**
     219 * Puts back a file descriptor and releases the table ownership.
     220 *
     221 * @param   pfdtab      The file descriptor table.
     222 * @param   file        The file.
     223 * @param   ptmp        See shmtx_leave.
     224 */
     225static void shfile_put(shfdtab *pfdtab, shfile *file, shmtxtmp *ptmp)
     226{
     227    shmtx_leave(&pfdtab->mtx, ptmp);
     228    assert(file);
     229    (void)file;
     230}
     231
     232
     233/**
     234 * Constructs a path from the current directory and the passed in path.
     235 *
     236 * @returns 0 on success, -1 and errno set to ENAMETOOLONG or EINVAL on failure.
     237 *
     238 * @param   pfdtab      The file descriptor table
     239 * @param   path        The path the caller supplied.
     240 * @param   buf         Where to put the path. This is assumed to be SHFILE_MAX_PATH
     241 *                      chars in size.
     242 */
     243int shfile_make_path(shfdtab *pfdtab, const char *path, char *buf)
     244{
     245    size_t path_len = strlen(path);
     246    if (path_len == 0)
     247    {
     248        errno = EINVAL;
     249        return -1;
     250    }
     251    if (path_len >= SHFILE_MAX_PATH)
     252    {
     253        errno = ENAMETOOLONG;
     254        return -1;
     255    }
     256    if (    *path == '/'
     257#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
     258        ||  *path == '\\'
     259        ||  (   !*path
     260             && path[1] == ':'
     261             && (   (*path >= 'A' && *path <= 'Z')
     262                 || (*path >= 'a' && *path <= 'z')))
     263#endif
     264        )
     265    {
     266        memcpy(buf, path, path_len + 1);
     267    }
     268    else
     269    {
     270        size_t      cwd_len;
     271        shmtxtmp    tmp;
     272
     273        shmtx_enter(&pfdtab->mtx, &tmp);
     274
     275        cwd_len = strlen(pfdtab->cwd);
     276        memcpy(buf, pfdtab->cwd, cwd_len);
     277
     278        shmtx_leave(&pfdtab->mtx, &tmp);
     279
     280        if (cwd_len + path_len + 1 >= SHFILE_MAX_PATH)
     281        {
     282            errno = ENAMETOOLONG;
     283            return -1;
     284        }
     285        if (    !cwd_len
     286            ||  buf[cwd_len - 1] != '/')
     287            buf[cwd_len++] = '/';
     288        memcpy(buf + cwd_len, path, path_len + 1);
     289    }
     290
     291#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
     292    if (!strcmp(buf, "/dev/null"))
     293        strcpy(buf, "NUL");
     294#endif
     295    return 0;
     296}
     297
     298# if K_OS == K_OS_WINDOWS
     299/**
     300 * Converts a DOS(/Windows) error code to errno,
     301 * assigning it to errno.
     302 *
     303 * @returns -1
     304 * @param   err     The DOS error.
     305 */
     306static int shfile_dos2errno(int err)
     307{
     308    switch (err)
     309    {
     310        case ERROR_BAD_ENVIRONMENT:         errno = E2BIG;      break;
     311        case ERROR_ACCESS_DENIED:           errno = EACCES;     break;
     312        case ERROR_CURRENT_DIRECTORY:       errno = EACCES;     break;
     313        case ERROR_LOCK_VIOLATION:          errno = EACCES;     break;
     314        case ERROR_NETWORK_ACCESS_DENIED:   errno = EACCES;     break;
     315        case ERROR_CANNOT_MAKE:             errno = EACCES;     break;
     316        case ERROR_FAIL_I24:                errno = EACCES;     break;
     317        case ERROR_DRIVE_LOCKED:            errno = EACCES;     break;
     318        case ERROR_SEEK_ON_DEVICE:          errno = EACCES;     break;
     319        case ERROR_NOT_LOCKED:              errno = EACCES;     break;
     320        case ERROR_LOCK_FAILED:             errno = EACCES;     break;
     321        case ERROR_NO_PROC_SLOTS:           errno = EAGAIN;     break;
     322        case ERROR_MAX_THRDS_REACHED:       errno = EAGAIN;     break;
     323        case ERROR_NESTING_NOT_ALLOWED:     errno = EAGAIN;     break;
     324        case ERROR_INVALID_HANDLE:          errno = EBADF;      break;
     325        case ERROR_INVALID_TARGET_HANDLE:   errno = EBADF;      break;
     326        case ERROR_DIRECT_ACCESS_HANDLE:    errno = EBADF;      break;
     327        case ERROR_WAIT_NO_CHILDREN:        errno = ECHILD;     break;
     328        case ERROR_CHILD_NOT_COMPLETE:      errno = ECHILD;     break;
     329        case ERROR_FILE_EXISTS:             errno = EEXIST;     break;
     330        case ERROR_ALREADY_EXISTS:          errno = EEXIST;     break;
     331        case ERROR_INVALID_FUNCTION:        errno = EINVAL;     break;
     332        case ERROR_INVALID_ACCESS:          errno = EINVAL;     break;
     333        case ERROR_INVALID_DATA:            errno = EINVAL;     break;
     334        case ERROR_INVALID_PARAMETER:       errno = EINVAL;     break;
     335        case ERROR_NEGATIVE_SEEK:           errno = EINVAL;     break;
     336        case ERROR_TOO_MANY_OPEN_FILES:     errno = EMFILE;     break;
     337        case ERROR_FILE_NOT_FOUND:          errno = ENOENT;     break;
     338        case ERROR_PATH_NOT_FOUND:          errno = ENOENT;     break;
     339        case ERROR_INVALID_DRIVE:           errno = ENOENT;     break;
     340        case ERROR_NO_MORE_FILES:           errno = ENOENT;     break;
     341        case ERROR_BAD_NETPATH:             errno = ENOENT;     break;
     342        case ERROR_BAD_NET_NAME:            errno = ENOENT;     break;
     343        case ERROR_BAD_PATHNAME:            errno = ENOENT;     break;
     344        case ERROR_FILENAME_EXCED_RANGE:    errno = ENOENT;     break;
     345        case ERROR_BAD_FORMAT:              errno = ENOEXEC;    break;
     346        case ERROR_ARENA_TRASHED:           errno = ENOMEM;     break;
     347        case ERROR_NOT_ENOUGH_MEMORY:       errno = ENOMEM;     break;
     348        case ERROR_INVALID_BLOCK:           errno = ENOMEM;     break;
     349        case ERROR_NOT_ENOUGH_QUOTA:        errno = ENOMEM;     break;
     350        case ERROR_DISK_FULL:               errno = ENOSPC;     break;
     351        case ERROR_DIR_NOT_EMPTY:           errno = ENOTEMPTY;  break;
     352        case ERROR_BROKEN_PIPE:             errno = EPIPE;      break;
     353        case ERROR_NOT_SAME_DEVICE:         errno = EXDEV;      break;
     354        default:                            errno = EINVAL;     break;
     355    }
     356    return -1;
     357}
     358# endif /* K_OS == K_OS_WINDOWS */
     359
     360#endif /* SHFILE_IN_USE */
     361
     362/**
     363 * Initializes a file descriptor table.
     364 *
     365 * @returns 0 on success, -1 and errno on failure.
     366 * @param   pfdtab      The table to initialize.
     367 * @param   inherit     File descriptor table to inherit from. If not specified
     368 *                      we will inherit from the current process as it were.
     369 */
     370int shfile_init(shfdtab *pfdtab, shfdtab *inherit)
     371{
     372    int rc;
     373
     374    pfdtab->cwd  = NULL;
     375    pfdtab->size = 0;
     376    pfdtab->tab  = NULL;
     377    rc = shmtx_init(&pfdtab->mtx);
     378    if (!rc)
     379    {
     380#ifdef SHFILE_IN_USE
     381        char buf[SHFILE_MAX_PATH];
     382        if (getcwd(buf, sizeof(buf)))
     383        {
     384            pfdtab->cwd = strdup(buf);
     385            if (!inherit)
     386            {
     387# if K_OS == K_OS_WINDOWS
     388                static const struct
     389                {
     390                    DWORD dwStdHandle;
     391                    unsigned flags;
     392                } aStdHandles[3] =
     393                {
     394                    { STD_INPUT_HANDLE,   _O_RDONLY },
     395                    { STD_OUTPUT_HANDLE,  _O_WRONLY },
     396                    { STD_ERROR_HANDLE,   _O_WRONLY }
     397                };
     398                unsigned            i;
     399                STARTUPINFO         Info;
     400
     401                rc = 0;
     402
     403                /* Try pick up the Visual C++ CRT file descriptor info. */
     404                __try {
     405                    GetStartupInfo(&Info);
     406                } __except (EXCEPTION_EXECUTE_HANDLER) {
     407                    memset(&Info, 0, sizeof(Info));
     408                }
     409                if (    Info.cbReserved2 <= sizeof(int)
     410                    &&  (uintptr_t)Info.lpReserved2 >= 0x1000
     411                    &&  *(int *)Info.lpReserved2 * (sizeof(int) + sizeof(intptr_t)) + 4 <= Info.cbReserved2
     412                    &&  *(int *)Info.lpReserved2 <= 2048
     413                    &&  *(int *)Info.lpReserved2 >= 1)
     414                {
     415                    unsigned    c       = *(int *)Info.lpReserved2;
     416                    char       *aosfile = (char *)Info.lpReserved2 + sizeof(int);
     417                    intptr_t   *aosfhnd = (intptr_t *)(aosfile + c);
     418
     419                    /** @todo process */
     420
     421                }
     422
     423                /* Check the three standard handles. */
     424                for (i = 0; i < 3; i++)
     425                {
     426                    HANDLE hFile = GetStdHandle(aStdHandles[i].dwStdHandle);
     427                    if (    hFile != INVALID_HANDLE_VALUE
     428                        &&  (   (unsigned)i >= pfdtab->size
     429                             || pfdtab->tab[i].fd == -1))
     430                    {
     431                        int fd2 = shfile_insert(pfdtab, (intptr_t)hFile, aStdHandles[i].flags, i, "shtab_init");
     432                        assert(fd2 == i); (void)fd2;
     433                        if (fd2 != i)
     434                            rc = -1;
     435                    }
     436                }
     437# else
     438# endif
     439            }
     440            else
     441            {
     442                /** @todo */
     443                errno = ENOSYS;
     444                rc = -1;
     445            }
     446        }
     447        else
     448            rc = -1;
     449#endif
     450    }
     451    return rc;
     452}
     453
     454/**
     455 * open().
     456 */
    48457int shfile_open(shfdtab *pfdtab, const char *name, unsigned flags, mode_t mode)
    49458{
    50459    int fd;
    51 
    52 #ifdef SH_PURE_STUB_MODE
     460#ifdef SHFILE_IN_USE
     461    char    absname[SHFILE_MAX_PATH];
     462# if K_OS == K_OS_WINDOWS
     463    HANDLE  hFile;
     464    DWORD   dwDesiredAccess;
     465    DWORD   dwShareMode;
     466    DWORD   dwCreationDisposition;
     467    DWORD   dwFlagsAndAttributes;
     468    SECURITY_ATTRIBUTES SecurityAttributes;
     469
     470# ifndef _O_ACCMODE
     471#  define _O_ACCMODE    (_O_RDONLY|_O_WRONLY|_O_RDWR)
     472# endif
     473    switch (flags & (_O_ACCMODE | _O_APPEND))
     474    {
     475        case _O_RDONLY:             dwDesiredAccess = GENERIC_READ; break;
     476        case _O_RDONLY | _O_APPEND: dwDesiredAccess = GENERIC_READ; break;
     477        case _O_WRONLY:             dwDesiredAccess = GENERIC_WRITE; break;
     478        case _O_WRONLY | _O_APPEND: dwDesiredAccess = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); break;
     479        case _O_RDWR:               dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; break;
     480        case _O_RDWR   | _O_APPEND: dwDesiredAccess = GENERIC_READ | (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); break;
     481
     482        default:
     483            RETURN_ERROR(-1, EINVAL, "invalid mode");
     484    }
     485
     486    dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
     487
     488    SecurityAttributes.nLength = sizeof(SecurityAttributes);
     489    SecurityAttributes.lpSecurityDescriptor = NULL;
     490    SecurityAttributes.bInheritHandle = (flags & _O_NOINHERIT) == 0;
     491
     492    if (flags & _O_CREAT)
     493    {
     494        if ((flags & (_O_EXCL | _O_TRUNC)) == (_O_EXCL | _O_TRUNC))
     495            RETURN_ERROR(-1, EINVAL, "_O_EXCL | _O_TRUNC");
     496
     497        if (flags & _O_TRUNC)
     498            dwCreationDisposition = CREATE_ALWAYS; /* not 100%, but close enough */
     499        else if (flags & _O_EXCL)
     500            dwCreationDisposition = CREATE_NEW;
     501        else
     502            dwCreationDisposition = OPEN_ALWAYS;
     503    }
     504    else if (flags & _O_TRUNC)
     505        dwCreationDisposition = TRUNCATE_EXISTING;
     506    else
     507        dwCreationDisposition = OPEN_EXISTING;
     508
     509    if (!(flags & _O_CREAT) || (mode & 0222))
     510        dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
     511    else
     512        dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY;
     513
     514    fd = shfile_make_path(pfdtab, name, &absname[0]);
     515    if (!fd)
     516    {
     517        SetLastError(0);
     518        hFile = CreateFileA(absname,
     519                            dwDesiredAccess,
     520                            dwShareMode,
     521                            &SecurityAttributes,
     522                            dwCreationDisposition,
     523                            dwFlagsAndAttributes,
     524                            NULL /* hTemplateFile */);
     525        if (hFile != INVALID_HANDLE_VALUE)
     526            fd = shfile_insert(pfdtab, (intptr_t)hFile, flags, -1, "shfile_open");
     527        else
     528            fd = shfile_dos2errno(GetLastError());
     529    }
     530
     531# else  /* K_OS != K_OS_WINDOWS */
     532    fd = shfile_make_path(pfdtab, name, &absname[0]);
     533    if (!fd)
     534    {
     535        fd = open(absname, flag, mode);
     536        if (fd != -1)
     537        {
     538            int native = fcntl(fd, F_DUPFD, SHFILE_UNIX_MIN_FD);
     539            int s = errno;
     540            close(fd);
     541            errno = s;
     542            if (native != -1)
     543                fd = shfile_insert(pfdtab, native, flags, -1, "shfile_open");
     544            else
     545                fd = -1;
     546        }
     547    }
     548
     549# endif /* K_OS != K_OS_WINDOWS */
     550
     551#elif defined(SH_PURE_STUB_MODE)
    53552    fd = -1;
    54 #elif defined(SH_STUB_MODE)
     553    errno = ENOSYS;
     554
     555#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    55556    fd = open(name, flags, mode);
    56 #else
    57557#endif
    58558
     
    69569    return -1;
    70570
    71 #elif defined(SH_STUB_MODE)
     571#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    72572# ifdef _MSC_VER
    73573    return _pipe(fds, PIPE_BUF, O_BINARY);
     
    86586    rc = -1;
    87587
    88 #elif defined(SH_STUB_MODE)
     588#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    89589    rc = dup(fd);
    90590
     
    96596}
    97597
     598/**
     599 * close().
     600 */
    98601int shfile_close(shfdtab *pfdtab, unsigned fd)
    99602{
    100     int rc;
    101 
    102 #ifdef SH_PURE_STUB_MODE
     603    int         rc;
     604#ifdef SHFILE_IN_USE
     605    shmtxtmp    tmp;
     606    shfile     *file = shfile_get(pfdtab, fd, &tmp);
     607    if (file)
     608    {
     609        shfile_native_close(file->native, file->flags);
     610
     611        file->fd = -1;
     612        file->flags = 0;
     613        file->native = -1;
     614
     615        shfile_put(pfdtab, file, &tmp);
     616        rc = 0;
     617    }
     618    else
     619        rc = -1;
     620
     621#elif defined(SH_PURE_STUB_MODE)
    103622    rc = -1;
    104623
    105 #elif defined(SH_STUB_MODE)
     624#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    106625    rc = close(fd);
    107 
    108 #else
    109626#endif
    110627
     
    113630}
    114631
     632/**
     633 * read().
     634 */
    115635long shfile_read(shfdtab *pfdtab, int fd, void *buf, size_t len)
    116636{
    117 #ifdef SH_PURE_STUB_MODE
    118     return -1;
    119 
    120 #elif defined(SH_STUB_MODE)
     637    long        rc;
     638#ifdef SHFILE_IN_USE
     639    shmtxtmp    tmp;
     640    shfile     *file = shfile_get(pfdtab, fd, &tmp);
     641    if (file)
     642    {
     643# if K_OS == K_OS_WINDOWS
     644        DWORD dwRead = 0;
     645        if (ReadFile((HANDLE)file->native, buf, (DWORD)len, &dwRead, NULL))
     646            rc = dwRead;
     647        else
     648            rc = shfile_dos2errno(GetLastError());
     649# else
     650        rc = read(file->native, buf, len);
     651# endif
     652
     653        shfile_put(pfdtab, file, &tmp);
     654    }
     655    else
     656        rc = -1;
     657
     658#elif defined(SH_PURE_STUB_MODE)
     659    rc = -1;
     660
     661#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    121662# ifdef _MSC_VER
    122     return read(fd, buf, (unsigned)len);
    123 # else
    124     return read(fd, buf, len);
    125 # endif
    126 
    127 #else
    128 #endif
    129 }
    130 
     663    rc = read(fd, buf, (unsigned)len);
     664# else
     665    rc = read(fd, buf, len);
     666# endif
     667#endif
     668    return rc;
     669}
     670
     671/**
     672 * write().
     673 */
    131674long shfile_write(shfdtab *pfdtab, int fd, const void *buf, size_t len)
    132675{
    133 #ifdef SH_PURE_STUB_MODE
    134     return -1;
    135 
    136 #elif defined(SH_STUB_MODE)
     676    long        rc;
     677#ifdef SHFILE_IN_USE
     678    shmtxtmp    tmp;
     679    shfile     *file = shfile_get(pfdtab, fd, &tmp);
     680    if (file)
     681    {
     682# if K_OS == K_OS_WINDOWS
     683        DWORD dwWritten = 0;
     684        if (WriteFile((HANDLE)file->native, buf, (DWORD)len, &dwWritten, NULL))
     685            rc = dwWritten;
     686        else
     687            rc = shfile_dos2errno(GetLastError());
     688# else
     689        rc = write(file->native, buf, len);
     690# endif
     691
     692        shfile_put(pfdtab, file, &tmp);
     693    }
     694    else
     695        rc = -1;
     696
     697#elif defined(SH_PURE_STUB_MODE)
     698    rc = -1;
     699
     700#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    137701# ifdef _MSC_VER
    138     return write(fd, buf, (unsigned)len);
    139 # else
    140     return write(fd, buf, len);
    141 # endif
    142 
    143 #else
    144 #endif
    145 }
    146 
     702    rc = write(fd, buf, (unsigned)len);
     703# else
     704    rc = write(fd, buf, len);
     705# endif
     706#endif
     707    return rc;
     708}
     709
     710/**
     711 * lseek().
     712 */
    147713long shfile_lseek(shfdtab *pfdtab, int fd, long off, int whench)
    148714{
    149 #ifdef SH_PURE_STUB_MODE
    150     return -1;
    151 
    152 #elif defined(SH_STUB_MODE)
    153     return lseek(fd, off, whench);
    154 
    155 #else
    156 #endif
     715    long        rc;
     716#ifdef SHFILE_IN_USE
     717    shmtxtmp    tmp;
     718    shfile     *file = shfile_get(pfdtab, fd, &tmp);
     719    if (file)
     720    {
     721# if K_OS == K_OS_WINDOWS
     722        assert(SEEK_SET == FILE_BEGIN);
     723        assert(SEEK_CUR == FILE_CURRENT);
     724        assert(SEEK_END == FILE_END);
     725        rc = SetFilePointer((HANDLE)file->native, off, NULL, whench);
     726        if (rc == INVALID_SET_FILE_POINTER)
     727            rc = shfile_dos2errno(GetLastError());
     728# else
     729        rc = lseek(file->native, off, whench);
     730# endif
     731
     732        shfile_put(pfdtab, file, &tmp);
     733    }
     734    else
     735        rc = -1;
     736
     737#elif defined(SH_PURE_STUB_MODE)
     738    rc = -1;
     739
     740#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
     741    rc = lseek(fd, off, whench);
     742#endif
     743
     744    return rc;
    157745}
    158746
     
    160748{
    161749    int rc;
    162 #ifdef SH_PURE_STUB_MODE
     750#ifdef SHFILE_IN_USE
     751    shmtxtmp    tmp;
     752    shfile     *file = shfile_get(pfdtab, fd, &tmp);
     753    if (file)
     754    {
     755        switch (cmd)
     756        {
     757            case F_GETFL:
     758                rc = file->flags;
     759                break;
     760
     761            case F_SETFL:
     762            {
     763                unsigned mask = O_NONBLOCK | O_APPEND | O_BINARY | O_TEXT;
     764# ifdef O_DIRECT
     765                mask |= O_DIRECT;
     766# endif
     767# ifdef O_ASYNC
     768                mask |= O_ASYNC;
     769# endif
     770# ifdef O_SYNC
     771                mask |= O_SYNC;
     772# endif
     773                if ((file->flags & mask) == (arg & mask))
     774                    rc = 0;
     775                else
     776                {
     777# if K_OS == K_OS_WINDOWS
     778                    assert(0);
     779                    errno = EINVAL;
     780                    rc = -1;
     781# else
     782                    rc = fcntl(file->native, F_SETFL, arg);
     783                    if (rc != -1)
     784                        file->flags = (file->flags & ~mask) | (arg & mask);
     785# endif
     786                }
     787                break;
     788            }
     789
     790            case F_DUPFD:
     791            {
     792# if K_OS == K_OS_WINDOWS
     793                HANDLE hNew = INVALID_HANDLE_VALUE;
     794                if (DuplicateHandle(GetCurrentProcess(),
     795                                    (HANDLE)file->native,
     796                                    GetCurrentProcess(),
     797                                    &hNew,
     798                                    0,
     799                                    TRUE /* bInheritHandle */,
     800                                    DUPLICATE_SAME_ACCESS))
     801                    rc = shfile_insert(pfdtab, (intptr_t)hNew, file->flags, arg, "shfile_fcntl");
     802                else
     803                    rc = shfile_dos2errno(GetLastError());
     804# else
     805                int nativeNew = fcntl(file->native F_DUPFD, SHFILE_UNIX_MIN_FD);
     806                if (nativeNew != -1)
     807                    rc = shfile_insert(pfdtab, nativeNew, file->flags, arg, "shfile_fcntl");
     808# endif
     809                break;
     810            }
     811
     812            default:
     813                errno = -EINVAL;
     814                rc = -1;
     815                break;
     816        }
     817
     818        shfile_put(pfdtab, file, &tmp);
     819    }
     820    else
     821        rc = -1;
     822
     823#elif defined(SH_PURE_STUB_MODE)
    163824    rc = -1;
    164825
     
    194855        case F_DUPFD:
    195856        {
    196 #  if 1
    197857            /* the brute force approach. */
    198858            int i = 0;
     
    213873                rc = -1;
    214874            }
    215 #  else
    216             /* A much quick approach which is spoiled by crash validation in the CRT. */
    217             int fdnew = arg;
    218             rc = -2;
    219             for (fdnew = arg; fdnew < 1024; fdnew++)
    220             {
    221                 /* is the file open? */
    222                 errno = 0;
    223                 _isatty(fdnew);
    224                 if (errno == EBADF)
    225                 {
    226                     rc = _dup2(fd, fdnew);
    227                     break;
    228                 }
    229             }
    230             if (rc == -2)
    231             {
    232                 errno = EMFILE;
    233                 rc = -1;
    234             }
    235 #  endif
    236875            break;
    237876        }
     
    240879    rc = fcntl(fd, cmd, arg);
    241880# endif
    242 
    243 #else
    244881#endif
    245882
     
    270907    return -1;
    271908
    272 #elif defined(SH_STUB_MODE)
     909#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    273910    return stat(path, pst);
    274911
     
    282919    return -1;
    283920
    284 #elif defined(SH_STUB_MODE)
     921#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    285922# ifdef _MSC_VER
    286923    return stat(link, pst);
     
    298935    return -1;
    299936
    300 #elif defined(SH_STUB_MODE)
     937#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    301938# ifdef _MSC_VER //???
    302939    return chdir(path);
     
    314951    return NULL;
    315952
    316 #elif defined(SH_STUB_MODE)
     953#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    317954    return getcwd(buf, len);
    318955
     
    326963    return -1;
    327964
    328 #elif defined(SH_STUB_MODE)
     965#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    329966# ifdef _MSC_VER
    330967    type &= ~X_OK;
     
    344981#ifdef SH_PURE_STUB_MODE
    345982    rc = 0;
    346 #elif defined(SH_STUB_MODE)
     983#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    347984    rc = isatty(fd);
    348985#else
     
    361998    rc = -1;
    362999
    363 #elif defined(SH_STUB_MODE)
     1000#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    3641001# ifdef _MSC_VER
    3651002    errno = ENOSYS;
     
    3851022    rc = -1;
    3861023
    387 #elif defined(SH_STUB_MODE)
     1024#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    3881025# ifdef _MSC_VER
    3891026    errno = ENOSYS;
     
    4061043    return 022;
    4071044
    408 #elif defined(SH_STUB_MODE)
     1045#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    4091046    return 022;
    4101047
     
    4191056    return NULL;
    4201057
    421 #elif defined(SH_STUB_MODE)
     1058#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    4221059# ifdef _MSC_VER
    4231060    errno = ENOSYS;
     
    4361073    return NULL;
    4371074
    438 #elif defined(SH_STUB_MODE)
     1075#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    4391076# ifdef _MSC_VER
    4401077    errno = ENOSYS;
     
    4541091    return NULL;
    4551092
    456 #elif defined(SH_STUB_MODE)
     1093#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
    4571094# ifdef _MSC_VER
    4581095    errno = ENOSYS;
Note: See TracChangeset for help on using the changeset viewer.

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