⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 write_log.c

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 C
字号:
/* * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved. *  * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. *  * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *  * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like.  Any license provided herein, whether implied or * otherwise, applies only to this software file.  Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. *  * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. *  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA  94043, or: *  * http://www.sgi.com  *  * For further information regarding this notice, see:  *  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ *//* * This module contains code for logging writes to files, and for * perusing the resultant logfile.  The main intent of all this is * to provide a 'write history' of a file which can be examined to * judge the state of a file (ie. whether it is corrupted or not) based * on the write activity. * * The main abstractions available to the user are the wlog_file, and * the wlog_rec.  A wlog_file is a handle encapsulating a write logfile. * It is initialized with the wlog_open() function.  This handle is * then passed to the various wlog_xxx() functions to provide transparent * access to the write logfile. * * The wlog_rec datatype is a structure which contains all the information * about a file write.  Examples include the file name, offset, length, * pattern, etc.  In addition there is a bit which is cleared/set based * on whether or not the write has been confirmed as complete.  This  * allows the write logfile to contain information on writes which have * been initiated, but not yet completed (as in async io). * * There is also a function to scan a write logfile in reverse order. * * NOTE:	For target file analysis based on a write logfile, the * 		assumption is made that the file being written to is * 		locked from simultaneous access, so that the order of * 		write completion is predictable.  This is an issue when * 		more than 1 process is trying to write data to the same *		target file simultaneously. * * The history file created is a collection of variable length records * described by scruct wlog_rec_disk in write_log.h.  See that module for * the layout of the data on disk. */#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/types.h>#include "write_log.h"#ifndef BSIZE#ifdef linux#define BSIZE DEV_BSIZE#else#ifdef __CYGWIN__#define BSIZE S_BLKSIZE#else#define BSIZE BBSIZE#endif#endif#endif#ifndef PATH_MAX#define PATH_MAX          255/*#define PATH_MAX pathconf("/", _PC_PATH_MAX)*/#endifchar	Wlog_Error_String[256];#if __STDC__static int	wlog_rec_pack(struct wlog_rec *wrec, char *buf, int flag);static int	wlog_rec_unpack(struct wlog_rec *wrec, char *buf);#elsestatic int	wlog_rec_pack();static int	wlog_rec_unpack();#endif/* * Initialize a write logfile.  wfile is a wlog_file structure that has * the w_file field filled in.  The rest of the information in the * structure is initialized by the routine. * * The trunc flag is used to indicate whether or not the logfile should * be truncated if it currently exists.  If it is non-zero, the file will * be truncated, otherwise it will be appended to. * * The mode argument is the [absolute] mode which the file will be * given if it does not exist.  This mode is not affected by your process * umask. */intwlog_open(wfile, trunc, mode)struct wlog_file	*wfile;int			trunc;int			mode;{	int	omask, oflags;	if (trunc)		trunc = O_TRUNC;	omask = umask(0);	/*	 * Open 1 file descriptor as O_APPEND	 */	oflags = O_WRONLY | O_APPEND | O_CREAT | trunc;	wfile->w_afd =		open(wfile->w_file, oflags, mode);	umask(omask);	if (wfile->w_afd == -1) {		sprintf(Wlog_Error_String,			"Could not open write_log - open(%s, %#o, %#o) failed:  %s\n",			wfile->w_file, oflags, mode, strerror(errno));		return -1;	}	/*	 * Open the next fd as a random access descriptor	 */	oflags = O_RDWR;	if ((wfile->w_rfd = open(wfile->w_file, oflags)) == -1) {		sprintf(Wlog_Error_String,			"Could not open write log - open(%s, %#o) failed:  %s\n",			wfile->w_file, oflags, strerror(errno));		close(wfile->w_afd);		wfile->w_afd = -1;		return -1;	}    	return 0;}/* * Release all resources associated with a wlog_file structure allocated * with the wlog_open() call. */intwlog_close(wfile)struct wlog_file	*wfile;{	close(wfile->w_afd);	close(wfile->w_rfd);	return 0;}/* * Write a wlog_rec structure to a write logfile.  Offset is used to * control where the record will be written.  If offset is < 0, the * record will be appended to the end of the logfile.  Otherwise, the * record which exists at the indicated offset will be overlayed.  This * is so that we can record writes which are outstanding (with the w_done * bit in wrec cleared), but not completed, and then later update the * logfile when the write request completes (as with async io).  When * offset is >= 0, only the fixed length portion of the record is  * rewritten.  See text in write_log.h for details on the format of an * on-disk record. *  * The return value of the function is the byte offset in the logfile * where the record begins. * * Note:  It is the callers responsibility to make sure that the offset * parameter 'points' to a valid record location when a record is to be * overlayed.  This is guarenteed by saving the return value of a previous * call to wlog_record_write() which wrote the record to be overlayed. * * Note2:  The on-disk version of the wlog_rec is MUCH different than * the user version.  Don't expect to od the logfile and see data formatted * as it is in the wlog_rec structure.  Considerable data packing takes * place before the record is written. */intwlog_record_write(wfile, wrec, offset)struct wlog_file	*wfile;struct wlog_rec		*wrec;long			offset;{    int		reclen;    char	wbuf[WLOG_REC_MAX_SIZE + 2];    /*     * If offset is -1, we append the record at the end of file     *     * Otherwise, we overlay wrec at the file offset indicated and assume     * that the caller passed us the correct offset.  We do not record the     * fname in this case.     */    reclen = wlog_rec_pack(wrec, wbuf, (offset < 0));    if (offset < 0) {	/*	 * Since we're writing a complete new record, we must also tack	 * its length onto the end so that wlog_scan_backward() will work.	 * Length is asumed to fit into 2 bytes.	 */	    	    wbuf[reclen] = reclen / 256;	    wbuf[reclen+1] = reclen % 256;	    reclen += 2;	    write(wfile->w_afd, wbuf, reclen);	    offset = lseek(wfile->w_afd, 0, SEEK_CUR) - reclen;    } else {	    lseek(wfile->w_rfd, offset, SEEK_SET);	    write(wfile->w_rfd, wbuf, reclen);    }        return offset;}/* * Function to scan a logfile in reverse order.  Wfile is a valid * wlog_file structure initialized by wlog_open().  nrecs is the number * of records to scan (all records are scanned if nrecs is 0).  func is * a user-supplied function to call for each record found.  The function * will be passed a single parameter - a wlog_rec structure . */intwlog_scan_backward(wfile, nrecs, func, data)struct wlog_file	*wfile;int 			nrecs;int 			(*func)();long			data;{	int			fd, leftover, nbytes, offset, recnum, reclen, rval;	char    		buf[BSIZE*32], *bufend, *cp, *bufstart;	char		albuf[WLOG_REC_MAX_SIZE];	struct wlog_rec	wrec;	fd = wfile->w_rfd;	/*	 * Move to EOF.  offset will always hold the current file offset	 */	lseek(fd, 0, SEEK_END);	offset = lseek(fd, 0, SEEK_CUR);	bufend = buf + sizeof(buf);	bufstart = buf;	recnum = 0;	leftover = 0;	while ((!nrecs || recnum < nrecs) && offset > 0) {		/*		 * Check for beginning of file - if there aren't enough bytes		 * remaining to fill buf, adjust bufstart.		 */		if (offset + leftover < sizeof(buf)) {			bufstart = bufend - (offset + leftover);			offset = 0;		} else {			offset -= sizeof(buf) - leftover;		}		/* 		 * Move to the proper file offset, and read into buf		 */		lseek(fd, offset, SEEK_SET);		nbytes = read(fd, bufstart, bufend - bufstart - leftover);		if (nbytes == -1) {			sprintf(Wlog_Error_String,				"Could not read history file at offset %d - read(%d, %#o, %d) failed:  %s\n",				offset, fd, (int)bufstart,				bufend - bufstart - leftover, strerror(errno));			return -1;		}		cp = bufend;		leftover = 0;		while (cp >= bufstart) {			/*			 * If cp-bufstart is not large enough to hold a piece			 * of record length information, copy remainder to end			 * of buf and continue reading the file.			 */			if (cp - bufstart < 2) {				leftover = cp - bufstart;				memcpy(bufend - leftover, bufstart, leftover);				break;			}			/*			 * Extract the record length.  We must do it this way			 * instead of casting cp to an int because cp might			 * not be word aligned.			 */			reclen = (*(cp-2) * 256) + *(cp -1);			/*			 * If cp-bufstart isn't large enough to hold a			 * complete record, plus the length information, copy			 * the leftover bytes to the end of buf and continue			 * reading.			 */			if (cp - bufstart < reclen + 2) {				leftover = cp - bufstart;				memcpy(bufend - leftover, bufstart, leftover);				break;			}			/*			 * Adjust cp to point at the start of the record.			 * Copy the record into wbuf so that it is word			 * aligned and pass the record to the user supplied			 * function.			 */			cp -= reclen + 2;			memcpy(albuf, cp, reclen);			wlog_rec_unpack(&wrec, albuf);			/*			 * Call the user supplied function -			 * stop if instructed to.			 */			if ((rval = (*func)(&wrec, data)) == WLOG_STOP_SCAN) {				break;			}			recnum++;			if (nrecs && recnum >= nrecs)				break;		}	}	return 0;}/* * The following 2 routines are used to pack and unpack the user * visible wlog_rec structure to/from a character buffer which is * stored or read from the write logfile.  Any changes to either of * these routines must be reflected in the other. */static intwlog_rec_pack(wrec, buf, flag)struct wlog_rec	*wrec;char		*buf;int             flag;{	char			*file, *host, *pattern;	struct wlog_rec_disk	*wrecd;	wrecd = (struct wlog_rec_disk *)buf;	wrecd->w_pid = (uint)wrec->w_pid;	wrecd->w_offset = (uint)wrec->w_offset;	wrecd->w_nbytes = (uint)wrec->w_nbytes;	wrecd->w_oflags = (uint)wrec->w_oflags;	wrecd->w_done = (uint)wrec->w_done;	wrecd->w_async = (uint)wrec->w_async;	wrecd->w_pathlen = (wrec->w_pathlen > 0) ? (uint)wrec->w_pathlen : 0;	wrecd->w_hostlen = (wrec->w_hostlen > 0) ? (uint)wrec->w_hostlen : 0;	wrecd->w_patternlen = (wrec->w_patternlen > 0) ? (uint)wrec->w_patternlen : 0;	/*	 * If flag is true, we should also pack the variable length parts	 * of the wlog_rec.  By default, we only pack the fixed length	 * parts.	 */	if (flag) {		file = buf + sizeof(struct wlog_rec_disk);		host = file + wrecd->w_pathlen;		pattern = host + wrecd->w_hostlen;			if (wrecd->w_pathlen > 0)			memcpy(file, wrec->w_path, wrecd->w_pathlen);			if (wrecd->w_hostlen > 0)			memcpy(host, wrec->w_host, wrecd->w_hostlen);			if (wrecd->w_patternlen > 0)			memcpy(pattern, wrec->w_pattern, wrecd->w_patternlen);		return (sizeof(struct wlog_rec_disk) +			wrecd->w_pathlen + wrecd->w_hostlen + wrecd->w_patternlen);	} else {		return sizeof(struct wlog_rec_disk);	}}static intwlog_rec_unpack(wrec, buf)struct wlog_rec	*wrec;char		*buf;{	char			*file, *host, *pattern;	struct wlog_rec_disk	*wrecd;	bzero((char *)wrec, sizeof(struct wlog_rec));	wrecd = (struct wlog_rec_disk *)buf;	wrec->w_pid = wrecd->w_pid;	wrec->w_offset = wrecd->w_offset;	wrec->w_nbytes = wrecd->w_nbytes;	wrec->w_oflags = wrecd->w_oflags;	wrec->w_hostlen = wrecd->w_hostlen;	wrec->w_pathlen = wrecd->w_pathlen;	wrec->w_patternlen = wrecd->w_patternlen;	wrec->w_done = wrecd->w_done;	wrec->w_async = wrecd->w_async;	if (wrec->w_pathlen > 0) {		file = buf + sizeof(struct wlog_rec_disk);		memcpy(wrec->w_path, file, wrec->w_pathlen);	}	if (wrec->w_hostlen > 0) {		host = buf + sizeof(struct wlog_rec_disk) + wrec->w_pathlen;		memcpy(wrec->w_host, host, wrec->w_hostlen);	}	if (wrec->w_patternlen > 0) {		pattern = buf + sizeof(struct wlog_rec_disk) +			wrec->w_pathlen + wrec->w_hostlen;		memcpy(wrec->w_pattern, pattern, wrec->w_patternlen);	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -