/*****************************************************************************\
* $Id: fillfile.c 77 2006-02-15 01:00:42Z garlick $
*****************************************************************************
* Copyright (C) 2005 The Regents of the University of California.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Jim Garlick <garlick@llnl.gov>.
* UCRL-CODE-2003-006.
*
* This file is part of Scrub, a program for erasing disks.
* For details, see <http://www.llnl.gov/linux/scrub/>.
*
* Scrub is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* Scrub is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with Scrub; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
\*****************************************************************************/
#if defined(linux) || defined(sun) || defined(UNIXWARE) || defined(__hpux)
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
#endif
#if defined(_AIX)
#define _LARGE_FILES
#include <sys/mode.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fillfile.h"
#include "util.h"
extern char *prog;
static void
_fsync_if_file(int fd)
{
struct stat sb;
if (fstat(fd, &sb) < 0) {
fprintf(stderr, "%s: ", prog);
perror("fstat");
exit(1);
}
if (S_ISREG(sb.st_mode)) {
if (fsync(fd) < 0) {
fprintf(stderr, "%s: ", prog);
perror("fsync");
exit(1);
}
}
}
/* Fill file (can be regular or special file) with pattern in mem.
* Writes will use memsize blocks.
* If 'refill' is non-null, call it before each write (for random fill).
* If 'progress' is non-null, call it after each write (for progress meter).
* The number of bytes written is returned.
*/
off_t
fillfile(char *path, off_t filesize, unsigned char *mem, int memsize,
progress_t progress, void *arg, refill_t refill)
{
int fd;
off_t n;
off_t res = 0LL;
fd = open(path, O_WRONLY);
if (fd < 0) {
fprintf(stderr, "%s: open ", prog);
perror(path);
exit(1);
}
do {
if (refill)
refill(mem, memsize);
if (res + memsize > filesize)
memsize = filesize - res;
n = write_all(fd, mem, memsize);
if (n < 0) {
fprintf(stderr, "%s: write ", prog);
perror(path);
exit(1);
}
res += n;
if (progress)
progress(arg, (double)res/filesize);
} while (res < filesize);
_fsync_if_file(fd);
if (close(fd) < 0) {
fprintf(stderr, "%s: close ", prog);
perror(path);
exit(1);
}
return res;
}
/* Verify that file was filled with 'mem' patterns.
*/
off_t
checkfile(char *path, off_t filesize, unsigned char *mem, int memsize,
progress_t progress, void *arg)
{
int fd;
off_t n;
off_t res = 0LL;
unsigned char *buf;
buf = malloc(memsize);
if (!buf) {
fprintf(stderr, "out of memory\n");
exit(1);
}
fd = open(path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "%s: open ", prog);
perror(path);
exit(1);
}
do {
if (res + memsize > filesize)
memsize = filesize - res;
n = read_all(fd, buf, memsize);
if (n < 0) {
fprintf(stderr, "%s: read ", prog);
perror(path);
exit(1);
}
if (n == 0) {
fprintf(stderr, "%s: premature EOF on %s\n", prog, path);
exit(1);
}
if (memcmp(mem, buf, memsize) != 0) {
fprintf(stderr, "%s: verification failure on %s\n", prog, path);
exit(1);
}
res += n;
if (progress)
progress(arg, (double)res/filesize);
} while (res < filesize);
if (close(fd) < 0) {
fprintf(stderr, "%s: close ", prog);
perror(path);
exit(1);
}
free(buf);
return res;
}
/* Create file and fill it with pattern in mem until the file system is full.
* Writes will use memsize blocks.
* The number of bytes written is returned.
*/
off_t
growfile(char *path, unsigned char *mem, int memsize, refill_t refill)
{
int fd;
off_t n;
off_t res = 0LL;
fd = open(path, O_WRONLY | O_CREAT, 0644);
if (fd < 0) {
fprintf(stderr, "%s: open ", prog);
perror(path);
exit(1);
}
do {
if (refill)
refill(mem, memsize);
n = write_all(fd, mem, memsize);
if (n < 0 && errno == ENOSPC && memsize > 1) {
memsize = 1;
continue;
}
if (n < 0 && errno != ENOSPC) {
fprintf(stderr, "%s: write ", prog);
perror(path);
exit(1);
}
if (n == 0) {
fprintf(stderr, "%s: write to %s returned 0, aborting\n",
prog, path);
exit(1);
}
if (n > 0)
res += n;
} while (n > 0);
_fsync_if_file(fd);
if (close(fd) < 0) {
fprintf(stderr, "%s: close ", prog);
perror(path);
exit(1);
}
return res;
}
/*
* vi:tabstop=4 shiftwidth=4 expandtab
*/
syntax highlighted by Code2HTML, v. 0.9.1