diff options
Diffstat (limited to 'db/env/env_file.c')
-rw-r--r-- | db/env/env_file.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/db/env/env_file.c b/db/env/env_file.c new file mode 100644 index 000000000..c7b0fd2e0 --- /dev/null +++ b/db/env/env_file.c @@ -0,0 +1,166 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2002 + * Sleepycat Software. All rights reserved. + */ + +#include "db_config.h" + +#ifndef lint +static const char revid[] = "Id: env_file.c,v 1.5 2002/03/08 17:47:18 sue Exp "; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <string.h> +#endif + +#include "db_int.h" + +static int __db_overwrite_pass __P((DB_ENV *, + const char *, DB_FH *, u_int32_t, u_int32_t, u_int32_t)); + +/* + * __db_fileinit -- + * Initialize a regular file, optionally zero-filling it as well. + * + * PUBLIC: int __db_fileinit __P((DB_ENV *, DB_FH *, size_t, int)); + */ +int +__db_fileinit(dbenv, fhp, size, zerofill) + DB_ENV *dbenv; + DB_FH *fhp; + size_t size; + int zerofill; +{ + db_pgno_t pages; + size_t i; + size_t nw; + u_int32_t relative; + int ret; + char buf[OS_VMPAGESIZE]; + + /* Write nuls to the new bytes. */ + memset(buf, 0, sizeof(buf)); + + /* + * Extend the region by writing the last page. If the region is >4Gb, + * increment may be larger than the maximum possible seek "relative" + * argument, as it's an unsigned 32-bit value. Break the offset into + * pages of 1MB each so that we don't overflow (2^20 + 2^32 is bigger + * than any memory I expect to see for awhile). + */ + if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_END)) != 0) + return (ret); + pages = (db_pgno_t)((size - OS_VMPAGESIZE) / MEGABYTE); + relative = (u_int32_t)((size - OS_VMPAGESIZE) % MEGABYTE); + if ((ret = __os_seek(dbenv, + fhp, MEGABYTE, pages, relative, 0, DB_OS_SEEK_CUR)) != 0) + return (ret); + if ((ret = __os_write(dbenv, fhp, buf, sizeof(buf), &nw)) != 0) + return (ret); + + /* + * We may want to guarantee that there is enough disk space for the + * file, so we also write a byte to each page. We write the byte + * because reading it is insufficient on systems smart enough not to + * instantiate disk pages to satisfy a read (e.g., Solaris). + */ + if (zerofill) { + pages = (db_pgno_t)(size / MEGABYTE); + relative = (u_int32_t)(size % MEGABYTE); + if ((ret = __os_seek(dbenv, fhp, + MEGABYTE, pages, relative, 1, DB_OS_SEEK_END)) != 0) + return (ret); + + /* Write a byte to each page. */ + for (i = 0; i < size; i += OS_VMPAGESIZE) { + if ((ret = __os_write(dbenv, fhp, buf, 1, &nw)) != 0) + return (ret); + if ((ret = __os_seek(dbenv, fhp, + 0, 0, OS_VMPAGESIZE - 1, 0, DB_OS_SEEK_CUR)) != 0) + return (ret); + } + } + return (0); +} + +/* + * __db_overwrite -- + * Overwrite a file. + * + * PUBLIC: int __db_overwrite __P((DB_ENV *, const char *)); + */ +int +__db_overwrite(dbenv, path) + DB_ENV *dbenv; + const char *path; +{ + DB_FH fh, *fhp; + u_int32_t mbytes, bytes; + int ret; + + fhp = &fh; + if ((ret = __os_open(dbenv, path, DB_OSO_REGION, 0, fhp)) == 0 && + (ret = __os_ioinfo(dbenv, path, fhp, &mbytes, &bytes, NULL)) == 0) { + /* + * !!! + * Overwrite a regular file with alternating 0xff, 0x00 and 0xff + * byte patterns. Implies a fixed-block filesystem, journaling + * or logging filesystems will require operating system support. + */ + if ((ret = __db_overwrite_pass( + dbenv, path, fhp, mbytes, bytes, 0xff)) != 0) + goto err; + if ((ret = __db_overwrite_pass( + dbenv, path, fhp, mbytes, bytes, 0x00)) != 0) + goto err; + if ((ret = __db_overwrite_pass( + dbenv, path, fhp, mbytes, bytes, 0xff)) != 0) + goto err; + } else + __db_err(dbenv, "%s: %s", path, db_strerror(ret)); + +err: if (F_ISSET(fhp, DB_FH_VALID)) + __os_closehandle(dbenv, fhp); + return (ret); +} + +/* + * __db_overwrite_pass -- + * A single pass over the file, writing the specified byte pattern. + */ +static int +__db_overwrite_pass(dbenv, path, fhp, mbytes, bytes, pattern) + DB_ENV *dbenv; + const char *path; + DB_FH *fhp; + u_int32_t mbytes, bytes, pattern; +{ + size_t len, nw; + int i, ret; + char buf[8 * 1024]; + + if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0) + goto err; + + memset(buf, pattern, sizeof(buf)); + + for (; mbytes > 0; --mbytes) + for (i = MEGABYTE / sizeof(buf); i > 0; --i) + if ((ret = + __os_write(dbenv, fhp, buf, sizeof(buf), &nw)) != 0) + goto err; + for (; bytes > 0; bytes -= (u_int32_t)len) { + len = bytes < sizeof(buf) ? bytes : sizeof(buf); + if ((ret = __os_write(dbenv, fhp, buf, len, &nw)) != 0) + goto err; + } + + if ((ret = __os_fsync(dbenv, fhp)) != 0) +err: __db_err(dbenv, "%s: %s", path, db_strerror(ret)); + + return (ret); +} |