📄 dtread.c
字号:
if ((size_t)count != size) { if (count == FAILURE) { report_error ("read", FALSE); ReportDeviceInfo (dip, 0, 0, (bool)(errno == EIO)); } else { /* * For reads at end of file or reads at end of block * devices, we'll read less than the requested count. * In this case, we'll treat this as a warning since * this is to be expected. In the case of tape, the * next read will indicate end of tape (in my driver). * * NOTE: The raw device should be used for disks. */ if ( (debug_flag || verbose_flag || ((size_t)count > size)) && (io_mode == TEST_MODE) /*&& (io_type == SEQUENTIAL_IO)*/ ) { Printf( "WARNING: Record #%lu, attempted to read %lu bytes, read only %lu bytes.\n", (dip->di_records_read + 1), size, count); } if ((size_t)count < size) { /* Partial read is a warning. */ warning_errors++; return (WARNING); } ReportDeviceInfo (dip, count, 0, FALSE); } (void)RecordError(); dip->di_read_errors++; status = FAILURE; } return (status);}/* * This function is envoked when reading multiple tape files, to * position past an expected file mark. This is especially important * when using the lbdata or iot options, since encountering an expected * EOF throws off the offset being maintained, resulting in an lba error. */intread_eof(struct dinfo *dip){ ssize_t count; size_t bsize = block_size; int status = SUCCESS; if (debug_flag) { Printf("Processing end of file... [file #%lu, record #%lu]\n", (dip->di_files_read + 1), (dip->di_records_read + 1)); } dip->di_eof_processing = TRUE; count = read_record (dip, data_buffer, bsize, bsize, &status); dip->di_eof_processing = FALSE; if (!end_of_file) { Fprintf("ERROR: File %lu, Record %lu, expected EOF was NOT detected!\n", (dip->di_files_read + 1), (dip->di_records_read + 1)); ReportDeviceInfo (dip, count, 0, FALSE); (void)RecordError(); dip->di_read_errors++; status = FAILURE; } return (status);}/* * This function is called after EOF is detected, to read the next record * which checks for reaching the end of logical tape (i.e. two successive * file marks). For multi-volume tapes, the user will be prompted for the * next volume via read_record(), and the end of file flag gets reset when * the tape is re-open'ed. */intread_eom(struct dinfo *dip){ ssize_t count; size_t bsize = block_size; int status = SUCCESS; if (debug_flag) { Printf("Processing end of media... [file #%lu, record #%lu]\n", (dip->di_files_read + 1), (dip->di_records_read + 1)); } dip->di_eom_processing = TRUE; count = read_record (dip, data_buffer, bsize, bsize, &status); dip->di_eom_processing = FALSE; if (multi_flag) { if (end_of_file) { Fprintf("ERROR: File %lu, Record %lu, expected EOM was NOT detected!\n", (dip->di_files_read + 1), (dip->di_records_read + 1)); ReportDeviceInfo (dip, count, 0, FALSE); (void)RecordError(); return (FAILURE); } } else if ( !dip->di_end_of_logical ) { Fprintf("ERROR: File %lu, Record %lu, expected EOM was NOT detected!\n", (dip->di_files_read + 1), (dip->di_records_read + 1)); ReportDeviceInfo (dip, count, 0, FALSE); (void)RecordError(); dip->di_read_errors++; return (FAILURE); } return (SUCCESS); /* We don't care about the read status! */}/************************************************************************ * * * read_record() - Read record from device or file. * * * * Inputs: dip = The device information pointer. * * buffer = The data buffer to read into. * * bsize = The number of bytes read. * * dsize = The users' requested size. * * status = Pointer to status variable. * * * * Outputs: status = SUCCESS/FAILURE/WARNING = Ok/Error/Warning * * Return value is number of bytes from read() request. * * * ************************************************************************/ssize_tread_record ( struct dinfo *dip, u_char *buffer, size_t bsize, size_t dsize, int *status ){ ssize_t count;retry: *status = SUCCESS; count = read (dip->di_fd, buffer, bsize);#if defined(EEI) if ( (count == FAILURE) && (dip->di_dtype->dt_dtype == DT_TAPE) ) { if ( (errno == EIO) && eei_resets) { if ( HandleTapeResets(dip) ) { goto retry; } } else if (eei_flag) { (void) get_eei_status(dip->di_fd, dip->di_mt); } }#endif /* defined(EEI) */ /* * Allow terminal reads to continue on end of file (eof). * [ NOTE: This allows reads with timeouts to continue. ] */ if ( count || (dip->di_dtype->dt_dtype != DT_TERMINAL) ) { if ( is_Eof (dip, count, status) ) { if (multi_flag && (!stdin_flag || (dip->di_ftype == OUTPUT_FILE)) ) { if ( (dip->di_dtype->dt_dtype == DT_TAPE) && !dip->di_end_of_logical ) { return (count); /* Expect two file marks @ EOM. */ } *status = HandleMultiVolume (dip); dip->di_offset = (off_t) 0; if ( !dip->di_eof_processing && !dip->di_eom_processing ) { if (*status == SUCCESS) goto retry; } } return (count); /* Stop reading at end of file. */ } } if ( dip->di_eof_processing || dip->di_eom_processing ) { return (count); } dip->di_end_of_file = FALSE; /* Reset saved end of file state. */ /* * If something was read, adjust counts and statistics. */ if (count > (ssize_t) 0) { dip->di_dbytes_read += count; dip->di_fbytes_read += count; dip->di_vbytes_read += count; if ((size_t)count == dsize) { records_processed++; } else { partial_records++; } } *status = check_read (dip, count, bsize); return (count);}/************************************************************************ * * * verify_record() - Verify record with selected output device/file. * * * * Inputs: dip = The device information pointer. * * buffer = The data buffer to compare. * * bsize = The number of bytes read. * * * * Outputs: Returns SUCCESS/FAILURE/WARNING = Ok/Error/Warning * * * ************************************************************************/intverify_record ( struct dinfo *dip, u_char *buffer, size_t bsize ){ struct dtfuncs *dtf = dip->di_funcs; ssize_t count; int status; u_int32 lba = lbdata_addr; /* * TODO: Re-write this using the verify buffer (when I have time). */ count = read_record (dip, pattern_buffer, bsize, bsize, &status); if ( (status == FAILURE) || end_of_file) return (status); /* * I realize this is real ugly, but I wanted to use existing code. */ patbuf_size = count; pattern_bufptr = pattern_buffer; pattern_bufend = pattern_buffer + count; status = (*dtf->tf_verify_data)(dip, buffer, count, pattern, &lba); /* TODO: Get this into read_record() where it belongs! */ dip->di_records_read++; return (status);}/************************************************************************ * * * FindCapacity() - Find capacity of a random access device. * * * * Inputs: dip = The device information pointer. * * * * Outputs: Fills in device capacity and data limit on success. * * * * Return Value: Returns SUCCESS/FAILURE/WARNING = Ok/Error/Warning * * * ************************************************************************/intFindCapacity (struct dinfo *dip){ u_int32 dsize = dip->di_dsize; off_t lba, max_seek = (MAX_SEEK - dsize); long adjust = ((250 * MBYTE_SIZE) / dsize); int attempts = 0; ssize_t count, last; u_char *buffer; int fd, saved_fd = NoFd, status = SUCCESS; bool temp_fd = FALSE; /* * Use the user specified capacity (if specified). */ if (user_capacity) { lba = (off_t)(user_capacity / dsize); goto set_capacity; } else if (dip->di_data_limit) { return (status); } if (debug_flag || Debug_flag || rDebugFlag) { Printf ("Attempting to calculate capacity via seek/read algorithm...\n"); } /* * If the device is open in write mode, open another * file descriptor for reading. */ if ( (dip->di_fd == NoFd) || (dip->di_mode == WRITE_MODE) ) { temp_fd = TRUE; saved_fd = dip->di_fd;#if defined(__WIN32__) if ( (fd = open (dip->di_dname, (O_RDONLY|O_BINARY))) < 0) {#else /* !defined(__WIN32__) */ if ( (fd = open (dip->di_dname, O_RDONLY)) < 0) {#endif /* defined(__WIN32__) */ report_error ("FindCapacity() open", FALSE); return (FAILURE); } dip->di_fd = fd; } buffer = (u_char *) malloc (dsize); if (buffer == NULL) return (FAILURE); /* * Algorthim: * There maybe a better may, but this works... */ lba = adjust; adjust /= 2; while (TRUE) { attempts++;#if defined(DEBUG) Printf("lba = " LUF ", adjust = %lu\n", lba, adjust);#endif /* * We cannot seek past the maximum allowable file position, * otherwise lseek() fails, and 'dt' exits. So, we must * limit seeks appropriately, and break out of this loop * if we hit the upper seek limit. */ if ( (off_t)(lba * dsize) < (off_t) 0 ) { lba = (max_seek / dsize); } (void) set_position (dip, (off_t)(lba * dsize)); if ( (count = read (dip->di_fd, buffer, dsize)) == (ssize_t)dsize) { if (lba == (off_t)(max_seek / dsize)) break; lba += adjust; if (adjust == 1) break;#if defined(SCO) || defined(HP_UX) || defined(AIX) } else if ( (count == 0) || ( (count < 0) && ((errno == ENOSPC) || (errno == ENXIO)) ) ) {#elif defined(BrokenEOF) } else if ( (count == 0) || ( (count < 0) && ((errno == ENOSPC) || (errno == EIO)) ) ) {#else /* !defined(SCO) */ } else if ( (count == 0) || ( (count < 0) && (errno == ENOSPC) ) ) {#endif /* defined(SCO) || defined(HP_UX) || defined(AIX) */ if (last) adjust /= 2; if (!adjust) adjust++; lba -= adjust; } else { report_error ("FindCapacity() read", FALSE); status = FAILURE; break; } last = count; } free (buffer); if (temp_fd) { (void) close (dip->di_fd); dip->di_fd = saved_fd; } else { (void) set_position (dip, (off_t) 0); } /* * If the read failed, set the lba to the last successful read, * and continue. Won't be perfect, but at least we can run. * Note: Workaround for problem seen on Linux w/ATAPI CD-ROM's. */ if (status == FAILURE) {#if 1#if defined(DEBUG) Printf("failed, last good lba was " LUF ", adjust was %ld\n", lba, adjust);#endif /* defined(DEBUG) */ lba -= adjust; exit_status = SUCCESS;#else return (status); /* Return the failure! */#endif }#if defined(DEBUG) Printf ("read attempts was %d, the max lba is " LUF "\n", attempts, lba);#endif /* defined(DEBUG) */set_capacity: dip->di_capacity = lba; dip->di_data_limit = (large_t)(lba * dsize); if (!record_limit) record_limit = INFINITY; if (data_limit == INFINITY) data_limit = dip->di_data_limit; /* * The proper data limit is necessary for random I/O processing. */ if ( (io_dir == REVERSE) || (io_type == RANDOM_IO) ) { if ( (rdata_limit == (large_t)0) || (rdata_limit > dip->di_data_limit) ) { rdata_limit = dip->di_data_limit; } if (debug_flag || Debug_flag || rDebugFlag || (status == FAILURE)) {/* TODO: Cleanup this mess! */#if !defined(__GNUC__) && defined(_NT_SOURCE) /* Avoid: error C2520: conversion from unsigned __int64 to double not implemented, use signed __int64 */ Printf ("Random data limit set to " LUF " bytes (%.3f Mbytes), " LUF " blocks.\n", rdata_limit, ((double)(slarge_t)rdata_limit/(double)MBYTE_SIZE), (rdata_limit / dsize));#else /* !defined(_NT_SOURCE) */ Printf ("Random data limit set to " LUF " bytes (%.3f Mbytes), " LUF " blocks.\n", rdata_limit, ((double)rdata_limit/(double)MBYTE_SIZE), (rdata_limit / dsize));#endif /* !defined(__GNUC__) && defined(_NT_SOURCE) */ } if (rdata_limit <= file_position) { LogMsg (efp, logLevelCrit, 0, "Please specify a random data limit > file position!\n"); exit (FATAL_ERROR); } } else if (debug_flag || Debug_flag || (status == FAILURE)) {#if !defined(__GNUC__) && defined(_NT_SOURCE) /* Avoid: error C2520: conversion from unsigned __int64 to double not implemented, use signed __int64 */ Printf ("Data limit set to " LUF " bytes (%.3f Mbytes), " LUF " blocks.\n", dip->di_data_limit, ((double)(slarge_t)dip->di_data_limit / (double)MBYTE_SIZE), (dip->di_data_limit / dsize));#else /* !defined(_NT_SOURCE) */ Printf ("Data limit set to " LUF " bytes (%.3f Mbytes), " LUF " blocks.\n", dip->di_data_limit, ((double)dip->di_data_limit/(double)MBYTE_SIZE), (dip->di_data_limit / dsize));#endif /* !defined(__GNUC__) && defined(_NT_SOURCE) */ if (file_position > dip->di_data_limit) { LogMsg (efp, logLevelCrit, 0, "Please specify a file position < media capacity!\n"); exit (FATAL_ERROR); } } return (SUCCESS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -