diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/dos/getcwd.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/crt32/dos/getcwd.c')
-rw-r--r-- | private/crt32/dos/getcwd.c | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/private/crt32/dos/getcwd.c b/private/crt32/dos/getcwd.c new file mode 100644 index 000000000..e2c8042a2 --- /dev/null +++ b/private/crt32/dos/getcwd.c @@ -0,0 +1,451 @@ +/*** +*getcwd.c - get current working directory (OS/2 version) +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +* contains functions _getcwd, _getdcwd and _getcdrv for getting the +* current working directory. getcwd gets the c.w.d. for the default disk +* drive, whereas _getdcwd allows one to get the c.w.d. for whatever disk +* drive is specified. _getcdrv gets the current drive. +* +*Revision History: +* 09-09-83 RKW created +* 05-??-84 DCW added conditional compilation to handle case of library +* where SS != DS (can't take address of a stack variable). +* 09-??-84 DCW changed comparison of path length to maxlen to take the +* terminating null character into account. +* 11-28-84 DCW changed to return errno values compatibly with the +* System 3 version. +* 05-19-86 SKS adapted for OS/2 +* 11-19-86 SKS if pnbuf==NULL, maxlen is ignored; +* eliminated use of intermediate buffer "buf[]"; added +* entry point "_getdcwd()" which takes a drive number. +* 12-03-86 SKS if pnbuf==NULL, maxlen is the minimum allocation size +* 02-05-87 BCM fixed comparison in _getdcwd, +* (unsigned)(len+3) > (int)(maxlen), to handle maxlen < 0, +* since implicit cast to (unsigned) was occurring. +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 12-21-87 WAJ Added _getcdrv() +* 06-22-88 WAJ _getcdrv() is now made for all OS/2 libs +* 10-03-88 JCR 386: Change DOS calls to SYS calls +* 10-04-88 JCR 386: Removed 'far' keyword +* 10-10-88 GJF Made API names match DOSCALLS.H +* 01-31-89 JCR Remove _getcdrv(), which has been renamed _getdrive() +* 04-12-89 JCR Use new OS/2 system calls +* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention +* 11-27-89 JCR Corrected ERRNO values +* 12-12-89 JCR Fixed bogus syscall introduced in previous fix (oops) +* 03-07-90 GJF Replaced _LOAD_DS by _CALLTYPE1, added #include +* <cruntime.h>, removed #include <register.h>, removed +* some leftover 16-bit support and fixed the copyright. +* Also, cleaned up the formatting a bit. +* 07-24-90 SBM Compiles cleanly with -W3 (removed unreferenced +* variable), removed redundant includes, removed +* '32' from API names +* 08-10-90 SBM Compiles cleanly with -W3 with new build of compiler +* 09-27-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-16-91 GJF ANSI naming. +* 08-21-91 JCR Test DOSQUERYCURRENTDIR call for error return (bug fix) +* 04-23-92 GJF Fixed initialization of DriveVar[]. +* 04-28-92 GJF Revised Win32 version. +* 12-13-93 GJF In _getdcwd(), was using local array to hold env +* string which was _putenv-ed. Ouch! +* +*******************************************************************************/ + +#include <cruntime.h> +#include <os2dll.h> +#include <msdos.h> +#include <errno.h> +#include <malloc.h> +#include <oscalls.h> +#include <stdlib.h> +#include <internal.h> +#include <direct.h> + + +#ifdef _CRUISER_ + +/*** +*char *_getcwd(pnbuf, maxlen) - get current working directory of default drive +* +*Purpose: +* _getcwd gets the current working directory for the user, +* placing it in the buffer pointed to by pnbuf. It returns +* the length of the string put in the buffer. If the length +* of the string exceeds the length of the buffer, maxlen, +* then NULL is returned. If pnbuf = NULL, maxlen is ignored. +* An entry point "_getdcwd()" is defined with takes the above +* parameters, plus a drive number. "_getcwd()" is implemented +* as a call to "_getcwd()" with the default drive (0). +* +* If pnbuf = NULL, maxlen is ignored, and a buffer is automatically +* allocated using malloc() -- a pointer to which is returned by +* _getcwd(). +* +* side effects: no global data is used or affected +* +*Entry: +* char *pnbuf = pointer to a buffer maintained by the user; +* int maxlen = length of the buffer pointed to by pnbuf; +* +*Exit: +* Returns pointer to the buffer containing the c.w.d. name +* (same as pnbuf if non-NULL; otherwise, malloc is +* used to allocate a buffer) +* +*Exceptions: +*******************************************************************************/ + +/* +** _getcwd() is just a call to _getdcwd() with the default drive +*/ + +char * _CALLTYPE1 _getcwd ( + char *pnbuf, + int maxlen + ) +{ + return(_getdcwd(0, pnbuf, maxlen)); +} + + +/*** +*char *_getdcwd(drive, pnbuf, maxlen) - get c.w.d. for given drive +* +*Purpose: +* _getdcwd gets the current working directory for the user, +* placing it in the buffer pointed to by pnbuf. It returns +* the length of the string put in the buffer. If the length +* of the string exceeds the length of the buffer, maxlen, +* then NULL is returned. If pnbuf = NULL, maxlen is ignored, +* and a buffer is automatically allocated using malloc() -- +* a pointer to which is returned by _getdcwd(). +* +* side effects: no global data is used or affected +* +*Entry: +* int drive - number of the drive being inquired about +* 0 = default, 1 = 'a:', 2 = 'b:', etc. +* char *pnbuf - pointer to a buffer maintained by the user; +* int maxlen - length of the buffer pointed to by pnbuf; +* +*Exit: +* Returns pointer to the buffer containing the c.w.d. name +* (same as pnbuf if non-NULL; otherwise, malloc is +* used to allocate a buffer) +* +*Exceptions: +* +*******************************************************************************/ + +char * _CALLTYPE1 _getdcwd ( + int drive, + char *pnbuf, + REG2 int maxlen + ) +{ + REG1 char *p; + char dirbuf[1]; + + unsigned len = 1; + unsigned oserr; + + /* + ** Get default drive if necessary + */ + if (drive == 0) + drive = _getdrive(); + + /* + ** Ask DOS the length of the current directory string + */ + + if ((oserr = DOSQUERYCURRENTDIR(drive,(char *)dirbuf,(unsigned *)&len)) + != ERROR_BUFFER_OVERFLOW) { + oserr_rtn: /* common error return */ + errno = EACCES; /* probably bogus drive */ + _doserrno = oserr; + return(NULL); + } + + /* see if need to try to allocate buffer in heap */ + + if (!(p = pnbuf)) { + if (((int)len+3) > maxlen) + maxlen = len+3; + if (!(p = malloc(maxlen))) { + errno = ENOMEM; + _doserrno = E_nomem; + return(p); + } + pnbuf = p; + } + + /* set up string - prepend drive letter + colon to the path name + */ + + *p++ = (char)(drive + 'A' - 1); /* drive specifier */ + *p++ = ':'; + *p++ = '\\'; + + /* check to make sure it all fits in the supplied (or created) buffer. + */ + + if ((int)len+3 > maxlen) { + errno = ERANGE; /* Won't fit in user buffer */ + return(NULL); + } + + /* get root relative path name + */ + + if (oserr = DOSQUERYCURRENTDIR(drive,(char *)p,(unsigned *)&len)) + goto oserr_rtn; /* join other DOSQUERYCURRENTDIRDIR error return */ + + return(p-3); + +} + + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + +/*** +*char *_getcwd(pnbuf, maxlen) - get current working directory of default drive +* +*Purpose: +* _getcwd gets the current working directory for the user, +* placing it in the buffer pointed to by pnbuf. It returns +* the length of the string put in the buffer. If the length +* of the string exceeds the length of the buffer, maxlen, +* then NULL is returned. If pnbuf = NULL, maxlen is ignored. +* An entry point "_getdcwd()" is defined with takes the above +* parameters, plus a drive number. "_getcwd()" is implemented +* as a call to "_getcwd()" with the default drive (0). +* +* If pnbuf = NULL, maxlen is ignored, and a buffer is automatically +* allocated using malloc() -- a pointer to which is returned by +* _getcwd(). +* +* side effects: no global data is used or affected +* +*Entry: +* char *pnbuf = pointer to a buffer maintained by the user; +* int maxlen = length of the buffer pointed to by pnbuf; +* +*Exit: +* Returns pointer to the buffer containing the c.w.d. name +* (same as pnbuf if non-NULL; otherwise, malloc is +* used to allocate a buffer) +* +*Exceptions: +* +*******************************************************************************/ + + +char * _CALLTYPE1 _getcwd ( + char *pnbuf, + int maxlen + ) +{ + char *retval; + + _mlock(_ENV_LOCK); + + retval = _getdcwd_lk(0, pnbuf, maxlen); + + _munlock(_ENV_LOCK); + + return retval; +} + + +/*** +*char *_getdcwd(drive, pnbuf, maxlen) - get c.w.d. for given drive +* +*Purpose: +* _getdcwd gets the current working directory for the user, +* placing it in the buffer pointed to by pnbuf. It returns +* the length of the string put in the buffer. If the length +* of the string exceeds the length of the buffer, maxlen, +* then NULL is returned. If pnbuf = NULL, maxlen is ignored, +* and a buffer is automatically allocated using malloc() -- +* a pointer to which is returned by _getdcwd(). +* +* side effects: no global data is used or affected +* +*Entry: +* int drive - number of the drive being inquired about +* 0 = default, 1 = 'a:', 2 = 'b:', etc. +* char *pnbuf - pointer to a buffer maintained by the user; +* int maxlen - length of the buffer pointed to by pnbuf; +* +*Exit: +* Returns pointer to the buffer containing the c.w.d. name +* (same as pnbuf if non-NULL; otherwise, malloc is +* used to allocate a buffer) +* +*Exceptions: +* +*******************************************************************************/ + + +#ifdef MTHREAD + +char * _CALLTYPE1 _getdcwd ( + int drive, + char *pnbuf, + int maxlen + ) +{ + char *retval; + + _mlock(_ENV_LOCK); + + retval = _getdcwd_lk(drive, pnbuf, maxlen); + + _munlock(_ENV_LOCK); + + return retval; +} + +char * _CALLTYPE1 _getdcwd_lk ( + int drive, + char *pnbuf, + int maxlen + ) +#else + +char * _CALLTYPE1 _getdcwd ( + int drive, + char *pnbuf, + int maxlen + ) +#endif + +{ + char *p; + char dirbuf[1]; + int len; + char DirOnDriveVar[4]; + char *envval; + + /* + * Only works for default drive in Win32 environment. + */ + if ( drive != 0 ) { + /* + * Not the default drive - make sure it's valid. + */ + if ( !_ValidDrive(drive) ) { + errno = EACCES; + return NULL; + } + + /* + * Get special environment variable that specifies the current + * directory on drive. + */ + DirOnDriveVar[0] = '='; + DirOnDriveVar[1] = (char)('A' + (char)drive - (char)1); + DirOnDriveVar[2] = ':'; + DirOnDriveVar[3] = '\0'; + + if ( (envval = _getenv_lk(DirOnDriveVar)) == NULL ) { + + /* + * Need to define the environment variable, allocate + * space from the heap to hold the string + */ + if ( (envval = malloc( 8 * sizeof(char) )) == NULL ) { + errno = ENOMEM; /* must be out of heap memory */ + return NULL; + } + + /* + * Environment variable not defined! Define it to be the + * root on that drive. + */ + envval[0] = envval[3] = '='; + envval[1] = envval[4] = (char)('A' + (char)drive + - (char)1); + envval[2] = envval[5] = ':'; + envval[6] = '\\'; + envval[7] = '\0'; + if ( _putenv_lk(envval) != 0 ) { + errno = ENOMEM; /* must be out of heap memory */ + return NULL; + } + envval += 4; + } + + len = strlen(envval) + 1; + + } else { + + /* + * Ask OS the length of the current directory string + */ + len = GetCurrentDirectory(sizeof(dirbuf), (LPSTR)dirbuf) + 1; + } + + /* + * Set up the buffer. + */ + if ( (p = pnbuf) == NULL ) { + /* + * Allocate a buffer for the user. + */ + if ( (p = malloc(__max(len, maxlen))) == NULL ) { + errno = ENOMEM; + return NULL; + } + } + else if ( len > maxlen ) { + /* + * Won't fit in the user-supplied buffer! + */ + errno = ERANGE; /* Won't fit in user buffer */ + return NULL; + } + + /* + * Place the current directory string into the user buffer + */ + + if ( drive != 0 ) + /* + * Copy value of special environment variable into user buffer. + */ + strcpy(p, envval); + else + /* + * Get the current directory directly from the OS + */ + if ( GetCurrentDirectory(len,p) == 0 ) { + /* + * Oops. For lack of a better idea, assume some sort + * of access error has occurred. + */ + errno = EACCES; + _doserrno = GetLastError(); + return NULL; + } + + return p; +} + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ |