blob: 4251bba22a6472efd362f921868e2bc74cd56cfc [file] [log] [blame]
/*
* CRTDLL drive/directory functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
*
* Implementation Notes:
* MT Safe.
*/
#include "crtdll.h"
#include <errno.h>
#include "ntddk.h"
#include <time.h>
DEFAULT_DEBUG_CHANNEL(crtdll);
/* INTERNAL: Translate find_t to PWIN32_FIND_DATAA */
static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft);
static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
{
DWORD dw;
/* Tested with crtdll.dll Version 2.50.4170 (NT) from win98 SE:
* attrib 0x80 (FILE_ATTRIBUTE_NORMAL)is returned as 0.
*/
if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
ft->attrib = 0;
else
ft->attrib = fd->dwFileAttributes;
RtlTimeToSecondsSince1970( &fd->ftCreationTime, &dw );
ft->time_create = dw;
RtlTimeToSecondsSince1970( &fd->ftLastAccessTime, &dw );
ft->time_access = dw;
RtlTimeToSecondsSince1970( &fd->ftLastWriteTime, &dw );
ft->time_write = dw;
ft->size = fd->nFileSizeLow;
strcpy(ft->name, fd->cFileName);
}
/*********************************************************************
* _chdir (CRTDLL.51)
*
* Change the current directory.
*
* PARAMS
* newdir [in] Directory to change to
*
* RETURNS
* Sucess: 0
*
* Failure: -1
*/
INT __cdecl CRTDLL__chdir(LPCSTR newdir)
{
if (!SetCurrentDirectoryA(newdir))
{
__CRTDLL__set_errno(newdir?GetLastError():0);
return -1;
}
return 0;
}
/*********************************************************************
* _chdrive (CRTDLL.52)
*
* Change the current drive.
*
* PARAMS
* newdrive [in] new drive to change to, A: =1, B: =2, etc
*
* RETURNS
* Sucess: 0
*
* Failure: 1
*/
BOOL __cdecl CRTDLL__chdrive(INT newdrive)
{
char buffer[3] = "A:";
buffer[0] += newdrive - 1;
if (!SetCurrentDirectoryA( buffer ))
{
__CRTDLL__set_errno(GetLastError());
if (newdrive <= 0)
CRTDLL_errno = EACCES;
return -1;
}
return 0;
}
/*********************************************************************
* _findclose (CRTDLL.098)
*
* Free the resources from a search handle created from _findfirst.
*
* PARAMS
* hand [in]: Search handle to close
*
* RETURNS
* Success: 0
*
* Failure: -1
*/
INT __cdecl CRTDLL__findclose(DWORD hand)
{
TRACE(":handle %ld\n",hand);
if (!FindClose((HANDLE)hand))
{
__CRTDLL__set_errno(GetLastError());
return -1;
}
return 0;
}
/*********************************************************************
* _findfirst (CRTDLL.099)
*
* Create and return a search handle for iterating through a file and
* directory list.
*
* PARAMS
* fspec [in] File specification string for search, e.g "C:\*.BAT"
*
* ft [out] A pointer to a find_t structure to populate.
*
* RETURNS
* Success: A handle for the search, suitable for passing to _findnext
* or _findclose. Populates the members of ft with the details
* of the first matching file.
*
* Failure: -1.
*/
DWORD __cdecl CRTDLL__findfirst(LPCSTR fspec, find_t* ft)
{
WIN32_FIND_DATAA find_data;
HANDLE hfind;
hfind = FindFirstFileA(fspec, &find_data);
if (hfind == INVALID_HANDLE_VALUE)
{
__CRTDLL__set_errno(GetLastError());
return -1;
}
__CRTDLL__fttofd(&find_data,ft);
TRACE(":got handle %d\n",hfind);
return hfind;
}
/*********************************************************************
* _findnext (CRTDLL.100)
*
* Return the next matching file/directory from a search hadle.
*
* PARAMS
* hand [in] Search handle from a pervious call to _findfirst
*
* ft [out] A pointer to a find_t structure to populate.
*
* RETURNS
* Success: 0. Populates the members of ft with the details
* of the first matching file
*
* Failure: -1
*/
INT __cdecl CRTDLL__findnext(DWORD hand, find_t * ft)
{
WIN32_FIND_DATAA find_data;
if (!FindNextFileA(hand, &find_data))
{
SetLastError(ERROR_INVALID_DRIVE);
__CRTDLL__set_errno(GetLastError());
return -1;
}
__CRTDLL__fttofd(&find_data,ft);
return 0;
}
/*********************************************************************
* _getcwd (CRTDLL.120)
*
* Get the current directory.
*
* PARAMS
* buf [out] A buffer to place the current directory name in
*
* size [in] The size of buf.
*
* RETURNS
* Success: buf, or if buf is NULL, an allocated buffer
*
* Failure: NULL
*/
CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT size)
{
char dir[_MAX_PATH];
int dir_len = GetCurrentDirectoryA(_MAX_PATH,dir);
if (dir_len < 1)
return NULL; /* FIXME: Real return value untested */
if (!buf)
{
if (size < 0)
return CRTDLL__strdup(dir);
return __CRTDLL__strndup(dir,size);
}
if (dir_len >= size)
{
CRTDLL_errno = ERANGE;
return NULL; /* buf too small */
}
strcpy(buf,dir);
return buf;
}
/*********************************************************************
* _getdcwd (CRTDLL.121)
*
* Get the current directory on a drive. A: =1, B: =2, etc.
* Passing drive 0 means the current drive.
*/
CHAR* __cdecl CRTDLL__getdcwd(INT drive,LPSTR buf, INT size)
{
static CHAR* dummy;
if (!drive || drive == CRTDLL__getdrive())
return CRTDLL__getcwd(buf,size); /* current */
else
{
char dir[_MAX_PATH];
char drivespec[4] = {'A', ':', '\\', 0};
int dir_len;
drivespec[0] += drive - 1;
if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
{
CRTDLL_errno = EACCES;
return NULL;
}
dir_len = GetFullPathNameA(drivespec,_MAX_PATH,dir,&dummy);
if (dir_len >= size || dir_len < 1)
{
CRTDLL_errno = ERANGE;
return NULL; /* buf too small */
}
if (!buf)
return CRTDLL__strdup(dir); /* allocate */
strcpy(buf,dir);
}
return buf;
}
/*********************************************************************
* _getdiskfree (CRTDLL.122)
*
* Get free disk space on given drive or the current drive.
*
*/
UINT __cdecl CRTDLL__getdiskfree(UINT disk, diskfree_t* d)
{
char drivespec[4] = {'@', ':', '\\', 0};
DWORD ret[4];
UINT err;
if (disk > 26)
return ERROR_INVALID_PARAMETER; /* CRTDLL doesn't set errno here */
drivespec[0] += disk; /* make a drive letter */
if (GetDiskFreeSpaceA(disk==0?NULL:drivespec,ret,ret+1,ret+2,ret+3))
{
d->cluster_sectors = (unsigned)ret[0];
d->sector_bytes = (unsigned)ret[1];
d->available = (unsigned)ret[2];
d->num_clusters = (unsigned)ret[3];
return 0;
}
err = GetLastError();
__CRTDLL__set_errno(err);
return err;
}
/*********************************************************************
* _getdrive (CRTDLL.124)
*
* Return current drive, A: =1, B: =2, etc
*/
INT __cdecl CRTDLL__getdrive(VOID)
{
char buffer[MAX_PATH];
if (!GetCurrentDirectoryA( sizeof(buffer), buffer )) return 0;
if (buffer[1] != ':') return 0;
return toupper(buffer[0]) - 'A' + 1;
}
/*********************************************************************
* _mkdir (CRTDLL.234)
*
* Create a directory.
*/
INT __cdecl CRTDLL__mkdir(LPCSTR newdir)
{
if (CreateDirectoryA(newdir,NULL))
return 0;
__CRTDLL__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* _rmdir (CRTDLL.255)
*
* Delete a directory
*
*/
INT __cdecl CRTDLL__rmdir(LPSTR dir)
{
if (RemoveDirectoryA(dir))
return 0;
__CRTDLL__set_errno(GetLastError());
return -1;
}