📄 extract.c
字号:
/* * Copyright (c) International Business Machines Corp., 2000-2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * COMPONENT_NAME: jfs_fscklog (formerly xchklog) * * The jfs_fscklog tool provides 2 basic functions - fsck.jfs * service log extraction and display. The code here extracts * the log. * */#include <config.h>#include <fcntl.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include "devices.h"#include "diskmap.h"#include "fsckwsp.h"#include "fsck_message.h"#include "jfs_endian.h"#include "jfs_fscklog.h"#include "super.h"#include "utilsubs.h"#include "xfsck.h"#define fsck_READ 1#define fsck_WRITE 2extern char file_name[128];FILE *outfp;extern struct fscklog_record fscklog_record;extern struct fscklog_record *local_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock I/O buffer and pointer * */struct superblock aggr_superblock;struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * input: fsck service log I/O buffer * output: fsck extracted service log I/O buffer * */char fscklog_buffer[FSCKLOG_BUFSIZE];char xchklog_buffer[XCHKLOG_BUFSIZE]; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * values are assigned by the main jfs_fscklog routine */extern char *Vol_Label; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Device information. * * values are assigned when (if) the device is opened. */FILE *Dev_IOPort;unsigned Dev_blksize;int Dev_SectorSize;/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */void extract_service_log(void);int xchklog_final_processing(void);int xchklog_fscklog_fill_buffer(void);int xchklog_initial_processing(struct fscklog_record *);int open_device_read(const char *);int open_outfile(void);int readwrite_device(int64_t, unsigned, unsigned *, void *, int);void record_msg(char *);int validate_super(int);int validate_superblock(void);/***************************************************************************** * NAME: xchklog * * FUNCTION: Entry point for jfs read aggregate fsck service log * * PARAMETERS: * local_recptr - fscklog record * * RETURNS: * success: 0 * failure: something else */int xchklog(struct fscklog_record *local_recptr){ int rc = 0; /* * some basic initializations */ sb_ptr = &aggr_superblock; rc = xchklog_initial_processing(local_recptr); if (rc == 0) { /* we have a buffer and the device is open */ extract_service_log(); } if (rc == 0) { rc = xchklog_final_processing(); } else { xchklog_final_processing(); } return (rc);}/*************************************************************************** * NAME: extract_service_log * * FUNCTION: * * PARAMETERS: none * * RETURNS: * success: 0 * failure: something else */void extract_service_log(){ char *msg_txt; int dsl_rc = 0; char *log_entry; int log_entry_pos; int bytes_left; struct fscklog_entry_hdr *hdptr; local_recptr->fscklog_last_read = 0; while ((!local_recptr->fscklog_last_read) && (dsl_rc == 0)) { dsl_rc = xchklog_fscklog_fill_buffer(); local_recptr->this_buffer_last_message = 0; while ((!local_recptr->this_buffer_last_message) && (dsl_rc == 0)) { hdptr = (struct fscklog_entry_hdr *) (local_recptr->infile_buf_ptr + local_recptr->infile_buf_data_len); if (hdptr->entry_length == 0) { /* no more entries in this buffer */ local_recptr->this_buffer_last_message = -1; } else { /* this entry_length != 0 */ /* swap if on big endian machine */ ujfs_swap_fscklog_entry_hdr(hdptr); log_entry = (char *) hdptr; log_entry_pos = sizeof (struct fscklog_entry_hdr); /* * Each FSCKLOG_BUFSIZE boundary starts a new * log record. Otherwise, we depend on a valid * entry_length to locate the next message. */ bytes_left = local_recptr->infile_buf_length - local_recptr->infile_buf_data_len; if ((bytes_left < 0) || (hdptr->entry_length < 0) || (hdptr->entry_length > bytes_left)) { /* this isn't a valid log record length */ send_msg(fsck_CHKLOGINVALRCD); local_recptr->this_buffer_last_message = -1; } else { /* the log record length looks ok */ msg_txt = &log_entry[log_entry_pos]; /* * record the message in the output file */ record_msg(msg_txt); /* * set up for the next record */ local_recptr->infile_buf_data_len += hdptr->entry_length; /*if (hdptr->msg_num == fsck_SESSEND) { local_recptr-> this_buffer_last_message = -1; }*/ if (local_recptr->infile_buf_data_len >= local_recptr->infile_buf_length) { local_recptr-> this_buffer_last_message = -1; } } } } } return;}/*************************************************************************** * NAME: xchklog_final_processing * * FUNCTION: If processing read/write, replicate the superblock and the * aggregate inode structures (i.e., the Aggregate Inode Map * and the Aggregate Inode Table). * * Notify the user about various things. * * PARAMETERS: none * * RETURNS: * success: 0 * failure: something else */int xchklog_final_processing(){ int pf_rc = 0; /* * Close the device */ if (local_recptr->device_is_open) { pf_rc = fclose(Dev_IOPort); } /* * Close the output file */ if (local_recptr->outfile_is_open) { /* * flush the buffer if necessary */ if (local_recptr->outfile_buf_data_len != 0) { fwrite((const void *) (local_recptr->outfile_buf_ptr), sizeof (char), local_recptr->outfile_buf_length, outfp); } fclose(outfp); } return (pf_rc);}/***************************************************************************** * NAME: fscklog_fill_buffer * * FUNCTION: If the current fsck session has write access to the aggregate, * and if the in-aggregate fsck log is not full, write the * contents of the current fscklog buffer into the in-aggregate * fsck log. * * PARAMETERS: none * * NOTES: o Unlike most _put_ routines in this module, fscklog_put_buffer * actually writes to the device. This is done because the fsck * log contains information which provides crucial serviceability * should the fsck session be interrupted. * * o Errors here are recorded in the control page of the fsck * in-aggregate workspace but never affect other fsck processing. * * RETURNS: * success: 0 * failure: something else */int xchklog_fscklog_fill_buffer(){ int flfb_rc = 0; int io_rc = 0; unsigned bytes_read = 0; unsigned log_bytes_left; io_rc = readwrite_device(local_recptr->infile_agg_offset, local_recptr->infile_buf_length, &bytes_read, (void *) local_recptr->infile_buf_ptr, fsck_READ); if ((io_rc != 0) || (bytes_read != (unsigned) local_recptr->infile_buf_length)) { /* * write failed or didn't read * correct number of bytes */ send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label); send_msg(fsck_ERRONLOG, FSCK_BADREAD_FSCKLOG, io_rc, fsck_READ, (long long) local_recptr->infile_agg_offset, (long int) local_recptr->infile_buf_length, (long int) bytes_read); } /* * We want to reset the buffer no matter what. If is useful * to keep going because the next section may be readable. */ local_recptr->infile_agg_offset += local_recptr->infile_buf_length; local_recptr->infile_log_offset += local_recptr->infile_buf_length; local_recptr->infile_buf_data_len = 0; log_bytes_left = (local_recptr->ondev_fscklog_byte_length / 2) - local_recptr->infile_log_offset; if (log_bytes_left < local_recptr->infile_buf_length) { /* this is the last one */ local_recptr->fscklog_last_read = -1; } return (flfb_rc);}/***************************************************************************** * NAME: xchklog_initial_processing * * FUNCTION: Parse and verify invocation parameters. * Open the device and verify that it contains a JFS file system. * Read the chkdsk workspace control page. * Calculate interesting aggregate offsets. * * * PARAMETERS: as specified to main() * * NOTES: * * RETURNS: * success: 0 * failure: something else */int xchklog_initial_processing(struct fscklog_record *local_recptr){ int pi_rc = 0; /* * Initialize the fscklog control block */ local_recptr->infile_buf_length = FSCKLOG_BUFSIZE; local_recptr->infile_buf_ptr = fscklog_buffer; local_recptr->outfile_buf_length = XCHKLOG_BUFSIZE; local_recptr->outfile_buf_ptr = xchklog_buffer; /* * Open the device and verify that it contains a valid JFS aggregate * If it does, check/repair the superblock. */ pi_rc = open_device_read(Vol_Label); if (pi_rc != 0) { /*device open failed */ send_msg(fsck_CNTRESUPB); } else { /* device is open */ local_recptr->device_is_open = 1; pi_rc = validate_superblock(); if (pi_rc == 0) { /* a valid superblock */ /* * add some stuff to the local record which is based on * superblock fields */ /* length of the on-device fsck service log */ local_recptr->ondev_fscklog_byte_length = sb_ptr->s_fsckloglen * sb_ptr->s_bsize; /* length of the on-device fsck service log */ local_recptr->ondev_fscklog_fsblk_length = sb_ptr->s_fsckloglen; /* length of the on-device fsck workspace */ local_recptr->ondev_wsp_fsblk_length = lengthPXD(&(sb_ptr->s_fsckpxd)) - local_recptr->ondev_fscklog_fsblk_length; /* length of the on-device fsck workspace */ local_recptr->ondev_wsp_byte_length = local_recptr->ondev_wsp_fsblk_length * sb_ptr->s_bsize; /* aggregate block offset of the on-device fsck workspace */ local_recptr->ondev_wsp_fsblk_offset = addressPXD(&(sb_ptr->s_fsckpxd)); /* byte offset of the on-device fsck workspace */ local_recptr->ondev_wsp_byte_offset = local_recptr->ondev_wsp_fsblk_offset * sb_ptr->s_bsize; /* aggregate block offset of the on-device fsck workspace */ local_recptr->ondev_fscklog_fsblk_offset = local_recptr->ondev_wsp_fsblk_offset + local_recptr->ondev_wsp_fsblk_length; /* byte offset of the on-device fsck workspace */ local_recptr->ondev_fscklog_byte_offset = local_recptr->ondev_wsp_byte_offset + local_recptr->ondev_wsp_byte_length; /* * The offsets now assume the most recent log is 1st in the * aggregate fsck service log space. Adjust if needed. */ if (local_recptr->which_log == NEWLOG) { /* most recent wanted */ if (sb_ptr->s_fscklog == 2) { /* the 2nd is most recent */ local_recptr-> ondev_fscklog_fsblk_offset += local_recptr-> ondev_fscklog_fsblk_length / 2; local_recptr-> ondev_fscklog_byte_offset += local_recptr-> ondev_fscklog_byte_length / 2; } } else { /* previous log wanted */ if (sb_ptr->s_fscklog != 2) { /* the 2nd is not most recent */ local_recptr-> ondev_fscklog_fsblk_offset += local_recptr-> ondev_fscklog_fsblk_length / 2; local_recptr-> ondev_fscklog_byte_offset += local_recptr-> ondev_fscklog_byte_length / 2; } } local_recptr->infile_agg_offset = local_recptr->ondev_fscklog_byte_offset; pi_rc = open_outfile(); } } if (local_recptr->which_log == NEWLOG) { send_msg(fsck_CHKLOGNEW); } else { send_msg(fsck_CHKLOGOLD); } return (pi_rc);}/***************************************************************************** * NAME: open_device_read * * FUNCTION: Open the specified device for read access. * * PARAMETERS: * Device - input - the device specification * * NOTES: * * RETURNS: * success: 0 * failure: something else */int open_device_read(const char *Device){ Dev_IOPort = fopen(Device, "r");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -