write_log.c revision 15226cdbc46b1a13023484bd304b13aa47d42b87
1b973f2b91343554586da3c952c63c2369acd879whr/* 2b973f2b91343554586da3c952c63c2369acd879whr * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3b973f2b91343554586da3c952c63c2369acd879whr * 4b973f2b91343554586da3c952c63c2369acd879whr * This program is free software; you can redistribute it and/or modify it 5b973f2b91343554586da3c952c63c2369acd879whr * under the terms of version 2 of the GNU General Public License as 6b973f2b91343554586da3c952c63c2369acd879whr * published by the Free Software Foundation. 7b973f2b91343554586da3c952c63c2369acd879whr * 8b973f2b91343554586da3c952c63c2369acd879whr * This program is distributed in the hope that it would be useful, but 9b973f2b91343554586da3c952c63c2369acd879whr * WITHOUT ANY WARRANTY; without even the implied warranty of 10b973f2b91343554586da3c952c63c2369acd879whr * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11b973f2b91343554586da3c952c63c2369acd879whr * 12b973f2b91343554586da3c952c63c2369acd879whr * Further, this software is distributed without any warranty that it is 13b973f2b91343554586da3c952c63c2369acd879whr * free of the rightful claim of any third person regarding infringement 14b973f2b91343554586da3c952c63c2369acd879whr * or the like. Any license provided herein, whether implied or 15b973f2b91343554586da3c952c63c2369acd879whr * otherwise, applies only to this software file. Patent licenses, if 16b973f2b91343554586da3c952c63c2369acd879whr * any, provided herein do not apply to combinations of this program with 17b973f2b91343554586da3c952c63c2369acd879whr * other software, or any other product whatsoever. 18b973f2b91343554586da3c952c63c2369acd879whr * 19b973f2b91343554586da3c952c63c2369acd879whr * You should have received a copy of the GNU General Public License along 20b973f2b91343554586da3c952c63c2369acd879whr * with this program; if not, write the Free Software Foundation, Inc., 59 21b973f2b91343554586da3c952c63c2369acd879whr * Temple Place - Suite 330, Boston MA 02111-1307, USA. 22b973f2b91343554586da3c952c63c2369acd879whr * 23b973f2b91343554586da3c952c63c2369acd879whr * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24b973f2b91343554586da3c952c63c2369acd879whr * Mountain View, CA 94043, or: 25b973f2b91343554586da3c952c63c2369acd879whr * 26b973f2b91343554586da3c952c63c2369acd879whr * http://www.sgi.com 27b973f2b91343554586da3c952c63c2369acd879whr * 28b973f2b91343554586da3c952c63c2369acd879whr * For further information regarding this notice, see: 29b973f2b91343554586da3c952c63c2369acd879whr * 30b973f2b91343554586da3c952c63c2369acd879whr * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ 31b973f2b91343554586da3c952c63c2369acd879whr */ 32b973f2b91343554586da3c952c63c2369acd879whr/* 33b973f2b91343554586da3c952c63c2369acd879whr * This module contains code for logging writes to files, and for 34b973f2b91343554586da3c952c63c2369acd879whr * perusing the resultant logfile. The main intent of all this is 35b973f2b91343554586da3c952c63c2369acd879whr * to provide a 'write history' of a file which can be examined to 36b973f2b91343554586da3c952c63c2369acd879whr * judge the state of a file (ie. whether it is corrupted or not) based 37b973f2b91343554586da3c952c63c2369acd879whr * on the write activity. 38b973f2b91343554586da3c952c63c2369acd879whr * 39b973f2b91343554586da3c952c63c2369acd879whr * The main abstractions available to the user are the wlog_file, and 40b973f2b91343554586da3c952c63c2369acd879whr * the wlog_rec. A wlog_file is a handle encapsulating a write logfile. 41b973f2b91343554586da3c952c63c2369acd879whr * It is initialized with the wlog_open() function. This handle is 42b973f2b91343554586da3c952c63c2369acd879whr * then passed to the various wlog_xxx() functions to provide transparent 43b973f2b91343554586da3c952c63c2369acd879whr * access to the write logfile. 44b973f2b91343554586da3c952c63c2369acd879whr * 45b973f2b91343554586da3c952c63c2369acd879whr * The wlog_rec datatype is a structure which contains all the information 46b973f2b91343554586da3c952c63c2369acd879whr * about a file write. Examples include the file name, offset, length, 47b973f2b91343554586da3c952c63c2369acd879whr * pattern, etc. In addition there is a bit which is cleared/set based 48b973f2b91343554586da3c952c63c2369acd879whr * on whether or not the write has been confirmed as complete. This 49b973f2b91343554586da3c952c63c2369acd879whr * allows the write logfile to contain information on writes which have 50b973f2b91343554586da3c952c63c2369acd879whr * been initiated, but not yet completed (as in async io). 51b973f2b91343554586da3c952c63c2369acd879whr * 52b973f2b91343554586da3c952c63c2369acd879whr * There is also a function to scan a write logfile in reverse order. 53b973f2b91343554586da3c952c63c2369acd879whr * 54b973f2b91343554586da3c952c63c2369acd879whr * NOTE: For target file analysis based on a write logfile, the 55b973f2b91343554586da3c952c63c2369acd879whr * assumption is made that the file being written to is 56b973f2b91343554586da3c952c63c2369acd879whr * locked from simultaneous access, so that the order of 57b973f2b91343554586da3c952c63c2369acd879whr * write completion is predictable. This is an issue when 58b973f2b91343554586da3c952c63c2369acd879whr * more than 1 process is trying to write data to the same 59b973f2b91343554586da3c952c63c2369acd879whr * target file simultaneously. 60b973f2b91343554586da3c952c63c2369acd879whr * 61b973f2b91343554586da3c952c63c2369acd879whr * The history file created is a collection of variable length records 62b973f2b91343554586da3c952c63c2369acd879whr * described by scruct wlog_rec_disk in write_log.h. See that module for 63b973f2b91343554586da3c952c63c2369acd879whr * the layout of the data on disk. 64b973f2b91343554586da3c952c63c2369acd879whr */ 65b973f2b91343554586da3c952c63c2369acd879whr 66b973f2b91343554586da3c952c63c2369acd879whr#include <stdio.h> 67b973f2b91343554586da3c952c63c2369acd879whr#include <unistd.h> 68b973f2b91343554586da3c952c63c2369acd879whr#include <fcntl.h> 69b973f2b91343554586da3c952c63c2369acd879whr#include <errno.h> 70b973f2b91343554586da3c952c63c2369acd879whr#include <string.h> 71b973f2b91343554586da3c952c63c2369acd879whr#include <sys/param.h> 72b973f2b91343554586da3c952c63c2369acd879whr#include <sys/stat.h> 73b973f2b91343554586da3c952c63c2369acd879whr#include <sys/types.h> 74b973f2b91343554586da3c952c63c2369acd879whr#include "write_log.h" 75b973f2b91343554586da3c952c63c2369acd879whr 76b973f2b91343554586da3c952c63c2369acd879whr#ifndef BSIZE 77b973f2b91343554586da3c952c63c2369acd879whr#ifdef linux 78b973f2b91343554586da3c952c63c2369acd879whr#define BSIZE DEV_BSIZE 79b973f2b91343554586da3c952c63c2369acd879whr#else 80b973f2b91343554586da3c952c63c2369acd879whr#define BSIZE BBSIZE 81b973f2b91343554586da3c952c63c2369acd879whr#endif 82b973f2b91343554586da3c952c63c2369acd879whr#endif 83b973f2b91343554586da3c952c63c2369acd879whr 84b973f2b91343554586da3c952c63c2369acd879whr#ifndef PATH_MAX 85b973f2b91343554586da3c952c63c2369acd879whr#define PATH_MAX 255 86b973f2b91343554586da3c952c63c2369acd879whr/*#define PATH_MAX pathconf("/", _PC_PATH_MAX)*/ 87b973f2b91343554586da3c952c63c2369acd879whr#endif 88b973f2b91343554586da3c952c63c2369acd879whr 89b973f2b91343554586da3c952c63c2369acd879whrchar Wlog_Error_String[256]; 90b973f2b91343554586da3c952c63c2369acd879whr 91b973f2b91343554586da3c952c63c2369acd879whr#if __STDC__ 92b973f2b91343554586da3c952c63c2369acd879whrstatic int wlog_rec_pack(struct wlog_rec *wrec, char *buf, int flag); 93b973f2b91343554586da3c952c63c2369acd879whrstatic int wlog_rec_unpack(struct wlog_rec *wrec, char *buf); 94b973f2b91343554586da3c952c63c2369acd879whr#else 95b973f2b91343554586da3c952c63c2369acd879whrstatic int wlog_rec_pack(); 96b973f2b91343554586da3c952c63c2369acd879whrstatic int wlog_rec_unpack(); 97b973f2b91343554586da3c952c63c2369acd879whr#endif 98b973f2b91343554586da3c952c63c2369acd879whr 99b973f2b91343554586da3c952c63c2369acd879whr/* 100b973f2b91343554586da3c952c63c2369acd879whr * Initialize a write logfile. wfile is a wlog_file structure that has 101b973f2b91343554586da3c952c63c2369acd879whr * the w_file field filled in. The rest of the information in the 102b973f2b91343554586da3c952c63c2369acd879whr * structure is initialized by the routine. 103b973f2b91343554586da3c952c63c2369acd879whr * 104b973f2b91343554586da3c952c63c2369acd879whr * The trunc flag is used to indicate whether or not the logfile should 105b973f2b91343554586da3c952c63c2369acd879whr * be truncated if it currently exists. If it is non-zero, the file will 106b973f2b91343554586da3c952c63c2369acd879whr * be truncated, otherwise it will be appended to. 107b973f2b91343554586da3c952c63c2369acd879whr * 108b973f2b91343554586da3c952c63c2369acd879whr * The mode argument is the [absolute] mode which the file will be 109b973f2b91343554586da3c952c63c2369acd879whr * given if it does not exist. This mode is not affected by your process 110b973f2b91343554586da3c952c63c2369acd879whr * umask. 111b973f2b91343554586da3c952c63c2369acd879whr */ 112b973f2b91343554586da3c952c63c2369acd879whr 113b973f2b91343554586da3c952c63c2369acd879whrint 114b973f2b91343554586da3c952c63c2369acd879whrwlog_open(wfile, trunc, mode) 115b973f2b91343554586da3c952c63c2369acd879whrstruct wlog_file *wfile; 116b973f2b91343554586da3c952c63c2369acd879whrint trunc; 117b973f2b91343554586da3c952c63c2369acd879whrint mode; 118b973f2b91343554586da3c952c63c2369acd879whr{ 119b973f2b91343554586da3c952c63c2369acd879whr int omask, oflags; 120b973f2b91343554586da3c952c63c2369acd879whr 121b973f2b91343554586da3c952c63c2369acd879whr if (trunc) 122b973f2b91343554586da3c952c63c2369acd879whr trunc = O_TRUNC; 123b973f2b91343554586da3c952c63c2369acd879whr 124b973f2b91343554586da3c952c63c2369acd879whr omask = umask(0); 125b973f2b91343554586da3c952c63c2369acd879whr 126b973f2b91343554586da3c952c63c2369acd879whr /* 127b973f2b91343554586da3c952c63c2369acd879whr * Open 1 file descriptor as O_APPEND 128b973f2b91343554586da3c952c63c2369acd879whr */ 129b973f2b91343554586da3c952c63c2369acd879whr 130b973f2b91343554586da3c952c63c2369acd879whr oflags = O_WRONLY | O_APPEND | O_CREAT | trunc; 131b973f2b91343554586da3c952c63c2369acd879whr wfile->w_afd = 132b973f2b91343554586da3c952c63c2369acd879whr open(wfile->w_file, oflags, mode); 133b973f2b91343554586da3c952c63c2369acd879whr umask(omask); 134b973f2b91343554586da3c952c63c2369acd879whr 135b973f2b91343554586da3c952c63c2369acd879whr if (wfile->w_afd == -1) { 136b973f2b91343554586da3c952c63c2369acd879whr sprintf(Wlog_Error_String, 137b973f2b91343554586da3c952c63c2369acd879whr "Could not open write_log - open(%s, %#o, %#o) failed: %s\n", 1389418108733276af88b5458a866b6cd9a90e9232anstraz wfile->w_file, oflags, mode, strerror(errno)); 139b973f2b91343554586da3c952c63c2369acd879whr return -1; 140b973f2b91343554586da3c952c63c2369acd879whr } 141b973f2b91343554586da3c952c63c2369acd879whr 142b973f2b91343554586da3c952c63c2369acd879whr /* 143b973f2b91343554586da3c952c63c2369acd879whr * Open the next fd as a random access descriptor 144b973f2b91343554586da3c952c63c2369acd879whr */ 145b973f2b91343554586da3c952c63c2369acd879whr 146b973f2b91343554586da3c952c63c2369acd879whr oflags = O_RDWR; 147b973f2b91343554586da3c952c63c2369acd879whr if ((wfile->w_rfd = open(wfile->w_file, oflags)) == -1) { 148b973f2b91343554586da3c952c63c2369acd879whr sprintf(Wlog_Error_String, 149b973f2b91343554586da3c952c63c2369acd879whr "Could not open write log - open(%s, %#o) failed: %s\n", 1509418108733276af88b5458a866b6cd9a90e9232anstraz wfile->w_file, oflags, strerror(errno)); 151b973f2b91343554586da3c952c63c2369acd879whr close(wfile->w_afd); 152b973f2b91343554586da3c952c63c2369acd879whr wfile->w_afd = -1; 153b973f2b91343554586da3c952c63c2369acd879whr return -1; 154b973f2b91343554586da3c952c63c2369acd879whr } 155b973f2b91343554586da3c952c63c2369acd879whr 156b973f2b91343554586da3c952c63c2369acd879whr return 0; 157b973f2b91343554586da3c952c63c2369acd879whr} 158b973f2b91343554586da3c952c63c2369acd879whr 159b973f2b91343554586da3c952c63c2369acd879whr/* 160b973f2b91343554586da3c952c63c2369acd879whr * Release all resources associated with a wlog_file structure allocated 161b973f2b91343554586da3c952c63c2369acd879whr * with the wlog_open() call. 162b973f2b91343554586da3c952c63c2369acd879whr */ 163b973f2b91343554586da3c952c63c2369acd879whr 164b973f2b91343554586da3c952c63c2369acd879whrint 165b973f2b91343554586da3c952c63c2369acd879whrwlog_close(wfile) 166b973f2b91343554586da3c952c63c2369acd879whrstruct wlog_file *wfile; 167b973f2b91343554586da3c952c63c2369acd879whr{ 168b973f2b91343554586da3c952c63c2369acd879whr close(wfile->w_afd); 169b973f2b91343554586da3c952c63c2369acd879whr close(wfile->w_rfd); 170b973f2b91343554586da3c952c63c2369acd879whr return 0; 171b973f2b91343554586da3c952c63c2369acd879whr} 172b973f2b91343554586da3c952c63c2369acd879whr 173b973f2b91343554586da3c952c63c2369acd879whr/* 174b973f2b91343554586da3c952c63c2369acd879whr * Write a wlog_rec structure to a write logfile. Offset is used to 175b973f2b91343554586da3c952c63c2369acd879whr * control where the record will be written. If offset is < 0, the 176b973f2b91343554586da3c952c63c2369acd879whr * record will be appended to the end of the logfile. Otherwise, the 177b973f2b91343554586da3c952c63c2369acd879whr * record which exists at the indicated offset will be overlayed. This 178b973f2b91343554586da3c952c63c2369acd879whr * is so that we can record writes which are outstanding (with the w_done 179b973f2b91343554586da3c952c63c2369acd879whr * bit in wrec cleared), but not completed, and then later update the 180b973f2b91343554586da3c952c63c2369acd879whr * logfile when the write request completes (as with async io). When 181b973f2b91343554586da3c952c63c2369acd879whr * offset is >= 0, only the fixed length portion of the record is 182b973f2b91343554586da3c952c63c2369acd879whr * rewritten. See text in write_log.h for details on the format of an 183b973f2b91343554586da3c952c63c2369acd879whr * on-disk record. 184b973f2b91343554586da3c952c63c2369acd879whr * 185b973f2b91343554586da3c952c63c2369acd879whr * The return value of the function is the byte offset in the logfile 186b973f2b91343554586da3c952c63c2369acd879whr * where the record begins. 187b973f2b91343554586da3c952c63c2369acd879whr * 188b973f2b91343554586da3c952c63c2369acd879whr * Note: It is the callers responsibility to make sure that the offset 189b973f2b91343554586da3c952c63c2369acd879whr * parameter 'points' to a valid record location when a record is to be 190b973f2b91343554586da3c952c63c2369acd879whr * overlayed. This is guarenteed by saving the return value of a previous 191b973f2b91343554586da3c952c63c2369acd879whr * call to wlog_record_write() which wrote the record to be overlayed. 192b973f2b91343554586da3c952c63c2369acd879whr * 193b973f2b91343554586da3c952c63c2369acd879whr * Note2: The on-disk version of the wlog_rec is MUCH different than 194b973f2b91343554586da3c952c63c2369acd879whr * the user version. Don't expect to od the logfile and see data formatted 195b973f2b91343554586da3c952c63c2369acd879whr * as it is in the wlog_rec structure. Considerable data packing takes 196b973f2b91343554586da3c952c63c2369acd879whr * place before the record is written. 197b973f2b91343554586da3c952c63c2369acd879whr */ 198b973f2b91343554586da3c952c63c2369acd879whr 199b973f2b91343554586da3c952c63c2369acd879whrint 200b973f2b91343554586da3c952c63c2369acd879whrwlog_record_write(wfile, wrec, offset) 201b973f2b91343554586da3c952c63c2369acd879whrstruct wlog_file *wfile; 202b973f2b91343554586da3c952c63c2369acd879whrstruct wlog_rec *wrec; 203b973f2b91343554586da3c952c63c2369acd879whrlong offset; 204b973f2b91343554586da3c952c63c2369acd879whr{ 205b973f2b91343554586da3c952c63c2369acd879whr int reclen; 206b973f2b91343554586da3c952c63c2369acd879whr char wbuf[WLOG_REC_MAX_SIZE + 2]; 207b973f2b91343554586da3c952c63c2369acd879whr 208b973f2b91343554586da3c952c63c2369acd879whr /* 209b973f2b91343554586da3c952c63c2369acd879whr * If offset is -1, we append the record at the end of file 210b973f2b91343554586da3c952c63c2369acd879whr * 211b973f2b91343554586da3c952c63c2369acd879whr * Otherwise, we overlay wrec at the file offset indicated and assume 212b973f2b91343554586da3c952c63c2369acd879whr * that the caller passed us the correct offset. We do not record the 213b973f2b91343554586da3c952c63c2369acd879whr * fname in this case. 214b973f2b91343554586da3c952c63c2369acd879whr */ 215b973f2b91343554586da3c952c63c2369acd879whr 216b973f2b91343554586da3c952c63c2369acd879whr reclen = wlog_rec_pack(wrec, wbuf, (offset < 0)); 217b973f2b91343554586da3c952c63c2369acd879whr 218b973f2b91343554586da3c952c63c2369acd879whr if (offset < 0) { 219b973f2b91343554586da3c952c63c2369acd879whr /* 220b973f2b91343554586da3c952c63c2369acd879whr * Since we're writing a complete new record, we must also tack 221b973f2b91343554586da3c952c63c2369acd879whr * its length onto the end so that wlog_scan_backward() will work. 222b973f2b91343554586da3c952c63c2369acd879whr * Length is asumed to fit into 2 bytes. 223b973f2b91343554586da3c952c63c2369acd879whr */ 224b973f2b91343554586da3c952c63c2369acd879whr 225b973f2b91343554586da3c952c63c2369acd879whr wbuf[reclen] = reclen / 256; 226b973f2b91343554586da3c952c63c2369acd879whr wbuf[reclen+1] = reclen % 256; 227b973f2b91343554586da3c952c63c2369acd879whr reclen += 2; 228b973f2b91343554586da3c952c63c2369acd879whr 229b973f2b91343554586da3c952c63c2369acd879whr write(wfile->w_afd, wbuf, reclen); 230b973f2b91343554586da3c952c63c2369acd879whr offset = lseek(wfile->w_afd, 0, SEEK_CUR) - reclen; 231b973f2b91343554586da3c952c63c2369acd879whr } else { 232b973f2b91343554586da3c952c63c2369acd879whr lseek(wfile->w_rfd, offset, SEEK_SET); 233b973f2b91343554586da3c952c63c2369acd879whr write(wfile->w_rfd, wbuf, reclen); 234b973f2b91343554586da3c952c63c2369acd879whr } 235b973f2b91343554586da3c952c63c2369acd879whr 236b973f2b91343554586da3c952c63c2369acd879whr return offset; 237b973f2b91343554586da3c952c63c2369acd879whr} 238b973f2b91343554586da3c952c63c2369acd879whr 239b973f2b91343554586da3c952c63c2369acd879whr/* 240b973f2b91343554586da3c952c63c2369acd879whr * Function to scan a logfile in reverse order. Wfile is a valid 241b973f2b91343554586da3c952c63c2369acd879whr * wlog_file structure initialized by wlog_open(). nrecs is the number 242b973f2b91343554586da3c952c63c2369acd879whr * of records to scan (all records are scanned if nrecs is 0). func is 243b973f2b91343554586da3c952c63c2369acd879whr * a user-supplied function to call for each record found. The function 244b973f2b91343554586da3c952c63c2369acd879whr * will be passed a single parameter - a wlog_rec structure . 245b973f2b91343554586da3c952c63c2369acd879whr */ 246b973f2b91343554586da3c952c63c2369acd879whr 247b973f2b91343554586da3c952c63c2369acd879whrint 248b973f2b91343554586da3c952c63c2369acd879whrwlog_scan_backward(wfile, nrecs, func, data) 249b973f2b91343554586da3c952c63c2369acd879whrstruct wlog_file *wfile; 250b973f2b91343554586da3c952c63c2369acd879whrint nrecs; 251b973f2b91343554586da3c952c63c2369acd879whrint (*func)(); 252b973f2b91343554586da3c952c63c2369acd879whrlong data; 253b973f2b91343554586da3c952c63c2369acd879whr{ 254b973f2b91343554586da3c952c63c2369acd879whr int fd, leftover, nbytes, offset, recnum, reclen, rval; 255b973f2b91343554586da3c952c63c2369acd879whr char buf[BSIZE*32], *bufend, *cp, *bufstart; 2569418108733276af88b5458a866b6cd9a90e9232anstraz char albuf[WLOG_REC_MAX_SIZE]; 257b973f2b91343554586da3c952c63c2369acd879whr struct wlog_rec wrec; 258b973f2b91343554586da3c952c63c2369acd879whr 259b973f2b91343554586da3c952c63c2369acd879whr fd = wfile->w_rfd; 260b973f2b91343554586da3c952c63c2369acd879whr 261b973f2b91343554586da3c952c63c2369acd879whr /* 262b973f2b91343554586da3c952c63c2369acd879whr * Move to EOF. offset will always hold the current file offset 263b973f2b91343554586da3c952c63c2369acd879whr */ 264b973f2b91343554586da3c952c63c2369acd879whr 265b973f2b91343554586da3c952c63c2369acd879whr lseek(fd, 0, SEEK_END); 266b973f2b91343554586da3c952c63c2369acd879whr offset = lseek(fd, 0, SEEK_CUR); 267b973f2b91343554586da3c952c63c2369acd879whr 268b973f2b91343554586da3c952c63c2369acd879whr bufend = buf + sizeof(buf); 269b973f2b91343554586da3c952c63c2369acd879whr bufstart = buf; 270b973f2b91343554586da3c952c63c2369acd879whr 271b973f2b91343554586da3c952c63c2369acd879whr recnum = 0; 272b973f2b91343554586da3c952c63c2369acd879whr leftover = 0; 273b973f2b91343554586da3c952c63c2369acd879whr while ((!nrecs || recnum < nrecs) && offset > 0) { 274b973f2b91343554586da3c952c63c2369acd879whr /* 275b973f2b91343554586da3c952c63c2369acd879whr * Check for beginning of file - if there aren't enough bytes 276b973f2b91343554586da3c952c63c2369acd879whr * remaining to fill buf, adjust bufstart. 277b973f2b91343554586da3c952c63c2369acd879whr */ 278b973f2b91343554586da3c952c63c2369acd879whr 279b973f2b91343554586da3c952c63c2369acd879whr if (offset + leftover < sizeof(buf)) { 280b973f2b91343554586da3c952c63c2369acd879whr bufstart = bufend - (offset + leftover); 281b973f2b91343554586da3c952c63c2369acd879whr offset = 0; 282b973f2b91343554586da3c952c63c2369acd879whr } else { 283b973f2b91343554586da3c952c63c2369acd879whr offset -= sizeof(buf) - leftover; 284b973f2b91343554586da3c952c63c2369acd879whr } 285b973f2b91343554586da3c952c63c2369acd879whr 286b973f2b91343554586da3c952c63c2369acd879whr /* 287b973f2b91343554586da3c952c63c2369acd879whr * Move to the proper file offset, and read into buf 288b973f2b91343554586da3c952c63c2369acd879whr */ 289b973f2b91343554586da3c952c63c2369acd879whr 290b973f2b91343554586da3c952c63c2369acd879whr lseek(fd, offset, SEEK_SET); 291b973f2b91343554586da3c952c63c2369acd879whr nbytes = read(fd, bufstart, bufend - bufstart - leftover); 292b973f2b91343554586da3c952c63c2369acd879whr 293b973f2b91343554586da3c952c63c2369acd879whr if (nbytes == -1) { 294b973f2b91343554586da3c952c63c2369acd879whr sprintf(Wlog_Error_String, 29515226cdbc46b1a13023484bd304b13aa47d42b87robbiew "Could not read history file at offset %d - read(%d, %#lo, %d) failed: %s\n", 29615226cdbc46b1a13023484bd304b13aa47d42b87robbiew offset, fd, bufstart, 29715226cdbc46b1a13023484bd304b13aa47d42b87robbiew (int)(bufend - bufstart - leftover), strerror(errno)); 298b973f2b91343554586da3c952c63c2369acd879whr return -1; 299b973f2b91343554586da3c952c63c2369acd879whr } 300b973f2b91343554586da3c952c63c2369acd879whr 301b973f2b91343554586da3c952c63c2369acd879whr cp = bufend; 302b973f2b91343554586da3c952c63c2369acd879whr leftover = 0; 303b973f2b91343554586da3c952c63c2369acd879whr 304b973f2b91343554586da3c952c63c2369acd879whr while (cp >= bufstart) { 305b973f2b91343554586da3c952c63c2369acd879whr 306b973f2b91343554586da3c952c63c2369acd879whr /* 307b973f2b91343554586da3c952c63c2369acd879whr * If cp-bufstart is not large enough to hold a piece 308b973f2b91343554586da3c952c63c2369acd879whr * of record length information, copy remainder to end 309b973f2b91343554586da3c952c63c2369acd879whr * of buf and continue reading the file. 310b973f2b91343554586da3c952c63c2369acd879whr */ 311b973f2b91343554586da3c952c63c2369acd879whr 312b973f2b91343554586da3c952c63c2369acd879whr if (cp - bufstart < 2) { 313b973f2b91343554586da3c952c63c2369acd879whr leftover = cp - bufstart; 314b973f2b91343554586da3c952c63c2369acd879whr memcpy(bufend - leftover, bufstart, leftover); 315b973f2b91343554586da3c952c63c2369acd879whr break; 316b973f2b91343554586da3c952c63c2369acd879whr } 317b973f2b91343554586da3c952c63c2369acd879whr 318b973f2b91343554586da3c952c63c2369acd879whr /* 319b973f2b91343554586da3c952c63c2369acd879whr * Extract the record length. We must do it this way 320b973f2b91343554586da3c952c63c2369acd879whr * instead of casting cp to an int because cp might 321b973f2b91343554586da3c952c63c2369acd879whr * not be word aligned. 322b973f2b91343554586da3c952c63c2369acd879whr */ 323b973f2b91343554586da3c952c63c2369acd879whr 324b973f2b91343554586da3c952c63c2369acd879whr reclen = (*(cp-2) * 256) + *(cp -1); 325b973f2b91343554586da3c952c63c2369acd879whr 326b973f2b91343554586da3c952c63c2369acd879whr /* 327b973f2b91343554586da3c952c63c2369acd879whr * If cp-bufstart isn't large enough to hold a 328b973f2b91343554586da3c952c63c2369acd879whr * complete record, plus the length information, copy 329b973f2b91343554586da3c952c63c2369acd879whr * the leftover bytes to the end of buf and continue 330b973f2b91343554586da3c952c63c2369acd879whr * reading. 331b973f2b91343554586da3c952c63c2369acd879whr */ 332b973f2b91343554586da3c952c63c2369acd879whr 333b973f2b91343554586da3c952c63c2369acd879whr if (cp - bufstart < reclen + 2) { 334b973f2b91343554586da3c952c63c2369acd879whr leftover = cp - bufstart; 335b973f2b91343554586da3c952c63c2369acd879whr memcpy(bufend - leftover, bufstart, leftover); 336b973f2b91343554586da3c952c63c2369acd879whr break; 337b973f2b91343554586da3c952c63c2369acd879whr } 338b973f2b91343554586da3c952c63c2369acd879whr 339b973f2b91343554586da3c952c63c2369acd879whr /* 340b973f2b91343554586da3c952c63c2369acd879whr * Adjust cp to point at the start of the record. 341b973f2b91343554586da3c952c63c2369acd879whr * Copy the record into wbuf so that it is word 342b973f2b91343554586da3c952c63c2369acd879whr * aligned and pass the record to the user supplied 343b973f2b91343554586da3c952c63c2369acd879whr * function. 344b973f2b91343554586da3c952c63c2369acd879whr */ 345b973f2b91343554586da3c952c63c2369acd879whr 346b973f2b91343554586da3c952c63c2369acd879whr cp -= reclen + 2; 347b973f2b91343554586da3c952c63c2369acd879whr memcpy(albuf, cp, reclen); 348b973f2b91343554586da3c952c63c2369acd879whr 349b973f2b91343554586da3c952c63c2369acd879whr wlog_rec_unpack(&wrec, albuf); 350b973f2b91343554586da3c952c63c2369acd879whr 351b973f2b91343554586da3c952c63c2369acd879whr /* 352b973f2b91343554586da3c952c63c2369acd879whr * Call the user supplied function - 353b973f2b91343554586da3c952c63c2369acd879whr * stop if instructed to. 354b973f2b91343554586da3c952c63c2369acd879whr */ 355b973f2b91343554586da3c952c63c2369acd879whr 356b973f2b91343554586da3c952c63c2369acd879whr if ((rval = (*func)(&wrec, data)) == WLOG_STOP_SCAN) { 357b973f2b91343554586da3c952c63c2369acd879whr break; 358b973f2b91343554586da3c952c63c2369acd879whr } 359b973f2b91343554586da3c952c63c2369acd879whr 360b973f2b91343554586da3c952c63c2369acd879whr recnum++; 361b973f2b91343554586da3c952c63c2369acd879whr 362b973f2b91343554586da3c952c63c2369acd879whr if (nrecs && recnum >= nrecs) 363b973f2b91343554586da3c952c63c2369acd879whr break; 364b973f2b91343554586da3c952c63c2369acd879whr } 365b973f2b91343554586da3c952c63c2369acd879whr } 366b973f2b91343554586da3c952c63c2369acd879whr 367b973f2b91343554586da3c952c63c2369acd879whr return 0; 368b973f2b91343554586da3c952c63c2369acd879whr} 369b973f2b91343554586da3c952c63c2369acd879whr 370b973f2b91343554586da3c952c63c2369acd879whr/* 371b973f2b91343554586da3c952c63c2369acd879whr * The following 2 routines are used to pack and unpack the user 372b973f2b91343554586da3c952c63c2369acd879whr * visible wlog_rec structure to/from a character buffer which is 373b973f2b91343554586da3c952c63c2369acd879whr * stored or read from the write logfile. Any changes to either of 374b973f2b91343554586da3c952c63c2369acd879whr * these routines must be reflected in the other. 375b973f2b91343554586da3c952c63c2369acd879whr */ 376b973f2b91343554586da3c952c63c2369acd879whr 377b973f2b91343554586da3c952c63c2369acd879whrstatic int 378b973f2b91343554586da3c952c63c2369acd879whrwlog_rec_pack(wrec, buf, flag) 379b973f2b91343554586da3c952c63c2369acd879whrstruct wlog_rec *wrec; 380b973f2b91343554586da3c952c63c2369acd879whrchar *buf; 381b973f2b91343554586da3c952c63c2369acd879whrint flag; 382b973f2b91343554586da3c952c63c2369acd879whr{ 383b973f2b91343554586da3c952c63c2369acd879whr char *file, *host, *pattern; 384b973f2b91343554586da3c952c63c2369acd879whr struct wlog_rec_disk *wrecd; 385b973f2b91343554586da3c952c63c2369acd879whr 386b973f2b91343554586da3c952c63c2369acd879whr wrecd = (struct wlog_rec_disk *)buf; 387b973f2b91343554586da3c952c63c2369acd879whr 388b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_pid = (uint)wrec->w_pid; 389b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_offset = (uint)wrec->w_offset; 390b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_nbytes = (uint)wrec->w_nbytes; 391b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_oflags = (uint)wrec->w_oflags; 392b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_done = (uint)wrec->w_done; 393b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_async = (uint)wrec->w_async; 394b973f2b91343554586da3c952c63c2369acd879whr 395b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_pathlen = (wrec->w_pathlen > 0) ? (uint)wrec->w_pathlen : 0; 396b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_hostlen = (wrec->w_hostlen > 0) ? (uint)wrec->w_hostlen : 0; 397b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_patternlen = (wrec->w_patternlen > 0) ? (uint)wrec->w_patternlen : 0; 398b973f2b91343554586da3c952c63c2369acd879whr 399b973f2b91343554586da3c952c63c2369acd879whr /* 400b973f2b91343554586da3c952c63c2369acd879whr * If flag is true, we should also pack the variable length parts 401b973f2b91343554586da3c952c63c2369acd879whr * of the wlog_rec. By default, we only pack the fixed length 402b973f2b91343554586da3c952c63c2369acd879whr * parts. 403b973f2b91343554586da3c952c63c2369acd879whr */ 404b973f2b91343554586da3c952c63c2369acd879whr 405b973f2b91343554586da3c952c63c2369acd879whr if (flag) { 406b973f2b91343554586da3c952c63c2369acd879whr file = buf + sizeof(struct wlog_rec_disk); 407b973f2b91343554586da3c952c63c2369acd879whr host = file + wrecd->w_pathlen; 408b973f2b91343554586da3c952c63c2369acd879whr pattern = host + wrecd->w_hostlen; 409b973f2b91343554586da3c952c63c2369acd879whr 410b973f2b91343554586da3c952c63c2369acd879whr if (wrecd->w_pathlen > 0) 411b973f2b91343554586da3c952c63c2369acd879whr memcpy(file, wrec->w_path, wrecd->w_pathlen); 412b973f2b91343554586da3c952c63c2369acd879whr 413b973f2b91343554586da3c952c63c2369acd879whr if (wrecd->w_hostlen > 0) 414b973f2b91343554586da3c952c63c2369acd879whr memcpy(host, wrec->w_host, wrecd->w_hostlen); 415b973f2b91343554586da3c952c63c2369acd879whr 416b973f2b91343554586da3c952c63c2369acd879whr if (wrecd->w_patternlen > 0) 417b973f2b91343554586da3c952c63c2369acd879whr memcpy(pattern, wrec->w_pattern, wrecd->w_patternlen); 418b973f2b91343554586da3c952c63c2369acd879whr 419b973f2b91343554586da3c952c63c2369acd879whr return (sizeof(struct wlog_rec_disk) + 420b973f2b91343554586da3c952c63c2369acd879whr wrecd->w_pathlen + wrecd->w_hostlen + wrecd->w_patternlen); 421b973f2b91343554586da3c952c63c2369acd879whr } else { 422b973f2b91343554586da3c952c63c2369acd879whr return sizeof(struct wlog_rec_disk); 423b973f2b91343554586da3c952c63c2369acd879whr } 424b973f2b91343554586da3c952c63c2369acd879whr} 425b973f2b91343554586da3c952c63c2369acd879whr 426b973f2b91343554586da3c952c63c2369acd879whrstatic int 427b973f2b91343554586da3c952c63c2369acd879whrwlog_rec_unpack(wrec, buf) 428b973f2b91343554586da3c952c63c2369acd879whrstruct wlog_rec *wrec; 429b973f2b91343554586da3c952c63c2369acd879whrchar *buf; 430b973f2b91343554586da3c952c63c2369acd879whr{ 431b973f2b91343554586da3c952c63c2369acd879whr char *file, *host, *pattern; 432b973f2b91343554586da3c952c63c2369acd879whr struct wlog_rec_disk *wrecd; 433b973f2b91343554586da3c952c63c2369acd879whr 434b973f2b91343554586da3c952c63c2369acd879whr bzero((char *)wrec, sizeof(struct wlog_rec)); 435b973f2b91343554586da3c952c63c2369acd879whr wrecd = (struct wlog_rec_disk *)buf; 436b973f2b91343554586da3c952c63c2369acd879whr 437b973f2b91343554586da3c952c63c2369acd879whr wrec->w_pid = wrecd->w_pid; 438b973f2b91343554586da3c952c63c2369acd879whr wrec->w_offset = wrecd->w_offset; 439b973f2b91343554586da3c952c63c2369acd879whr wrec->w_nbytes = wrecd->w_nbytes; 440b973f2b91343554586da3c952c63c2369acd879whr wrec->w_oflags = wrecd->w_oflags; 441b973f2b91343554586da3c952c63c2369acd879whr wrec->w_hostlen = wrecd->w_hostlen; 442b973f2b91343554586da3c952c63c2369acd879whr wrec->w_pathlen = wrecd->w_pathlen; 443b973f2b91343554586da3c952c63c2369acd879whr wrec->w_patternlen = wrecd->w_patternlen; 444b973f2b91343554586da3c952c63c2369acd879whr wrec->w_done = wrecd->w_done; 445b973f2b91343554586da3c952c63c2369acd879whr wrec->w_async = wrecd->w_async; 446b973f2b91343554586da3c952c63c2369acd879whr 447b973f2b91343554586da3c952c63c2369acd879whr if (wrec->w_pathlen > 0) { 448b973f2b91343554586da3c952c63c2369acd879whr file = buf + sizeof(struct wlog_rec_disk); 449b973f2b91343554586da3c952c63c2369acd879whr memcpy(wrec->w_path, file, wrec->w_pathlen); 450b973f2b91343554586da3c952c63c2369acd879whr } 451b973f2b91343554586da3c952c63c2369acd879whr 452b973f2b91343554586da3c952c63c2369acd879whr if (wrec->w_hostlen > 0) { 453b973f2b91343554586da3c952c63c2369acd879whr host = buf + sizeof(struct wlog_rec_disk) + wrec->w_pathlen; 454b973f2b91343554586da3c952c63c2369acd879whr memcpy(wrec->w_host, host, wrec->w_hostlen); 455b973f2b91343554586da3c952c63c2369acd879whr } 456b973f2b91343554586da3c952c63c2369acd879whr 457b973f2b91343554586da3c952c63c2369acd879whr if (wrec->w_patternlen > 0) { 458b973f2b91343554586da3c952c63c2369acd879whr pattern = buf + sizeof(struct wlog_rec_disk) + 459b973f2b91343554586da3c952c63c2369acd879whr wrec->w_pathlen + wrec->w_hostlen; 460b973f2b91343554586da3c952c63c2369acd879whr memcpy(wrec->w_pattern, pattern, wrec->w_patternlen); 461b973f2b91343554586da3c952c63c2369acd879whr } 462b973f2b91343554586da3c952c63c2369acd879whr 463b973f2b91343554586da3c952c63c2369acd879whr return 0; 464b973f2b91343554586da3c952c63c2369acd879whr} 465