Changeset 2742


Ignore:
Timestamp:
Jul 26, 2006, 3:35:40 AM (19 years ago)
Author:
bird
Message:

More backend porting.

Location:
trunk/libc
Files:
3 added
8 edited
5 copied
4 moved

Legend:

Unmodified
Added
Removed
  • trunk/libc/include/InnoTekLIBC/backend.h

    r2739 r2742  
    906906/** @defgroup grp_Back_process  LIBC Backend - Process Management
    907907 * @{ */
     908
     909/**
     910 * Sets the exit code for the current process and terminates it.
     911 * This call never returns.
     912 *
     913 * @param   rc      The process exit code.
     914 */
     915void __libc_Back_processExit(int rc);
    908916
    909917/**
  • trunk/libc/include/InnoTekLIBC/logstrict.h

    r2436 r2742  
    159159/** Macro to log an unsigned long int return and do the return. */
    160160#define LIBCLOG_RETURN_ULONG(rc)        LIBCLOG_RETURN_MSG((rc), "ret %lu (%#lx)\n", (rc), (rc))
     161/** Macro to log an off_t return and do the return. */
     162#define LIBCLOG_RETURN_OFF(rc)          LIBCLOG_RETURN_MSG((rc), "ret %lld (%#llx)\n", (rc), (rc))
    161163/** Macro to log a pointer return and do the return. */
    162164#define LIBCLOG_RETURN_P(rc)            LIBCLOG_RETURN_MSG((rc), "ret %p\n", (void*)(rc))
  • trunk/libc/include/emx/syscalls.h

    r2739 r2742  
    131131int __endthread (void *pvThrd);
    132132int __execname (char *buf, size_t bufsize);
    133 void __exit (int ret) __attribute__ ((__noreturn__));
     133/*void __exit (int ret) __attribute__ ((__noreturn__));*/
    134134/*int __fcntl (int handle, int request, int arg);*/
    135135int __filesys (__const__ char *drive, char *name, size_t size);
  • trunk/libc/include/klibc/io.h

    r2739 r2742  
    8585     */
    8686    int (*pfnWrite)(struct __libc_FileHandle *pFH, const void *pvBuf, size_t cbWrite, size_t *pcbWritten);
     87    /** Seek operation.
     88     * @returns 0 on success.
     89     * @returns Negated errno on failure.
     90     * @param   pFH         Pointer to the handle structure to operate on.
     91     * @param   off         The seek offset.
     92     * @param   iMethod     The seek method (SEEK_SET, SEEK_CUR, SEEK_END).
     93     * @param   poffActual  Where to store the new offset.
     94     */
     95    int (*pfnSeek)(struct __libc_FileHandle *pFH, off_t off, int iMethod, off_t *poffActual);
     96    /**
     97     * Sets the size of an open file.
     98     *
     99     * @returns 0 on success.
     100     * @returns Negative error code (errno.h) on failure.
     101     * @param   pFH     The file handle structure.
     102     * @param   cbFile  The new filesize.
     103     * @param   fZero   If set any new allocated file space should be initialized to zero.
     104     */
     105    int (*pfnSizeSet)(struct __libc_FileHandle *pFH, off_t cbFile, int fZero);
    87106    /** Duplicate handle operation.
    88107     * @returns 0 on success.
  • trunk/libc/src/kNIX/Makefile.kmk

    r2739 r2742  
    3737    $(PATH_LIBC_SRC)/kNIX/b_ioRead.c \
    3838    $(PATH_LIBC_SRC)/kNIX/b_ioWrite.c \
     39    $(PATH_LIBC_SRC)/kNIX/b_ioSeek.c \
     40    $(PATH_LIBC_SRC)/kNIX/b_ioFileSizeSet.c \
    3941    $(PATH_LIBC_SRC)/kNIX/b_mmanBrk.c \
    4042    $(PATH_LIBC_SRC)/kNIX/b_mmanSBrk.c \
    4143    $(PATH_LIBC_SRC)/kNIX/b_mmanSBrkGetModel.c \
    4244    $(PATH_LIBC_SRC)/kNIX/b_mmanSBrkSetModel.c \
     45    $(PATH_LIBC_SRC)/kNIX/b_signalSendPid.c \
    4346    $(PATH_LIBC_SRC)/kNIX/filehandles.c \
     47    $(PATH_LIBC_SRC)/kNIX/fs.c \
    4448    $(PATH_LIBC_SRC)/kNIX/heap.c \
    4549    $(PATH_LIBC_SRC)/kNIX/heapdata.c \
     
    9296    $(PATH_LIBC_SRC)/kNIX/os2/b_panic.c \
    9397    $(PATH_LIBC_SRC)/kNIX/os2/b_processCredentials.c \
     98    $(PATH_LIBC_SRC)/kNIX/os2/b_processExit.c \
    9499    $(PATH_LIBC_SRC)/kNIX/os2/b_processGetPriority.c \
    95100    $(PATH_LIBC_SRC)/kNIX/os2/b_processSetPriority.c \
     
    166171    $(PATH_LIBC_SRC)/kNIX/os2/__dup.c \
    167172    $(PATH_LIBC_SRC)/kNIX/os2/__dup2.c \
    168     $(PATH_LIBC_SRC)/kNIX/os2/__exit.c \
    169173    $(PATH_LIBC_SRC)/kNIX/os2/__fcntl.c \
    170174    $(PATH_LIBC_SRC)/kNIX/os2/__ftime.c \
     
    196200
    197201libc_kNIX_SOURCES.nt = \
     202        $(PATH_LIBC_SRC)/kNIX/nt/b_fsUnlink.c \
    198203        $(PATH_LIBC_SRC)/kNIX/nt/b_panic.c \
     204        $(PATH_LIBC_SRC)/kNIX/nt/b_processExit.c \
     205        $(PATH_LIBC_SRC)/kNIX/nt/b_signalAction.c \
     206        $(PATH_LIBC_SRC)/kNIX/nt/b_signalMask.c \
     207        $(PATH_LIBC_SRC)/kNIX/nt/b_signalSendPGrp.c \
     208        $(PATH_LIBC_SRC)/kNIX/nt/b_threadCleanup.c \
     209        $(PATH_LIBC_SRC)/kNIX/nt/b_threadInit.c \
    199210        $(PATH_LIBC_SRC)/kNIX/nt/fhNtFile.c \
    200211        $(PATH_LIBC_SRC)/kNIX/nt/NtStatus.c \
  • trunk/libc/src/kNIX/b_ioFileSizeSet.c

    r2738 r2742  
    22/** @file
    33 *
    4  * LIBC SYS Backend - chsize.
     4 * kNIX - _chsize() / ftruncate().
    55 *
    6  * Copyright (c) 2003-2004 knut st. osmundsen <bird@innotek.de>
     6 * Copyright (c) 2006 knut st. osmundsen <bird-srcspam@anduin.net>
    77 *
    88 *
    9  * This file is part of InnoTek LIBC.
     9 * This file is part of kLIBC.
    1010 *
    11  * InnoTek LIBC is free software; you can redistribute it and/or modify
     11 * kLIBC is free software; you can redistribute it and/or modify
    1212 * it under the terms of the GNU Lesser General Public License as published
    1313 * by the Free Software Foundation; either version 2 of the License, or
    1414 * (at your option) any later version.
    1515 *
    16  * InnoTek LIBC is distributed in the hope that it will be useful,
     16 * kLIBC is distributed in the hope that it will be useful,
    1717 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     
    2020 *
    2121 * You should have received a copy of the GNU Lesser General Public License
    22  * along with InnoTek LIBC; if not, write to the Free Software
     22 * along with kLIBC; if not, write to the Free Software
    2323 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2424 *
     
    2929*   Header Files                                                               *
    3030*******************************************************************************/
    31 #include "libc-alias.h"
    32 #define INCL_FSMACROS
    33 #define INCL_ERRORS
    34 #include <os2emx.h>
    35 #include "b_fs.h"
    36 #include <limits.h>
    37 #include <errno.h>
    38 #include <InnoTekLIBC/backend.h>
    3931#define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_BACK_IO
    40 #include <InnoTekLIBC/logstrict.h>
     32#include "kNIX.h"
     33#include <klibc/backend.h>
     34#include <klibc/logstrict.h>
    4135
    42 /*******************************************************************************
    43 *   Global Variables                                                           *
    44 *******************************************************************************/
    45 /** A page of zeros.
    46  * @todo Make this a separate segment for optimal thunking effiency! */
    47 static const char __libc_gachZeros[65536 - 4096];
    48 
    49 
    50 /*******************************************************************************
    51 *   Internal Functions                                                         *
    52 *******************************************************************************/
    53 static inline int getFileSize(HFILE hFile, off_t *pcb);
    54 static inline int setFileSize(HFILE hFile, off_t cbFile);
    55 static inline int seekFile(HFILE hFile, off_t cbFile, int iMethod, off_t *poffFile);
    56 
    57 /**
    58  * Calls the correct OS/2 api for this operation.
    59  * FS is saved and loaded by caller.
    60  * @returns OS/2 error code or negative errno.
    61  */
    62 static inline int getFileSize(HFILE hFile, off_t *pcb)
    63 {
    64     union
    65     {
    66         FILESTATUS3     fsts3;
    67         FILESTATUS3L    fsts3L;
    68     } info;
    69     int     rc;
    70 #if OFF_MAX > LONG_MAX
    71     if (__libc_gpfnDosOpenL)
    72     {
    73         rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &info, sizeof(info.fsts3L));
    74         *pcb = info.fsts3L.cbFile;
    75     }
    76     else
    77 #endif
    78     {
    79         rc = DosQueryFileInfo(hFile, FIL_STANDARD, &info, sizeof(info.fsts3));
    80         *pcb = info.fsts3.cbFile;
    81     }
    82     return rc;
    83 }
    84 
    85 /**
    86  * Calls the correct OS/2 api for this operation.
    87  * FS is saved and loaded by caller.
    88  * @returns OS/2 error code or negative errno.
    89  */
    90 static inline int setFileSize(HFILE hFile, off_t cbFile)
    91 {
    92     int rc;
    93 #if OFF_MAX > LONG_MAX
    94     if (__libc_gpfnDosSetFileSizeL)
    95         rc = __libc_gpfnDosSetFileSizeL(hFile, cbFile);
    96     else
    97     {
    98         if (cbFile > __LONG_MAX)
    99             return -EOVERFLOW;
    100         rc = DosSetFileSize(hFile, cbFile);
    101     }
    102 #else
    103     rc = DosSetFileSize(hFile, cbFile);
    104 #endif
    105     return rc;
    106 }
    107 
    108 /**
    109  * Calls the correct OS/2 api for this operation.
    110  * FS is saved and loaded by caller.
    111  * @returns OS/2 error code or negative errno.
    112  */
    113 static inline int seekFile(HFILE hFile, off_t off, int iMethod, off_t *poffFile)
    114 {
    115     int rc;
    116 #if OFF_MAX > LONG_MAX
    117     if (__libc_gpfnDosSetFilePtrL)
    118     {
    119         LONGLONG cbNewTmp;
    120         rc = __libc_gpfnDosSetFilePtrL(hFile, off, iMethod, &cbNewTmp);
    121         off = cbNewTmp;
    122     }
    123     else
    124     {
    125         ULONG cbNewTmp;
    126         if (off > LONG_MAX || off < LONG_MIN)
    127             return -EOVERFLOW;
    128         rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp);
    129         off = cbNewTmp;
    130     }
    131 #else
    132     {
    133         ULONG cbNewTmp;
    134         rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp);
    135         off = cbNewTmp;
    136     }
    137 #endif
    138     if (poffFile)
    139         *poffFile = off;
    140     return rc;
    141 }
    14236
    14337
     
    16256     * Get filehandle.
    16357     */
    164     PLIBCFH    pFH;
    165     int rc = __libc_FHEx(fh, &pFH);
     58    __LIBC_PFH pFH;
     59    int rc = __libc_FHGet(fh, &pFH);
    16660    if (rc)
    16761        LIBCLOG_ERROR_RETURN_INT(rc);
    16862
    169     if (!pFH->pOps)
    170     {
    171         /*
    172          * Standard OS/2 file handle.
    173          *
    174          * Get the current file size so we can perform
    175          * any necessary zero padding.
    176          */
    177         FS_VAR();
    178         FS_SAVE_LOAD();
    179         off_t   cbCur;
    180         rc = getFileSize(fh, &cbCur);
    181         if (!rc)
    182         {
    183             if (cbCur != cbFile)
    184             {
    185                 /*
    186                  * File size change needed.
    187                  */
    188                 rc = setFileSize(fh, cbFile);
    189                 if (!rc)
    190                 {
    191                     /*
    192                      * We're done if it was a truncation.
    193                      */
    194                     off_t   cbLeft = cbFile - cbCur;
    195                     if (    cbLeft <= 0
    196                         ||  !fZero
    197                         || (pFH->pFsInfo && pFH->pFsInfo->fZeroNewBytes))
    198                     {
    199                         FS_RESTORE();
    200                         LIBCLOG_RETURN_INT(0);
    201                     }
    202 
    203                     /*
    204                      * Must fill the allocated file space with zeros.
    205                      */
    206                     off_t offSaved;
    207                     rc = seekFile(fh, 0, FILE_CURRENT, &offSaved);
    208                     if (!rc)
    209                         rc = seekFile(fh, cbCur, FILE_BEGIN, NULL);
    210                     while (!rc && cbLeft > 0)
    211                     {
    212                         ULONG cb = cbLeft >= sizeof(__libc_gachZeros) ? sizeof(__libc_gachZeros) : cbLeft;
    213                         rc = DosWrite(fh, &__libc_gachZeros[0], cb, &cb);
    214                         cbLeft -= cb;
    215                     }
    216                     int rc2 = seekFile(fh, offSaved, FILE_BEGIN, NULL);
    217                     if (!rc && !rc2)
    218                     {
    219                         FS_RESTORE();
    220                         LIBCLOG_RETURN_INT(0);
    221                     }
    222 
    223                     /*
    224                      * Shit, we failed writing zeros.
    225                      * Try undo the expand operation.
    226                      */
    227                     setFileSize(fh, cbCur);
    228                     if (rc2)
    229                     {
    230                         seekFile(fh, offSaved, FILE_BEGIN, NULL);
    231                         if (!rc)
    232                             rc = rc2;
    233                     }
    234                 }
    235             }
    236         }
    237 
    238         FS_RESTORE();
    239         if (rc > 0)
    240             rc = -__libc_native2errno(rc);
    241         LIBCLOG_ERROR_RETURN_INT(rc);
    242     }
    243     else
    244     {
    245         /*
    246          * Non-standard file handle - fail.
    247          */
    248         LIBCLOG_ERROR_RETURN_INT(-EOPNOTSUPP);
    249     }
     63    /*
     64     * Perform the operation.
     65     */
     66    rc = pFH->pOps->pfnSizeSet(pFH, cbFile, fZero);
     67    __libc_FHPut(pFH);
     68    if (!rc)
     69        LIBCLOG_RETURN_INT(rc);
     70    LIBCLOG_ERROR_RETURN_INT(rc);
    25071}
    25172
  • trunk/libc/src/kNIX/b_ioSeek.c

    r2738 r2742  
    22/** @file
    33 *
    4  * LIBC SYS Backend - seek.
     4 * kNIX - seek().
    55 *
    6  * Copyright (c) 2003-2004 knut st. osmundsen <bird@innotek.de>
     6 * Copyright (c) 2006 knut st. osmundsen <bird-srcspam@anduin.net>
    77 *
    88 *
    9  * This file is part of InnoTek LIBC.
     9 * This file is part of kLIBC.
    1010 *
    11  * InnoTek LIBC is free software; you can redistribute it and/or modify
     11 * kLIBC is free software; you can redistribute it and/or modify
    1212 * it under the terms of the GNU Lesser General Public License as published
    1313 * by the Free Software Foundation; either version 2 of the License, or
    1414 * (at your option) any later version.
    1515 *
    16  * InnoTek LIBC is distributed in the hope that it will be useful,
     16 * kLIBC is distributed in the hope that it will be useful,
    1717 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     
    2020 *
    2121 * You should have received a copy of the GNU Lesser General Public License
    22  * along with InnoTek LIBC; if not, write to the Free Software
     22 * along with kLIBC; if not, write to the Free Software
    2323 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2424 *
     
    2929*   Header Files                                                               *
    3030*******************************************************************************/
    31 #include "libc-alias.h"
    32 #define INCL_FSMACROS
    33 #include <os2emx.h>
    34 #include "b_fs.h"
    35 #include <limits.h>
     31#define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_BACK_IO
     32#include "kNIX.h"
    3633#include <errno.h>
    3734#include <stdio.h>
    38 #include <InnoTekLIBC/backend.h>
    39 #define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_BACK_IO
    40 #include <InnoTekLIBC/logstrict.h>
     35#include <unistd.h>
     36#include <klibc/backend.h>
     37#include <klibc/logstrict.h>
    4138
    4239
     
    4643 * @returns new file offset on success.
    4744 * @returns Negative error code (errno) on failure.
    48  * @param   hFile       File handle to preform seek operation on.
     45 * @param   fh          File handle to preform seek operation on.
    4946 * @param   off         Offset to seek to.
    50  * @param   iOrigin     The seek method. SEEK_CUR, SEEK_SET or SEEK_END.
     47 * @param   iMethod     The seek method. SEEK_CUR, SEEK_SET or SEEK_END.
    5148 */
    52 off_t __libc_Back_ioSeek(int hFile, off_t off, int iMethod)
     49off_t __libc_Back_ioSeek(int fh, off_t off, int iMethod)
    5350{
    54     LIBCLOG_ENTER("hFile=%d off=%lld iMethod=%d\n", hFile, off, iMethod);
     51    LIBCLOG_ENTER("fh=%d off=%lld iMethod=%d\n", fh, off, iMethod);
    5552
    5653    /*
    57      * Get filehandle / validate input.
     54     * Validate the method and get the filehandle.
    5855     */
    5956    if (iMethod != SEEK_SET && iMethod != SEEK_CUR && iMethod != SEEK_END)
    60         LIBCLOG_RETURN_INT(-EINVAL);
    61     PLIBCFH pFH;
    62     int rc = __libc_FHEx(hFile, &pFH);
     57        LIBCLOG_ERROR_RETURN_INT(-EINVAL);
     58    __LIBC_PFH pFH;
     59    int rc = __libc_FHGet(fh, &pFH);
    6360    if (rc)
    6461        LIBCLOG_ERROR_RETURN_INT(rc);
    6562
    66     off_t   cbNew;
    67     if (!pFH->pOps)
    68     {
    69         /*
    70          * Standard OS/2 filehandle.
    71          */
    72         FS_VAR();
    73         FS_SAVE_LOAD();
    74 #if OFF_MAX > LONG_MAX
    75         if (__libc_gpfnDosSetFilePtrL)
    76         {
    77             LONGLONG cbNewTmp;
    78             rc = __libc_gpfnDosSetFilePtrL(hFile, off, iMethod, &cbNewTmp);
    79             cbNew = cbNewTmp;
    80         }
    81         else
    82         {
    83             ULONG cbNewTmp;
    84             if (off > LONG_MAX || off < LONG_MIN)
    85             {
    86                 FS_RESTORE();
    87                 LIBCLOG_ERROR_RETURN_INT(-EOVERFLOW);
    88             }
    89             rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp);
    90             cbNew = cbNewTmp;
    91         }
    92 #else
    93         {
    94             ULONG cbNewTmp;
    95             rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp);
    96             cbNew = cbNewTmp;
    97         }
    98 #endif
    99         FS_RESTORE();
    100 
    101         if (rc)
    102         {
    103             rc = -__libc_native2errno(rc);
    104             LIBCLOG_ERROR_RETURN_INT(rc);
    105         }
    106     }
    107     else
    108     {
    109         /*
    110          * Non-standard filehandle - fail for the present.
    111          */
    112         LIBCLOG_ERROR_RETURN_INT(-EOPNOTSUPP);
    113     }
    114 
    115     LIBCLOG_RETURN_MSG(cbNew, "ret %lld (%#llx)\n", cbNew, cbNew);
     63    /*
     64     * Perform the operation.
     65     */
     66    rc = pFH->pOps->pfnSeek(pFH, off, iMethod, &off);
     67    __libc_FHPut(pFH);
     68    if (!rc)
     69        LIBCLOG_RETURN_OFF(off);
     70    LIBCLOG_ERROR_RETURN_INT(rc);
    11671}
    11772
    118 
  • trunk/libc/src/kNIX/b_signalSendPid.c

    r2738 r2742  
    2929*   Header Files                                                               *
    3030*******************************************************************************/
    31 #include "libc-alias.h"
    32 #define INCL_BASE
    33 #define INCL_FSMACROS
    34 #define INCL_DOSSIGNALS
    35 #include <os2emx.h>
    36 
     31#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_SIGNAL
     32#include "kNIX.h"
    3733#include <signal.h>
    3834#include <errno.h>
    39 #include <InnoTekLIBC/backend.h>
    40 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_SIGNAL
    41 #include <InnoTekLIBC/logstrict.h>
     35#include <klibc/backend.h>
     36#include <klibc/logstrict.h>
     37#ifdef __OS2__ /* later on NT. */
    4238#include "b_signal.h"
    43 #include "syscalls.h"
     39#endif
    4440
    4541
     
    7066        LIBCLOG_ERROR_RETURN(-EINVAL, "ret -EINVAL - Invalid pid %d\n", pid);
    7167
     68#ifdef __OS2__
    7269    /*
    7370     * Differ between others and our self.
     
    8986        LIBCLOG_RETURN_INT(rc);
    9087    LIBCLOG_ERROR_RETURN_INT(rc);
     88#else
     89    /* stub */
     90    LIBCLOG_ERROR_RETURN_INT(-ENOSYS);
     91#endif
    9192}
    9293
  • trunk/libc/src/kNIX/fs.c

    r2738 r2742  
    22/** @file
    33 *
    4  * LIBC SYS Backend - file system stuff.
    5  *
    6  * Copyright (c) 2004-2005 knut st. osmundsen <bird@innotek.de>
    7  *
    8  *
    9  * This file is part of InnoTek LIBC.
    10  *
    11  * InnoTek LIBC is free software; you can redistribute it and/or modify
     4 * kNIX - file system, common bits.
     5 *
     6 * Copyright (c) 2004-2006 knut st. osmundsen <bird-srcspam@anduin.net>
     7 *
     8 *
     9 * This file is part of kLIBC.
     10 *
     11 * kLIBC is free software; you can redistribute it and/or modify
    1212 * it under the terms of the GNU Lesser General Public License as published
    1313 * by the Free Software Foundation; either version 2 of the License, or
    1414 * (at your option) any later version.
    1515 *
    16  * InnoTek LIBC is distributed in the hope that it will be useful,
     16 * kLIBC is distributed in the hope that it will be useful,
    1717 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     
    2020 *
    2121 * You should have received a copy of the GNU Lesser General Public License
    22  * along with InnoTek LIBC; if not, write to the Free Software
     22 * along with kLIBC; if not, write to the Free Software
    2323 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2424 *
     
    2929*   Header Files                                                               *
    3030*******************************************************************************/
     31#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS
     32#include "kNIX.h"
    3133#define _GNU_SOURCE
    32 #include "libc-alias.h"
    33 #define INCL_FSMACROS
    34 #define INCL_BASE
    35 #define INCL_ERRORS
    36 #include <os2emx.h>
    37 #include "b_fs.h"
    3834#include <stddef.h>
    3935#include <string.h>
    4036#include <errno.h>
    41 #include <386/builtin.h>
    4237#include <sys/stat.h>
    4338#include <sys/fmutex.h>
    4439#include <sys/smutex.h>
    4540#include <emx/startup.h>
    46 #include "syscalls.h"
    47 #include <InnoTekLIBC/sharedpm.h>
    48 #include <InnoTekLIBC/pathrewrite.h>
    49 #include <InnoTekLIBC/libc.h>
    50 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS
    51 #include <InnoTekLIBC/logstrict.h>
    52 
    53 
    54 /*******************************************************************************
    55 *   Defined Constants And Macros                                               *
    56 *******************************************************************************/
    57 #define ORD_DOS32OPENL              981
    58 #define ORD_DOS32SETFILEPTRL        988
    59 #define ORD_DOS32SETFILESIZEL       989
    60 #define ORD_DOS32SETFILELOCKSL      986
    61 
    62 #define SIZEOF_ACHBUFFER    (sizeof(FILEFINDBUF4) + 32)
     41#ifdef __OS2__
     42# include <InnoTekLIBC/sharedpm.h> //???
     43# include <InnoTekLIBC/pathrewrite.h>//??!
     44#endif
     45#include <klibc/backend.h>
     46#include <klibc/logstrict.h>
    6347
    6448
     
    8064
    8165
    82 ULONG (* _System __libc_gpfnDosOpenL)(PCSZ pszFileName, PHFILE phFile, PULONG pulAction, LONGLONG llFileSize, ULONG ulAttribute, ULONG ulOpenFlags, ULONG ulOpenMode, PEAOP2 pEABuf) = NULL;
    83 ULONG (* _System __libc_gpfnDosSetFilePtrL)(HFILE hFile, LONGLONG llOffset, ULONG ulOrigin, PLONGLONG pllPos) = NULL;
    84 ULONG (* _System __libc_gpfnDosSetFileSizeL)(HFILE hFile, LONGLONG cbSize) = NULL;
    85 ULONG (* _System __libc_gpfnDosSetFileLocksL)(HFILE hFile, __const__ FILELOCKL *pflUnlock, __const__ FILELOCKL *pflLock, ULONG ulTimeout, ULONG flFlags) = NULL;
    86 
    87 /** Symlink EA name. */
    88 static const char __libc_gszSymlinkEA[] = EA_SYMLINK;
    89 /** UID EA name. */
    90 static const char __libc_gszUidEA[]     = EA_UID;
    91 /** GID EA name. */
    92 static const char __libc_gszGidEA[]     = EA_GID;
    93 /** Mode EA name. */
    94 static const char __libc_gszModeEA[]    = EA_MODE;
    95 /** Ino EA name. */
    96 static const char __libc_gszInoEA[]     = EA_INO;
    97 /** RDev EA name. */
    98 static const char __libc_gszRDevEA[]    = EA_RDEV;
    99 /** Gen(eration) EA name. */
    100 static const char __libc_gszGenEA[]     = EA_GEN;
    101 /** User flags EA name. */
    102 static const char __libc_gszFlagsEA[]   = EA_FLAGS;
    103 
    104 /**
    105  * The prefilled GEA2LIST construct for querying a symlink.
    106  */
    107 #pragma pack(1)
    108 static const struct
    109 {
    110     ULONG   cbList;
    111     ULONG   oNextEntryOffset;
    112     BYTE    cbName;
    113     CHAR    szName[sizeof(EA_SYMLINK)];
    114 } gGEA2ListSymlink =
    115 {
    116     sizeof(gGEA2ListSymlink),
    117     0,
    118     sizeof(EA_SYMLINK) - 1,
    119     EA_SYMLINK
    120 };
    121 #pragma pack()
    122 
    123 /**
    124  * The prefilled GEA2LIST construct for querying all unix attributes.
    125  */
    126 const struct __LIBC_BACK_FSUNIXATTRIBSGEA2LIST __libc_gFsUnixAttribsGEA2List =
    127 {
    128 #define OFF(a,b)  offsetof(struct __LIBC_BACK_FSUNIXATTRIBSGEA2LIST, a) - offsetof(struct __LIBC_BACK_FSUNIXATTRIBSGEA2LIST, b)
    129     sizeof(__libc_gFsUnixAttribsGEA2List),
    130     OFF(offUID,   offSymlink), sizeof(EA_SYMLINK) - 1, EA_SYMLINK,
    131     OFF(offGID,   offUID),     sizeof(EA_UID) - 1,     EA_UID,
    132     OFF(offMode,  offGID),     sizeof(EA_GID) - 1,     EA_GID,
    133     OFF(offINO,   offMode),    sizeof(EA_MODE) - 1,    EA_MODE,
    134     OFF(offRDev,  offINO),     sizeof(EA_INO) - 1,     EA_INO,
    135     OFF(offGen,   offRDev),    sizeof(EA_RDEV) - 1,    EA_RDEV,
    136     OFF(offFlags, offGen),     sizeof(EA_GEN) - 1,     EA_GEN,
    137     0,                         sizeof(EA_FLAGS) - 1,   EA_FLAGS
    138 #undef OFF
    139 };
    140 #pragma pack()
    141 
    142 /**
    143  * The prefilled GEA2LIST construct for querying all the mode attribute.
    144  */
    145 #pragma pack(1)
    146 static const struct
    147 {
    148     ULONG   cbList;
    149     ULONG   oNextEntryOffset;
    150     BYTE    cbName;
    151     CHAR    szName[sizeof(EA_MODE)];
    152 } gGEA2ListMode =
    153 {
    154     sizeof(gGEA2ListMode),
    155     0,
    156     sizeof(EA_MODE) - 1,
    157     EA_MODE
    158 };
    159 #pragma pack()
    160 
    161 /**
    162  * The prefilled FEA2LIST construct for setting all attributes during a creation operation.
    163  */
    164 #pragma pack(1)
    165 const struct __LIBC_FSUNIXATTRIBSCREATEFEA2LIST __libc_gFsUnixAttribsCreateFEA2List =
    166 {
    167 #define OFF(a,b)  offsetof(struct __LIBC_FSUNIXATTRIBSCREATEFEA2LIST, a)  - offsetof(struct __LIBC_FSUNIXATTRIBSCREATEFEA2LIST, b)
    168     sizeof(__libc_gFsUnixAttribsCreateFEA2List),
    169     OFF(offGID,    offUID),   FEA_NEEDEA,  sizeof(EA_UID) - 1,   sizeof(uint32_t) + 4, EA_UID,   EAT_BINARY, sizeof(uint32_t), 0, "",
    170     OFF(offMode,   offGID),   FEA_NEEDEA,  sizeof(EA_GID) - 1,   sizeof(uint32_t) + 4, EA_GID,   EAT_BINARY, sizeof(uint32_t), 0, "",
    171     OFF(offINO,    offMode),  FEA_NEEDEA,  sizeof(EA_MODE) - 1,  sizeof(uint32_t) + 4, EA_MODE,  EAT_BINARY, sizeof(uint32_t), 0, "",
    172     OFF(offRDev,   offINO),   FEA_NEEDEA,  sizeof(EA_INO) - 1,   sizeof(uint64_t) + 4, EA_INO,   EAT_BINARY, sizeof(uint64_t), 0, "",
    173     OFF(offGen,    offRDev),  FEA_NEEDEA,  sizeof(EA_RDEV) - 1,  sizeof(uint32_t) + 4, EA_RDEV,  EAT_BINARY, sizeof(uint32_t), 0, "",
    174     OFF(offFlags,  offGen),   FEA_NEEDEA,  sizeof(EA_GEN) - 1,   sizeof(uint32_t) + 4, EA_GEN,   EAT_BINARY, sizeof(uint32_t), 0, "",
    175     0,                        FEA_NEEDEA,  sizeof(EA_FLAGS) - 1, sizeof(uint32_t) + 4, EA_FLAGS, EAT_BINARY, sizeof(uint32_t), 0, ""
    176 #undef OFF
    177 };
    178 #pragma pack()
    179 
    180 /**
    181  * The prefilled GEA2LIST construct for querying unix attributes for directory listing.
    182  */
    183 const struct __LIBC_BACK_FSUNIXATTRIBSDIRGEA2LIST __libc_gFsUnixAttribsDirGEA2List =
    184 {
    185 #define OFF(a,b)  offsetof(struct __LIBC_BACK_FSUNIXATTRIBSDIRGEA2LIST, a) - offsetof(struct __LIBC_BACK_FSUNIXATTRIBSDIRGEA2LIST, b)
    186     sizeof(__libc_gFsUnixAttribsDirGEA2List),
    187     OFF(offINO,   offMode),    sizeof(EA_MODE) - 1,    EA_MODE,
    188     0,                         sizeof(EA_INO) - 1,     EA_INO,
    189 #undef OFF
    190 };
    191 #pragma pack()
    192 
     66#ifdef __OS2__
    19367/**
    19468 * The special /@unixroot rewrite rule.
     
    19872    __LIBC_PRWF_CASE_SENSITIVE | __LIBC_PRWF_TYPE_DIR,      "/@unixroot",  10, __libc_gszUnixRoot, 0
    19973};
    200 
    201 
    202 /** Array of pointers to fs info objects for all
    203  * possible OS/2 volumes.
    204  */
    205 static __LIBC_FSINFO  g_aFSInfoVolumes['Z' - 'A' + 1];
    206 /** Mutex semaphore protecting the g_aFSInfoVolumes array. */
    207 static _fmutex        g_mtxFSInfoVolumes = _FMUTEX_INITIALIZER_EX(_FMC_MUST_COMPLETE, "mtxFSInfoVolumes");
     74#endif
    20875
    20976
     
    21178*   Internal Functions                                                         *
    21279*******************************************************************************/
    213 static int fsResolveUnix(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree);
    214 static int fsResolveOS2(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree);
    21580static uint32_t crc32str(const char *psz);
    21681#if 0
     
    22085
    22186
    222 #ifndef STANDALONE_TEST
    22387/**
    22488 * Init the file system stuff.
     
    246110        LIBCLOG_RETURN_INT(-1);
    247111
     112#ifdef __OS2__ /** @todo move this! */
    248113    /*
    249114     * Inherit File System Data from parent.
     
    344209    }
    345210    DosFreeModule(hmod);
    346 
     211#endif /* __OS2__ */
    347212    LIBCLOG_RETURN_INT(0);
    348213}
    349214
     215#ifdef __OS2__ /** @todo move this! */
    350216/**
    351217 * Pack inherit data.
     
    407273    LIBCLOG_RETURN_INT(rc);
    408274}
     275#endif /*__OS2__ */
    409276
    410277
     
    414281    if (!rc)
    415282        return 0;
    416     return -__libc_native2errno(rc);
     283    return -EDOOFUS;
    417284}
    418285
     
    426293}
    427294
    428 #endif /*!STANDALONE_TEST*/
    429 
    430 /**
    431  * Reads the content of a symbolic link.
    432  *
    433  * This is weird interface as it will return a truncated result if not
    434  * enough buffer space. It is also weird in that there is no string
    435  * terminator.
    436  *
    437  * @returns Number of bytes returned in pachBuf.
    438  * @returns -1 and errno on failure.
    439  * @param   pszNativePath   The path to the symlink to read.
    440  * @param   pachBuf         Where to store the symlink value.
    441  * @param   cchBuf          Size of buffer.
    442  */
    443 int __libc_back_fsNativeSymlinkRead(const char *pszNativePath, char *pachBuf, size_t cchBuf)
    444 {
    445     LIBCLOG_ENTER("pszNativePath=%p:{%s} pachBuf=%p cchBuf=%d\n", (void *)pszNativePath, pszNativePath, (void *)pachBuf, cchBuf);
    446 
    447     /*
    448      * Query the symlink EA value.
    449      */
    450     char    _achBuffer[SIZEOF_ACHBUFFER + 4];
    451     char   *pachBuffer = (char *)((uintptr_t)&_achBuffer[3] & ~3);
    452     EAOP2   EaOp;
    453     EaOp.fpGEA2List = (PGEA2LIST)&gGEA2ListSymlink;
    454     EaOp.fpFEA2List = (PFEA2LIST)pachBuffer;
    455     EaOp.oError     = 0;
    456     EaOp.fpFEA2List->cbList = SIZEOF_ACHBUFFER;
    457     int rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, &EaOp, sizeof(EaOp));
    458     if (!rc)
    459     {
    460         if (    EaOp.fpFEA2List->cbList > sizeof(EaOp.fpFEA2List->list[0])
    461             &&  EaOp.fpFEA2List->list[0].cbValue)
    462         {
    463             /*
    464              * Validate the EA.
    465              */
    466             PUSHORT pusType = (PUSHORT)((char *)&EaOp.fpFEA2List->list[1] + EaOp.fpFEA2List->list[0].cbName);
    467             int     cchSymlink = pusType[1];
    468             char   *pszSymlink = (char *)&pusType[2];
    469             if (    pusType[0] == EAT_ASCII
    470                 &&  cchSymlink < EaOp.fpFEA2List->list[0].cbValue
    471                 &&  cchSymlink > 0
    472                 &&  *pszSymlink)
    473             {
    474                 /*
    475                  * Copy it to the buffer and return.
    476                  */
    477                 if (cchSymlink > cchBuf)
    478                 {
    479                     LIBCLOG_ERROR("Buffer to small. %d bytes required, %d bytes available. pszSymlink='%.*s' pszNativePath='%s'\n",
    480                                   cchSymlink, cchBuf, cchSymlink, pszSymlink, pszNativePath);
    481                     cchSymlink = cchBuf;
    482                 }
    483                 memcpy(pachBuf, pszSymlink, cchSymlink);
    484                 LIBCLOG_RETURN_INT(cchSymlink);
    485             }
    486             else
    487                 LIBCLOG_ERROR_RETURN(-EFTYPE, "ret -EFTYPE - Invalid symlink EA! type=%x len=%d cbValue=%d *pszSymlink=%c pszNativePath='%s'\n",
    488                                      pusType[0], pusType[1], EaOp.fpFEA2List->list[0].cbValue, *pszSymlink, pszNativePath);
    489         }
    490         else
    491             LIBCLOG_ERROR_RETURN(-EINVAL, "ret -EINVAL - %s is not a symlink!\n", pszNativePath);
    492     }
    493     else
    494         LIBCLOG_ERROR("DosQueryPathInfo(%s) -> %d!\n", pszNativePath, rc);
    495 
    496     /* failure */
    497     rc = -__libc_native2errno(rc);
    498     LIBCLOG_ERROR_RETURN_INT(rc);
    499 }
    500 
    501 
    502 /**
    503  * Checks if the specified path is a symlink or not.
    504  * @returns true / false.
    505  * @param   pszNativePath       Path to the potential symlink.
    506  */
    507 static int fsIsSymlink(const char *pszNativePath)
    508 {
    509     char sz[16];
    510     return __libc_back_fsNativeSymlinkRead(pszNativePath, sz, sizeof(sz)) >= 0;
    511 }
    512 
    513 
    514 #if 0 //just testing, not useful.
    515 /**
    516  * Updates a symlink.
    517  *
    518  * @returns 0 on success.
    519  * @returns -1 and errno on failure.
    520  * @param   pszTarget       The symlink target.
    521  * @param   pszSymlink      The symlink, the one to be updated.
    522  */
    523 int __libc_back_fsSymlinkWrite(const char *pszTarget, const char *pszSymlink)
    524 {
    525     LIBCLOG_ENTER("pszTarget=%s pszSymlink=%s\n", pszTarget, pszSymlink);
    526 
    527     /*
    528      * Validate input.
    529      */
    530     int cchTarget = strlen(pszTarget);
    531     if (cchTarget >= PATH_MAX)
    532         LIBCLOG_ERROR_RETURN(-ENAMETOOLONG, "ret -ENAMETOOLONG - Target is too long, %d bytes. (%s)\n", cchTarget, pszTarget);
    533 
    534     /*
    535      * Allocate FEA buffer.
    536      */
    537     EAOP2   EaOp = {0,0,0};
    538     int     cb = cchTarget + sizeof(USHORT) * 2 + sizeof(EA_SYMLINK) + sizeof(FEALIST);
    539     EaOp.fpFEA2List = alloca(cb);
    540     if (!EaOp.fpFEA2List)
    541         LIBCLOG_ERROR_RETURN(-ENOMEM, "ret -ENOMEM - Out of stack! alloca(%d) failed\n", cb);
    542 
    543     /*
    544      * Setup the EAOP structure.
    545      */
    546     EaOp.fpFEA2List->cbList = cb;
    547     PFEA2   pFEA = &EaOp.fpFEA2List->list[0];
    548     pFEA->oNextEntryOffset  = 0;
    549     pFEA->cbName            = sizeof(EA_SYMLINK) - 1;
    550     pFEA->cbValue           = cchTarget + sizeof(USHORT) * 2;
    551     pFEA->fEA               = FEA_NEEDEA;
    552     memcpy(pFEA->szName, EA_SYMLINK, sizeof(EA_SYMLINK));
    553     PUSHORT pus = (PUSHORT)&pFEA->szName[sizeof(EA_SYMLINK)];
    554     pus[0]                  = EAT_ASCII;
    555     pus[1]                  = cchTarget;
    556     memcpy(&pus[2], pszTarget, cchTarget);
    557     int rc = DosSetPathInfo((PCSZ)pszTarget, FIL_QUERYEASIZE, &EaOp, sizeof(EAOP2), 0);
    558     if (!rc)
    559         LIBCLOG_RETURN_INT(0);
    560 
    561     rc = -__libc_native2errno(rc);
    562     LIBCLOG_ERROR_RETURN_INT(rc);
    563 }
    564 #endif
    565 
    566295
    567296/**
     
    573302void __libc_back_fsUpdateUnixRoot(const char *pszUnixRoot)
    574303{
     304#ifdef __OS2__
    575305    gaRewriteRule.pszTo = "/";
    576306    gaRewriteRule.cchTo = 1;
     307#endif
    577308
    578309    int cch = strlen(pszUnixRoot);
    579310    memcpy(__libc_gszUnixRoot, pszUnixRoot, cch + 1);
    580311    __libc_gcchUnixRoot = cch;
    581 }
    582 
    583 
    584 /**
    585  * Cleans up a path specifier a little bit.
    586  * This includes removing duplicate slashes, uncessary single dots, and
    587  * trailing slashes.
    588  *
    589  * @returns Number of bytes in the clean path.
    590  * @param   pszPath     The path to cleanup.
    591  * @param   fFlags      Flags controlling the operation of the function.
    592  *                      See the BACKFS_FLAGS_* defines.
    593  * @param   pfFlags     Where to clear the BACKFS_FLAGS_RESOLVE_DIR_MAYBE_ flag if a
    594  *                      trailing slash was found.
    595  */
    596 static int fsCleanPath(char *pszPath, unsigned fFlags, unsigned *pfFlags)
    597 {
    598     /*
    599      * Change to '/' and remove duplicates.
    600      */
    601     int     fUnc = 0;
    602     char   *pszSrc = pszPath;
    603     char   *pszTrg = pszPath;
    604     if (    (pszPath[0] == '\\' || pszPath[0] == '/')
    605         &&  (pszPath[1] == '\\' || pszPath[1] == '/')
    606         &&   pszPath[2] != '\\' && pszPath[2] != '/')
    607     {   /* Skip first slash in a unc path. */
    608         pszSrc++;
    609         *pszTrg++ = '/';
    610         fUnc = 1;
    611     }
    612 
    613     for (;;)
    614     {
    615         char ch = *pszSrc++;
    616         if (ch == '/' || ch == '\\')
    617         {
    618             *pszTrg++ = '/';
    619             for (;;)
    620             {
    621                 do  ch = *pszSrc++;
    622                 while (ch == '/' || ch == '\\');
    623 
    624                 /* Remove '/./' and '/.'. */
    625                 if (ch != '.' || (*pszSrc && *pszSrc != '/' && *pszSrc != '\\'))
    626                     break;
    627             }
    628         }
    629         *pszTrg = ch;
    630         if (!ch)
    631             break;
    632         pszTrg++;
    633     }
    634 
    635     /*
    636      * Remove trailing slash if the path may be pointing to a directory.
    637      * A symlink search is converted to a directory search if this is encountered.
    638      */
    639     int cch = pszTrg - pszPath;
    640     if (    (fFlags & (BACKFS_FLAGS_RESOLVE_DIR | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK))
    641         &&  cch > 1
    642         &&  pszTrg[-1] == '/'
    643         &&  pszTrg[-2] != ':'
    644         &&  pszTrg[-2] != '/')
    645     {
    646         pszPath[--cch] = '\0';
    647         if (pfFlags)
    648         {
    649             *pfFlags &= ~(BACKFS_FLAGS_RESOLVE_DIR_MAYBE_ | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK);
    650             if (fFlags & BACKFS_FLAGS_RESOLVE_FULL_SYMLINK)
    651                 *pfFlags |= BACKFS_FLAGS_RESOLVE_DIR | BACKFS_FLAGS_RESOLVE_FULL;
    652         }
    653     }
    654 
    655     return cch;
    656 }
    657 
    658 
    659 /**
    660  * Resolves and verifies the user path to a native path.
    661  *
    662  * @returns 0 on success.
    663  * @returns Negative error code (errno.h) on failiure.
    664  * @param   pszUserPath     The user path.
    665  * @parm    fFlags          Flags controlling the operation of the function.
    666  *                          See the BACKFS_FLAGS_* defines.
    667  * @param   pszNativePath   Where to store the native path. This buffer is at
    668  *                          least PATH_MAX bytes big.
    669  * @param   pfInUnixTree    Where to store the result-in-unix-tree indicator. Optional.
    670  */
    671 int __libc_back_fsResolve(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree)
    672 {
    673     if (pszUserPath && *pszUserPath)
    674     {
    675         if (!__libc_gfNoUnix)
    676             return fsResolveUnix(pszUserPath, fFlags, pszNativePath, pfInUnixTree);
    677         else
    678             return fsResolveOS2(pszUserPath, fFlags, pszNativePath, pfInUnixTree);
    679     }
    680 
    681     /* failure */
    682     *pszNativePath = '\0';
    683     if (pfInUnixTree)
    684         *pfInUnixTree = 0;
    685 
    686     LIBC_ASSERT(pszUserPath);
    687     if (!pszUserPath)
    688         return -EINVAL;
    689     return -ENOENT;
    690 }
    691 
    692 
    693 /**
    694  * Resolves and verifies the user path to a native path.
    695  *
    696  * @returns 0 on success.
    697  * @returns Negative error code (errno.h) on failiure.
    698  * @param   pszUserPath     The user path.
    699  * @parm    fFlags          Flags controlling the operation of the function.
    700  *                          See the BACKFS_FLAGS_* defines.
    701  * @param   pszNativePath   Where to store the native path. This buffer is at
    702  *                          least PATH_MAX bytes big.
    703  * @param   pfInUnixTree    Where to store the result-in-unix-tree indicator. Optional.
    704  */
    705 static int fsResolveUnix(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree)
    706 {
    707     LIBCLOG_ENTER("pszUserPath=%p:{%s} pszNativePath=%p *pfInUnixTree=%p\n",
    708                   (void *)pszUserPath, pszUserPath, (void *)pszNativePath, (void *)pfInUnixTree);
    709     const char     *pszUserPathIn = pszUserPath;
    710     char            _achBuffer[SIZEOF_ACHBUFFER + 4];
    711     char           *pachBuffer = (char *)((uintptr_t)&_achBuffer[3] & ~3);
    712     unsigned        cLoopsLeft = 8;
    713     int             fInUnixTree = __libc_gfInUnixTree;
    714     int             rcRet = 0;
    715     HDIR            hDir = HDIR_CREATE;
    716     __LIBC_PFSINFO  pFsInfo = NULL;
    717     int             fUnixEAs;
    718     FS_VAR()
    719     FS_SAVE_LOAD();
    720     for (;;)
    721     {
    722         /*
    723          * Determin root slash position.
    724          */
    725         int iRoot;
    726         if (pszUserPath[0] == '/' || pszUserPath[0] == '\\')
    727         {
    728             iRoot = 0;
    729             fInUnixTree = __libc_gfInUnixTree;
    730         }
    731         else if (   pszUserPath[0] && pszUserPath[1] == ':'
    732                  && (pszUserPath[2] == '/' || pszUserPath[2] == '\\'))
    733         {
    734             iRoot = 2;
    735             fInUnixTree = 0;
    736         }
    737         /*
    738          * No root slash? Make one!
    739          * This can only happen in the first pass (unless something BAD happens of course).
    740          */
    741         else
    742         {
    743             ULONG   ul;
    744             int     rc;
    745             if (pszUserPath[1] != ':')
    746             {
    747                 /*
    748                  * Current drive.
    749                  */
    750                 ULONG ulDisk;
    751                 rc = DosQueryCurrentDisk(&ulDisk, &ul);
    752                 pszNativePath[0] = ulDisk + 'A' - 1;
    753                 ul = PATH_MAX - 2;
    754                 if (!rc)
    755                     rc = DosQueryCurrentDir(0, (PSZ)&pszNativePath[3], &ul);
    756                 iRoot = __libc_gfInUnixTree ? __libc_gcchUnixRoot : 2;
    757                 /* fInUnixTree remains whatever it is */
    758             }
    759             else
    760             {
    761                 /*
    762                  * Drive letter but no root slash.
    763                  */
    764                 pszNativePath[0] = pszUserPath[0];
    765                 ul = PATH_MAX - 2;
    766                 rc = DosQueryCurrentDir(pszUserPath[0] - (pszUserPath[0] >= 'A' && pszUserPath[0] <= 'Z' ? 'A' : 'a') + 1, (PSZ)&pszNativePath[3], &ul);
    767                 pszUserPath += 2;
    768                 iRoot = 2;
    769                 fInUnixTree = 0;
    770             }
    771             /* failed? */
    772             if (rc)
    773             {
    774                 rcRet = -__libc_native2errno(rc);
    775                 break;
    776             }
    777 
    778             /*
    779              * Add the path stuff from the user.
    780              */
    781             pszNativePath[1] = ':';
    782             pszNativePath[2] = '/';
    783             int cch = strlen(pszNativePath);
    784             pszNativePath[cch++] = '/';
    785             int cchUserPath = strlen(pszUserPath) + 1;
    786             if (cch + cchUserPath > PATH_MAX)
    787             {
    788                 rcRet = -ENAMETOOLONG;
    789                 break;
    790             }
    791             memcpy(&pszNativePath[cch], pszUserPath, cchUserPath);
    792             pszUserPath = memcpy(pachBuffer, pszNativePath, cch + cchUserPath);
    793         }
    794 
    795         /*
    796          * Verify any drive specifier.
    797          */
    798         if (pszUserPath[1] == ':')
    799         {
    800             if (*pszUserPath >= 'a' && *pszUserPath <= 'z')
    801             {
    802                 if ((uintptr_t)(pszUserPath - pachBuffer) > SIZEOF_ACHBUFFER)
    803                     pszUserPath = strcpy(pachBuffer, pszUserPath);
    804                 *(char *)(void *)pszUserPath += 'A' - 'a';
    805             }
    806             else if (!(*pszUserPath >= 'A' && *pszUserPath <= 'Z'))
    807             {
    808                 rcRet = -ENOENT;
    809                 break;
    810             }
    811         }
    812 
    813         /*
    814          * Apply rewrite rules.
    815          * Path now goes to pszNativePath buffer.
    816          */
    817         int cchNativePath = __libc_PathRewrite(pszUserPath, pszNativePath, PATH_MAX);
    818         if (cchNativePath > 0)
    819         {
    820             /*
    821              * Redetermin root because of rewrite.
    822              */
    823             iRoot = pszNativePath[1] == ':' ? 2 : 0;
    824         }
    825         else if (!cchNativePath)
    826         {
    827             cchNativePath = strlen(pszUserPath);
    828             if (cchNativePath + 2 > PATH_MAX)
    829             {
    830                 rcRet = -ENAMETOOLONG;
    831                 break;
    832             }
    833             memcpy(pszNativePath, pszUserPath, cchNativePath + 1);
    834         }
    835         else
    836         {
    837             rcRet = -EINVAL;
    838             break;
    839         }
    840 
    841         /*
    842          * Check if special OS/2 name.
    843          */
    844         if (pszNativePath[0] == '/' || pszNativePath[0] == '\\')
    845         {
    846             int fDone = 0;
    847             if (    (pszNativePath[1] == 'p' || pszNativePath[1] == 'P')
    848                 &&  (pszNativePath[2] == 'i' || pszNativePath[2] == 'I')
    849                 &&  (pszNativePath[3] == 'p' || pszNativePath[3] == 'P')
    850                 &&  (pszNativePath[4] == 'e' || pszNativePath[4] == 'E')
    851                 &&  (pszNativePath[5] == '/' || pszNativePath[5] == '\\'))
    852                 fDone = 1;
    853             else if ((pszNativePath[1]== 'd' || pszNativePath[1] == 'D')
    854                 &&  (pszNativePath[2] == 'e' || pszNativePath[2] == 'E')
    855                 &&  (pszNativePath[3] == 'v' || pszNativePath[3] == 'V')
    856                 &&  (pszNativePath[4] == '/' || pszNativePath[4] == '\\')
    857                 )
    858             {
    859                 PFSQBUFFER2 pfsqb = (PFSQBUFFER2)pachBuffer;
    860                 ULONG       cb = SIZEOF_ACHBUFFER;
    861                 fDone = !DosQueryFSAttach((PCSZ)pszNativePath, 0, FSAIL_QUERYNAME, pfsqb, &cb);
    862             }
    863 
    864             /* If it was, copy path to pszNativePath and go to exit code. */
    865             if (fDone)
    866             {
    867                 int cch = strlen(pszNativePath) + 1;
    868                 if (cch <= PATH_MAX)
    869                 {
    870                     fsCleanPath(pszNativePath, fFlags, NULL);
    871                     rcRet = 0;
    872                 }
    873                 else
    874                     rcRet = -ENAMETOOLONG;
    875                 break;
    876             }
    877         }
    878 
    879         /*
    880          * Remove excessive slashing and convert all slashes to '/'.
    881          */
    882         cchNativePath = fsCleanPath(pszNativePath, fFlags, &fFlags);
    883 
    884         /*
    885          * Expand unix root or add missing drive letter.
    886          */
    887         if (pszNativePath[0] == '/' && pszNativePath[1] != '/')
    888         {
    889             memcpy(pachBuffer, pszNativePath, cchNativePath + 1);
    890             if (__libc_gcchUnixRoot)
    891             {
    892                 iRoot = __libc_gcchUnixRoot;
    893                 if (cchNativePath + iRoot >= PATH_MAX)
    894                 {
    895                     rcRet = -ENAMETOOLONG;
    896                     break;
    897                 }
    898                 memcpy(pszNativePath, __libc_gszUnixRoot, iRoot);
    899                 fInUnixTree = 1;
    900             }
    901             else
    902             {
    903                 iRoot = 2;
    904                 ULONG   ulDisk = 0;
    905                 ULONG   ul;
    906                 DosQueryCurrentDisk(&ulDisk, &ul);
    907                 if (cchNativePath + iRoot >= PATH_MAX)
    908                 {
    909                     rcRet = -ENAMETOOLONG;
    910                     break;
    911                 }
    912                 pszNativePath[0] = ulDisk + 'A' - 1;
    913                 pszNativePath[1] = ':';
    914             }
    915             if (cchNativePath != 1 || iRoot <= 2)
    916                 memcpy(&pszNativePath[iRoot], pachBuffer, cchNativePath + 1);
    917             else
    918                 pszNativePath[iRoot] = pszNativePath[iRoot + 1] = '\0'; /* The +1 fixes '/' access in an compartement (pszPrev below). */
    919             cchNativePath += iRoot;
    920         }
    921 
    922 
    923         /*
    924          * Check all directory components.
    925          *
    926          * We actually don't bother checking if they're directories, only that
    927          * they exists. This shouldn't matter much since any operation on the
    928          * next/final component will assume the previous one being a directory.
    929          *
    930          * While walking we will clean up all use of '.' and '..' so we'll end
    931          * up with an optimal path in the end.
    932          */
    933         /** @todo If we've retreived the current directory, we can safely save of the effort of validating it! */
    934 
    935         /*
    936          * Find the end of the first component (start and end + 1).
    937          */
    938         char *pszPrev;
    939         char *psz;
    940         if (pszNativePath[0] == '/' && pszNativePath[1] == '/' && pszNativePath[2] != '/')
    941         {
    942             /* UNC - skip past the share name. */
    943             psz = strchr(&pszNativePath[2], '/');
    944             if (!psz)
    945             {
    946                 rcRet = -ENOENT;
    947                 break;
    948             }
    949             psz = strchr(psz + 1, '/');
    950             if (!psz)
    951             {
    952                 strupr(pszNativePath);  /* The server + share is uppercased for consistant ino_t calculations. */
    953                 rcRet = 0;
    954                 break;
    955             }
    956             *psz = '\0';                /* The server + share is uppercased for consistant ino_t calculations. */
    957             strupr(pszNativePath);
    958             *psz = '/';
    959             pszPrev = ++psz;
    960             fInUnixTree = 0;            /* Unix root cannot be UNC. */
    961             iRoot = psz - pszNativePath;
    962             psz = strchr(psz, '/');
    963 
    964             /* We don't do UNIX EAs on UNCs */
    965             fUnixEAs = 0;
    966         }
    967         else
    968         {
    969             /* drive letters are always uppercase! (inode dev number req) */
    970             LIBC_ASSERT(pszNativePath[1] == ':');
    971             if (pszNativePath[0] >= 'a' && pszNativePath[0] <= 'z')
    972                 pszNativePath[0] -= 'a' - 'A';
    973             pszPrev = &pszNativePath[iRoot + 1];
    974             psz = strchr(pszPrev, '/');
    975 
    976             /* Unix EAs? */
    977             pFsInfo = __libc_back_fsInfoObjByPathCached(pszNativePath, pFsInfo);
    978             LIBC_ASSERTM(pFsInfo, "%s\n", pszNativePath);
    979             fUnixEAs = pFsInfo ? pFsInfo->fUnixEAs : 0;
    980         }
    981         LIBC_ASSERTM(pszPrev - pszNativePath >= iRoot, "iRoot=%d  pszPrev offset %d  pszNativePath=%s\n", iRoot, pszPrev - pszNativePath, pszNativePath);
    982         /* If only one component, we'll check if the fVerifyLast was requested. */
    983         if (    !psz
    984             &&  (fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK))
    985             &&  *pszPrev)
    986             psz = strchr(pszNativePath, '\0');
    987 
    988         /*
    989          * Walking loop.
    990          */
    991         int fDone = 1;
    992         while (psz)
    993         {
    994             char chSlash = *psz;
    995             *psz = '\0';
    996 
    997             /*
    998              * Kill . and .. specs.
    999              */
    1000             if (    pszPrev[0] == '.'
    1001                 &&  (   pszPrev[1] == '\0'
    1002                      || (pszPrev[1] == '.' && pszPrev[2] == '\0') ) )
    1003             {
    1004                 if (    pszPrev[1] != '\0'
    1005                     &&  (uintptr_t)(pszPrev - pszNativePath) != iRoot + 1)
    1006                 {
    1007                     for (pszPrev -= 2; *pszPrev != '/'; pszPrev--)
    1008                         /* noop */;
    1009                     pszPrev++;
    1010                 }
    1011                 *psz = chSlash;
    1012                 memmove(pszPrev - 1, psz, cchNativePath - (psz - pszNativePath) + 1);
    1013                 cchNativePath -= psz - (pszPrev - 1);
    1014 
    1015                 /*
    1016                  * Next path component and restart loop.
    1017                  */
    1018                 if (!chSlash)
    1019                 {
    1020                     rcRet = 0;
    1021                     break;
    1022                 }
    1023                 psz = pszPrev;
    1024                 while (*psz != '/')
    1025                 {
    1026                     if (*psz)
    1027                         psz++;
    1028                     else
    1029                     {
    1030                         if (!(fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK)))
    1031                         {
    1032                             rcRet = 0;
    1033                             psz = NULL;
    1034                         }
    1035                         break;
    1036                     }
    1037                 }
    1038                 continue;
    1039             }
    1040 
    1041             /*
    1042              * Check for obviously illegal characters in this path component
    1043              * saving us from having DosFindFirst getting '*' and '?'.
    1044              */
    1045             if (strpbrk(pszPrev, "*?"))
    1046             {
    1047                 rcRet = -ENOENT;        /* hmm. will this be correct for all situation? */
    1048                 break;
    1049             }
    1050 
    1051             /*
    1052              * Find the correct name and to check if it is a directory or not.
    1053              * This'll of course also provide proper verification of the path too. :-)
    1054              *
    1055              * This is a little bit messed up since we'll have to use wildcard for
    1056              * getting the casing resolved.
    1057              *
    1058              * The two find buffers are assumed to be equal down thru attrFile.
    1059              */
    1060             //LIBC_ASSERT(psz - pszNativePath == cchNativePath); - figure this one.
    1061             PFILEFINDBUF4 pFindBuf4 = (PFILEFINDBUF4)pachBuffer;
    1062             PFILEFINDBUF3 pFindBuf3 = (PFILEFINDBUF3)pachBuffer;
    1063             ULONG cFiles = 1;
    1064             char chNext = psz[1];
    1065             psz[0] = '?';
    1066             psz[1] = '\0';
    1067             int rc = DosFindFirst((PCSZ)pszNativePath, &hDir, FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED,
    1068                                   pachBuffer, SIZEOF_ACHBUFFER, &cFiles, fUnixEAs ? FIL_QUERYEASIZE : FIL_STANDARD);
    1069             psz[0] = '\0';
    1070             psz[1] = chNext;
    1071             if (rc || cFiles == 0)
    1072                 hDir = HDIR_CREATE;
    1073             while (!rc && cFiles == 1 && (fUnixEAs ? pFindBuf4->cchName : pFindBuf3->cchName) != psz - pszPrev)
    1074                 rc = DosFindNext(hDir, pachBuffer, SIZEOF_ACHBUFFER, &cFiles);
    1075             if (rc || cFiles == 0)
    1076             {
    1077                 LIBCLOG_MSG("DosFindFirst/Next('%s',,,,,) -> %d resolving '%s'\n", pszNativePath, rc, pszUserPathIn);
    1078                 if ((fFlags & BACKFS_FLAGS_RESOLVE_FULL_MAYBE_) && !chSlash)
    1079                 {
    1080                     *psz = chSlash;
    1081                     rcRet = 0;
    1082                 }
    1083                 else
    1084                     rcRet = rc == ERROR_FILE_NOT_FOUND && chSlash ? -ENOENT : -__libc_native2errno(rc);
    1085                 break;
    1086             }
    1087             memcpy(pszPrev, fUnixEAs ? pFindBuf4->achName : pFindBuf3->achName, psz - pszPrev);
    1088             int     fIsDirectory = (pFindBuf4->attrFile & FILE_DIRECTORY) != 0;
    1089 
    1090             /*
    1091              * Try querying the symlink EA value.
    1092              * (This operation will reuse the achBuffer overwriting the pFindBuf[3/4] data!)
    1093              *
    1094              * Yeah, we could do this in the same operation as the DosFindFirst() but
    1095              * a little bird told me that level 3 DosFindFirst request had not been
    1096              * returning the right things at some point, and besides it's return data
    1097              * is rather clumsily laid out. So, I decided not to try my luck on it.
    1098              *
    1099              * On second thought, we seems to end up having to use DosFindFirst in some
    1100              * cases anyway... very nice.
    1101              */
    1102             if (    fUnixEAs
    1103                 &&   pFindBuf4->cbList > sizeof(USHORT) * 2 + 1
    1104                 &&  (   (fFlags & BACKFS_FLAGS_RESOLVE_FULL)
    1105                      || chSlash)
    1106                 &&  !fIsDirectory)
    1107             {
    1108                 PEAOP2  pEaOp2 = (PEAOP2)pachBuffer;
    1109                 pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListSymlink;
    1110                 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);
    1111                 pEaOp2->oError     = 0;
    1112                 pEaOp2->fpFEA2List->cbList = SIZEOF_ACHBUFFER - sizeof(*pEaOp2);
    1113                 rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(*pEaOp2));
    1114                 if (rc)
    1115                 {
    1116                     cFiles = 1;
    1117                     pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListSymlink;
    1118                     pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);
    1119                     pEaOp2->oError     = 0;
    1120                     pEaOp2->fpFEA2List->cbList = SIZEOF_ACHBUFFER - sizeof(*pEaOp2);
    1121                     rc = DosFindFirst((PCSZ)pszNativePath, &hDir, 0, pEaOp2, pEaOp2->fpFEA2List->cbList + sizeof(*pEaOp2), &cFiles, FIL_QUERYEASFROMLIST);
    1122                     if (rc || cFiles == 0)
    1123                     {
    1124                         hDir = HDIR_CREATE;
    1125                         LIBCLOG_MSG("DosFindFirst('%s',,,pEaOp2,) -> %d resolving '%s'\n", pszNativePath, rc, pszUserPathIn);
    1126                         if ((fFlags & BACKFS_FLAGS_RESOLVE_FULL_MAYBE_) && !chSlash)
    1127                             rcRet = 0;
    1128                         else
    1129                             rcRet = rc == ERROR_FILE_NOT_FOUND && chSlash ? -ENOENT : -__libc_native2errno(rc);
    1130                         break;
    1131                     }
    1132                     pEaOp2->fpFEA2List = (PFEA2LIST)((char *)pEaOp2 + sizeof(EAOP2) + offsetof(FILEFINDBUF3, cchName));
    1133                 }
    1134 
    1135                 /*
    1136                  * Did we find any symlink EA?
    1137                  */
    1138                 if (    pEaOp2->fpFEA2List->cbList > sizeof(pEaOp2->fpFEA2List->list[0])
    1139                     &&  pEaOp2->fpFEA2List->list[0].cbValue)
    1140                 {
    1141                     /* Validate the EA. */
    1142                     PUSHORT pusType = (PUSHORT)((char *)&pEaOp2->fpFEA2List->list[1] + pEaOp2->fpFEA2List->list[0].cbName);
    1143                     char   *pszSymlink = (char *)&pusType[2];
    1144                     if (    pusType[0] != EAT_ASCII
    1145                         ||  pusType[1] > pEaOp2->fpFEA2List->list[0].cbValue
    1146                         ||  !pusType[1]
    1147                         ||  !*pszSymlink)
    1148                     {
    1149                         LIBCLOG_ERROR("Invalid symlink EA! type=%x len=%d cbValue=%d *pszSymlink=%c\n",
    1150                                       pusType[0], pusType[1], pEaOp2->fpFEA2List->list[0].cbValue, *pszSymlink);
    1151                         rcRet = -EFTYPE;
    1152                         break;
    1153                     }
    1154 
    1155                     /* Check if we've reached the max number of symlink loops before we continue. */
    1156                     if (cLoopsLeft-- <= 0)
    1157                     {
    1158                         rcRet = -ELOOP;
    1159                         break;
    1160                     }
    1161 
    1162                     /* Cleanup the symlink and find it's length. */
    1163                     pszSymlink[pusType[1]] = '\0';
    1164                     int cchSymlink = fsCleanPath(pszSymlink, fFlags, NULL);
    1165 
    1166                     /* Merge the symlink with the path. */
    1167                     int cchLeft = cchNativePath - (psz - pszNativePath);
    1168                     if (*pszSymlink == '/' || *pszSymlink == '\\' || pszSymlink[1] == ':')
    1169                     {
    1170                         /*
    1171                          * Replace the path up to the current point with the symlink,
    1172                          */
    1173                         if (cchSymlink + cchLeft + 2 >= PATH_MAX)
    1174                         {
    1175                             rcRet = -ENAMETOOLONG;
    1176                             break;
    1177                         }
    1178                         if (cchLeft)
    1179                         {
    1180                             if (pszSymlink[cchSymlink - 1] != '/')
    1181                                 pszSymlink[cchSymlink++] = '/';
    1182                             memcpy(&pszSymlink[cchSymlink], psz + 1, cchLeft + 1);
    1183                         }
    1184 
    1185                         /* restart the whole shebang. */
    1186                         pszUserPath = pszSymlink;
    1187                         fDone = 0;
    1188                         break;
    1189                     }
    1190                     else
    1191                     {
    1192                         /*
    1193                          * Squeeze the symlink in instead of the current path component.
    1194                          */
    1195                         if (cchSymlink + cchNativePath + 2 >= PATH_MAX)
    1196                         {
    1197                             rcRet = -ENAMETOOLONG;
    1198                             break;
    1199                         }
    1200                         if (cchLeft)
    1201                         {
    1202                             pszSymlink[cchSymlink++] = '/';
    1203                             memcpy(&pszSymlink[cchSymlink], psz + 1, cchLeft + 1);
    1204                             cchSymlink += cchLeft;
    1205                         }
    1206                         memcpy(pszPrev, pszSymlink, cchSymlink + 1);
    1207                         cchNativePath += cchSymlink - (psz - pszPrev);
    1208 
    1209                         /* restart this component. */
    1210                         psz = pszPrev;
    1211                         while (*psz != '/')
    1212                         {
    1213                             if (*psz)
    1214                                 psz++;
    1215                             else
    1216                             {
    1217                                 if (!(fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK)))
    1218                                 {
    1219                                     rcRet = 0;
    1220                                     psz = NULL;
    1221                                 }
    1222                                 break;
    1223                             }
    1224                         }
    1225                         continue;
    1226                     }
    1227                 }
    1228             }
    1229 
    1230             /*
    1231              * If we get here it was not a symlink and we should check how the directoryness
    1232              * of it fit's into the big picture...
    1233              */
    1234             if (!fIsDirectory && chSlash)
    1235             {
    1236                 LIBCLOG_ERROR("'%s' is not a directory (resolving '%s')\n", pszNativePath, pszUserPathIn);
    1237                 rcRet = -ENOTDIR;
    1238                 break;
    1239             }
    1240 
    1241             /*
    1242              * Next path component.
    1243              */
    1244             *psz++ = chSlash;
    1245             if (!chSlash)
    1246             {
    1247                 rcRet = 0;
    1248                 if (    (fFlags & (BACKFS_FLAGS_RESOLVE_DIR | BACKFS_FLAGS_RESOLVE_DIR_MAYBE_)) == BACKFS_FLAGS_RESOLVE_DIR
    1249                     &&  !fIsDirectory
    1250                     &&  (     !fUnixEAs
    1251                          ||    pFindBuf4->cbList <= sizeof(USHORT) * 2 + 1
    1252                          ||   !fsIsSymlink(pszNativePath)))
    1253                     rcRet = -ENOTDIR;
    1254                 break;
    1255             }
    1256             pszPrev = psz;
    1257             while (*psz != '/')
    1258             {
    1259                 if (!*psz)
    1260                 {
    1261                     if (!(fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK)))
    1262                     {
    1263                         rcRet = 0;
    1264                         psz = NULL;
    1265                     }
    1266                     break;
    1267                 }
    1268                 psz++;
    1269             }
    1270         } /* inner loop */
    1271 
    1272         if (fDone)
    1273             break;
    1274     } /* outer loop */
    1275 
    1276     /*
    1277      * Cleanup find handle and fs object.
    1278      */
    1279     if (hDir != HDIR_CREATE)
    1280         DosFindClose(hDir);
    1281     if (pFsInfo)
    1282         __libc_back_fsInfoObjRelease(pFsInfo);
    1283     FS_RESTORE();
    1284 
    1285     /*
    1286      * Copy the resolved path the the caller buffer.
    1287      */
    1288     if (pfInUnixTree)
    1289         *pfInUnixTree = fInUnixTree;
    1290     if (!rcRet)
    1291     {
    1292         int cch = strlen(pszNativePath) + 1;
    1293         if (cch == 1 || (cch == 3 && pszNativePath[1] == ':'))
    1294         {
    1295             pszNativePath[cch - 1] = '/';
    1296             pszNativePath[cch] = '\0';
    1297         }
    1298         LIBCLOG_RETURN_MSG(0, "ret 0 pszNativePath=%p:{%s}\n", (void *)pszNativePath, pszNativePath);
    1299     }
    1300 
    1301     /* failure */
    1302     LIBCLOG_ERROR_RETURN_MSG(rcRet, "ret %d pszNativePath=%p:{%s}\n", rcRet, (void *)pszNativePath, pszNativePath);
    1303     pszUserPathIn = pszUserPathIn;
    1304 }
    1305 
    1306 
    1307 /**
    1308  * Resolves and verifies the user path to a native path.
    1309  *
    1310  * @returns 0 on success.
    1311  * @returns Negative error code (errno.h) on failiure.
    1312  * @param   pszUserPath     The user path.
    1313  * @parm    fFlags          Flags controlling the operation of the function.
    1314  *                          See the BACKFS_FLAGS_* defines.
    1315  * @param   pszNativePath   Where to store the native path. This buffer is at
    1316  *                          least PATH_MAX bytes big.
    1317  * @param   pfInUnixTree    Where to store the result-in-unix-tree indicator. Optional.
    1318  */
    1319 static int fsResolveOS2(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree)
    1320 {
    1321     LIBCLOG_ENTER("pszUserPath=%p:{%s} fFlags=%x pszNativePath=%p pfInUnixTree=%p\n",
    1322                   (void *)pszUserPath, pszUserPath, fFlags, (void *)pszNativePath, (void *)pfInUnixTree);
    1323 
    1324     /*
    1325      * Apply rewrite rule.
    1326      */
    1327     int cch = __libc_PathRewrite(pszUserPath, pszNativePath, PATH_MAX);
    1328     if (cch < 0)
    1329         LIBCLOG_ERROR_RETURN_INT(-EINVAL);
    1330     if (cch == 0)
    1331     {
    1332         cch = strlen(pszUserPath);
    1333         if (cch >= PATH_MAX)
    1334             LIBCLOG_ERROR_RETURN_INT(-ENAMETOOLONG);
    1335         memcpy(pszNativePath, pszUserPath, cch + 1);
    1336     }
    1337 
    1338     /*
    1339      * Convert slashes.
    1340      */
    1341     char *psz = strchr(pszNativePath, '/');
    1342     while (psz)
    1343     {
    1344         *psz++ = '\\';
    1345         psz = strchr(psz, '/');
    1346     }
    1347 
    1348     /** @todo Validate the path? hopefully not necessary. */
    1349 
    1350     if (pfInUnixTree)
    1351         *pfInUnixTree = 0;
    1352 
    1353     LIBCLOG_RETURN_INT(0);
    1354 }
    1355 
    1356 
    1357 /**
    1358  * Initializes a unix attribute structure before creating a new inode.
    1359  * The call must have assigned default values to the the structure before doing this call!
    1360  *
    1361  * @returns Device number.
    1362  * @param   pFEas           The attribute structure to fill with actual values.
    1363  * @param   pszNativePath   The native path, used to calculate the inode number.
    1364  * @param   Mode            The correct mode (the caller have fixed this!).
    1365  */
    1366 dev_t __libc_back_fsUnixAttribsInit(struct __LIBC_FSUNIXATTRIBSCREATEFEA2LIST *pFEas, char *pszNativePath, mode_t Mode)
    1367 {
    1368     /*
    1369      * Calc Inode number.
    1370      * We replace the lower 32-bit with a random value.
    1371      */
    1372     /* low 32-bit - random */
    1373     static union
    1374     {
    1375         uint64_t        u64TSC;
    1376         unsigned short  ausSeed[4];
    1377     } s_Seed = {0};
    1378     static _smutex s_smtxSeed = 0;
    1379     _smutex_request(&s_smtxSeed);
    1380     /* seed it ? */
    1381     if (!s_Seed.ausSeed[3])
    1382     {
    1383         __asm__ __volatile__ ("rdtsc" : "=A" (s_Seed.u64TSC));
    1384         s_Seed.ausSeed[3] = 1;
    1385     }
    1386     pFEas->u64INO = nrand48(&s_Seed.ausSeed[0]) & 0xffffffff;
    1387     _smutex_release(&s_smtxSeed);
    1388 
    1389     /* high 32-bit - crc32 */
    1390     const char *psz = pszNativePath;
    1391     if (psz[1] == ':')
    1392         psz += 2;
    1393     pFEas->u64INO |= (uint64_t)crc32str(psz) << 32;
    1394 
    1395     /*
    1396      * The other stuff.
    1397      */
    1398     pFEas->u32UID = __libc_spmGetId(__LIBC_SPMID_EUID);
    1399     pFEas->u32GID = __libc_spmGetId(__LIBC_SPMID_EGID); /** @todo sticky bit! */
    1400     pFEas->u32Mode = Mode;
    1401     LIBC_ASSERT(pFEas->u32RDev == 0);
    1402     LIBC_ASSERT(pFEas->u32Gen == 0);
    1403     LIBC_ASSERT(pFEas->u32Flags == 0);
    1404 
    1405     /*
    1406      * Calc device.
    1407      */
    1408     char chDrv = *pszNativePath;
    1409     if (chDrv == '/' || chDrv == '\\')
    1410         return makedev('U', 0);          /* U as in UNC */
    1411     LIBC_ASSERT(chDrv >= 'A' && chDrv <= 'Z');
    1412     return makedev('V', chDrv);      /* V as in Volume */
    1413 }
    1414 
    1415 
    1416 /**
    1417  * Reads the unix EAs for a file which is being stat'ed.
    1418  *
    1419  * @returns 0 on success.
    1420  * @returns Negative errno on failure.
    1421  * @param   hFile           File handle to the fs object. If no handle handy, set to -1.
    1422  * @param   pszNativePath   Native path to the fs object. If handle is give this will be ignored.
    1423  * @param   pStat           Pointer to the stat buffer.
    1424  *                          The buffer is only updated if and with the EAs we find,
    1425  *                          so the caller must fill the fields with defaults before
    1426  *                          calling this function.
    1427  */
    1428 int __libc_back_fsUnixAttribsGet(int hFile, const char *pszNativePath, struct stat *pStat)
    1429 {
    1430     LIBCLOG_ENTER("hFile=%d pszNativePath=%p:{%s} pStat=%p\n", hFile, (void *)pszNativePath, pszNativePath, (void *)pStat);
    1431 
    1432     /* Try come up with an accurate max estimate of a maximum result. */
    1433     char    achBuffer[sizeof(EAOP2) + sizeof(FILEFINDBUF3) + sizeof(__libc_gFsUnixAttribsGEA2List) + 7 * (sizeof(USHORT) * 2 + sizeof(BYTE)) + CCHMAXPATH + 6 * sizeof(uint32_t) + 0x30];
    1434     char   *pachBuffer = (char *)((uintptr_t)&achBuffer[3] & ~3);
    1435     PEAOP2  pEaOp2 = (PEAOP2)pachBuffer;
    1436     int     rc = -1000;
    1437 
    1438     /*
    1439      * Issue the query.
    1440      */
    1441     if (hFile >= 0)
    1442     {
    1443         pEaOp2->fpGEA2List = (PGEA2LIST)&__libc_gFsUnixAttribsGEA2List;
    1444         pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);
    1445         pEaOp2->oError     = 0;
    1446         pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);
    1447         rc = DosQueryFileInfo(hFile, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(EAOP2));
    1448     }
    1449     if (rc && pszNativePath)
    1450     {
    1451         pEaOp2->fpGEA2List = (PGEA2LIST)&__libc_gFsUnixAttribsGEA2List;
    1452         pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);
    1453         pEaOp2->oError     = 0;
    1454         pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);
    1455         rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(EAOP2));
    1456         if (rc == ERROR_SHARING_VIOLATION || rc == ERROR_ACCESS_DENIED || rc == ERROR_INVALID_ACCESS)
    1457         {
    1458             HDIR hDir = HDIR_CREATE;
    1459             ULONG cFiles = 1;
    1460             pEaOp2->fpGEA2List = (PGEA2LIST)&__libc_gFsUnixAttribsGEA2List;
    1461             pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);
    1462             pEaOp2->oError     = 0;
    1463             pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);
    1464             rc = DosFindFirst((PCSZ)pszNativePath, &hDir, 0, pEaOp2, pEaOp2->fpFEA2List->cbList + sizeof(*pEaOp2), &cFiles, FIL_QUERYEASFROMLIST);
    1465             if (!rc)
    1466             {
    1467                 DosFindClose(hDir);
    1468                 pEaOp2->fpFEA2List = (PFEA2LIST)((char *)pEaOp2 + sizeof(EAOP2) + offsetof(FILEFINDBUF3, cchName));
    1469             }
    1470         }
    1471     }
    1472     if (rc)
    1473     {
    1474         LIBC_ASSERTM(rc == ERROR_ACCESS_DENIED || rc == ERROR_SHARING_VIOLATION || rc == ERROR_EAS_NOT_SUPPORTED,
    1475                      "Bogus EAs? rc=%d oError=%ld\n", rc, pEaOp2->oError);
    1476         rc = -__libc_native2errno(rc);
    1477         LIBCLOG_ERROR_RETURN_INT(rc);
    1478     }
    1479     if (pEaOp2->fpFEA2List->cbList < LIBC_UNIX_EA_MIN)
    1480         LIBCLOG_RETURN_INT(0);
    1481 
    1482     /*
    1483      * Parse the result.
    1484      */
    1485     PFEA2   pFea2 = &pEaOp2->fpFEA2List->list[0];
    1486     for (;;)
    1487     {
    1488         if (pFea2->cbValue > 0)
    1489         {
    1490 #define COMPARE_EANAME(name) (pFea2->cbName == sizeof(name) - 1 && !memcmp(name, pFea2->szName, sizeof(name) - 1))
    1491             if (COMPARE_EANAME(__libc_gszSymlinkEA))
    1492                 pStat->st_mode = (pStat->st_mode & ~S_IFMT) | S_IFLNK;
    1493             else
    1494             {
    1495                 PUSHORT pusType = (PUSHORT)&pFea2->szName[pFea2->cbName + 1];
    1496                 if (*pusType == EAT_BINARY)
    1497                 {
    1498                     pusType++;
    1499                     if (*pusType == sizeof(uint32_t))
    1500                     {
    1501                         uint32_t u32 = *(uint32_t *)++pusType;
    1502                         if (COMPARE_EANAME(__libc_gszUidEA))
    1503                             pStat->st_uid  = u32;
    1504                         else if (COMPARE_EANAME(__libc_gszGidEA))
    1505                             pStat->st_gid  = u32;
    1506                         else if (COMPARE_EANAME(__libc_gszModeEA))
    1507                         {
    1508                             if (    S_ISDIR(u32)  || S_ISCHR(u32) || S_ISBLK(u32)  || S_ISREG(u32)
    1509                                 ||  S_ISFIFO(u32) || S_ISLNK(u32) || S_ISSOCK(u32) || S_ISWHT(u32))
    1510                                 pStat->st_mode = u32;
    1511                             else
    1512                                 LIBC_ASSERTM_FAILED("Invalid file mode EA: u32=0%o (st_mode=0%o)\n", u32, pStat->st_mode);
    1513                         }
    1514                         else if (COMPARE_EANAME(__libc_gszRDevEA))
    1515                             pStat->st_rdev = u32;
    1516                         else if (COMPARE_EANAME(__libc_gszGenEA))
    1517                             pStat->st_gen  = u32;
    1518                         else if (COMPARE_EANAME(__libc_gszFlagsEA))
    1519                             pStat->st_flags = u32;
    1520                         else
    1521                             LIBC_ASSERTM_FAILED("Huh?!? got an ea named '%s', namelen=%d! u32=%#x (%d)\n", pFea2->szName, pFea2->cbName, u32, u32);
    1522                     }
    1523                     else if (*pusType == sizeof(uint64_t))
    1524                     {
    1525                         uint64_t u64 = *(uint64_t *)++pusType;
    1526                         if (COMPARE_EANAME(__libc_gszInoEA))
    1527                             pStat->st_ino = u64;
    1528                         else
    1529                             LIBC_ASSERTM_FAILED("Huh?!? got an ea named '%s', namelen=%d! u64=%#llx (%lld)\n", pFea2->szName, pFea2->cbName, u64, u64);
    1530                     }
    1531                     else
    1532                         LIBC_ASSERTM_FAILED("Invalid LIBC EA! '%s' len=%#x and len=4 or 8.\n", pFea2->szName, *pusType);
    1533                 }
    1534                 else
    1535                     LIBC_ASSERTM_FAILED("Invalid LIBC EA! '%s' type=%#x len=%#x, expected type=%#x and len=4 or 8.\n",
    1536                                         pFea2->szName, pusType[0], pusType[1], EAT_BINARY);
    1537             }
    1538 #undef COMPARE_EANAME
    1539         }
    1540 
    1541         /* next */
    1542         if (pFea2->oNextEntryOffset <= sizeof(FEA2))
    1543             break;
    1544         pFea2 = (PFEA2)((uintptr_t)pFea2 + pFea2->oNextEntryOffset);
    1545     }
    1546 
    1547     /*
    1548      * Calc st_ino and st_dev if not found.
    1549      */
    1550     if ((!pStat->st_ino || !pStat->st_dev) && pszNativePath)
    1551     {
    1552         ino_t Inode;
    1553         dev_t Dev = __libc_back_fsPathCalcInodeAndDev(pszNativePath, &Inode);
    1554         if (!pStat->st_ino)
    1555             pStat->st_ino = Inode;
    1556         if (!pStat->st_dev)
    1557             pStat->st_dev = Dev;
    1558     }
    1559 
    1560     LIBCLOG_RETURN_INT(0);
    1561 }
    1562 
    1563 
    1564 /**
    1565  * Reads the unix file mode EA.
    1566  *
    1567  * @returns 0 on success.
    1568  * @returns -ENOTSUP if the file mode EA is not present or if Unix EAs isn't supported on the volume.
    1569  * @returns Negative errno on failure.
    1570  * @param   hFile           File handle to the fs object. If no handle handy, set to -1.
    1571  * @param   pszNativePath   Native path to the fs object. If handle is give this will be ignored.
    1572  * @param   pMode           Where to store the mode mask.
    1573  */
    1574 int __libc_back_fsUnixAttribsGetMode(int hFile, const char *pszNativePath, mode_t *pMode)
    1575 {
    1576      LIBCLOG_ENTER("hFile=%d pszNativePath=%p:{%s} pMode=%p\n", hFile, (void *)pszNativePath, pszNativePath, (void *)pMode);
    1577 
    1578      /* Try come up with an accurate max estimate of a maximum result. */
    1579      char    achBuffer[sizeof(EAOP2) + sizeof(FILEFINDBUF3) + sizeof(gGEA2ListMode) + 1 * (sizeof(USHORT) * 2 + sizeof(BYTE)) + 1 * sizeof(uint32_t) + 0x30];
    1580      char   *pachBuffer = (char *)((uintptr_t)&achBuffer[3] & ~3);
    1581      PEAOP2  pEaOp2 = (PEAOP2)pachBuffer;
    1582      int     rc = -1000;
    1583 
    1584      *pMode = 0;
    1585 
    1586 /** @todo the following query is generic! It's repeated 3 times already in this file (only the gea list and buffer size varies). */
    1587      /*
    1588       * Issue the query.
    1589       */
    1590      if (hFile >= 0)
    1591      {
    1592          pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListMode;
    1593          pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);
    1594          pEaOp2->oError     = 0;
    1595          pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);
    1596          rc = DosQueryFileInfo(hFile, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(EAOP2));
    1597      }
    1598      if (rc && pszNativePath)
    1599      {
    1600          pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListMode;
    1601          pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);
    1602          pEaOp2->oError     = 0;
    1603          pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);
    1604          rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(EAOP2));
    1605          if (rc == ERROR_SHARING_VIOLATION || rc == ERROR_ACCESS_DENIED || rc == ERROR_INVALID_ACCESS)
    1606          {
    1607              HDIR hDir = HDIR_CREATE;
    1608              ULONG cFiles = 1;
    1609              pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListMode;
    1610              pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);
    1611              pEaOp2->oError     = 0;
    1612              pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);
    1613              rc = DosFindFirst((PCSZ)pszNativePath, &hDir, 0, pEaOp2, pEaOp2->fpFEA2List->cbList + sizeof(*pEaOp2), &cFiles, FIL_QUERYEASFROMLIST);
    1614              if (!rc)
    1615              {
    1616                  DosFindClose(hDir);
    1617                  pEaOp2->fpFEA2List = (PFEA2LIST)((char *)pEaOp2 + sizeof(EAOP2) + offsetof(FILEFINDBUF3, cchName));
    1618              }
    1619          }
    1620      }
    1621      if (rc)
    1622      {
    1623          LIBC_ASSERTM(rc == ERROR_ACCESS_DENIED || rc == ERROR_SHARING_VIOLATION || rc == ERROR_EAS_NOT_SUPPORTED,
    1624                       "Bogus EAs? rc=%d oError=%ld\n", rc, pEaOp2->oError);
    1625          rc = -__libc_native2errno(rc);
    1626          LIBCLOG_ERROR_RETURN_INT(rc);
    1627      }
    1628 
    1629      /*
    1630       * Parse the result.
    1631       * There is only one EA here, so this is gonna be pretty simple...
    1632       */
    1633      rc = -ENOTSUP;
    1634      PFEA2   pFea2 = &pEaOp2->fpFEA2List->list[0];
    1635      if (   pEaOp2->fpFEA2List->cbList > sizeof(*pFea2)
    1636          && pFea2->cbValue > 0
    1637          && pFea2->cbName == sizeof(EA_MODE) - 1
    1638          && !memcmp(EA_MODE, pFea2->szName, sizeof(EA_MODE) - 1)
    1639         )
    1640      {
    1641          PUSHORT pusType = (PUSHORT)&pFea2->szName[pFea2->cbName + 1];
    1642          if (   pusType[0] == EAT_BINARY
    1643              && pusType[1] == sizeof(uint32_t)
    1644              )
    1645          {
    1646              uint32_t u32 = *(uint32_t *)(pusType + 2);
    1647              if (    S_ISDIR(u32)  || S_ISCHR(u32) || S_ISBLK(u32)  || S_ISREG(u32)
    1648                  ||  S_ISFIFO(u32) || S_ISLNK(u32) || S_ISSOCK(u32) || S_ISWHT(u32))
    1649              {
    1650                  *pMode = u32;
    1651                  rc = 0;
    1652              }
    1653              else
    1654                  LIBC_ASSERTM_FAILED("Invalid file mode EA: u32=0%o\n", u32);
    1655          }
    1656          else
    1657              LIBC_ASSERTM_FAILED("Invalid LIBC EA! '%s' type=%#x len=%#x, expected type=%#x and len=4.\n",
    1658                                  pFea2->szName, pusType[0], pusType[1], EAT_BINARY);
    1659      }
    1660 
    1661      LIBCLOG_RETURN_MSG(rc, "ret %d *pMode=#%x\n", rc, *pMode);
    1662312}
    1663313
     
    1700350
    1701351
    1702 /**
    1703  * Updates the FS info object.
    1704  */
    1705 static void fsInfoObjUpdate(__LIBC_PFSINFO pFsInfo, dev_t Dev)
    1706 {
    1707     static char achBuffer[384]; /* we're protected by the mutex, don't assume too much stack! */
    1708     ULONG       cb = sizeof(achBuffer);
    1709     PFSQBUFFER2 pfsqb = (PFSQBUFFER2)achBuffer;
    1710 
    1711     /* init the structure */
    1712     pFsInfo->fZeroNewBytes = 0;
    1713     pFsInfo->fUnixEAs = 0;
    1714     pFsInfo->Dev = Dev;
    1715     pFsInfo->szName[0] = '\0';
    1716     pFsInfo->szMountpoint[0] = minor(Dev);
    1717     pFsInfo->szMountpoint[1] = ':';
    1718     pFsInfo->szMountpoint[2] = '\0';
    1719     pFsInfo->szMountpoint[3] = '\0';
    1720 
    1721     /* query fs info */
    1722     FS_VAR_SAVE_LOAD();
    1723     int rc = DosQueryFSAttach((PCSZ)pFsInfo->szMountpoint, 0, FSAIL_QUERYNAME, pfsqb, &cb);
    1724     LIBC_ASSERTM(!rc, "rc=%d\n", rc);
    1725     if (!rc)
    1726         strncat(pFsInfo->szName, (const char *)&pfsqb->szName[pfsqb->cbName + 1], sizeof(pFsInfo->szName) - 1);
    1727     if (    !strcmp(pFsInfo->szName, "JFS")
    1728         ||  !strcmp(pFsInfo->szName, "HPFS")
    1729         ||  !strcmp(pFsInfo->szName, "FAT"))
    1730     {
    1731         pFsInfo->fZeroNewBytes  = 1;
    1732         pFsInfo->fUnixEAs       = 1;
    1733     }
    1734     else if (!strcmp(pFsInfo->szName, "LAN"))
    1735     {
    1736         /* should find a way of getting the remote fs... */
    1737         pFsInfo->fZeroNewBytes  = 1;    /* for performance reasons, assume it zeros. */
    1738         pFsInfo->fUnixEAs       = 0;
    1739     }
    1740     else if (!strcmp(pFsInfo->szName, "RAMFS"))
    1741     {
    1742         pFsInfo->fZeroNewBytes  = 0;
    1743         pFsInfo->fUnixEAs       = 1; /* but it doesn't zero */
    1744     }
    1745     /*else if (!strcmp(pFsInfo->szName, "FAT32"))
    1746     {
    1747         pFsInfo->fZeroNewBytes  = 0;
    1748         pFsInfo->fUnixEAs       = 0;
    1749     }*/
    1750     else
    1751     {
    1752         pFsInfo->fZeroNewBytes  = 0;
    1753         pFsInfo->fUnixEAs       = 0;
    1754     }
    1755 
    1756     LIBCLOG_MSG2("fsInfoObjUpdate: dev:%#x mp:%s fsd:%s fZeroNewBytes=%d fUnixEAs=%d\n",
    1757                  pFsInfo->Dev, pFsInfo->szMountpoint, pFsInfo->szName, pFsInfo->fZeroNewBytes,
    1758                  pFsInfo->fUnixEAs);
    1759     FS_RESTORE();
    1760 }
    1761 
    1762 
     352#ifdef __OS2__
    1763353/**
    1764354 * Gets the fs info object for the specfied path.
     
    1846436    return __libc_back_fsInfoObjByDev(Dev);
    1847437}
     438#endif
    1848439
    1849440
     
    1883474
    1884475
     476#ifdef __OS2__
    1885477/**
    1886478 * Checks if the path supports Unix EAs or not.
     
    1899491    return fUnixEAs;
    1900492}
     493#endif
    1901494
    1902495
  • trunk/libc/src/kNIX/nt/b_fsUnlink.c

    r2738 r2742  
    2929*   Header Files                                                               *
    3030*******************************************************************************/
    31 #include "libc-alias.h"
    32 #define INCL_FSMACROS
    33 #define INCL_ERRORS
    34 #define INCL_DOSFILEMGR
    35 #define INCL_DOSMISC
    36 #include <os2emx.h>
    37 #include "b_fs.h"
     31#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS
     32#include "../kNIX.h"
     33#include <klibc/nt/nt.h>
     34//#include "b_fs.h" - later?
    3835#include <errno.h>
    3936#include <string.h>
    4037#include <sys/stat.h>
    41 #include <InnoTekLIBC/backend.h>
    42 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS
    43 #include <InnoTekLIBC/logstrict.h>
     38#include <klibc/backend.h>
     39#include <klibc/logstrict.h>
    4440
    4541
     
    6157        LIBCLOG_ERROR_RETURN_INT(-ENOENT);
    6258
     59#if 0 /* later */
    6360    /*
    6461     * Resolve the path.
     
    167164        LIBCLOG_RETURN_INT(rc);
    168165    LIBCLOG_ERROR_RETURN_INT(rc);
     166
     167#else
     168
     169    LIBCLOG_ERROR_RETURN_INT(-ENOSYS);
     170#endif
    169171}
    170172
  • trunk/libc/src/kNIX/nt/b_signalMask.c

    r2738 r2742  
    22/** @file
    33 *
    4  * LIBC SYS Backend - sigprocmask().
     4 * kNIX - sigprocmask().
    55 *
    6  * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
     6 * Copyright (c) 2004-2006 knut st. osmundsen <bird-srcspam@anduin.net>
    77 *
    88 *
    9  * This file is part of InnoTek LIBC.
     9 * This file is part of kLIBC.
    1010 *
    11  * InnoTek LIBC is free software; you can redistribute it and/or modify
     11 * kLIBC is free software; you can redistribute it and/or modify
    1212 * it under the terms of the GNU Lesser General Public License as published
    1313 * by the Free Software Foundation; either version 2 of the License, or
    1414 * (at your option) any later version.
    1515 *
    16  * InnoTek LIBC is distributed in the hope that it will be useful,
     16 * kLIBC is distributed in the hope that it will be useful,
    1717 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     
    2020 *
    2121 * You should have received a copy of the GNU Lesser General Public License
    22  * along with InnoTek LIBC; if not, write to the Free Software
     22 * along with kLIBC; if not, write to the Free Software
    2323 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2424 *
     
    2929*   Header Files                                                               *
    3030*******************************************************************************/
    31 #include "libc-alias.h"
    32 #define INCL_BASE
    33 #define INCL_FSMACROS
    34 #define INCL_DOSSIGNALS
    35 #include <os2emx.h>
    36 
     31#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_SIGNAL
     32#include "../kNIX.h"
    3733#include <signal.h>
    3834#include <errno.h>
    39 #include <InnoTekLIBC/thread.h>
    40 #include <InnoTekLIBC/backend.h>
    41 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_SIGNAL
    42 #include <InnoTekLIBC/logstrict.h>
    43 #include "b_signal.h"
     35#include <klibc/thread.h>
     36#include <klibc/backend.h>
     37#include <klibc/logstrict.h>
     38//#include "b_signal.h" - later?
    4439
    4540
     
    9489        __SIGSET_EMPTY(&SigSetNew);
    9590
     91#if 0 /* this will be a server call later. */
    9692    /*
    9793     * Gain exclusive access to the signal stuff.
     
    157153                SigSetNew.__bitmap[1], SigSetNew.__bitmap[0]);
    158154    LIBCLOG_RETURN_INT(0);
     155#else
     156    LIBCLOG_ERROR_RETURN_INT(-ENOSYS);
     157#endif
    159158}
    160159
  • trunk/libc/src/kNIX/nt/b_threadCleanup.c

    r2738 r2742  
    22/** @file
    33 *
    4  * LIBC SYS Backend - Thread structure cleanup.
     4 * kNIX - Thread structure cleanup, NT.
    55 *
    6  * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
     6 * Copyright (c) 2006 knut st. osmundsen <bird-srcspam@anduin.net>
    77 *
    88 *
    9  * This file is part of InnoTek LIBC.
     9 * This file is part of kLIBC.
    1010 *
    11  * InnoTek LIBC is free software; you can redistribute it and/or modify
     11 * kLIBC is free software; you can redistribute it and/or modify
    1212 * it under the terms of the GNU Lesser General Public License as published
    1313 * by the Free Software Foundation; either version 2 of the License, or
    1414 * (at your option) any later version.
    1515 *
    16  * InnoTek LIBC is distributed in the hope that it will be useful,
     16 * kLIBC is distributed in the hope that it will be useful,
    1717 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     
    2020 *
    2121 * You should have received a copy of the GNU Lesser General Public License
    22  * along with InnoTek LIBC; if not, write to the Free Software
     22 * along with kLIBC; if not, write to the Free Software
    2323 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2424 *
    2525 */
    2626
     27
    2728/*******************************************************************************
    2829*   Header Files                                                               *
    2930*******************************************************************************/
    30 #include "libc-alias.h"
    31 #define INCL_DOS
    32 #define INCL_FSMACROS
    33 #include <os2emx.h>
    34 #include "syscalls.h"
    35 #include <InnoTekLIBC/thread.h>
    36 #include <InnoTekLIBC/backend.h>
     31#define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_BACK_THREAD
     32#include "../kNIX.h"
     33#include <sys/signal.h>
     34#include <klibc/thread.h>
     35#include <klibc/backend.h>
     36#include <klibc/logstrict.h>
     37
    3738
    3839void __libc_Back_threadCleanup(__LIBC_PTHREAD pThrd)
     
    4041    if (!pThrd)
    4142        return;
    42 
    43     if (pThrd->b.sys.fd.hdir != HDIR_CREATE)
    44     {
    45         FS_VAR();
    46         FS_SAVE_LOAD();
    47         DosFindClose(pThrd->b.sys.fd.hdir);
    48         FS_RESTORE();
    49         pThrd->b.sys.fd.hdir = HDIR_CREATE;
    50     }
     43    /** @todo later... */
    5144}
  • trunk/libc/src/kNIX/nt/b_threadInit.c

    r2738 r2742  
    22/** @file
    33 *
    4  * LIBC SYS Backend - thread structure init.
     4 * kNIX - thread structure init, NT.
    55 *
    6  * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
     6 * Copyright (c) 2006 knut st. osmundsen <bird-srcspam@anduin.net>
    77 *
    88 *
    9  * This file is part of InnoTek LIBC.
     9 * This file is part of kLIBC.
    1010 *
    11  * InnoTek LIBC is free software; you can redistribute it and/or modify
     11 * kLIBC is free software; you can redistribute it and/or modify
    1212 * it under the terms of the GNU Lesser General Public License as published
    1313 * by the Free Software Foundation; either version 2 of the License, or
    1414 * (at your option) any later version.
    1515 *
    16  * InnoTek LIBC is distributed in the hope that it will be useful,
     16 * kLIBC is distributed in the hope that it will be useful,
    1717 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     
    2020 *
    2121 * You should have received a copy of the GNU Lesser General Public License
    22  * along with InnoTek LIBC; if not, write to the Free Software
     22 * along with kLIBC; if not, write to the Free Software
    2323 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2424 *
     
    2828*   Header Files                                                               *
    2929*******************************************************************************/
    30 #include "libc-alias.h"
    31 #define INCL_DOSEXCEPTIONS
    32 #define INCL_FSMACROS
    33 #include <os2emx.h>
     30#define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_BACK_THREAD
     31#include "../kNIX.h"
    3432#include <sys/signal.h>
    35 #include <emx/syscalls.h>
    36 #include "syscalls.h"
    37 #include "b_signal.h"
    38 #include <InnoTekLIBC/thread.h>
    39 #include <InnoTekLIBC/backend.h>
     33#include <klibc/thread.h>
     34#include <klibc/backend.h>
     35#include <klibc/logstrict.h>
    4036
    4137
    4238void __libc_Back_threadInit(__LIBC_PTHREAD pThrd, const __LIBC_PTHREAD pParentThrd)
    4339{
    44     pThrd->b.sys.fd.hdir = HDIR_CREATE;
    45     pThrd->b.sys.fd.cFiles = 0;
     40    /** @todo Tell server about this (unless it's the primary thread which it should know about already). */
    4641
    47     if (pParentThrd && pParentThrd->tid)
    48     {
    49         /*
    50          * We don't mess with the signal semaphore here because that *will*
    51          * cause deadlocks. So to protect ourselves against signals
    52          * we'll simply enter a must complete section while accessing the
    53          * variables. This naturally assumes that WE are the parent!
    54          */
    55         FS_VAR_SAVE_LOAD();
    56         ULONG ulNesting = 0;
    57         DosEnterMustComplete(&ulNesting);
    58 
    59         /*
    60          * Copy signal stuff.
    61          */
    62         pThrd->SigSetBlocked    = pParentThrd->SigSetBlocked;
    63         if (pParentThrd->fSigSetBlockedOld)
    64         {
    65             pThrd->SigSetBlockedOld     = pParentThrd->SigSetBlockedOld;
    66             pThrd->fSigSetBlockedOld    = pParentThrd->fSigSetBlockedOld;
    67         }
    68 
    69         /*
    70          * Exit must complete section.
    71          */
    72         DosExitMustComplete(&ulNesting);
    73         FS_RESTORE();
    74     }
    7542}
    7643
  • trunk/libc/src/kNIX/nt/fhNtFile.c

    r2739 r2742  
    3535#include <klibc/logstrict.h>
    3636
     37/**
     38 * Helper function for waiting on pending I/O.
     39 *
     40 * @returns nt status of the completed operation.
     41 * @param   pFH     The handle.
     42 */
     43static NTSTATUS fhNtFileWaitPending(__LIBC_PFH pFH)
     44{
     45    for (;;)
     46    {
     47        LARGE_INTEGER Interval;
     48        Interval.QuadPart = -3000*10000; /* 3 sec */
     49        NTSTATUS rc = NtWaitForSingleObject((HANDLE)pFH->hNative, TRUE, &Interval);
     50        if (    rc != STATUS_TIMEOUT
     51            &&  rc != STATUS_ALERTED
     52            &&  rc != STATUS_USER_APC
     53            &&  rc != STATUS_KERNEL_APC /* yea sure */
     54            &&  rc != STATUS_PENDING    /* yea sure */
     55           )
     56            return rc;
     57        /** @todo check if we're exitting or something. */
     58    }
     59}
    3760
    3861
     
    7699                             NULL,                  /* ByteOffset */
    77100                             NULL);                 /* Key */
     101    if (rc == STATUS_PENDING)
     102        rc = fhNtFileWaitPending(pFH);
    78103    if (NT_SUCCESS(rc))
    79104    {
     
    109134                              NULL,                 /* ByteOffset */
    110135                              NULL);                /* Key */
     136    if (rc == STATUS_PENDING)
     137        rc = fhNtFileWaitPending(pFH);
    111138    if (NT_SUCCESS(rc))
    112139    {
     
    114141        LIBCLOG_RETURN_MSG(0, "ret 0 *pcbWritten=%zu\n", *pcbWritten);
    115142    }
     143    rc = -__libc_back_NtStatus2Errno(rc);
     144    LIBCLOG_ERROR_RETURN_INT(rc);
     145}
     146
     147
     148/** Seek operation.
     149 * @returns 0 on success.
     150 * @returns Negated errno on failure.
     151 * @param   pFH         Pointer to the handle structure to operate on.
     152 * @param   off         The seek offset.
     153 * @param   iMethod     The seek method (SEEK_SET, SEEK_CUR, SEEK_END).
     154 * @param   poffActual  Where to store the new offset.
     155 */
     156static int fhNtFileSeek(__LIBC_PFH pFH, off_t off, int iMethod, off_t *poffActual)
     157{
     158    LIBCLOG_ENTER("pFH=%p:{.fh=%d} off=%llx iMethod=%d poffActual=%p\n", pFH, pFH->fh, off, iMethod, poffActual);
     159
     160    NTSTATUS                    rc;
     161    IO_STATUS_BLOCK             IoSB = {0};
     162
     163    /*
     164     * Figure out the seek target.
     165     * Only SEEK_SET is simple here, for the two other methods we'll have to query the
     166     * value it's relative to first.
     167     */
     168    FILE_POSITION_INFORMATION   FilePosInfo = {0};
     169    switch (iMethod)
     170    {
     171        case SEEK_SET:
     172            FilePosInfo.CurrentByteOffset.QuadPart = off;
     173            break;
     174
     175        case SEEK_CUR:
     176        {
     177            rc = ZwQueryInformationFile((HANDLE)pFH->hNative,       /* FileHandle */
     178                                        &IoSB,                      /* IoStatusBlock */
     179                                        &FilePosInfo,               /* FileInformation */
     180                                        sizeof(FilePosInfo),        /* Length */
     181                                        FilePositionInformation);   /* FileInformationClass */
     182            if (rc == STATUS_PENDING) /* paranoia */
     183                rc = fhNtFileWaitPending(pFH);
     184            if (!NT_SUCCESS(rc))
     185            {
     186                rc = -__libc_back_NtStatus2Errno(rc);
     187                LIBCLOG_ERROR_RETURN_INT(rc);
     188            }
     189            /** @todo Could we return here if off is 0, or do we really have to set the file position?
     190             * The only reasons why we should set it are:
     191             *      -# permission check.
     192             *      -# could be resetting EOF and similar flags.
     193             * It would speed up tell() if we could skip the NtSetInformationFile stuff.
     194             */
     195            FilePosInfo.CurrentByteOffset.QuadPart += off;
     196            break;
     197        }
     198
     199        case SEEK_END:
     200        {
     201            FILE_END_OF_FILE_INFORMATION FileEofInfo = {0};
     202            rc = ZwQueryInformationFile((HANDLE)pFH->hNative,       /* FileHandle */
     203                                        &IoSB,                      /* IoStatusBlock */
     204                                        &FileEofInfo,               /* FileInformation */
     205                                        sizeof(FileEofInfo),        /* Length */
     206                                        FileEndOfFileInformation);  /* FileInformationClass */
     207            if (rc == STATUS_PENDING) /* paranoia */
     208                rc = fhNtFileWaitPending(pFH);
     209            if (!NT_SUCCESS(rc))
     210            {
     211                rc = -__libc_back_NtStatus2Errno(rc);
     212                LIBCLOG_ERROR_RETURN_INT(rc);
     213            }
     214            FilePosInfo.CurrentByteOffset.QuadPart = FileEofInfo.EndOfFile.QuadPart + off;
     215            break;
     216        }
     217
     218        default:
     219            LIBC_ASSERTM_FAILED("iMethod=%d\n", iMethod);
     220            LIBCLOG_ERROR_RETURN_INT(-EINVAL);
     221    }
     222
     223    /*
     224     * Try change the file position.
     225     */
     226    *poffActual = FilePosInfo.CurrentByteOffset.QuadPart;
     227    rc = ZwSetInformationFile((HANDLE)pFH->hNative,                 /* FileHandle */
     228                              &IoSB,                                /* IoStatusBlock */
     229                              &FilePosInfo,                         /* FileInformation */
     230                              sizeof(FilePosInfo),                  /* Length */
     231                              FilePositionInformation);             /* FileInformationClass */
     232    if (rc == STATUS_PENDING) /* paranoia */
     233        rc = fhNtFileWaitPending(pFH);
     234    if (NT_SUCCESS(rc))
     235        LIBCLOG_RETURN_MSG(0, "ret 0 *poffActual=%llx\n", *poffActual);
     236    rc = -__libc_back_NtStatus2Errno(rc);
     237    LIBCLOG_ERROR_RETURN_INT(rc);
     238}
     239
     240
     241/**
     242 * Sets the size of an open file.
     243 *
     244 * @returns 0 on success.
     245 * @returns Negative error code (errno.h) on failure.
     246 * @param   pFH     The file handle structure.
     247 * @param   cbFile  The new filesize.
     248 * @param   fZero   If set any new allocated file space should be initialized to zero.
     249 */
     250static int fhNtFileSizeSet(__LIBC_PFH pFH, off_t cbFile, int fZero)
     251{
     252    LIBCLOG_ENTER("fh=%d cbFile=%lld fZero=%d\n", fh, cbFile, fZero);
     253
     254    /** @todo Check if having a file position *AFTER* the new EOF is a problem. */
     255    /** @todo Check if all file systems on NT will initialize new space with zeros. */
     256    IO_STATUS_BLOCK                 IoSB = {0};
     257    FILE_END_OF_FILE_INFORMATION    FileEofInfo = {0};
     258    FileEofInfo.EndOfFile.QuadPart = cbFile;
     259    NTSTATUS rc = ZwSetInformationFile((HANDLE)pFH->hNative,                 /* FileHandle */
     260                                       &IoSB,                                /* IoStatusBlock */
     261                                       &FileEofInfo,                         /* FileInformation */
     262                                       sizeof(FileEofInfo),                  /* Length */
     263                                       FileEndOfFileInformation);            /* FileInformationClass */
     264    if (rc == STATUS_PENDING) /* paranoia */
     265        rc = fhNtFileWaitPending(pFH);
     266    if (NT_SUCCESS(rc))
     267        LIBCLOG_RETURN_INT(0);
    116268    rc = -__libc_back_NtStatus2Errno(rc);
    117269    LIBCLOG_ERROR_RETURN_INT(rc);
     
    199351    fhNtFileRead,
    200352    fhNtFileWrite,
     353    fhNtFileSeek,
     354    fhNtFileSizeSet,
    201355    fhNtFileDuplicate,
    202356    fhNtFileFileControl,
  • trunk/libc/src/kNIX/os2/fhOS2File.c

    r2739 r2742  
    2727
    2828/*******************************************************************************
     29*   Global Variables                                                           *
     30*******************************************************************************/
     31/** A page of zeros.
     32 * @todo Make this a separate segment for optimal thunking effiency! */
     33static const char __libc_gachZeros[65536 - 4096];
     34
     35
     36/*******************************************************************************
    2937*   Internal Functions                                                         *
    3038*******************************************************************************/
    31 static int fhOs2FileClose(__LIBC_PFH pFH);
    32 
    33 /** Operations on sockets. */
    34 static const __LIBC_FHOPS       gSocketOps =
    35 {
    36     enmFH_File,             /* Handle type. */
    37     fhOs2FileClose,
    38     fhOs2FileRead,
    39     fhOs2FileWrite,
    40     fhOs2FileDuplicate,
    41     fhOs2FileFileControl,
    42     fhOs2FileIOControl,
    43     fhOs2FileSelect,
    44     NULL /* fork parent */,
    45     NULL /* for child */
    46 };
     39static inline int getFileSize(HFILE hFile, off_t *pcb);
     40static inline int setFileSize(HFILE hFile, off_t cbFile);
     41static inline int seekFile(HFILE hFile, off_t cbFile, int iMethod, off_t *poffFile);
     42
    4743
    4844
     
    124120 * @returns Negated errno on failure.
    125121 * @param   pFH         Pointer to the handle structure to operate on.
    126  * @param   fh          It's associated filehandle.
    127122 * @param   pvBuf       Pointer to the buffer which contains the data to write.
    128123 * @param   cbToWrite   Number of bytes to write.
     
    172167
    173168
     169/** Seek operation.
     170 * @returns 0 on success.
     171 * @returns Negated errno on failure.
     172 * @param   pFH         Pointer to the handle structure to operate on.
     173 * @param   off         The seek offset.
     174 * @param   iMethod     The seek method (SEEK_SET, SEEK_CUR, SEEK_END).
     175 * @param   poffActual  Where to store the new offset.
     176 */
     177static int fhOs2FileSeek(__LIBC_PFH pFH, off_t off, int iMethod, off_t *poffActual)
     178{
     179    LIBCLOG_ENTER("pFH=%p:{.fh=%d} off=%llx iMethod=%d poffActual=%p\n", pFH, pFH->fh, off, iMethod, poffActual);
     180    FS_VAR_SAVE_LOAD();
     181    union
     182    {
     183        off_t       off;
     184        LONGLONG    ll;
     185        ULONG       ul;
     186    } u;
     187#if OFF_MAX > LONG_MAX
     188    if (__libc_gpfnDosSetFilePtrL)
     189        rc = __libc_gpfnDosSetFilePtrL(hFile, off, iMethod, &u.ll);
     190    else
     191    {
     192        if (off > LONG_MAX || off < LONG_MIN)
     193        {
     194            FS_RESTORE();
     195            LIBCLOG_ERROR_RETURN_INT(-EOVERFLOW);
     196        }
     197        u.off = 0;
     198        rc = DosSetFilePtr(hFile, off, iMethod, &u.ul);
     199    }
     200#else
     201    {
     202        u.off = 0;
     203        rc = DosSetFilePtr(hFile, off, iMethod, &u.ul);
     204    }
     205#endif
     206    FS_RESTORE();
     207    if (__predict_true(!rc))
     208    {
     209        poffActual = u.off;
     210        LIBCLOG_RETURN_INT(0);
     211    }
     212    rc = -__libc_native2errno(rc);
     213    LIBCLOG_ERROR_RETURN_INT(rc);
     214}
     215
     216
     217/**
     218 * Calls the correct OS/2 api for this operation.
     219 * FS is saved and loaded by caller.
     220 * @returns OS/2 error code or negative errno.
     221 */
     222static inline int getFileSize(HFILE hFile, off_t *pcb)
     223{
     224    union
     225    {
     226        FILESTATUS3     fsts3;
     227        FILESTATUS3L    fsts3L;
     228    } info;
     229    int     rc;
     230#if OFF_MAX > LONG_MAX
     231    if (__libc_gpfnDosOpenL)
     232    {
     233        rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &info, sizeof(info.fsts3L));
     234        *pcb = info.fsts3L.cbFile;
     235    }
     236    else
     237#endif
     238    {
     239        rc = DosQueryFileInfo(hFile, FIL_STANDARD, &info, sizeof(info.fsts3));
     240        *pcb = info.fsts3.cbFile;
     241    }
     242    return rc;
     243}
     244
     245/**
     246 * Calls the correct OS/2 api for this operation.
     247 * FS is saved and loaded by caller.
     248 * @returns OS/2 error code or negative errno.
     249 */
     250static inline int setFileSize(HFILE hFile, off_t cbFile)
     251{
     252    int rc;
     253#if OFF_MAX > LONG_MAX
     254    if (__libc_gpfnDosSetFileSizeL)
     255        rc = __libc_gpfnDosSetFileSizeL(hFile, cbFile);
     256    else
     257    {
     258        if (cbFile > __LONG_MAX)
     259            return -EOVERFLOW;
     260        rc = DosSetFileSize(hFile, cbFile);
     261    }
     262#else
     263    rc = DosSetFileSize(hFile, cbFile);
     264#endif
     265    return rc;
     266}
     267
     268/**
     269 * Calls the correct OS/2 api for this operation.
     270 * FS is saved and loaded by caller.
     271 * @returns OS/2 error code or negative errno.
     272 */
     273static inline int seekFile(HFILE hFile, off_t off, int iMethod, off_t *poffFile)
     274{
     275    int rc;
     276#if OFF_MAX > LONG_MAX
     277    if (__libc_gpfnDosSetFilePtrL)
     278    {
     279        LONGLONG cbNewTmp;
     280        rc = __libc_gpfnDosSetFilePtrL(hFile, off, iMethod, &cbNewTmp);
     281        off = cbNewTmp;
     282    }
     283    else
     284    {
     285        ULONG cbNewTmp;
     286        if (off > LONG_MAX || off < LONG_MIN)
     287            return -EOVERFLOW;
     288        rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp);
     289        off = cbNewTmp;
     290    }
     291#else
     292    {
     293        ULONG cbNewTmp;
     294        rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp);
     295        off = cbNewTmp;
     296    }
     297#endif
     298    if (poffFile)
     299        *poffFile = off;
     300    return rc;
     301}
     302
     303
     304/**
     305 * Sets the size of an open file.
     306 *
     307 * @returns 0 on success.
     308 * @returns Negative error code (errno.h) on failure.
     309 * @param   pFH     The file handle structure.
     310 * @param   cbFile  The new filesize.
     311 * @param   fZero   If set any new allocated file space should be initialized to zero.
     312 */
     313static int fhOS2FileSizeSet(__LIBC_PFH pFH, off_t cbFile, int fZero)
     314{
     315    LIBCLOG_ENTER("fh=%d cbFile=%lld fZero=%d\n", fh, cbFile, fZero);
     316    FS_VAR_SAVE_LOAD();
     317
     318    /*
     319     * Get the current file size so we can perform
     320     * any necessary zero padding.
     321     */
     322    off_t   cbCur;
     323    int rc = getFileSize(fh, &cbCur);
     324    if (!rc)
     325    {
     326        if (cbCur != cbFile)
     327        {
     328            /*
     329             * File size change needed.
     330             */
     331            rc = setFileSize(fh, cbFile);
     332            if (!rc)
     333            {
     334                /*
     335                 * We're done if it was a truncation, or if we don't have to zero new
     336                 * bytes, or if the file system driver will zero new bytes.
     337                 */
     338                off_t   cbLeft = cbFile - cbCur;
     339                if (    cbLeft <= 0
     340                    ||  !fZero
     341                    || (    pFH->pFsInfo
     342                        &&  pFH->pFsInfo->fZeroNewBytes))
     343                {
     344                    FS_RESTORE();
     345                    LIBCLOG_RETURN_INT(0);
     346                }
     347
     348                /*
     349                 * Must fill the allocated file space with zeros.
     350                 */
     351                off_t offSaved, offIgnored;
     352                rc = fhOs2FileSeek(pFH, 0, SEEK_CUR, &offSaved);
     353                if (!rc)
     354                    rc = fhOs2FileSeek(pFH, cbCur, SEEK_SET, &offIgnored);
     355                while (!rc && cbLeft > 0)
     356                {
     357                    ULONG cb = cbLeft >= sizeof(__libc_gachZeros) ? sizeof(__libc_gachZeros) : cbLeft;
     358                    rc = DosWrite(fh, &__libc_gachZeros[0], cb, &cb);
     359                    cbLeft -= cb;
     360                }
     361                int rc2 = fhOs2FileSeek(fh, offSaved, SEEK_SET, &offIgnored);
     362                if (!rc && !rc2)
     363                {
     364                    FS_RESTORE();
     365                    LIBCLOG_RETURN_INT(0);
     366                }
     367
     368                /*
     369                 * Shit, we failed writing zeros. Try undo the expand operation.
     370                 */
     371                setFileSize(fh, cbCur);
     372                if (rc2)
     373                {
     374                    fhOs2FileSeek(fh, offSaved, SEEK_SET, &offIgnored);
     375                    if (!rc)
     376                        rc = rc2;
     377                }
     378            }
     379        }
     380    }
     381
     382    FS_RESTORE();
     383    if (rc > 0)
     384        rc = -__libc_native2errno(rc);
     385    LIBCLOG_ERROR_RETURN_INT(rc);
     386}
     387
     388
    174389/** Duplicate handle operation.
    175390 * @returns 0 on success.
    176391 * @returns Negated errno on failure.
    177392 * @param   pFH         Pointer to the handle structure to operate on.
    178  * @param   fh          It's associated filehandle.
    179393 * @param   pfhNew      Where to store the duplicate filehandle.
    180394 *                      The input value describe how the handle is to be
     
    193407 * @returns Negated errno on failure.
    194408 * @param   pFH         Pointer to the handle structure to operate on.
    195  * @param   fh          It's associated filehandle.
    196409 * @param   iRequest    Which file file descriptior request to perform.
    197410 * @param   iArg        Argument which content is specific to each
     
    209422 * @returns Negated errno on failure.
    210423 * @param   pFH         Pointer to the handle structure to operate on.
    211  * @param   fh          It's associated filehandle.
    212424 * @param   iIOControl  Which I/O control operation to perform.
    213425 * @param   iArg        Argument which content is specific to each
     
    240452}
    241453
     454
     455
     456/** Operations on sockets. */
     457static const __LIBC_FHOPS       gSocketOps =
     458{
     459    enmFH_File,             /* Handle type. */
     460    fhOs2FileClose,
     461    fhOs2FileRead,
     462    fhOs2FileWrite,
     463    fhOs2FileSeek,
     464    fhOS2FileSizeSet,
     465    fhOs2FileDuplicate,
     466    fhOs2FileFileControl,
     467    fhOs2FileIOControl,
     468    fhOs2FileSelect,
     469    NULL /* fork parent */,
     470    NULL /* for child */
     471};
     472
  • trunk/libc/src/libc/startup/_exit.c

    r2259 r2742  
    22
    33#include <stdlib.h>
    4 #include <emx/syscalls.h>
    54#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_INITTERM
    6 #include <InnoTekLIBC/logstrict.h>
     5#include <klibc/backend.h>
     6#include <klibc/logstrict.h>
    77
    88/* mkstd.awk: NOUNDERSCORE(exit) */
     
    1111    LIBCLOG_ENTER("ret=%d\n", ret);
    1212    for (;;)
    13         __exit(ret);
     13        __libc_Back_processExit(ret);
    1414    LIBCLOG_MSG("shut up\n");
    1515}
Note: See TracChangeset for help on using the changeset viewer.