Index: extract.c
===================================================================
--- extract.c (nonexistent)
+++ extract.c (revision 5)
@@ -0,0 +1,984 @@
+/*
+ * 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 <stdint.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 2
+
+extern 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];
+extern char xchklog_buffer[];
+
+ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ *
+ * 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");
+ if (Dev_IOPort == NULL) {
+ send_msg(fsck_DEVOPENRDRC, ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+ Dev_blksize = Dev_SectorSize = PBSIZE;
+ return 0;
+}
+
+/*****************************************************************************
+ * NAME: open_outfile
+ *
+ * FUNCTION: Open the output file.
+ *
+ * PARAMETERS:
+ * Device - input - the device specification
+ *
+ * RETURNS:
+ * success: 0
+ * failure: something else
+ */
+int open_outfile()
+{
+ int openof_rc = 0;
+
+ if (!local_recptr->file_name_specified) {
+ /* no output file name given */
+ if (local_recptr->which_log == NEWLOG) {
+ /* most recent wanted */
+ memcpy((void *) file_name, (void *) default_logfile_new,
+ default_logfile_name_len);
+ } else {
+ /* prior log wanted */
+ memcpy((void *) file_name, (void *) default_logfile_old,
+ default_logfile_name_len);
+ }
+ }
+
+ outfp = fopen(file_name, "w");
+ if (outfp == NULL) {
+ /* output file open failed */
+ openof_rc = XCHKLOG_CANTOPENOUTFILE;
+ send_msg(fsck_XCHKLOGOPNFAIL, file_name);
+ } else {
+ /* output file is open */
+ local_recptr->outfile_is_open = -1;
+
+ /*
+ * write the eyecatcher into the output buffer
+ */
+ memcpy((void *) (local_recptr->outfile_buf_ptr),
+ (void *) jfs_chklog_eyecatcher, 16);
+ local_recptr->outfile_buf_data_len = 16;
+
+ /*
+ * announce the output file name
+ */
+ if (local_recptr->which_log == NEWLOG) {
+ /* most recent */
+ send_msg(fsck_XCHKLOGNEW, file_name);
+ } else {
+ /* previous */
+ send_msg(fsck_XCHKLOGOLD, file_name);
+ }
+ }
+ return (openof_rc);
+}
+
+/*****************************************************************************
+ * NAME: readwrite_device
+ *
+ * FUNCTION: Read data from or write data to the device on which the
+ * aggregate resides.
+ *
+ * PARAMETERS:
+ * dev_offset - input - the offset, in bytes, into the aggregate
+ * of the data to read or to which to write
+ * the data.
+ * requested_data_size - input - the number of bytes requested
+ * actual_data_size - input - pointer to a variable in which to return
+ * the number of bytes actually read or
+ * written
+ * data_buffer - input - the address of the buffer in which to
+ * put the data or from which to write
+ * the data
+ * mode - input - { fsck_READ | fsck_WRITE }
+ *
+ * NOTES: This routine also exists in fsck code. When there is time,
+ * examine both copies for differences and put the combined
+ * copy in libfs to eliminate extra code.
+ *
+ * RETURNS:
+ * success: 0
+ * failure: something else
+ */
+int readwrite_device(int64_t dev_offset,
+ unsigned requested_data_size,
+ unsigned *actual_data_size, void *data_buffer, int mode)
+{
+ int rwdb_rc = 0;
+
+ if ((dev_offset % Dev_SectorSize)
+ || (requested_data_size % Dev_SectorSize)) {
+ rwdb_rc = FSCK_FAILED_SEEK;
+ } else {
+ switch (mode) {
+ case fsck_READ:
+ rwdb_rc =
+ ujfs_rw_diskblocks(Dev_IOPort, dev_offset,
+ requested_data_size, data_buffer,
+ GET);
+ break;
+ case fsck_WRITE:
+ rwdb_rc =
+ ujfs_rw_diskblocks(Dev_IOPort, dev_offset,
+ requested_data_size, data_buffer,
+ PUT);
+ break;
+ default:
+ rwdb_rc = FSCK_INTERNAL_ERROR_3;
+ break;
+ }
+ }
+
+ if (rwdb_rc == 0)
+ *actual_data_size = requested_data_size;
+ else
+ *actual_data_size = 0;
+
+ return (rwdb_rc);
+}
+
+/*****************************************************************************
+ * NAME: record_msg
+ *
+ * FUNCTION: Record an fsck service log message in the output file,
+ * formatted for the common fsck service log display tool.
+ *
+ * PARAMETERS:
+ * ? - input -
+ * ? - returned -
+ *
+ * NOTES: Any message designated fsck_debug is english-only, and
+ * is issued in english, even if it is sent to stdout.
+ *
+ * All other messages are local-language (in the nls context)
+ * and, when sent to stdout or stderr, are issued in the
+ * local language.
+ *
+ * Regardless of the language used to send a message to
+ * stdout and stderr, messages are ALWAYS LOGGED IN ENGLISH.
+ *
+ * RETURNS:
+ * nothing
+ */
+void record_msg(char *msg_txt)
+{
+ char *msg;
+ char log_entry[4096];
+ int entry_length = sizeof (struct chklog_entry_hdr);
+ struct chklog_entry_hdr *hdptr;
+ int buffer_bytes_left;
+
+ hdptr = (struct chklog_entry_hdr *) log_entry;
+ msg = &log_entry[entry_length];
+ strcpy(msg, msg_txt);
+ entry_length += strlen(msg_txt);
+ /* add null terminator to string */
+ log_entry[entry_length++] = '\0';
+
+ /*
+ * round the length up so the next entry will
+ * start on a doubleword (4 byte) boundary
+ */
+ entry_length = ((entry_length + 3) / 4) * 4;
+
+ hdptr->entry_length = entry_length;
+
+ buffer_bytes_left =
+ local_recptr->outfile_buf_length -
+ local_recptr->outfile_buf_data_len;
+ if (buffer_bytes_left < entry_length) {
+ /* won't fit */
+ local_recptr->last_msghdr->entry_length += buffer_bytes_left;
+ fwrite((const void *) (local_recptr->outfile_buf_ptr),
+ sizeof (char), local_recptr->outfile_buf_length, outfp);
+ /* clear the buffer */
+ memset((void *) (local_recptr->outfile_buf_ptr), 0,
+ local_recptr->outfile_buf_length);
+ local_recptr->outfile_buf_data_len = 0;
+ }
+ local_recptr->last_msghdr = (struct fscklog_entry_hdr *)
+ (local_recptr->outfile_buf_ptr +
+ local_recptr->outfile_buf_data_len);
+ memcpy((void *) local_recptr->last_msghdr, (void *) hdptr,
+ entry_length);
+
+ local_recptr->outfile_buf_data_len += entry_length;
+
+ return;
+}
+
+/*****************************************************************************
+ * NAME: validate_super
+ *
+ * FUNCTION: This routine validates the JFS superblock currently in the
+ * buffer. If any problem is detected, the which_superblock
+ * input parm is used to tailor the message issued to notify
+ * the user.
+ *
+ * PARAMETERS:
+ * which_super - input - specifies the superblock on which is in the
+ * buffer { fsck_primary | fsck_secondary }
+ *
+ * NOTES: This routine also exists in fsck code. When there is time,
+ * examine both copies for differences and put the combined
+ * copy in libfs to eliminate extra code.
+ *
+ * RETURNS:
+ * success: 0
+ * failure: something else
+ */
+int validate_super(int which_super)
+{
+ int vs_rc = 0; /* assume the superblock is ok */
+ int64_t bytes_on_device;
+ int64_t agg_blks_in_aggreg = 0, agg_blks_on_device =
+ 0, dev_blks_on_device;
+ int64_t fsck_start_from_pxd, fsck_blkmap_start_blks;
+ uint32_t fsck_length_from_pxd, fsck_blkmap_size_blks,
+ fsck_blkmap_size_pages;
+ int64_t jlog_start_from_pxd;
+ uint32_t jlog_length_from_pxd;
+ int agl2size;
+ unsigned expected_flag = JFS_GROUPCOMMIT;
+ unsigned agsize;
+ int bad_bsize = 0;
+
+ if (memcmp(sb_ptr->s_magic, JFS_MAGIC, sizeof (sb_ptr->s_magic)) != 0) {
+ vs_rc = FSCK_BADSBMGC;
+ send_msg(fsck_BADSBMGC, fsck_ref_msg(which_super));
+ } else if (sb_ptr->s_version > JFS_VERSION) {
+ vs_rc = FSCK_BADSBVRSN;
+ send_msg(fsck_BADSBVRSN, fsck_ref_msg(which_super));
+ } else {
+ /* the magic number and version number are correct so it
+ * probably is a JFS superblock with the format we are expecting
+ */
+
+ /* get physical device size */
+ ujfs_get_dev_size(Dev_IOPort, &bytes_on_device);
+
+ dev_blks_on_device = bytes_on_device / Dev_blksize;
+
+ if (sb_ptr->s_pbsize != Dev_blksize) {
+ vs_rc = FSCK_BADSBOTHR1;
+ send_msg(fsck_BADSBOTHR, "1", fsck_ref_msg(which_super));
+ }
+ if (sb_ptr->s_l2pbsize != log2shift(Dev_blksize)) {
+ vs_rc = FSCK_BADSBOTHR2;
+ send_msg(fsck_BADSBOTHR, "2", fsck_ref_msg(which_super));
+ }
+ if (!inrange(sb_ptr->s_bsize, 512, 4096)) {
+ bad_bsize = -1;
+ vs_rc = FSCK_BADSBOTHR3;
+ send_msg(fsck_BADSBBLSIZ, fsck_ref_msg(which_super));
+ } else {
+ /* else the filesystem block size is a legal value */
+ if (sb_ptr->s_l2bsize != log2shift(sb_ptr->s_bsize)) {
+ vs_rc = FSCK_BADSBOTHR4;
+ send_msg(fsck_BADSBOTHR, "4",
+ fsck_ref_msg(which_super));
+ }
+ if (sb_ptr->s_l2bfactor !=
+ log2shift(sb_ptr->s_bsize / Dev_blksize)) {
+ vs_rc = FSCK_BADSBOTHR5;
+ send_msg(fsck_BADSBOTHR, "5",
+ fsck_ref_msg(which_super));
+ }
+ if (sb_ptr->s_bsize < Dev_blksize) {
+ bad_bsize = -1;
+ vs_rc = FSCK_BLSIZLTLVBLSIZ;
+ send_msg(fsck_BLSIZLTLVBLSIZ,
+ fsck_ref_msg(which_super));
+ }
+ }
+
+ if (!bad_bsize) {
+ agg_blks_on_device = bytes_on_device / sb_ptr->s_bsize;
+ }
+
+ if (sb_ptr->s_size > dev_blks_on_device) {
+ vs_rc = FSCK_BADSBFSSIZ;
+ send_msg(fsck_BADSBFSSIZ, fsck_ref_msg(which_super));
+ }
+#ifdef _JFS_DFS_LFS
+ s_size_inbytes = sb_ptr->s_size * Dev_blksize;
+ sum_inbytes = (int64_t) (sb_ptr->totalUsable * 1024) +
+ (int64_t) (sb_ptr->minFree * 1024);
+ if ((sum_inbytes > s_size_inbytes)
+ || ((s_size_inbytes - sum_inbytes) >= 1024)) {
+ /* the sum is greater or the difference is at least 1K */
+ vs_rc = FSCK_BADBLKCTTTL;
+ send_msg(fsck_BADBLKCTTTL, fsck_ref_msg(which_super));
+ }
+#endif
+ /* must have JFS_OS2 or JFS_LINUX */
+ if (!(((sb_ptr->s_flag & JFS_OS2) == JFS_OS2)
+ || ((sb_ptr->s_flag & JFS_LINUX) == JFS_LINUX))) {
+ vs_rc = FSCK_BADSBOTHR6;
+ send_msg(fsck_BADSBOTHR, "6", fsck_ref_msg(which_super));
+ }
+
+ if ((sb_ptr->s_flag & expected_flag) != expected_flag) {
+ vs_rc = FSCK_BADSBOTHR6;
+ send_msg(fsck_BADSBOTHR, "6", fsck_ref_msg(which_super));
+ }
+ if (sb_ptr->s_agsize < (1 << L2BPERDMAP)) {
+ vs_rc = FSCK_BADSBAGSIZ;
+ send_msg(fsck_BADSBAGSIZ, fsck_ref_msg(which_super));
+ } else {
+ /* else the alloc group size is possibly correct */
+ agg_blks_in_aggreg =
+ sb_ptr->s_size * sb_ptr->s_pbsize / sb_ptr->s_bsize;
+ agl2size =
+ ujfs_getagl2size(agg_blks_in_aggreg,
+ sb_ptr->s_bsize);
+ /* get the allocation group size */
+ agsize = (int64_t) 1 << agl2size;
+ if (sb_ptr->s_agsize != agsize) {
+ vs_rc = FSCK_BADAGFSSIZ;
+ send_msg(fsck_BADSBAGSIZ, fsck_ref_msg(which_super));
+ }
+ }
+
+ if (!vs_rc) {
+ /*
+ * check out the fsck in-aggregate workspace
+ */
+ fsck_length_from_pxd = lengthPXD(&(sb_ptr->s_fsckpxd));
+ fsck_start_from_pxd = addressPXD(&(sb_ptr->s_fsckpxd));
+ agg_blks_in_aggreg = fsck_length_from_pxd +
+ (sb_ptr->s_size * sb_ptr->s_pbsize /
+ sb_ptr->s_bsize);
+
+ if (agg_blks_in_aggreg > agg_blks_on_device) {
+ /* wsp length is bad */
+ vs_rc = FSCK_BADSBFWSL1;
+ send_msg(fsck_BADSBFWSL1, fsck_ref_msg(which_super));
+ } else {
+ fsck_blkmap_size_pages =
+ ((agg_blks_in_aggreg +
+ (BITSPERPAGE - 1)) / BITSPERPAGE) + 1 +
+ 50;
+ /* size in aggregate blocks */
+ fsck_blkmap_size_blks =
+ (fsck_blkmap_size_pages << L2PSIZE) /
+ sb_ptr->s_bsize;
+ /*
+ * aggregate block offset of the
+ * fsck workspace in the aggregate.
+ */
+ fsck_blkmap_start_blks =
+ agg_blks_in_aggreg - fsck_blkmap_size_blks;
+ if (fsck_length_from_pxd !=
+ fsck_blkmap_size_blks) {
+ /*
+ * length of fsck in-aggregate
+ * workspace is incorrect
+ */
+ vs_rc = FSCK_BADSBFWSL;
+ send_msg(fsck_BADSBFWSL,
+ fsck_ref_msg(which_super));
+ }
+ if (fsck_start_from_pxd !=
+ fsck_blkmap_start_blks) {
+ /*
+ * address of fsck in-aggregate
+ * workspace is incorrect
+ */
+ vs_rc = FSCK_BADSBFWSA;
+ send_msg(fsck_BADSBFWSA,
+ fsck_ref_msg(which_super));
+ }
+ }
+ }
+ if (!vs_rc) {
+ /*
+ * check out the in-aggregate journal log
+ *
+ * if there is one it starts at the end of the fsck
+ * in-aggregate workspace.
+ */
+ jlog_length_from_pxd = lengthPXD(&(sb_ptr->s_logpxd));
+ jlog_start_from_pxd = addressPXD(&(sb_ptr->s_logpxd));
+
+ if (jlog_start_from_pxd != 0) {
+ /* there's one in there */
+ if (jlog_start_from_pxd != agg_blks_in_aggreg) {
+ /*
+ * address of in-aggregate
+ * journal log is incorrect
+ */
+ vs_rc = FSCK_BADSBFJLA;
+ send_msg(fsck_BADSBFJLA,
+ fsck_ref_msg(which_super));
+ }
+ agg_blks_in_aggreg += jlog_length_from_pxd;
+ if (agg_blks_in_aggreg > agg_blks_on_device) {
+ /* log length is bad */
+ vs_rc = FSCK_BADSBFJLL;
+ send_msg(fsck_BADSBFJLL,
+ fsck_ref_msg(which_super));
+ }
+ }
+ }
+ }
+ return (vs_rc);
+}
+
+/*****************************************************************************
+ * NAME: validate_superblock
+ *
+ * FUNCTION: Verify that the primary superblock is valid.
+ * If not, verify that the secondary superblock is valid.
+ *
+ * PARAMETERS: none
+ *
+ * NOTES: If this routine returns 0 then the superblock
+ * I/O buffer contains a valid superblock.
+ *
+ * This routine also exists in fsck code. When there is time,
+ * examine both copies for differences and put the combined
+ * copy in libfs to eliminate extra code.
+ *
+ * RETURNS:
+ * success: 0
+ * failure: something else
+ */
+int validate_superblock()
+{
+ int vsb_rc = 0;
+ int primary_sb_bad = 1;
+ int secondary_sb_bad = 1;
+ int which_sb = 0;
+
+ /* get primary */
+ vsb_rc = ujfs_get_superblk(Dev_IOPort, sb_ptr, 1);
+
+ if (vsb_rc != 0) {
+ /* if read primary fails */
+ send_msg(fsck_CNTRESUPP);
+ } else {
+ /* got primary superblock */
+ which_sb = fsck_primary;
+ primary_sb_bad = validate_super(fsck_primary);
+ }
+
+ if (primary_sb_bad) {
+ /* can't use the primary superblock */
+ send_msg(fsck_SBBADP);
+
+ /* get 2ndary */
+ vsb_rc = ujfs_get_superblk(Dev_IOPort, sb_ptr, 0);
+
+ if (vsb_rc != 0) {
+ send_msg(fsck_CNTRESUPS);
+ } else {
+ /* got secondary superblock */
+ which_sb = fsck_secondary;
+ secondary_sb_bad = validate_super(fsck_secondary);
+ }
+
+ if (!secondary_sb_bad) {
+ /* secondary is ok */
+ vsb_rc = 0;
+ } else {
+ send_msg(fsck_SBBADS);
+ }
+ }
+ if ((!primary_sb_bad) || (!secondary_sb_bad)) {
+ /* the buffer holds a valid superblock */
+
+ /* aggregate block size */
+ local_recptr->ag_blk_size = sb_ptr->s_bsize;
+
+ send_msg(fsck_XCHKLOGSBOK, fsck_ref_msg(which_sb));
+ }
+
+ return (vsb_rc);
+}
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 5)
Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~