findlfn.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 175 行
C
175 行
/****************************************************************************
*
* 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: LFN-enabled findfirst/next/close functions for DOS.
*
****************************************************************************/
#include "variety.h"
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <direct.h>
#include <string.h>
#include <dos.h>
#include "seterrno.h"
/* The find block for the LFN findfirst */
struct lfnfind_t {
long attributes;
long creattime;
long creatdate;
long accesstime;
long accessdate;
long wrtime;
long wrdate;
long hfilesize;
long lfilesize;
char reserved[8];
char lfn[260];
char sfn[14];
};
/* The normal findfirst/next functions written in assembler */
_WCRTLINK extern unsigned _old_dos_findfirst( const char *path,
unsigned attr, struct find_t *buf );
_WCRTLINK extern unsigned _old_dos_findnext( struct find_t *buf );
static void convert_to_find_t( struct find_t *dosblock,
struct lfnfind_t *lfnblock )
{
dosblock->attrib = lfnblock->attributes;
dosblock->cr_time = lfnblock->creattime;
dosblock->cr_date = lfnblock->creatdate;
dosblock->ac_time = lfnblock->accesstime;
dosblock->ac_date = lfnblock->accessdate;
dosblock->wr_time = lfnblock->wrtime;
dosblock->wr_date = lfnblock->wrdate;
dosblock->size = lfnblock->lfilesize;
if( lfnblock->lfn ) {
memcpy( dosblock->name, lfnblock->lfn, sizeof( lfnblock->lfn ) );
} else {
memcpy( dosblock->name, lfnblock->sfn, sizeof( lfnblock->sfn ) );
}
}
_WCRTLINK unsigned _dos_findfirst( const char *path, unsigned attr,
struct find_t *buf )
{
union REGS r;
struct SREGS s;
struct lfnfind_t lfnblock;
buf->lfnax = buf->lfnsup = 0; /* Zero find handle and LFN-supported flag */
r.w.ax = 0x714E; /* LFN Findfirst */
r.w.cx = attr;
r.w.si = 1; /* Use DOS date/time format */
s.ds = FP_SEG( path ); /* path goes in DS:DX */
r.w.dx = FP_OFF( path );
s.es = FP_SEG( &lfnblock ); /* LFN find block goes in ES:DI */
r.w.di = FP_OFF( &lfnblock );
intdosx( &r, &r, &s ); /* Let's call the LFN version */
/*
* If ax = 7100, there is probably an LFN TSR but no LFN support for
* whatever drive or directory is being searched. In that case, fall back on
* the old findfirst. Also if the function fails, it could be because of
* no LFN TSR so fall back to the old findfirst.
*/
if( r.w.ax == 0x7100 || r.w.cflag )
return( _old_dos_findfirst( path, attr, buf ) );
/*
* If there was no failure, the next step is to move the values from the
* LFN block into the non-lfn block
*/
buf->lfnax = r.w.ax; /* The find handle for findnext */
buf->lfnsup = 1;
convert_to_find_t( buf, &lfnblock );
/*
* 0 is always returned because we've already checked cflag; the
* old_dos_findfirst will handle any errors
*/
return( 0 );
}
_WCRTLINK unsigned _dos_findnext( struct find_t *buf )
{
union REGS r;
struct SREGS s;
struct lfnfind_t lfnblock;
/*
* Before going through the possibly unnecessary steps of calling the LFN
* function first, buf->lfnsup will tell us if LFN was supported with the
* previous call to findfirst.
*/
if( !buf->lfnsup ) {
return( _old_dos_findnext( buf ) );
}
r.w.ax = 0x714F;
r.w.bx = buf->lfnax; /* The lfn handle set by findfirst */
r.w.si = 1; /* Use DOS times */
s.es = FP_SEG( &lfnblock );
r.w.di = FP_OFF( &lfnblock ); /* The LFN find block */
intdosx( &r, &r, &s ); /* Call the function */
/* Check for errors */
if( r.w.cflag ) {
__set_errno_dos( r.w.ax );
return( r.w.ax );
}
convert_to_find_t( buf, &lfnblock );
return( 0 );
}
_WCRTLINK unsigned _dos_findclose( struct find_t *buf )
{
union REGS r;
/* Let's check if LFN was used; if not, there is no need for findclose */
if( !buf->lfnsup ) return( 0 );
r.w.ax = 0x71A1; /* LFN findclose */
r.w.bx = buf->lfnax; /* Findfirst handle */
intdos( &r, &r );
/* Check for errors (which really shouldn't be a problem anyways
* except for bad code)
*/
if( r.w.cflag ) {
__set_errno_dos( r.w.ax );
return( r.w.ax );
}
return( 0 );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?