1b973f2b91343554586da3c952c63c2369acd879whr/* 2b973f2b91343554586da3c952c63c2369acd879whr * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 345a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 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. 745a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 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. 1145a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 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. 1845a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 19b973f2b91343554586da3c952c63c2369acd879whr * You should have received a copy of the GNU General Public License along 20fed9641096e27f79a0f2d9adfe9839dd8d11dc0fWanlong Gao * with this program; if not, write the Free Software Foundation, Inc., 21fed9641096e27f79a0f2d9adfe9839dd8d11dc0fWanlong Gao * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 2245a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 23b973f2b91343554586da3c952c63c2369acd879whr * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24b973f2b91343554586da3c952c63c2369acd879whr * Mountain View, CA 94043, or: 2545a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 2645a8ba0302fa0632410b2f100f92701651dd7a0fvapier * http://www.sgi.com 2745a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 2845a8ba0302fa0632410b2f100f92701651dd7a0fvapier * For further information regarding this notice, see: 2945a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 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 4845a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 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 77e6508f8343333b4fe0696cf354e5f0cd7a2289b6mridge#ifdef DEV_BSIZE 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 89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaochar Wlog_Error_String[256]; 90b973f2b91343554586da3c952c63c2369acd879whr 91b973f2b91343554586da3c952c63c2369acd879whr#if __STDC__ 92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic int wlog_rec_pack(struct wlog_rec *wrec, char *buf, int flag); 93354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic int wlog_rec_unpack(struct wlog_rec *wrec, char *buf); 94b973f2b91343554586da3c952c63c2369acd879whr#else 95354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic int wlog_rec_pack(); 96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic 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 11387aa2dc20992208fd7478d14425c1e395a57e0c4Stanislav Kholmanskikhint wlog_open(struct wlog_file *wfile, int trunc, int mode) 114b973f2b91343554586da3c952c63c2369acd879whr{ 115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int omask, oflags; 116b973f2b91343554586da3c952c63c2369acd879whr 117b973f2b91343554586da3c952c63c2369acd879whr if (trunc) 118b973f2b91343554586da3c952c63c2369acd879whr trunc = O_TRUNC; 119b973f2b91343554586da3c952c63c2369acd879whr 120b973f2b91343554586da3c952c63c2369acd879whr omask = umask(0); 121b973f2b91343554586da3c952c63c2369acd879whr 122b973f2b91343554586da3c952c63c2369acd879whr /* 123b973f2b91343554586da3c952c63c2369acd879whr * Open 1 file descriptor as O_APPEND 124b973f2b91343554586da3c952c63c2369acd879whr */ 125b973f2b91343554586da3c952c63c2369acd879whr 126b973f2b91343554586da3c952c63c2369acd879whr oflags = O_WRONLY | O_APPEND | O_CREAT | trunc; 127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wfile->w_afd = open(wfile->w_file, oflags, mode); 128b973f2b91343554586da3c952c63c2369acd879whr umask(omask); 129b973f2b91343554586da3c952c63c2369acd879whr 130b973f2b91343554586da3c952c63c2369acd879whr if (wfile->w_afd == -1) { 131b973f2b91343554586da3c952c63c2369acd879whr sprintf(Wlog_Error_String, 132b973f2b91343554586da3c952c63c2369acd879whr "Could not open write_log - open(%s, %#o, %#o) failed: %s\n", 1339418108733276af88b5458a866b6cd9a90e9232anstraz wfile->w_file, oflags, mode, strerror(errno)); 134b973f2b91343554586da3c952c63c2369acd879whr return -1; 135b973f2b91343554586da3c952c63c2369acd879whr } 136b973f2b91343554586da3c952c63c2369acd879whr 137b973f2b91343554586da3c952c63c2369acd879whr /* 138b973f2b91343554586da3c952c63c2369acd879whr * Open the next fd as a random access descriptor 139b973f2b91343554586da3c952c63c2369acd879whr */ 140b973f2b91343554586da3c952c63c2369acd879whr 141b973f2b91343554586da3c952c63c2369acd879whr oflags = O_RDWR; 142e753fd7967c95651b952dd6fe67d2cb56478056esubrata_modak if ((wfile->w_rfd = open(wfile->w_file, oflags)) == -1) { 143b973f2b91343554586da3c952c63c2369acd879whr sprintf(Wlog_Error_String, 144b973f2b91343554586da3c952c63c2369acd879whr "Could not open write log - open(%s, %#o) failed: %s\n", 1459418108733276af88b5458a866b6cd9a90e9232anstraz wfile->w_file, oflags, strerror(errno)); 146b973f2b91343554586da3c952c63c2369acd879whr close(wfile->w_afd); 147b973f2b91343554586da3c952c63c2369acd879whr wfile->w_afd = -1; 148b973f2b91343554586da3c952c63c2369acd879whr return -1; 149b973f2b91343554586da3c952c63c2369acd879whr } 15045a8ba0302fa0632410b2f100f92701651dd7a0fvapier 151b973f2b91343554586da3c952c63c2369acd879whr return 0; 152b973f2b91343554586da3c952c63c2369acd879whr} 153b973f2b91343554586da3c952c63c2369acd879whr 154b973f2b91343554586da3c952c63c2369acd879whr/* 155b973f2b91343554586da3c952c63c2369acd879whr * Release all resources associated with a wlog_file structure allocated 156b973f2b91343554586da3c952c63c2369acd879whr * with the wlog_open() call. 157b973f2b91343554586da3c952c63c2369acd879whr */ 158b973f2b91343554586da3c952c63c2369acd879whr 15987aa2dc20992208fd7478d14425c1e395a57e0c4Stanislav Kholmanskikhint wlog_close(struct wlog_file *wfile) 160b973f2b91343554586da3c952c63c2369acd879whr{ 161b973f2b91343554586da3c952c63c2369acd879whr close(wfile->w_afd); 162b973f2b91343554586da3c952c63c2369acd879whr close(wfile->w_rfd); 163b973f2b91343554586da3c952c63c2369acd879whr return 0; 164b973f2b91343554586da3c952c63c2369acd879whr} 165b973f2b91343554586da3c952c63c2369acd879whr 166b973f2b91343554586da3c952c63c2369acd879whr/* 167b973f2b91343554586da3c952c63c2369acd879whr * Write a wlog_rec structure to a write logfile. Offset is used to 168b973f2b91343554586da3c952c63c2369acd879whr * control where the record will be written. If offset is < 0, the 169b973f2b91343554586da3c952c63c2369acd879whr * record will be appended to the end of the logfile. Otherwise, the 170b973f2b91343554586da3c952c63c2369acd879whr * record which exists at the indicated offset will be overlayed. This 171b973f2b91343554586da3c952c63c2369acd879whr * is so that we can record writes which are outstanding (with the w_done 172b973f2b91343554586da3c952c63c2369acd879whr * bit in wrec cleared), but not completed, and then later update the 173b973f2b91343554586da3c952c63c2369acd879whr * logfile when the write request completes (as with async io). When 17445a8ba0302fa0632410b2f100f92701651dd7a0fvapier * offset is >= 0, only the fixed length portion of the record is 175b973f2b91343554586da3c952c63c2369acd879whr * rewritten. See text in write_log.h for details on the format of an 176b973f2b91343554586da3c952c63c2369acd879whr * on-disk record. 17745a8ba0302fa0632410b2f100f92701651dd7a0fvapier * 178b973f2b91343554586da3c952c63c2369acd879whr * The return value of the function is the byte offset in the logfile 179b973f2b91343554586da3c952c63c2369acd879whr * where the record begins. 180b973f2b91343554586da3c952c63c2369acd879whr * 181b973f2b91343554586da3c952c63c2369acd879whr * Note: It is the callers responsibility to make sure that the offset 182b973f2b91343554586da3c952c63c2369acd879whr * parameter 'points' to a valid record location when a record is to be 183b973f2b91343554586da3c952c63c2369acd879whr * overlayed. This is guarenteed by saving the return value of a previous 184b973f2b91343554586da3c952c63c2369acd879whr * call to wlog_record_write() which wrote the record to be overlayed. 185b973f2b91343554586da3c952c63c2369acd879whr * 186b973f2b91343554586da3c952c63c2369acd879whr * Note2: The on-disk version of the wlog_rec is MUCH different than 187b973f2b91343554586da3c952c63c2369acd879whr * the user version. Don't expect to od the logfile and see data formatted 188b973f2b91343554586da3c952c63c2369acd879whr * as it is in the wlog_rec structure. Considerable data packing takes 189b973f2b91343554586da3c952c63c2369acd879whr * place before the record is written. 190b973f2b91343554586da3c952c63c2369acd879whr */ 191b973f2b91343554586da3c952c63c2369acd879whr 19287aa2dc20992208fd7478d14425c1e395a57e0c4Stanislav Kholmanskikhint wlog_record_write(struct wlog_file *wfile, struct wlog_rec *wrec, 19387aa2dc20992208fd7478d14425c1e395a57e0c4Stanislav Kholmanskikh long offset) 194b973f2b91343554586da3c952c63c2369acd879whr{ 195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int reclen; 196354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char wbuf[WLOG_REC_MAX_SIZE + 2]; 197b973f2b91343554586da3c952c63c2369acd879whr 198b973f2b91343554586da3c952c63c2369acd879whr /* 199354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * If offset is -1, we append the record at the end of file 200354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * 201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * Otherwise, we overlay wrec at the file offset indicated and assume 202354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * that the caller passed us the correct offset. We do not record the 203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * fname in this case. 204b973f2b91343554586da3c952c63c2369acd879whr */ 20545a8ba0302fa0632410b2f100f92701651dd7a0fvapier 206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao reclen = wlog_rec_pack(wrec, wbuf, (offset < 0)); 207354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 208354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (offset < 0) { 209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* 210354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * Since we're writing a complete new record, we must also tack 211354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * its length onto the end so that wlog_scan_backward() will work. 212354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * Length is asumed to fit into 2 bytes. 213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao */ 214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wbuf[reclen] = reclen / 256; 216354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wbuf[reclen + 1] = reclen % 256; 217354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao reclen += 2; 218354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 219354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (write(wfile->w_afd, wbuf, reclen) == -1) { 220354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sprintf(Wlog_Error_String, 221354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Could not write log - write(%s, %s, %d) failed: %s\n", 222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wfile->w_file, wbuf, reclen, strerror(errno)); 223354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return -1; 224354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 225354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao offset = lseek(wfile->w_afd, 0, SEEK_CUR) - reclen; 226354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (offset == -1) { 227354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sprintf(Wlog_Error_String, 228354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Could not reposition file pointer - lseek(%s, 0, SEEK_CUR) failed: %s\n", 229354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wfile->w_file, strerror(errno)); 230354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return -1; 231354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 232354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 233354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 234354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((lseek(wfile->w_rfd, offset, SEEK_SET)) == -1) { 235354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sprintf(Wlog_Error_String, 236354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Could not reposition file pointer - lseek(%s, %ld, SEEK_SET) failed: %s\n", 237354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wfile->w_file, offset, strerror(errno)); 238354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return -1; 239354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((write(wfile->w_rfd, wbuf, reclen)) == -1) { 241354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sprintf(Wlog_Error_String, 242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Could not write log - write(%s, %s, %d) failed: %s\n", 243354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wfile->w_file, wbuf, reclen, 244354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao strerror(errno)); 245354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return -1; 246354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 247354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 250354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return offset; 251b973f2b91343554586da3c952c63c2369acd879whr} 252b973f2b91343554586da3c952c63c2369acd879whr 253b973f2b91343554586da3c952c63c2369acd879whr/* 254b973f2b91343554586da3c952c63c2369acd879whr * Function to scan a logfile in reverse order. Wfile is a valid 255b973f2b91343554586da3c952c63c2369acd879whr * wlog_file structure initialized by wlog_open(). nrecs is the number 256b973f2b91343554586da3c952c63c2369acd879whr * of records to scan (all records are scanned if nrecs is 0). func is 257b973f2b91343554586da3c952c63c2369acd879whr * a user-supplied function to call for each record found. The function 258b973f2b91343554586da3c952c63c2369acd879whr * will be passed a single parameter - a wlog_rec structure . 259b973f2b91343554586da3c952c63c2369acd879whr */ 260b973f2b91343554586da3c952c63c2369acd879whr 26187aa2dc20992208fd7478d14425c1e395a57e0c4Stanislav Kholmanskikhint wlog_scan_backward(struct wlog_file *wfile, int nrecs, 26287aa2dc20992208fd7478d14425c1e395a57e0c4Stanislav Kholmanskikh int (*func)(), long data) 263b973f2b91343554586da3c952c63c2369acd879whr{ 264354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int fd, leftover, nbytes, offset, recnum, reclen, rval; 265354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char buf[BSIZE * 32], *bufend, *cp, *bufstart; 266354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char albuf[WLOG_REC_MAX_SIZE]; 267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct wlog_rec wrec; 268b973f2b91343554586da3c952c63c2369acd879whr 269b973f2b91343554586da3c952c63c2369acd879whr fd = wfile->w_rfd; 270b973f2b91343554586da3c952c63c2369acd879whr 271b973f2b91343554586da3c952c63c2369acd879whr /* 272b973f2b91343554586da3c952c63c2369acd879whr * Move to EOF. offset will always hold the current file offset 273b973f2b91343554586da3c952c63c2369acd879whr */ 274b973f2b91343554586da3c952c63c2369acd879whr 275354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((lseek(fd, 0, SEEK_END)) == -1) { 276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sprintf(Wlog_Error_String, 277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Could not reposition file pointer - lseek(%s, 0, SEEK_END) failed: %s\n", 278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wfile->w_file, strerror(errno)); 279354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return -1; 280354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 281b973f2b91343554586da3c952c63c2369acd879whr offset = lseek(fd, 0, SEEK_CUR); 282354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((offset == -1)) { 283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sprintf(Wlog_Error_String, 284354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Could not reposition file pointer - lseek(%s, 0, SEEK_CUR) failed: %s\n", 285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wfile->w_file, strerror(errno)); 286354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return -1; 287354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 288b973f2b91343554586da3c952c63c2369acd879whr 289b973f2b91343554586da3c952c63c2369acd879whr bufend = buf + sizeof(buf); 290b973f2b91343554586da3c952c63c2369acd879whr bufstart = buf; 291b973f2b91343554586da3c952c63c2369acd879whr 292b973f2b91343554586da3c952c63c2369acd879whr recnum = 0; 293b973f2b91343554586da3c952c63c2369acd879whr leftover = 0; 294b973f2b91343554586da3c952c63c2369acd879whr while ((!nrecs || recnum < nrecs) && offset > 0) { 295b973f2b91343554586da3c952c63c2369acd879whr /* 296b973f2b91343554586da3c952c63c2369acd879whr * Check for beginning of file - if there aren't enough bytes 297b973f2b91343554586da3c952c63c2369acd879whr * remaining to fill buf, adjust bufstart. 298b973f2b91343554586da3c952c63c2369acd879whr */ 299b973f2b91343554586da3c952c63c2369acd879whr 3000ccc8271427b5d80cc67a8164a0876549e7873ebrobbiew if ((unsigned int)offset + leftover < sizeof(buf)) { 301b973f2b91343554586da3c952c63c2369acd879whr bufstart = bufend - (offset + leftover); 302b973f2b91343554586da3c952c63c2369acd879whr offset = 0; 303b973f2b91343554586da3c952c63c2369acd879whr } else { 304b973f2b91343554586da3c952c63c2369acd879whr offset -= sizeof(buf) - leftover; 305b973f2b91343554586da3c952c63c2369acd879whr } 306b973f2b91343554586da3c952c63c2369acd879whr 30745a8ba0302fa0632410b2f100f92701651dd7a0fvapier /* 308b973f2b91343554586da3c952c63c2369acd879whr * Move to the proper file offset, and read into buf 309b973f2b91343554586da3c952c63c2369acd879whr */ 310354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((lseek(fd, offset, SEEK_SET)) == -1) { 311354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sprintf(Wlog_Error_String, 312354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Could not reposition file pointer - lseek(%s, %d, SEEK_SET) failed: %s\n", 313354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wfile->w_file, offset, strerror(errno)); 314354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return -1; 315354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 316b973f2b91343554586da3c952c63c2369acd879whr 317b973f2b91343554586da3c952c63c2369acd879whr nbytes = read(fd, bufstart, bufend - bufstart - leftover); 318b973f2b91343554586da3c952c63c2369acd879whr 319b973f2b91343554586da3c952c63c2369acd879whr if (nbytes == -1) { 320b973f2b91343554586da3c952c63c2369acd879whr sprintf(Wlog_Error_String, 321f3a83d59cce260ab513313b2c43c41fc16983959robbiew "Could not read history file at offset %d - read(%d, %p, %d) failed: %s\n", 32215226cdbc46b1a13023484bd304b13aa47d42b87robbiew offset, fd, bufstart, 323354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (int)(bufend - bufstart - leftover), 324354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao strerror(errno)); 325b973f2b91343554586da3c952c63c2369acd879whr return -1; 326b973f2b91343554586da3c952c63c2369acd879whr } 327b973f2b91343554586da3c952c63c2369acd879whr 328b973f2b91343554586da3c952c63c2369acd879whr cp = bufend; 329b973f2b91343554586da3c952c63c2369acd879whr leftover = 0; 330b973f2b91343554586da3c952c63c2369acd879whr 331b973f2b91343554586da3c952c63c2369acd879whr while (cp >= bufstart) { 332b973f2b91343554586da3c952c63c2369acd879whr 333b973f2b91343554586da3c952c63c2369acd879whr /* 334b973f2b91343554586da3c952c63c2369acd879whr * If cp-bufstart is not large enough to hold a piece 335b973f2b91343554586da3c952c63c2369acd879whr * of record length information, copy remainder to end 336b973f2b91343554586da3c952c63c2369acd879whr * of buf and continue reading the file. 337b973f2b91343554586da3c952c63c2369acd879whr */ 338b973f2b91343554586da3c952c63c2369acd879whr 339b973f2b91343554586da3c952c63c2369acd879whr if (cp - bufstart < 2) { 340b973f2b91343554586da3c952c63c2369acd879whr leftover = cp - bufstart; 341b973f2b91343554586da3c952c63c2369acd879whr memcpy(bufend - leftover, bufstart, leftover); 342b973f2b91343554586da3c952c63c2369acd879whr break; 343b973f2b91343554586da3c952c63c2369acd879whr } 344b973f2b91343554586da3c952c63c2369acd879whr 345b973f2b91343554586da3c952c63c2369acd879whr /* 346b973f2b91343554586da3c952c63c2369acd879whr * Extract the record length. We must do it this way 347b973f2b91343554586da3c952c63c2369acd879whr * instead of casting cp to an int because cp might 348b973f2b91343554586da3c952c63c2369acd879whr * not be word aligned. 349b973f2b91343554586da3c952c63c2369acd879whr */ 350b973f2b91343554586da3c952c63c2369acd879whr 351354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao reclen = (*(cp - 2) * 256) + *(cp - 1); 352b973f2b91343554586da3c952c63c2369acd879whr 353b973f2b91343554586da3c952c63c2369acd879whr /* 354b973f2b91343554586da3c952c63c2369acd879whr * If cp-bufstart isn't large enough to hold a 355b973f2b91343554586da3c952c63c2369acd879whr * complete record, plus the length information, copy 356b973f2b91343554586da3c952c63c2369acd879whr * the leftover bytes to the end of buf and continue 357b973f2b91343554586da3c952c63c2369acd879whr * reading. 358b973f2b91343554586da3c952c63c2369acd879whr */ 359b973f2b91343554586da3c952c63c2369acd879whr 360b973f2b91343554586da3c952c63c2369acd879whr if (cp - bufstart < reclen + 2) { 361b973f2b91343554586da3c952c63c2369acd879whr leftover = cp - bufstart; 362b973f2b91343554586da3c952c63c2369acd879whr memcpy(bufend - leftover, bufstart, leftover); 363b973f2b91343554586da3c952c63c2369acd879whr break; 364b973f2b91343554586da3c952c63c2369acd879whr } 365b973f2b91343554586da3c952c63c2369acd879whr 366b973f2b91343554586da3c952c63c2369acd879whr /* 367b973f2b91343554586da3c952c63c2369acd879whr * Adjust cp to point at the start of the record. 368b973f2b91343554586da3c952c63c2369acd879whr * Copy the record into wbuf so that it is word 369b973f2b91343554586da3c952c63c2369acd879whr * aligned and pass the record to the user supplied 370b973f2b91343554586da3c952c63c2369acd879whr * function. 371b973f2b91343554586da3c952c63c2369acd879whr */ 372b973f2b91343554586da3c952c63c2369acd879whr 373b973f2b91343554586da3c952c63c2369acd879whr cp -= reclen + 2; 374b973f2b91343554586da3c952c63c2369acd879whr memcpy(albuf, cp, reclen); 375b973f2b91343554586da3c952c63c2369acd879whr 376b973f2b91343554586da3c952c63c2369acd879whr wlog_rec_unpack(&wrec, albuf); 377b973f2b91343554586da3c952c63c2369acd879whr 378b973f2b91343554586da3c952c63c2369acd879whr /* 379b973f2b91343554586da3c952c63c2369acd879whr * Call the user supplied function - 380b973f2b91343554586da3c952c63c2369acd879whr * stop if instructed to. 381b973f2b91343554586da3c952c63c2369acd879whr */ 382b973f2b91343554586da3c952c63c2369acd879whr 383354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((rval = (*func) (&wrec, data)) == WLOG_STOP_SCAN) { 384b973f2b91343554586da3c952c63c2369acd879whr break; 385b973f2b91343554586da3c952c63c2369acd879whr } 386b973f2b91343554586da3c952c63c2369acd879whr 387b973f2b91343554586da3c952c63c2369acd879whr recnum++; 388b973f2b91343554586da3c952c63c2369acd879whr 389b973f2b91343554586da3c952c63c2369acd879whr if (nrecs && recnum >= nrecs) 390b973f2b91343554586da3c952c63c2369acd879whr break; 391b973f2b91343554586da3c952c63c2369acd879whr } 392b973f2b91343554586da3c952c63c2369acd879whr } 393b973f2b91343554586da3c952c63c2369acd879whr 394b973f2b91343554586da3c952c63c2369acd879whr return 0; 395b973f2b91343554586da3c952c63c2369acd879whr} 396b973f2b91343554586da3c952c63c2369acd879whr 397b973f2b91343554586da3c952c63c2369acd879whr/* 398b973f2b91343554586da3c952c63c2369acd879whr * The following 2 routines are used to pack and unpack the user 399b973f2b91343554586da3c952c63c2369acd879whr * visible wlog_rec structure to/from a character buffer which is 400b973f2b91343554586da3c952c63c2369acd879whr * stored or read from the write logfile. Any changes to either of 401b973f2b91343554586da3c952c63c2369acd879whr * these routines must be reflected in the other. 402b973f2b91343554586da3c952c63c2369acd879whr */ 403b973f2b91343554586da3c952c63c2369acd879whr 40487aa2dc20992208fd7478d14425c1e395a57e0c4Stanislav Kholmanskikhstatic int wlog_rec_pack(struct wlog_rec *wrec, char *buf, int flag) 405b973f2b91343554586da3c952c63c2369acd879whr{ 406354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *file, *host, *pattern; 407354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct wlog_rec_disk *wrecd; 408b973f2b91343554586da3c952c63c2369acd879whr 409b973f2b91343554586da3c952c63c2369acd879whr wrecd = (struct wlog_rec_disk *)buf; 410b973f2b91343554586da3c952c63c2369acd879whr 411354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_pid = (uint) wrec->w_pid; 412354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_offset = (uint) wrec->w_offset; 413354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_nbytes = (uint) wrec->w_nbytes; 414354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_oflags = (uint) wrec->w_oflags; 415354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_done = (uint) wrec->w_done; 416354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_async = (uint) wrec->w_async; 417b973f2b91343554586da3c952c63c2369acd879whr 418354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_pathlen = (wrec->w_pathlen > 0) ? (uint) wrec->w_pathlen : 0; 419354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_hostlen = (wrec->w_hostlen > 0) ? (uint) wrec->w_hostlen : 0; 420354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_patternlen = 421354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (wrec->w_patternlen > 0) ? (uint) wrec->w_patternlen : 0; 422b973f2b91343554586da3c952c63c2369acd879whr 423b973f2b91343554586da3c952c63c2369acd879whr /* 424b973f2b91343554586da3c952c63c2369acd879whr * If flag is true, we should also pack the variable length parts 425b973f2b91343554586da3c952c63c2369acd879whr * of the wlog_rec. By default, we only pack the fixed length 426b973f2b91343554586da3c952c63c2369acd879whr * parts. 427b973f2b91343554586da3c952c63c2369acd879whr */ 428b973f2b91343554586da3c952c63c2369acd879whr 429b973f2b91343554586da3c952c63c2369acd879whr if (flag) { 430b973f2b91343554586da3c952c63c2369acd879whr file = buf + sizeof(struct wlog_rec_disk); 431b973f2b91343554586da3c952c63c2369acd879whr host = file + wrecd->w_pathlen; 432b973f2b91343554586da3c952c63c2369acd879whr pattern = host + wrecd->w_hostlen; 43345a8ba0302fa0632410b2f100f92701651dd7a0fvapier 434b973f2b91343554586da3c952c63c2369acd879whr if (wrecd->w_pathlen > 0) 435b973f2b91343554586da3c952c63c2369acd879whr memcpy(file, wrec->w_path, wrecd->w_pathlen); 43645a8ba0302fa0632410b2f100f92701651dd7a0fvapier 437b973f2b91343554586da3c952c63c2369acd879whr if (wrecd->w_hostlen > 0) 438b973f2b91343554586da3c952c63c2369acd879whr memcpy(host, wrec->w_host, wrecd->w_hostlen); 43945a8ba0302fa0632410b2f100f92701651dd7a0fvapier 440b973f2b91343554586da3c952c63c2369acd879whr if (wrecd->w_patternlen > 0) 441b973f2b91343554586da3c952c63c2369acd879whr memcpy(pattern, wrec->w_pattern, wrecd->w_patternlen); 442b973f2b91343554586da3c952c63c2369acd879whr 443b973f2b91343554586da3c952c63c2369acd879whr return (sizeof(struct wlog_rec_disk) + 444354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_pathlen + wrecd->w_hostlen + 445354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrecd->w_patternlen); 446b973f2b91343554586da3c952c63c2369acd879whr } else { 447b973f2b91343554586da3c952c63c2369acd879whr return sizeof(struct wlog_rec_disk); 448b973f2b91343554586da3c952c63c2369acd879whr } 449b973f2b91343554586da3c952c63c2369acd879whr} 450b973f2b91343554586da3c952c63c2369acd879whr 45187aa2dc20992208fd7478d14425c1e395a57e0c4Stanislav Kholmanskikhstatic int wlog_rec_unpack(struct wlog_rec *wrec, char *buf) 452b973f2b91343554586da3c952c63c2369acd879whr{ 453354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *file, *host, *pattern; 454354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct wlog_rec_disk *wrecd; 455b973f2b91343554586da3c952c63c2369acd879whr 45632cc0acd99e36836b13056c6d0e3e62a115678f3vapier memset((char *)wrec, 0x00, sizeof(struct wlog_rec)); 457b973f2b91343554586da3c952c63c2369acd879whr wrecd = (struct wlog_rec_disk *)buf; 458b973f2b91343554586da3c952c63c2369acd879whr 459b973f2b91343554586da3c952c63c2369acd879whr wrec->w_pid = wrecd->w_pid; 460b973f2b91343554586da3c952c63c2369acd879whr wrec->w_offset = wrecd->w_offset; 461b973f2b91343554586da3c952c63c2369acd879whr wrec->w_nbytes = wrecd->w_nbytes; 462b973f2b91343554586da3c952c63c2369acd879whr wrec->w_oflags = wrecd->w_oflags; 463b973f2b91343554586da3c952c63c2369acd879whr wrec->w_hostlen = wrecd->w_hostlen; 464b973f2b91343554586da3c952c63c2369acd879whr wrec->w_pathlen = wrecd->w_pathlen; 465b973f2b91343554586da3c952c63c2369acd879whr wrec->w_patternlen = wrecd->w_patternlen; 466b973f2b91343554586da3c952c63c2369acd879whr wrec->w_done = wrecd->w_done; 467b973f2b91343554586da3c952c63c2369acd879whr wrec->w_async = wrecd->w_async; 468b973f2b91343554586da3c952c63c2369acd879whr 469b973f2b91343554586da3c952c63c2369acd879whr if (wrec->w_pathlen > 0) { 470b973f2b91343554586da3c952c63c2369acd879whr file = buf + sizeof(struct wlog_rec_disk); 471b973f2b91343554586da3c952c63c2369acd879whr memcpy(wrec->w_path, file, wrec->w_pathlen); 472b973f2b91343554586da3c952c63c2369acd879whr } 473b973f2b91343554586da3c952c63c2369acd879whr 474b973f2b91343554586da3c952c63c2369acd879whr if (wrec->w_hostlen > 0) { 475b973f2b91343554586da3c952c63c2369acd879whr host = buf + sizeof(struct wlog_rec_disk) + wrec->w_pathlen; 476b973f2b91343554586da3c952c63c2369acd879whr memcpy(wrec->w_host, host, wrec->w_hostlen); 477b973f2b91343554586da3c952c63c2369acd879whr } 478b973f2b91343554586da3c952c63c2369acd879whr 479b973f2b91343554586da3c952c63c2369acd879whr if (wrec->w_patternlen > 0) { 480b973f2b91343554586da3c952c63c2369acd879whr pattern = buf + sizeof(struct wlog_rec_disk) + 481354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao wrec->w_pathlen + wrec->w_hostlen; 482b973f2b91343554586da3c952c63c2369acd879whr memcpy(wrec->w_pattern, pattern, wrec->w_patternlen); 483b973f2b91343554586da3c952c63c2369acd879whr } 484b973f2b91343554586da3c952c63c2369acd879whr 485b973f2b91343554586da3c952c63c2369acd879whr return 0; 486ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman} 487