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

📄 zftape-ctl.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
						mtftseg->mt_mode);	if (mtftseg->mt_result < 0) {		/*  a negativ result is not an ioctl error. if		 *  the user wants to read damaged tapes,		 *  it's up to her/him		 */		TRACE_EXIT 0;	}	if (copy_to_user(mtftseg->mt_data,			 zft_deblock_buf,			 mtftseg->mt_result) != 0) {		TRACE_EXIT -EFAULT;	}	TRACE_EXIT 0;}#endif#ifdef MTIOCWRFTSEG/* *  write a floppy tape segment. This version features writing of *  deleted address marks, and gracefully ignores the (software) *  ft_formatted flag to support writing of header segments after *  formatting. */static int mtiocwrftseg(struct mtftseg * mtftseg, int arg_size){	int result;	TRACE_FUN(ft_t_flow);		TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCWRFTSEG");	if (zft_write_protected || zft_qic_mode) {		TRACE_EXIT -EACCES;	} 	if (arg_size != sizeof(struct mtftseg)) {		TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",			    arg_size);	}	if (zft_offline) {		TRACE_EXIT -ENXIO;	}	if (mtftseg->mt_mode != FT_WR_ASYNC   && 	    mtftseg->mt_mode != FT_WR_MULTI   &&	    mtftseg->mt_mode != FT_WR_SINGLE  &&	    mtftseg->mt_mode != FT_WR_DELETE) {		TRACE_ABORT(-EINVAL, ft_t_info, "invalid write mode");	}	/*	 *  We don't check for ft_formatted, because this gives	 *  only the software status of the driver.	 *	 *  We assume that the user knows what it is	 *  doing. And rely on the low level stuff to fail	 *  when the tape isn't formatted. We only make sure	 *  that The header segment buffer is allocated,	 *  because it holds the bad sector map.	 */	if (zft_hseg_buf == NULL) {		TRACE_EXIT -ENXIO;	}	if (mtftseg->mt_mode != FT_WR_DELETE) {		if (copy_from_user(zft_deblock_buf, 				   mtftseg->mt_data,				   FT_SEGMENT_SIZE) != 0) {			TRACE_EXIT -EFAULT;		}	}	mtftseg->mt_result = ftape_write_segment(mtftseg->mt_segno, 						 zft_deblock_buf,						 mtftseg->mt_mode);	if (mtftseg->mt_result >= 0 && mtftseg->mt_mode == FT_WR_SINGLE) {		/*  		 *  a negativ result is not an ioctl error. if		 *  the user wants to write damaged tapes,		 *  it's up to her/him		 */		if ((result = ftape_loop_until_writes_done()) < 0) {			mtftseg->mt_result = result;		}	}	TRACE_EXIT 0;}#endif  #ifdef MTIOCVOLINFO/* *  get information about volume positioned at. */static int mtiocvolinfo(struct mtvolinfo *volinfo, int arg_size){	const zft_volinfo *volume;	TRACE_FUN(ft_t_flow);		TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCVOLINFO");	if (arg_size != sizeof(struct mtvolinfo)) {		TRACE_ABORT(-EINVAL,			    ft_t_info, "bad argument size: %d", arg_size);	}	if (zft_offline) {		TRACE_EXIT -ENXIO;	}	if (!ft_formatted) {		TRACE_EXIT -EACCES;	}	TRACE_CATCH(zft_def_idle_state(),);	volume = zft_find_volume(zft_pos.seg_pos);	volinfo->mt_volno   = volume->count;	volinfo->mt_blksz   = volume->blk_sz == 1 ? 0 : volume->blk_sz;	volinfo->mt_size    = volume->size >> 10;	volinfo->mt_rawsize = ((zft_calc_tape_pos(volume->end_seg + 1) >> 10) -			       (zft_calc_tape_pos(volume->start_seg) >> 10));	volinfo->mt_cmpr    = volume->use_compression;	TRACE_EXIT 0;}#endif#ifdef ZFT_OBSOLETE  static int mtioc_zftape_getblksz(struct mtblksz *blksz, int arg_size){	TRACE_FUN(ft_t_flow);		TRACE(ft_t_noise, "\n"	      KERN_INFO "Mag tape ioctl command: MTIOC_ZTAPE_GETBLKSZ\n"	      KERN_INFO "This ioctl is here merely for compatibility.\n"	      KERN_INFO "Please use MTIOCVOLINFO instead");	if (arg_size != sizeof(struct mtblksz)) {		TRACE_ABORT(-EINVAL,			    ft_t_info, "bad argument size: %d", arg_size);	}	if (zft_offline) {		TRACE_EXIT -ENXIO;	}	if (!ft_formatted) {		TRACE_EXIT -EACCES;	}	TRACE_CATCH(zft_def_idle_state(),);	blksz->mt_blksz = zft_find_volume(zft_pos.seg_pos)->blk_sz;	TRACE_EXIT 0;}#endif#ifdef MTIOCGETSIZE/* *  get the capacity of the tape cartridge. */static int mtiocgetsize(struct mttapesize *size, int arg_size){	TRACE_FUN(ft_t_flow);		TRACE(ft_t_noise, "Mag tape ioctl command: MTIOC_ZFTAPE_GETSIZE");	if (arg_size != sizeof(struct mttapesize)) {		TRACE_ABORT(-EINVAL,			    ft_t_info, "bad argument size: %d", arg_size);	}	if (zft_offline) {		TRACE_EXIT -ENXIO;	}	if (!ft_formatted) {		TRACE_EXIT -EACCES;	}	TRACE_CATCH(zft_def_idle_state(),);	size->mt_capacity = (unsigned int)(zft_capacity>>10);	size->mt_used     = (unsigned int)(zft_get_eom_pos()>>10);	TRACE_EXIT 0;}#endifstatic int mtiocpos(struct mtpos *mtpos, int arg_size){	int result;	TRACE_FUN(ft_t_flow);		TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCPOS");	if (arg_size != sizeof(struct mtpos)) {		TRACE_ABORT(-EINVAL,			    ft_t_info, "bad argument size: %d", arg_size);	}	result = mt_tell((int *)&mtpos->mt_blkno);	TRACE_EXIT result;}#ifdef MTIOCFTFORMAT/* * formatting of floppy tape cartridges. This is intended to be used * together with the MTIOCFTCMD ioctl and the new mmap feature  *//*  *  This function uses ftape_decode_header_segment() to inform the low *  level ftape module about the new parameters. * *  It erases the hseg_buf. The calling process must specify all *  parameters to assure proper operation. * *  return values: -EINVAL - wrong argument size *                 -EINVAL - if ftape_decode_header_segment() failed. */static int set_format_parms(struct ftfmtparms *p, __u8 *hseg_buf){	ft_trace_t old_level = TRACE_LEVEL;	TRACE_FUN(ft_t_flow);	TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_SETPARMS");	memset(hseg_buf, 0, FT_SEGMENT_SIZE);	PUT4(hseg_buf, FT_SIGNATURE, FT_HSEG_MAGIC);	/*  fill in user specified parameters	 */	hseg_buf[FT_FMT_CODE] = (__u8)p->ft_fmtcode;	PUT2(hseg_buf, FT_SPT, p->ft_spt);	hseg_buf[FT_TPC]      = (__u8)p->ft_tpc;	hseg_buf[FT_FHM]      = (__u8)p->ft_fhm;	hseg_buf[FT_FTM]      = (__u8)p->ft_ftm;	/*  fill in sane defaults to make ftape happy.	 */ 	hseg_buf[FT_FSM] = (__u8)128; /* 128 is hard wired all over ftape */	if (p->ft_fmtcode == fmt_big) {		PUT4(hseg_buf, FT_6_HSEG_1,   0);		PUT4(hseg_buf, FT_6_HSEG_2,   1);		PUT4(hseg_buf, FT_6_FRST_SEG, 2);		PUT4(hseg_buf, FT_6_LAST_SEG, p->ft_spt * p->ft_tpc - 1);	} else {		PUT2(hseg_buf, FT_HSEG_1,    0);		PUT2(hseg_buf, FT_HSEG_2,    1);		PUT2(hseg_buf, FT_FRST_SEG,  2);		PUT2(hseg_buf, FT_LAST_SEG, p->ft_spt * p->ft_tpc - 1);	}	/*  Synchronize with the low level module. This is particularly	 *  needed for unformatted cartridges as the QIC std was previously 	 *  unknown BUT is needed to set data rate and to calculate timeouts.	 */	TRACE_CATCH(ftape_calibrate_data_rate(p->ft_qicstd&QIC_TAPE_STD_MASK),		    _res = -EINVAL);	/*  The following will also recalcualte the timeouts for the tape	 *  length and QIC std we want to format to.	 *  abort with -EINVAL rather than -EIO	 */	SET_TRACE_LEVEL(ft_t_warn);	TRACE_CATCH(ftape_decode_header_segment(hseg_buf),		    SET_TRACE_LEVEL(old_level); _res = -EINVAL);	SET_TRACE_LEVEL(old_level);	TRACE_EXIT 0;}/* *  Return the internal SOFTWARE status of the kernel driver. This does *  NOT query the tape drive about its status. */static int get_format_parms(struct ftfmtparms *p, __u8 *hseg_buffer){	TRACE_FUN(ft_t_flow);	TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_GETPARMS");	p->ft_qicstd  = ft_qic_std;	p->ft_fmtcode = ft_format_code;	p->ft_fhm     = hseg_buffer[FT_FHM];	p->ft_ftm     = hseg_buffer[FT_FTM];	p->ft_spt     = ft_segments_per_track;	p->ft_tpc     = ft_tracks_per_tape;	TRACE_EXIT 0;}static int mtiocftformat(struct mtftformat *mtftformat, int arg_size){	int result;	union fmt_arg *arg = &mtftformat->fmt_arg;	TRACE_FUN(ft_t_flow);	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTFORMAT");	if (zft_offline) {		if (ft_no_tape) {			TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");		} else {			TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");		}	}	if (zft_qic_mode) {		TRACE_ABORT(-EACCES, ft_t_info,			    "driver needs to be in raw mode for this ioctl");	} 	if (zft_hseg_buf == NULL) {		TRACE_CATCH(zft_vcalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);	}	zft_header_read = 0;	switch(mtftformat->fmt_op) {	case FTFMT_SET_PARMS:		TRACE_CATCH(set_format_parms(&arg->fmt_parms, zft_hseg_buf),);		TRACE_EXIT 0;	case FTFMT_GET_PARMS:		TRACE_CATCH(get_format_parms(&arg->fmt_parms, zft_hseg_buf),);		TRACE_EXIT 0;	case FTFMT_FORMAT_TRACK:		if ((ft_formatted && zft_check_write_access(&zft_pos) < 0) ||		    (!ft_formatted && zft_write_protected)) {			TRACE_ABORT(-EACCES, ft_t_info, "Write access denied");		}		TRACE_CATCH(ftape_format_track(arg->fmt_track.ft_track,					       arg->fmt_track.ft_gap3),);		TRACE_EXIT 0;	case FTFMT_STATUS:		TRACE_CATCH(ftape_format_status(&arg->fmt_status.ft_segment),);		TRACE_EXIT 0;	case FTFMT_VERIFY:		TRACE_CATCH(ftape_verify_segment(arg->fmt_verify.ft_segment,				(SectorMap *)&arg->fmt_verify.ft_bsm),);		TRACE_EXIT 0;	default:		TRACE_ABORT(-EINVAL, ft_t_err, "Invalid format operation");	}	TRACE_EXIT result;}#endif#ifdef MTIOCFTCMD/* *  send a QIC-117 command to the drive, with optional timeouts, *  parameter and result bits. This is intended to be used together *  with the formatting ioctl. */static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size){	int i;	TRACE_FUN(ft_t_flow);	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");	if (!capable(CAP_SYS_ADMIN)) {		TRACE_ABORT(-EPERM, ft_t_info,			    "need CAP_SYS_ADMIN capability to send raw qic-117 commands");	}	if (zft_qic_mode) {		TRACE_ABORT(-EACCES, ft_t_info,			    "driver needs to be in raw mode for this ioctl");	} 	if (arg_size != sizeof(struct mtftcmd)) {		TRACE_ABORT(-EINVAL,			    ft_t_info, "bad argument size: %d", arg_size);	}	if (ftcmd->ft_wait_before) {		TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_before,					     &ftcmd->ft_status),);	}	if (ftcmd->ft_status & QIC_STATUS_ERROR)		goto ftmtcmd_error;	if (ftcmd->ft_result_bits != 0) {		TRACE_CATCH(ftape_report_operation(&ftcmd->ft_result,						   ftcmd->ft_cmd,						   ftcmd->ft_result_bits),);	} else {		TRACE_CATCH(ftape_command(ftcmd->ft_cmd),);		if (ftcmd->ft_status & QIC_STATUS_ERROR)			goto ftmtcmd_error;		for (i = 0; i < ftcmd->ft_parm_cnt; i++) {			TRACE_CATCH(ftape_parameter(ftcmd->ft_parms[i]&0x0f),);			if (ftcmd->ft_status & QIC_STATUS_ERROR)				goto ftmtcmd_error;		}	}	if (ftcmd->ft_wait_after != 0) {		TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_after,					     &ftcmd->ft_status),);	}ftmtcmd_error:	       	if (ftcmd->ft_status & QIC_STATUS_ERROR) {		TRACE(ft_t_noise, "error status set");		TRACE_CATCH(ftape_report_error(&ftcmd->ft_error,					       &ftcmd->ft_cmd, 1),);	}	TRACE_EXIT 0; /* this is not an i/o error */}#endif/*  IOCTL routine called by kernel-interface code */int _zft_ioctl(unsigned int command, void __user * arg){	int result;	union { struct mtop       mtop;		struct mtget      mtget;		struct mtpos      mtpos;#ifdef MTIOCRDFTSEG		struct mtftseg    mtftseg;#endif#ifdef MTIOCVOLINFO		struct mtvolinfo  mtvolinfo;#endif#ifdef MTIOCGETSIZE		struct mttapesize mttapesize;#endif#ifdef MTIOCFTFORMAT		struct mtftformat mtftformat;#endif#ifdef ZFT_OBSOLETE		struct mtblksz mtblksz;#endif#ifdef MTIOCFTCMD		struct mtftcmd mtftcmd;#endif	} krnl_arg;	int arg_size = _IOC_SIZE(command);	int dir = _IOC_DIR(command);	TRACE_FUN(ft_t_flow);	/* This check will only catch arguments that are too large !	 */	if (dir & (_IOC_READ | _IOC_WRITE) && arg_size > sizeof(krnl_arg)) {		TRACE_ABORT(-EINVAL,			    ft_t_info, "bad argument size: %d", arg_size);	}	if (dir & _IOC_WRITE) {		if (copy_from_user(&krnl_arg, arg, arg_size) != 0) {			TRACE_EXIT -EFAULT;		}	}	TRACE(ft_t_flow, "called with ioctl command: 0x%08x", command);	switch (command) {	case MTIOCTOP:		result = mtioctop(&krnl_arg.mtop, arg_size);		break;	case MTIOCGET:		result = mtiocget(&krnl_arg.mtget, arg_size);		break;	case MTIOCPOS:		result = mtiocpos(&krnl_arg.mtpos, arg_size);		break;#ifdef MTIOCVOLINFO	case MTIOCVOLINFO:		result = mtiocvolinfo(&krnl_arg.mtvolinfo, arg_size);		break;#endif#ifdef ZFT_OBSOLETE	case MTIOC_ZFTAPE_GETBLKSZ:		result = mtioc_zftape_getblksz(&krnl_arg.mtblksz, arg_size);		break;#endif#ifdef MTIOCRDFTSEG	case MTIOCRDFTSEG: /* read a segment via ioctl */		result = mtiocrdftseg(&krnl_arg.mtftseg, arg_size);		break;#endif#ifdef MTIOCWRFTSEG	case MTIOCWRFTSEG: /* write a segment via ioctl */		result = mtiocwrftseg(&krnl_arg.mtftseg, arg_size);		break;#endif#ifdef MTIOCGETSIZE	case MTIOCGETSIZE:		result = mtiocgetsize(&krnl_arg.mttapesize, arg_size);		break;#endif#ifdef MTIOCFTFORMAT	case MTIOCFTFORMAT:		result = mtiocftformat(&krnl_arg.mtftformat, arg_size);		break;#endif#ifdef MTIOCFTCMD	case MTIOCFTCMD:		result = mtiocftcmd(&krnl_arg.mtftcmd, arg_size);		break;#endif	default:		result = -EINVAL;		break;	}	if ((result >= 0) && (dir & _IOC_READ)) {		if (copy_to_user(arg, &krnl_arg, arg_size) != 0) {			TRACE_EXIT -EFAULT;		}	}	TRACE_EXIT result;}

⌨️ 快捷键说明

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