home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / getcwd.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  10KB  |  373 lines

  1. /***
  2. *getcwd.c - get current working directory
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *       contains functions _getcwd, _getdcwd and _getcdrv for getting the
  9. *       current working directory.  getcwd gets the c.w.d. for the default disk
  10. *       drive, whereas _getdcwd allows one to get the c.w.d. for whatever disk
  11. *       drive is specified. _getcdrv gets the current drive.
  12. *
  13. *******************************************************************************/
  14.  
  15. #ifndef _MAC
  16.  
  17. #include <cruntime.h>
  18. #include <mtdll.h>
  19. #include <msdos.h>
  20. #include <errno.h>
  21. #include <malloc.h>
  22. #include <oscalls.h>
  23. #include <stdlib.h>
  24. #include <internal.h>
  25. #include <direct.h>
  26. #include <tchar.h>
  27.  
  28.  
  29. /***
  30. *_TSCHAR *_getcwd(pnbuf, maxlen) - get current working directory of default drive
  31. *
  32. *Purpose:
  33. *       _getcwd gets the current working directory for the user,
  34. *       placing it in the buffer pointed to by pnbuf.  It returns
  35. *       the length of the string put in the buffer.  If the length
  36. *       of the string exceeds the length of the buffer, maxlen,
  37. *       then NULL is returned.  If pnbuf = NULL, maxlen is ignored.
  38. *       An entry point "_getdcwd()" is defined with takes the above
  39. *       parameters, plus a drive number.  "_getcwd()" is implemented
  40. *       as a call to "_getcwd()" with the default drive (0).
  41. *
  42. *       If pnbuf = NULL, maxlen is ignored, and a buffer is automatically
  43. *       allocated using malloc() -- a pointer to which is returned by
  44. *       _getcwd().
  45. *
  46. *       side effects: no global data is used or affected
  47. *
  48. *Entry:
  49. *       _TSCHAR *pnbuf = pointer to a buffer maintained by the user;
  50. *       int maxlen = length of the buffer pointed to by pnbuf;
  51. *
  52. *Exit:
  53. *       Returns pointer to the buffer containing the c.w.d. name
  54. *       (same as pnbuf if non-NULL; otherwise, malloc is
  55. *       used to allocate a buffer)
  56. *
  57. *Exceptions:
  58. *
  59. *******************************************************************************/
  60.  
  61. _TSCHAR * __cdecl _tgetcwd (
  62.         _TSCHAR *pnbuf,
  63.         int maxlen
  64.         )
  65. {
  66.         _TSCHAR *retval;
  67.  
  68.         _mlock(_ENV_LOCK);
  69.  
  70. #ifdef WPRFLAG
  71.         retval = _wgetdcwd_lk(0, pnbuf, maxlen);
  72. #else  /* WPRFLAG */
  73.         retval = _getdcwd_lk(0, pnbuf, maxlen);
  74. #endif  /* WPRFLAG */
  75.  
  76.         _munlock(_ENV_LOCK);
  77.  
  78.         return retval;
  79. }
  80.  
  81.  
  82. /***
  83. *_TSCHAR *_getdcwd(drive, pnbuf, maxlen) - get c.w.d. for given drive
  84. *
  85. *Purpose:
  86. *       _getdcwd gets the current working directory for the user,
  87. *       placing it in the buffer pointed to by pnbuf.  It returns
  88. *       the length of the string put in the buffer.  If the length
  89. *       of the string exceeds the length of the buffer, maxlen,
  90. *       then NULL is returned.  If pnbuf = NULL, maxlen is ignored,
  91. *       and a buffer is automatically allocated using malloc() --
  92. *       a pointer to which is returned by _getdcwd().
  93. *
  94. *       side effects: no global data is used or affected
  95. *
  96. *Entry:
  97. *       int drive   - number of the drive being inquired about
  98. *                     0 = default, 1 = 'a:', 2 = 'b:', etc.
  99. *       _TSCHAR *pnbuf - pointer to a buffer maintained by the user;
  100. *       int maxlen  - length of the buffer pointed to by pnbuf;
  101. *
  102. *Exit:
  103. *       Returns pointer to the buffer containing the c.w.d. name
  104. *       (same as pnbuf if non-NULL; otherwise, malloc is
  105. *       used to allocate a buffer)
  106. *
  107. *Exceptions:
  108. *
  109. *******************************************************************************/
  110.  
  111.  
  112. #ifdef _MT
  113.  
  114. _TSCHAR * __cdecl _tgetdcwd (
  115.         int drive,
  116.         _TSCHAR *pnbuf,
  117.         int maxlen
  118.         )
  119. {
  120.         _TSCHAR *retval;
  121.  
  122.         _mlock(_ENV_LOCK);
  123.  
  124. #ifdef WPRFLAG
  125.         retval = _wgetdcwd_lk(drive, pnbuf, maxlen);
  126. #else  /* WPRFLAG */
  127.         retval = _getdcwd_lk(drive, pnbuf, maxlen);
  128. #endif  /* WPRFLAG */
  129.  
  130.         _munlock(_ENV_LOCK);
  131.  
  132.         return retval;
  133. }
  134.  
  135. #ifdef WPRFLAG
  136. wchar_t * __cdecl _wgetdcwd_lk (
  137. #else  /* WPRFLAG */
  138. char * __cdecl _getdcwd_lk (
  139. #endif  /* WPRFLAG */
  140.         int drive,
  141.         _TSCHAR *pnbuf,
  142.         int maxlen
  143.         )
  144. #else  /* _MT */
  145.  
  146. _TSCHAR * __cdecl _tgetdcwd (
  147.         int drive,
  148.         _TSCHAR *pnbuf,
  149.         int maxlen
  150.         )
  151. #endif  /* _MT */
  152.  
  153. {
  154.         _TSCHAR *p;
  155.         _TSCHAR dirbuf[_MAX_PATH];
  156.         _TSCHAR drvstr[4];
  157.         int len;
  158.         _TSCHAR *pname; /* only used as argument to GetFullPathName */
  159.  
  160.         /*
  161.          * GetCurrentDirectory only works for the default drive in Win32
  162.          */
  163.         if ( drive != 0 ) {
  164.             /*
  165.              * Not the default drive - make sure it's valid.
  166.              */
  167.             if ( !_validdrive(drive) ) {
  168.                 _doserrno = ERROR_INVALID_DRIVE;
  169.                 errno = EACCES;
  170.                 return NULL;
  171.             }
  172.  
  173.             /*
  174.              * Get the current directory string on that drive and its length
  175.              */
  176.             drvstr[0] = _T('A') - 1 + drive;
  177.             drvstr[1] = _T(':');
  178.             drvstr[2] = _T('.');
  179.             drvstr[3] = _T('\0');
  180.             len = GetFullPathName( drvstr,
  181.                                    sizeof(dirbuf) / sizeof(_TSCHAR),
  182.                                    dirbuf,
  183.                                    &pname );
  184.  
  185.         } else {
  186.  
  187.             /*
  188.              * Get the current directory string and its length
  189.              */
  190.             len = GetCurrentDirectory( sizeof(dirbuf) / sizeof(_TSCHAR),
  191.                                        (LPTSTR)dirbuf );
  192.         }
  193.  
  194.         /* API call failed, or buffer not large enough */
  195.         if ( len == 0 || ++len > sizeof(dirbuf)/sizeof(_TSCHAR) )
  196.             return NULL;
  197.  
  198.         /*
  199.          * Set up the buffer.
  200.          */
  201.         if ( (p = pnbuf) == NULL ) {
  202.             /*
  203.              * Allocate a buffer for the user.
  204.              */
  205.             if ( (p = (_TSCHAR *)malloc(__max(len, maxlen) * sizeof(_TSCHAR)))
  206.                  == NULL )
  207.             {
  208.                 errno = ENOMEM;
  209.                 return NULL;
  210.             }
  211.         }
  212.         else if ( len > maxlen ) {
  213.             /*
  214.              * Won't fit in the user-supplied buffer!
  215.              */
  216.             errno = ERANGE; /* Won't fit in user buffer */
  217.             return NULL;
  218.         }
  219.  
  220.         /*
  221.          * Place the current directory string into the user buffer
  222.          */
  223.  
  224.         return _tcscpy(p, dirbuf);
  225. }
  226.  
  227. #ifndef WPRFLAG
  228.  
  229. /***
  230. *int _validdrive( unsigned drive ) -
  231. *
  232. *Purpose: returns non zero if drive is a valid drive number.
  233. *
  234. *Entry: drive = 0 => default drive, 1 => a:, 2 => b: ...
  235. *
  236. *Exit:  0 => drive does not exist.
  237. *
  238. *Exceptions:
  239. *
  240. *******************************************************************************/
  241.  
  242. int __cdecl _validdrive (
  243.     unsigned drive
  244.     )
  245. {
  246.         unsigned retcode;
  247.         char drvstr[4];
  248.  
  249.         if ( drive == 0 )
  250.             return 1;
  251.  
  252.         drvstr[0] = 'A' + drive - 1;
  253.         drvstr[1] = ':';
  254.         drvstr[2] = '\\';
  255.         drvstr[3] = '\0';
  256.  
  257.         if ( ((retcode = GetDriveType( drvstr )) == DRIVE_UNKNOWN) ||
  258.              (retcode == DRIVE_NO_ROOT_DIR) )
  259.             return 0;
  260.  
  261.         return 1;
  262. }
  263.  
  264. #endif  /* WPRFLAG */
  265.  
  266. #else  /* _MAC */
  267.  
  268. #include <cruntime.h>
  269. #include <errno.h>
  270. #include <malloc.h>
  271. #include <stdlib.h>
  272. #include <internal.h>
  273. #include <direct.h>
  274. #include <string.h>
  275. #include <macos\osutils.h>
  276. #include <macos\files.h>
  277. #include <macos\errors.h>
  278.  
  279. /***
  280. *char *_getcwd(pnbuf, maxlen) - get current working directory of default drive
  281. *
  282. *Purpose:
  283. *       _getcwd gets the current working directory for the user,
  284. *       placing it in the buffer pointed to by pnbuf.  It returns
  285. *       the length of the string put in the buffer.  If the length
  286. *       of the string exceeds the length of the buffer, maxlen,
  287. *       then NULL is returned.  If pnbuf = NULL, maxlen is ignored.
  288. *       An entry point "_getdcwd()" is defined with takes the above
  289. *       parameters, plus a drive number.  "_getcwd()" is implemented
  290. *       as a call to "_getcwd()" with the default drive (0).
  291. *
  292. *       If pnbuf = NULL, maxlen is ignored, and a buffer is automatically
  293. *       allocated using malloc() -- a pointer to which is returned by
  294. *       _getcwd().
  295. *
  296. *       side effects: no global data is used or affected
  297. *
  298. *Entry:
  299. *       char *pnbuf = pointer to a buffer maintained by the user;
  300. *       int maxlen = length of the buffer pointed to by pnbuf;
  301. *
  302. *Exit:
  303. *       Returns pointer to the buffer containing the c.w.d. name
  304. *       (same as pnbuf if non-NULL; otherwise, malloc is
  305. *       used to allocate a buffer)
  306. *
  307. *Exceptions:
  308. *******************************************************************************/
  309.  
  310. /*
  311. ** _getcwd() is just a call to _getdcwd() with the default drive
  312. */
  313.  
  314. char * __cdecl _getcwd (
  315.         char *pnbuf,
  316.         int maxlen
  317.         )
  318. {
  319.         OSErr osErr;
  320.         WDPBRec wdPB;
  321.         Str255 st;
  322.         int retval;
  323.         HParamBlockRec parm;
  324.  
  325.  
  326.         /* see if need to try to allocate buffer in heap */
  327.  
  328.         if (pnbuf == NULL) {
  329.             maxlen = 256;
  330.             if ((pnbuf = malloc(maxlen)) == NULL) {
  331.                 errno = ENOMEM;
  332.                 _macerrno = mFulErr;
  333.                 return NULL;
  334.             }
  335.         }
  336.  
  337.         /* see if the volume exist */
  338.         memset(&parm, 0, sizeof(HParamBlockRec));
  339.         osErr = PBHGetVolParmsSync(&parm);
  340.         if (osErr)
  341.         {
  342.             _dosmaperr(osErr);
  343.             *pnbuf = '\0';
  344.             return NULL;
  345.         }
  346.  
  347.  
  348.         /* get current/default volumne and directory string.
  349.          */
  350.  
  351.         memset(&wdPB, '\0', sizeof(WDPBRec));
  352.         wdPB.ioNamePtr = st;
  353.         osErr = PBHGetVolSync(&wdPB);
  354.         if (osErr)
  355.         {
  356.             _dosmaperr(osErr);
  357.             *pnbuf = '\0';
  358.             return NULL;
  359.         }
  360.  
  361.         retval = SzPathNameFromDirID(wdPB.ioWDDirID, pnbuf, maxlen);
  362.         if (!retval)
  363.         {
  364.             *pnbuf = '\0';
  365.             return NULL;
  366.         }
  367.  
  368.         return pnbuf;
  369.  
  370. }
  371.  
  372. #endif  /* _MAC */
  373.