📄 dtwrite.c
字号:
/**************************************************************************** * * * COPYRIGHT (c) 1990 - 2004 * * This Software Provided * * By * * Robin's Nest Software Inc. * * * * Permission to use, copy, modify, distribute and sell this software and * * its documentation for any purpose and without fee is hereby granted, * * provided that the above copyright notice appear in all copies and that * * both that copyright notice and this permission notice appear in the * * supporting documentation, and that the name of the author not be used * * in advertising or publicity pertaining to distribution of the software * * without specific, written prior permission. * * * * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * * NO EVENT SHALL HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL * * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF * * THIS SOFTWARE. * * * ****************************************************************************//* * Module: dtwrite.c * Author: Robin T. Miller * * Description: * Write routines for generic data test program. */#include "dt.h"#if !defined(_QNX_SOURCE)# include <sys/file.h>#endif /* !defined(_QNX_SOURCE) *//* * Modification History: * * February 13th, 2004 by Robin Miller. * Factor in the file position when doing reverse I/O, to avoid * writing into that area (which is now deemed protected). * * November 17th, 2003 by Robin Miller. * Breakup output to stdout or stderr, rather than writing * all output to stderr. If output file is stdout ('-') or a log * file is specified, then all output reverts to stderr. * * September 27th, 2003 by Robin Miller. * Added support for AIX. * * June 25th, 2001 by Robin Miller. * Restructured code associated with Tru64 Unix EEI, so we obtain * the EEI status for all tape errors, not just EIO errors. * * February 24th, 2001 by Robin Miller. * Add conditionalization for QNX RTP (Neutrino). * * January 26th, 2001 by Robin Miller. * Added support for reverse writing. * * January 24th, 2001 by Robin Miller. * Add support for variable I/O requests sizes. * * January 14th, 2001 by Robin Miller. * Added support for multiple volumes option. * * December 30th, 2000 by Robin Miller. * Make changes to build using MKS/NuTCracker product. * * March 28th, 2000 by Robin Miller. * Modified calls to file position functions which now accept a * device information parameter. * * February 18th, 2000 by Robin Miller. * Fix a problem where the records written value was not updated * when the data limit was reached first. * * January 22nd, 2000 by Robin Miller. * Added support for Cygwin tape devices for Windows/NT. * * January 6th, 2000 by Robin Miller. * Added support for multi-volume media. * * January 1st, 2000 by Robin Miller. * Added read after write support. * * December 30th, 1999 by Robin Miller. * Modify call to do_random() to pass the transfer size. * Fix lbdata problem when using step option (wrong lba). * * July 22nd, 1999 by Robin Miller. * Added support for IOT (DJ's) test pattern. * * May 27, 1999 by Robin Miller. * Added support for micro-second delays. * * March 1, 1999 by Robin Miller. * For tapes when Debug is enabled, report the file number. * * January 18, 1999 by Robin Miller. * Modified logic in check_write() of partial record writes, so * these warnings can be turned off by "disable=verbose". This change * is also consistent with logic done in check_read(). * * December 21, 1998 by Robin Miller. * Add hooks to handle tape device resets (DUNIX specific). * * October 26, 1998 by Robin Miller. * When random I/O and lbdata options are both enabled, use the * file offset seeked to as the starting lbdata address. * * January 9, 1998 by Robin. * Don't initialize data buffer being written for "disable=compare" * which yields better performance. * * September 6, 1996 by Robin Miller. * Modified write_record() to properly check write errors!. * * February 28, 1996 by Robin Miller. * Added function for copying records to device or file. * Modified logic so write errors honor users' error limit. * * February 23, 1996 by Robin Miller. * Only report partial record warning for sequential I/O testing. * Random I/O can position us towards the end of media often, and * partial transfers are likely especially with large block sizes. * * July 15, 1995 by Robin Miller. * Fix end of media error handling (ENOSPC), and cleanup code. * * September 17, 1993 by Robin Miller. * Report record number on warning errors (for debug). * * September 4, 1993 by Robin Miller. * Moved memory mapped I/O logic to seperate module. * * Septemeber 1, 1993 by Robin Miller. * Add ability to write variable record sizes. * * August 31, 1993 by Robin Miller. * Rotate starting data buffer address through sizeof(long). * * August 27, 1993 by Robin MIller. * Added support for DEC OSF/1 POSIX Asynchronous I/O (AIO). * * August 18, 1992 by Robin Miller. * If "step=" option was specified, then seek that many bytes * before the next write request (for disks). * * September 11, 1992 by Robin Miller. * Ensure data limit specified by user is not exceeded, incase * the block size isn't modulo the data limit. * * September 5, 1992 by Robin Miller. * Initial port to QNX 4.1 Operating System. * * August 21, 1990 by Robin Miller. * Changed exit status so scripts can detect and handle errors * based on the exit code. If not success, fatal error, or end * of file/tape, the exit code is the error number (errno). * * August 7, 1990 by Robin Miller. * If "skip=n" option is specified, then skip that many records * before starting to write. The "skip=n" option skips records * by reading, while "seek=n" seeks past records (for disks). *//************************************************************************ * * * write_data() - Write specified data to the output file. * * * * Inputs: dip = The device information pointer. * * * * Outputs: Returns SUCCESS/FAILURE = Ok/Error. * * * ************************************************************************/intwrite_data (struct dinfo *dip){ register ssize_t count; register size_t bsize, dsize; int status = SUCCESS; u_int32 lba; /* * For variable length records, initialize to minimum record size. */ if (min_size) { dsize = min_size; } else { dsize = block_size; } if (dip->di_random_access) { if (io_dir == REVERSE) { (void)set_position(dip, (off_t)rdata_limit); } lba = get_lba(dip); dip->di_offset = get_position(dip); } else { lba = make_lbdata (dip, dip->di_offset); } /* * Now write the specifed number of records. */ while ( (error_count < error_limit) && (dip->di_fbytes_written < data_limit) && (dip->di_records_written < record_limit) ) { if (volumes_flag && (multi_volume >= volume_limit) && (dip->di_volume_records >= volume_records)) { break; } if (wdelay_count) { /* Optional write delay */ mySleep (wdelay_count); } /* * If data limit was specified, ensure we don't exceed it. */ if ( (dip->di_fbytes_written + dsize) > data_limit) { bsize = (size_t)(data_limit - dip->di_fbytes_written); } else { bsize = dsize; } if (io_dir == REVERSE) { bsize = MIN((dip->di_offset-file_position), bsize); dip->di_offset = set_position(dip, (off_t)(dip->di_offset - bsize)); } else if (io_type == RANDOM_IO) { dip->di_offset = do_random (dip, TRUE, bsize); } if (debug_flag && (bsize != dsize) && !variable_flag) { Printf ("Record #%lu, Writing a partial record of %lu bytes...\n", (dip->di_records_written + 1), bsize); } if (iot_pattern || lbdata_flag) { lba = make_lbdata (dip, (off_t)(dip->di_volume_bytes + dip->di_offset)); } /* * If requested, rotate the data buffer through ROTATE_SIZE * bytes to force various unaligned buffer accesses. */ if (rotate_flag) { data_buffer = (base_buffer + (rotate_offset++ % ROTATE_SIZE)); } /* * Initialize the data buffer with a pattern. */ if ((io_mode == TEST_MODE) && compare_flag) { if (iot_pattern) { lba = init_iotdata(bsize, lba, lbdata_size); } fill_buffer (data_buffer, bsize, pattern); } /* * Initialize the logical block data (if enabled). */ if (lbdata_flag && lbdata_size && !iot_pattern) { lba = init_lbdata (data_buffer, bsize, lba, lbdata_size); } if (Debug_flag) { u_int32 iolba = NO_LBA; if (dip->di_random_access) { iolba = (get_position(dip) / dip->di_dsize); } else if (lbdata_flag || iot_pattern) { iolba = make_lbdata (dip, (off_t)(dip->di_volume_bytes + dip->di_offset)); } report_record(dip, (dip->di_files_written + 1), (dip->di_records_written + 1), iolba, WRITE_MODE, data_buffer, bsize); } count = write_record (dip, data_buffer, bsize, dsize, &status); if (end_of_file) break; /* Stop writing at end of file. */ if ( (status == FAILURE) && (error_count >= error_limit) ) break; /* * If we had a partial transfer, perhaps due to an error, adjust * the logical block address in preparation for the next request. */ if (iot_pattern && ((size_t)count < bsize)) { size_t resid = (bsize - count); lba -= howmany(resid, lbdata_size); } if ( (count > (ssize_t) 0) && raw_flag) { status = write_verify(dip, data_buffer, count, dsize, dip->di_offset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -