diros2.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 399 行

C
399
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  OS/2 implementation of directory functions.
*
****************************************************************************/


#include "variety.h"
#include "widechar.h"
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <mbstring.h>
#include <sys/types.h>
#include <direct.h>
#include <dos.h>
#define INCL_ERRORS
#include <wos2.h>
#include "tinyio.h"
#include "rtdata.h"
#include "strdup.h"
#include "seterrno.h"
#include "msdos.h"
#include "_direct.h"

#if defined(__WARP__)
  #define FF_LEVEL      1
  #define FF_BUFFER     FILEFINDBUF3
#else
  #define FF_LEVEL      0
  #define FF_BUFFER     FILEFINDBUF
#endif

#define _DIR_ISFIRST            0
#define _DIR_NOTFIRST           1
#define _DIR_MAX_FOR_CLOSE_OK   2       /* dummy value used by closedir */
#define _DIR_CLOSED             3

#define SEEK_ATTRIB (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | _A_RDONLY | _A_ARCH)

/* Since dptr->d_dta is not used under OS/2, we will store the handle for
 * this directory scan in it.  This macro simply does the appropriate casting
 * for us. DJG
 */
#define HANDLE_OF(dirp)         ( *( HDIR * )( &( dirp )->d_dta[ 0 ] ) )

/* we'll use this to copy from a FILEFINDBUF to a DIR in copydir() */
struct name {
    char buf[ NAME_MAX + 1 ];
};

static void copydir( DIR_TYPE *dirp, FF_BUFFER *dir_buff )
/********************************************************/
{

#ifdef __WIDECHAR__
    wchar_t             wcs[_MAX_PATH];
#endif

    /*** Copy the structure data ***/
    dirp->d_attr = dir_buff->attrFile;
    dirp->d_time = *(unsigned short *)&dir_buff->ftimeLastWrite;
    dirp->d_date = *(unsigned short *)&dir_buff->fdateLastWrite;
    dirp->d_size = dir_buff->cbFile;
    *(struct name *)dirp->d_name = *(struct name *)dir_buff->achName;

#ifdef __WIDECHAR__
    mbstowcs( wcs, (char*)dirp->d_name, _MAX_PATH );    /* convert string */
    wcscpy( dirp->d_name, wcs );                        /* copy string */
#endif
}


static int is_directory( const CHAR_TYPE *name )
/**********************************************/
{
    /* 28-oct-98 */
#ifndef __WIDECHAR__
    unsigned    curr_ch;
    unsigned    prev_ch;
#else
    CHAR_TYPE   curr_ch;
    CHAR_TYPE   prev_ch;
#endif

    curr_ch = NULLCHAR;
    for(;;) {
        prev_ch = curr_ch;
#ifdef __WIDECHAR__
        curr_ch = *name;
#else
        curr_ch = _mbsnextc( name );
#endif
        if( curr_ch == NULLCHAR )
            break;
        if( prev_ch == '*' )
            break;
        if( prev_ch == '?' )
            break;
#ifdef __WIDECHAR__
        ++name;
#else
        name = _mbsinc( name );
#endif
    }
    if( curr_ch == NULLCHAR ) {
        if( prev_ch == '\\' || prev_ch == '/' || prev_ch == '.' ){
            return( 1 );
        }
    }
    return( 0 );
}


_WCRTLINK DIR_TYPE *__F_NAME(__opendir,_w__opendir)( const CHAR_TYPE *dirname,
                                               unsigned attr, DIR_TYPE *dirp )
/****************************************************************************/
{

    /*** Convert a wide char string to a multibyte string ***/
#ifdef __WIDECHAR__
    char            mbcsName[MB_CUR_MAX*_MAX_PATH];

    if( wcstombs( mbcsName, dirname, MB_CUR_MAX*(wcslen(dirname)+1) ) == (size_t)-1 )
        return( NULL );
#endif

#if defined(__OS2_286__)
    if( _RWD_osmode == OS2_MODE )
#endif
    {
        FF_BUFFER       dir_buff;
        HFILE           handle;
        OS_UINT         rc;
        OS_UINT         searchcount;

        handle = ~0;            /* we want our own handle */
        searchcount = 1;        /* only one at a time */
#ifndef __WIDECHAR__
        rc = DosFindFirst( (PSZ)dirname, &handle, attr, (PVOID)&dir_buff,
                    sizeof( dir_buff ), &searchcount, FF_LEVEL );
#else
        rc = DosFindFirst( (PSZ)mbcsName, &handle, attr, (PVOID)&dir_buff,
                    sizeof( dir_buff ), &searchcount, FF_LEVEL );
#endif

        if( rc != 0 ) {
            __set_errno_dos( rc );
            return( NULL );
        }
        if( searchcount != 1 ) {
            DosFindClose( handle );
            __set_errno_dos( ERROR_NO_MORE_FILES );
            return( NULL );
        }
        HANDLE_OF( dirp ) = handle;     /* store our handle     */
        copydir( dirp, &dir_buff );     /* copy in other fields */
    }
#if defined(__OS2_286__)
    else {                              /* real mode */
        DIR_TYPE        buf;
        tiny_ret_t      rc;

        TinySetDTA( buf.d_dta );        /* set our DTA */
  #ifndef __WIDECHAR__
        rc = TinyFindFirst( dirname, attr );
  #else
        rc = TinyFindFirst( mbcsName, attr );
  #endif
        if( TINY_ERROR( rc ) ) {
            __set_errno_dos( TINY_INFO( rc ) );
            return( NULL );
        }
        *dirp = buf;                    /* copy to new memory */
    }
#endif

    dirp->d_first = _DIR_ISFIRST;       /* indicate we have 1st name */
    return( dirp );
}


_WCRTLINK DIR_TYPE *__F_NAME(_opendir,_w_opendir)( const CHAR_TYPE *dirname,
                                                             unsigned attr )
/**************************************************************************/
{

    DIR_TYPE        *dirp;
    int             i;
    auto CHAR_TYPE  pathname[_MAX_PATH+6];
    const CHAR_TYPE *dirnameStart = dirname;
#ifndef __WIDECHAR__
    unsigned    curr_ch;
    unsigned    prev_ch;
#else
    CHAR_TYPE   curr_ch;
    CHAR_TYPE   prev_ch;
#endif

    dirp = malloc( sizeof( DIR_TYPE ) );
    HANDLE_OF( dirp ) = 0;                  /* initialize handle    */
    if( dirp == NULL ) {
        __set_errno_dos( ERROR_NOT_ENOUGH_MEMORY );
        return( NULL );
    }
    if( ! is_directory( dirname ) ) {
        if( __F_NAME(__opendir,_w__opendir)( dirname, attr, dirp ) == NULL ) {
            free( dirp );
            return( NULL );
        }
    } else {
        dirp->d_attr = _A_SUBDIR;
    }
    if( dirp->d_attr & _A_SUBDIR ) {                    /* 05-apr-91 */
        prev_ch = NULLCHAR;                             /* 28-oct-98 */
        for( i = 0; i < _MAX_PATH; i++ ) {
#ifdef __WIDECHAR__
            curr_ch = *dirname;
#else
            curr_ch = _mbsnextc( dirname );
#endif
            pathname[i] = *dirname;
#ifndef __WIDECHAR__
            if( curr_ch > 256 ) {
                ++i;
                ++dirname;
                pathname[i] = *dirname;     /* copy double-byte */
            }
#endif
            if( curr_ch == NULLCHAR ) {
                if( i != 0  &&  prev_ch != '\\' && prev_ch != '/' ){
                    pathname[i++] = '\\';
                }
#ifndef __WIDECHAR__
                strcpy( &pathname[i], "*.*" );
#else
                wcscpy( &pathname[i], L"*.*" );
#endif
                if( HANDLE_OF( dirp ) != 0 ) {
                    DosFindClose( HANDLE_OF(dirp) );
                }
                if( __F_NAME(__opendir,_w__opendir)( pathname, attr, dirp ) == NULL ) {
                    free( dirp );
                    return( NULL );
                }
                break;
            }
            if( *dirname == '*' )
                break;
            if( *dirname == '?' )
                break;
            ++dirname;
            prev_ch = curr_ch;
        }

    }
    if( dirp != NULL )
        dirp->d_openpath = __F_NAME(__clib_strdup,__clib_wcsdup)( dirnameStart );
    return( dirp );
}


