summaryrefslogtreecommitdiffstats
path: root/private/crt32/dos/getcwd.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/dos/getcwd.c
downloadNT4.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.c451
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_ */