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

  1. /***
  2. *chsize.c - change size of a file
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       contains the _chsize() function - changes the size of a file.
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <errno.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <dbgint.h>
  16. #include <fcntl.h>
  17. #include <msdos.h>
  18. #include <io.h>
  19. #include <string.h>
  20.  
  21. #ifndef _MAC
  22. #include <windows.h>
  23. #endif  /* _MAC */
  24.  
  25. #include <internal.h>
  26. #include <mtdll.h>
  27.  
  28. #ifdef _MAC
  29. #include <memory.h>
  30. #include <macos\errors.h>
  31. #include <macos\types.h>
  32. #include <macos\files.h>
  33. #endif  /* _MAC */
  34.  
  35. /***
  36. *int _chsize(filedes, size) - change size of a file
  37. *
  38. *Purpose:
  39. *       Change file size. Assume file is open for writing, or we can't do it.
  40. *       The DOS way to do this is to go to the right spot and write 0 bytes. The
  41. *       Xenix way to do this is to make a system call. We write '\0' bytes because
  42. *       DOS won't do this for you if you lseek beyond eof, though Xenix will.
  43. *
  44. *Entry:
  45. *       int filedes - file handle to change size of
  46. *       long size - new size of file
  47. *
  48. *Exit:
  49. *       return 0 if successful
  50. *       returns -1 and sets errno if fails
  51. *
  52. *Exceptions:
  53. *
  54. *******************************************************************************/
  55.  
  56. #ifdef _MT
  57.  
  58. /* define normal version that locks/unlocks, validates fh */
  59.  
  60. int __cdecl _chsize (
  61.         REG1 int filedes,
  62.         long size
  63.         )
  64. {
  65.         int r;                          /* return value */
  66.  
  67. #ifndef _MAC
  68.         if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
  69.              !(_osfile(filedes) & FOPEN) )
  70. #else  /* _MAC */
  71.         if ( filedes < 0 || filedes >= _nfile )
  72. #endif  /* _MAC */
  73.         {
  74.                 errno = EBADF;
  75.                 return(-1);
  76.         }
  77.         _lock_fh(filedes);
  78.         r = _chsize_lk(filedes,size);
  79.         _unlock_fh(filedes);
  80.  
  81.         return r;
  82. }
  83.  
  84. /* now define version that doesn't lock/unlock, validate fh */
  85. int __cdecl _chsize_lk (
  86.         REG1 int filedes,
  87.         long size
  88.         )
  89. {
  90.         long filend;
  91.         long extend;
  92.         long place;
  93.         int cnt;
  94.         char blanks[_INTERNAL_BUFSIZ];
  95.         REG2 char *bl = blanks;
  96.         int oldmode;
  97.         int retval = 0; /* assume good return */
  98.  
  99. #else  /* _MT */
  100.  
  101. /* now define normal version */
  102.  
  103. int __cdecl _chsize (
  104.         REG1 int filedes,
  105.         long size
  106.         )
  107. {
  108.         long filend;
  109.         long extend;
  110.         long place;
  111.         int cnt;
  112.         char blanks[_INTERNAL_BUFSIZ];
  113.         REG2 char *bl = blanks;
  114.         int oldmode;
  115.         int retval = 0; /* assume good return */
  116.  
  117. #ifndef _MAC
  118.         if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
  119.              !(_osfile(filedes) & FOPEN) )
  120. #else  /* _MAC */
  121.         if ( filedes < 0 || filedes >= _nfile )
  122. #endif  /* _MAC */
  123.         {
  124.             errno = EBADF;
  125.             return(-1);
  126.         }
  127.  
  128. #endif  /* _MT */
  129.         _ASSERTE(size >= 0);
  130.  
  131.         /* Get current file position and seek to end */
  132.         if ( ((place = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L) ||
  133.              ((filend = _lseek_lk(filedes, 0L, SEEK_END)) == -1L) )
  134.             return -1;
  135.  
  136.         extend = size - filend;
  137.  
  138.         /* Grow or shrink the file as necessary */
  139.  
  140.         if (extend > 0L) {
  141.  
  142.             /* extending the file */
  143.  
  144.             memset(bl, '\0', _INTERNAL_BUFSIZ);
  145.             oldmode = _setmode_lk(filedes, _O_BINARY);
  146.  
  147.             /* pad out with nulls */
  148.             do  {
  149.                 cnt = (extend >= (long)_INTERNAL_BUFSIZ ) ?
  150.                       _INTERNAL_BUFSIZ : (int)extend;
  151.                 if ( (cnt = _write_lk( filedes,
  152.                                        bl,
  153.                                        (extend >= (long)_INTERNAL_BUFSIZ) ?
  154.                                             _INTERNAL_BUFSIZ : (int)extend ))
  155.                      == -1 )
  156.                 {
  157. #ifndef _MAC
  158.                     /* Error on write */
  159.                     if (_doserrno == ERROR_ACCESS_DENIED)
  160.                         errno = EACCES;
  161. #endif  /* _MAC */
  162.                     retval = cnt;
  163.                     break;  /* leave write loop */
  164.                 }
  165.             }
  166.             while ((extend -= (long)cnt) > 0L);
  167.  
  168.             _setmode_lk(filedes, oldmode);
  169.             /* retval set correctly */
  170.         }
  171.  
  172.         else  if ( extend < 0L ) {
  173.             /* shortening the file */
  174.  
  175. #ifndef _MAC
  176.             /*
  177.              * Set file pointer to new eof...and truncate it there.
  178.              */
  179.             _lseek_lk(filedes, size, SEEK_SET);
  180.  
  181.             if ( (retval = SetEndOfFile((HANDLE)_get_osfhandle(filedes)) ?
  182.                  0 : -1) == -1 )
  183.             {
  184.                 errno = EACCES;
  185.                 _doserrno = GetLastError();
  186.             }
  187. #endif  /* _MAC */
  188.  
  189. #ifdef _MAC
  190.             {
  191.             ParamBlockRec parm;
  192.             OSErr osErr;
  193.  
  194.             parm.ioParam.ioRefNum = _osfhnd[filedes];
  195.             parm.ioParam.ioMisc = (char *)size;
  196.             osErr = PBSetEOFSync(&parm);
  197.             if (osErr)
  198.             {
  199.                 _dosmaperr(osErr);
  200.                 retval = -1;
  201.             }
  202.             else
  203.             {
  204.                 retval = 0;
  205.             }
  206.             }
  207. #endif  /* _MAC */
  208.  
  209.         }
  210.  
  211.         /* else */
  212.         /* no file change needed */
  213.         /* retval = 0; */
  214.  
  215.  
  216. /* Common return code */
  217.  
  218.         _lseek_lk(filedes, place, SEEK_SET);
  219.         return retval;
  220. }
  221.