_WCRTLINK DIR_TYPE *__F_NAME(opendir,_wopendir)( const CHAR_TYPE *dirname )
/*************************************************************************/
{
    return( __F_NAME(_opendir,_w_opendir)( dirname, SEEK_ATTRIB ) );
}


_WCRTLINK DIR_TYPE *__F_NAME(readdir,_wreaddir)( DIR_TYPE *dirp )
/***************************************************************/
{
    if( dirp == NULL ) {
        return( NULL );
    }
    if( dirp->d_first == _DIR_CLOSED )
        return( NULL );
    if( dirp->d_first == _DIR_ISFIRST ) {       /* if we already have one */
        dirp->d_first = _DIR_NOTFIRST;
        return( dirp );
    }

#if defined(__OS2_286__)
    if( _RWD_osmode == OS2_MODE )               /* protected mode */
#endif
    {
        OS_UINT         rc;
        FF_BUFFER       dir_buff;
        OS_UINT         searchcount = 1;

        rc = DosFindNext( HANDLE_OF( dirp ), (PVOID)&dir_buff,
            sizeof( dir_buff ), &searchcount );
        if( rc == ERROR_NO_MORE_FILES ) {
            return( NULL );
        }
        if( rc != 0 ) {
            __set_errno_dos( rc );
            return( NULL );
        }
        if( searchcount != 1 ) {
            __set_errno_dos( ERROR_NO_MORE_FILES );
            return( NULL );
        }
        copydir( dirp, &dir_buff );

    }
#if defined(__OS2_286__)
    else {              /* real mode */
        tiny_ret_t      rc;

        TinySetDTA( dirp->d_dta );
        rc = TinyFindNext();
        if( TINY_ERROR( rc ) ) {
            if( TINY_INFO( rc ) != E_nomore ) {
                __set_errno_dos( TINY_INFO( rc ) );
            }
            return( NULL );
        }
    }
#endif
    return( dirp );
}


_WCRTLINK int __F_NAME(closedir,_wclosedir)( DIR_TYPE *dirp )
/***********************************************************/
{

    if( dirp == NULL || dirp->d_first > _DIR_MAX_FOR_CLOSE_OK  ) {/* error */
        __set_errno_dos( ERROR_INVALID_HANDLE );
        return( -1 );
    }

#if defined(__OS2_286__)
    if( _RWD_osmode == OS2_MODE )
#endif
        DosFindClose( HANDLE_OF( dirp ) );

    dirp->d_first = _DIR_CLOSED;
    if( dirp->d_openpath != NULL )
        free( dirp->d_openpath );
    free( dirp );
    return( 0 );                        /* ok */
}


_WCRTLINK void __F_NAME(rewinddir,_wrewinddir)( DIR_TYPE *dirp )
/**************************************************************/
{
    CHAR_TYPE *         openpath;
    DIR_TYPE *          newDirp;

    /*** Get the name of the directory before closing it ***/
    if( dirp->d_openpath == NULL )
        return;                         /* can't continue if NULL */
    openpath = __F_NAME(__clib_strdup,__clib_wcsdup)( dirp->d_openpath ); /* store path */
    if( openpath == NULL ) {
        dirp->d_first = _DIR_CLOSED;    /* so reads won't work any more */
        return;
    }

    /*** Reopen the directory ***/
    __F_NAME(closedir,_wclosedir)( dirp );              /* close directory */
    newDirp = __F_NAME(opendir,_wopendir)( openpath );  /* open it again */
    if( newDirp == NULL ) {
        dirp->d_first = _DIR_CLOSED;    /* so reads won't work any more */
        return;
    }

    /*** Clean up and go home ***/
    free( openpath );                       /* don't need this any more */
    memcpy( dirp, newDirp, sizeof(DIR_TYPE) );   /* copy into user buffer */
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?