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

📄 zftape-vtbl.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *      Copyright (c) 1995-1997 Claus-Justus Heine  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, 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; see the file COPYING.  If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.c,v $ * $Revision: 1.7.6.1 $ * $Date: 1997/11/24 13:48:31 $ * *      This file defines a volume table as defined in various QIC *      standards. *  *      This is a minimal implementation, just allowing ordinary DOS *      :( prgrams to identify the cartridge as used. */#include <linux/errno.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/zftape.h>#include "../zftape/zftape-init.h"#include "../zftape/zftape-eof.h"#include "../zftape/zftape-ctl.h"#include "../zftape/zftape-write.h"#include "../zftape/zftape-read.h"#include "../zftape/zftape-rw.h"#include "../zftape/zftape-vtbl.h"#define ZFT_CMAP_HACK /* leave this defined to hide the compression map *//* *  global variables  */int zft_qic_mode   = 1; /* use the vtbl */int zft_old_ftape; /* prevents old ftaped tapes to be overwritten */int zft_volume_table_changed; /* for write_header_segments() *//* *  private variables (only exported for inline functions) */LIST_HEAD(zft_vtbl);/*  We could also allocate these dynamically when extracting the volume table *  sizeof(zft_volinfo) is about 32 or something close to that */static zft_volinfo  tape_vtbl;static zft_volinfo  eot_vtbl;static zft_volinfo *cur_vtbl;static inline void zft_new_vtbl_entry(void){	struct list_head *tmp = &zft_last_vtbl->node;	zft_volinfo *new = zft_kmalloc(sizeof(zft_volinfo));	list_add(&new->node, tmp);	new->count = zft_eom_vtbl->count ++;}void zft_free_vtbl(void){	for (;;) {		struct list_head *tmp = zft_vtbl.prev;		zft_volinfo *vtbl;		if (tmp == &zft_vtbl)			break;		list_del(tmp);		vtbl = list_entry(tmp, zft_volinfo, node);		zft_kfree(vtbl, sizeof(zft_volinfo));	}	INIT_LIST_HEAD(&zft_vtbl);	cur_vtbl = NULL;}/*  initialize vtbl, called by ftape_new_cartridge() */void zft_init_vtbl(void){ 	zft_volinfo *new;	zft_free_vtbl();		/*  Create the two dummy vtbl entries	 */	new = zft_kmalloc(sizeof(zft_volinfo));	list_add(&new->node, &zft_vtbl);	new = zft_kmalloc(sizeof(zft_volinfo));	list_add(&new->node, &zft_vtbl);	zft_head_vtbl->end_seg   = ft_first_data_segment;	zft_head_vtbl->blk_sz    = zft_blk_sz;	zft_head_vtbl->count     = -1;	zft_eom_vtbl->start_seg  = ft_first_data_segment + 1;	zft_eom_vtbl->end_seg    = ft_last_data_segment + 1;	zft_eom_vtbl->blk_sz     = zft_blk_sz;	zft_eom_vtbl->count      = 0;	/*  Reset the pointer for zft_find_volume()	 */	cur_vtbl = zft_eom_vtbl;	/* initialize the dummy vtbl entries for zft_qic_mode == 0	 */	eot_vtbl.start_seg       = ft_last_data_segment + 1;	eot_vtbl.end_seg         = ft_last_data_segment + 1;	eot_vtbl.blk_sz          = zft_blk_sz;	eot_vtbl.count           = -1;	tape_vtbl.start_seg = ft_first_data_segment;	tape_vtbl.end_seg   = ft_last_data_segment;	tape_vtbl.blk_sz    = zft_blk_sz;	tape_vtbl.size      = zft_capacity;	tape_vtbl.count     = 0;}/* check for a valid VTBL signature.  */static int vtbl_signature_valid(__u8 signature[4]){	const char *vtbl_ids[] = VTBL_IDS; /* valid signatures */	int j;		for (j = 0; 	     (j < NR_ITEMS(vtbl_ids)) && (memcmp(signature, vtbl_ids[j], 4) != 0);	     j++);	return j < NR_ITEMS(vtbl_ids);}/* We used to store the block-size of the volume in the volume-label, * using the keyword "blocksize". The blocksize written to the * volume-label is in bytes. * * We use this now only for compatibility with old zftape version. We * store the blocksize directly as binary number in the vendor * extension part of the volume entry. */static int check_volume_label(const char *label, int *blk_sz){ 	int valid_format;	char *blocksize;	TRACE_FUN(ft_t_flow);		TRACE(ft_t_noise, "called with \"%s\" / \"%s\"", label, ZFT_VOL_NAME);	if (strncmp(label, ZFT_VOL_NAME, strlen(ZFT_VOL_NAME)) != 0) {		*blk_sz = 1; /* smallest block size that we allow */		valid_format = 0;	} else {		TRACE(ft_t_noise, "got old style zftape vtbl entry");		/* get the default blocksize */		/* use the kernel strstr()   */		blocksize= strstr(label, " blocksize ");		if (blocksize) {			blocksize += strlen(" blocksize ");			for(*blk_sz= 0; 			    *blocksize >= '0' && *blocksize <= '9'; 			    blocksize++) {				*blk_sz *= 10;				*blk_sz += *blocksize - '0';			}			if (*blk_sz > ZFT_MAX_BLK_SZ) {				*blk_sz= 1;				valid_format= 0;			} else {				valid_format = 1;			}		} else {			*blk_sz= 1;			valid_format= 0;		}	}	TRACE_EXIT valid_format;}/*   check for a zftape volume */static int check_volume(__u8 *entry, zft_volinfo *volume){	TRACE_FUN(ft_t_flow);		if(strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,		   strlen(ZFTAPE_SIG)) == 0) {		TRACE(ft_t_noise, "got new style zftape vtbl entry");		volume->blk_sz = GET2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ);		volume->qic113 = entry[VTBL_EXT+EXT_ZFTAPE_QIC113];		TRACE_EXIT 1;	} else {		TRACE_EXIT check_volume_label(&entry[VTBL_DESC], &volume->blk_sz);	}}/* create zftape specific vtbl entry, the volume bounds are inserted * in the calling function, zft_create_volume_headers() */static void create_zft_volume(__u8 *entry, zft_volinfo *vtbl){	TRACE_FUN(ft_t_flow);	memset(entry, 0, VTBL_SIZE);	memcpy(&entry[VTBL_SIG], VTBL_ID, 4);	sprintf(&entry[VTBL_DESC], ZFT_VOL_NAME" %03d", vtbl->count);	entry[VTBL_FLAGS] = (VTBL_FL_NOT_VERIFIED | VTBL_FL_SEG_SPANNING);	entry[VTBL_M_NO] = 1; /* multi_cartridge_count */	strcpy(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG);	PUT2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ, vtbl->blk_sz);	if (zft_qic113) {		PUT8(entry, VTBL_DATA_SIZE, vtbl->size);		entry[VTBL_CMPR] = VTBL_CMPR_UNREG; 		if (vtbl->use_compression) { /* use compression: */			entry[VTBL_CMPR] |= VTBL_CMPR_USED;		}		entry[VTBL_EXT+EXT_ZFTAPE_QIC113] = 1;	} else {		PUT4(entry, VTBL_DATA_SIZE, vtbl->size);		entry[VTBL_K_CMPR] = VTBL_CMPR_UNREG; 		if (vtbl->use_compression) { /* use compression: */			entry[VTBL_K_CMPR] |= VTBL_CMPR_USED;		}	}	if (ft_format_code == fmt_big) {		/* SCSI like vtbl, store the number of used		 * segments as 4 byte value 		 */		PUT4(entry, VTBL_SCSI_SEGS, vtbl->end_seg-vtbl->start_seg + 1);	} else {		/* normal, QIC-80MC like vtbl 		 */		PUT2(entry, VTBL_START, vtbl->start_seg);		PUT2(entry, VTBL_END, vtbl->end_seg);	}	TRACE_EXIT;}/* this one creates the volume headers for each volume. It is assumed * that buffer already contains the old volume-table, so that vtbl * entries without the zft_volume flag set can savely be ignored. */static void zft_create_volume_headers(__u8 *buffer){   	__u8 *entry;	struct list_head *tmp;	zft_volinfo *vtbl;	TRACE_FUN(ft_t_flow);	#ifdef ZFT_CMAP_HACK	if((strncmp(&buffer[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,		    strlen(ZFTAPE_SIG)) == 0) && 	   buffer[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {		TRACE(ft_t_noise, "deleting cmap volume");		memmove(buffer, buffer + VTBL_SIZE,			FT_SEGMENT_SIZE - VTBL_SIZE);	}#endif	entry = buffer;	for (tmp = zft_head_vtbl->node.next;	     tmp != &zft_eom_vtbl->node;	     tmp = tmp->next) {		vtbl = list_entry(tmp, zft_volinfo, node);		/* we now fill in the values only for newly created volumes.		 */		if (vtbl->new_volume) {			create_zft_volume(entry, vtbl);			vtbl->new_volume = 0; /* clear the flag */		}				DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], vtbl);		entry += VTBL_SIZE;	}	memset(entry, 0, FT_SEGMENT_SIZE - zft_eom_vtbl->count * VTBL_SIZE);	TRACE_EXIT;}/*  write volume table to tape. Calls zft_create_volume_headers() */int zft_update_volume_table(unsigned int segment){	int result = 0;	__u8 *verify_buf = NULL;	TRACE_FUN(ft_t_flow);	TRACE_CATCH(result = ftape_read_segment(ft_first_data_segment, 						zft_deblock_buf,						FT_RD_SINGLE),);	zft_create_volume_headers(zft_deblock_buf);	TRACE(ft_t_noise, "writing volume table segment %d", segment);	if (zft_vmalloc_once(&verify_buf, FT_SEGMENT_SIZE) == 0) {		TRACE_CATCH(zft_verify_write_segments(segment, 						      zft_deblock_buf, result,						      verify_buf),			    zft_vfree(&verify_buf, FT_SEGMENT_SIZE));		zft_vfree(&verify_buf, FT_SEGMENT_SIZE);	} else {		TRACE_CATCH(ftape_write_segment(segment, zft_deblock_buf, 						FT_WR_SINGLE),);	}	TRACE_EXIT 0;}/* non zftape volumes are handled in raw mode. Thus we need to * calculate the raw amount of data contained in those segments.   */static void extract_alien_volume(__u8 *entry, zft_volinfo *vtbl){	TRACE_FUN(ft_t_flow);	vtbl->size  = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1) -		       zft_calc_tape_pos(zft_last_vtbl->start_seg));	vtbl->use_compression = 0;	vtbl->qic113 = zft_qic113;	if (vtbl->qic113) {		TRACE(ft_t_noise, 		      "Fake alien volume's size from " LL_X " to " LL_X, 		      LL(GET8(entry, VTBL_DATA_SIZE)), LL(vtbl->size));	} else {		TRACE(ft_t_noise,		      "Fake alien volume's size from %d to " LL_X, 		      (int)GET4(entry, VTBL_DATA_SIZE), LL(vtbl->size));	}	TRACE_EXIT;}/* extract an zftape specific volume */static void extract_zft_volume(__u8 *entry, zft_volinfo *vtbl){	TRACE_FUN(ft_t_flow);	if (vtbl->qic113) {		vtbl->size = GET8(entry, VTBL_DATA_SIZE);		vtbl->use_compression = 			(entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0; 	} else {		vtbl->size = GET4(entry, VTBL_DATA_SIZE);		if (entry[VTBL_K_CMPR] & VTBL_CMPR_UNREG) {			vtbl->use_compression = 				(entry[VTBL_K_CMPR] & VTBL_CMPR_USED) != 0;		} else if (entry[VTBL_CMPR] & VTBL_CMPR_UNREG) {			vtbl->use_compression = 				(entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0; 		} else {			TRACE(ft_t_warn, "Geeh! There is something wrong:\n"			      KERN_INFO "QIC compression (Rev = K): %x\n"			      KERN_INFO "QIC compression (Rev > K): %x",			      entry[VTBL_K_CMPR], entry[VTBL_CMPR]);		}	}	TRACE_EXIT;}/* extract the volume table from buffer. "buffer" must already contain * the vtbl-segment  */int zft_extract_volume_headers(__u8 *buffer){                                    __u8 *entry;	TRACE_FUN(ft_t_flow);		zft_init_vtbl();	entry = buffer;#ifdef ZFT_CMAP_HACK	if ((strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,		     strlen(ZFTAPE_SIG)) == 0) &&	    entry[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {		TRACE(ft_t_noise, "ignoring cmap volume");		entry += VTBL_SIZE;

⌨️ 快捷键说明

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