Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
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
+*~