Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

os_truncate.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2004-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: os_truncate.c,v 12.4 2005/10/12 17:57:33 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #include "db_int.h"
00013 
00014 /*
00015  * __os_truncate --
00016  *      Truncate the file.
00017  */
00018 int
00019 __os_truncate(dbenv, fhp, pgno, pgsize)
00020         DB_ENV *dbenv;
00021         DB_FH *fhp;
00022         db_pgno_t pgno;
00023         u_int32_t pgsize;
00024 {
00025         /* Yes, this really is how Microsoft have designed their API */
00026         union {
00027                 __int64 bigint;
00028                 struct {
00029                         unsigned long low;
00030                         long high;
00031                 };
00032         } off;
00033         off_t offset;
00034         HANDLE dup_handle;
00035         int ret;
00036 
00037         ret = 0;
00038         offset = (off_t)pgsize * pgno;
00039 
00040         if (DB_GLOBAL(j_ftruncate) != NULL) {
00041                 ret = DB_GLOBAL(j_ftruncate)(fhp->fd, offset);
00042                 goto done;
00043         }
00044 
00045 #ifdef HAVE_FILESYSTEM_NOTZERO
00046         /*
00047          * If the filesystem doesn't zero fill, it isn't safe to extend the
00048          * file, or we end up with junk blocks.  Just return in that case.
00049          */
00050         if (__os_fs_notzero()) {
00051                 off_t stat_offset;
00052                 u_int32_t mbytes, bytes;
00053 
00054                 /* Stat the file. */
00055                 if ((ret =
00056                     __os_ioinfo(dbenv, NULL, fhp, &mbytes, &bytes, NULL)) != 0)
00057                         return (ret);
00058                 stat_offset = (off_t)mbytes * MEGABYTE + bytes;
00059 
00060                 if (offset > stat_offset)
00061                         return (0);
00062         }
00063 #endif
00064 
00065         /*
00066          * Windows doesn't provide truncate directly.  Instead, it has
00067          * SetEndOfFile, which truncates to the current position.  To
00068          * deal with that, we first duplicate the file handle, then
00069          * seek and set the end of file.  This is necessary to avoid
00070          * races with {Read,Write}File in other threads.
00071          */
00072         if (!DuplicateHandle(GetCurrentProcess(), fhp->handle,
00073             GetCurrentProcess(), &dup_handle, 0, FALSE,
00074             DUPLICATE_SAME_ACCESS)) {
00075                 ret = __os_get_errno();
00076                 goto done;
00077         }
00078 
00079         off.bigint = (__int64)pgsize * pgno;
00080         RETRY_CHK((SetFilePointer(dup_handle,
00081             off.low, &off.high, FILE_BEGIN) == INVALID_SET_FILE_POINTER &&
00082             GetLastError() != NO_ERROR) ||
00083             !SetEndOfFile(dup_handle), ret);
00084 
00085         if (!CloseHandle(dup_handle) && ret == 0)
00086                 ret = __os_get_errno();
00087 
00088 done:   if (ret != 0)
00089                 __db_err(dbenv,
00090                     "ftruncate: %lu: %s", pgno * pgsize, strerror(ret));
00091 
00092         return (ret);
00093 }

Generated on Sun Dec 25 12:14:42 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2