📄 transport.hxx
字号:
{ if (i==0) { memset(&ccb,0,sizeof(ccb)); ccb.ccb_h.path_id = cam->path_id; ccb.ccb_h.target_id = cam->target_id; ccb.ccb_h.target_lun = cam->target_lun; cam_fill_csio (&(ccb.csio), 1, // retries NULL, // cbfncp CAM_DEV_QFRZDIS, // flags MSG_SIMPLE_Q_TAG, // tag_action NULL, // data_ptr 0, // dxfer_len sizeof(ccb.csio.sense_data), // sense_len 0, // cdb_len 30*1000); // timeout } ccb.csio.cdb_len = i+1; return ccb.csio.cdb_io.cdb_bytes[i]; } unsigned char &operator()(size_t i) { return ((unsigned char *)&ccb.csio.sense_data)[i]; } unsigned char *sense() { return (unsigned char*)&ccb.csio.sense_data; } void timeout(int i) { ccb.ccb_h.timeout=i*1000; } size_t residue() { return ccb.csio.resid; } int transport(Direction dir=NONE,void *buf=NULL,size_t sz=0) { int ret=0; ccb.csio.ccb_h.flags |= dir; ccb.csio.data_ptr = (u_int8_t *)buf; ccb.csio.dxfer_len = sz; if ((ret = cam_send_ccb(cam, &ccb)) < 0) return -1; if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) return 0; unsigned char *sense=(unsigned char *)&ccb.csio.sense_data; errno = EIO; // FreeBSD 5-CURRENT since 2003-08-24, including 5.2 fails to // pull sense data automatically, at least for ATAPI transport, // so I reach for it myself... if ((ccb.csio.scsi_status==SCSI_STATUS_CHECK_COND) && !(ccb.ccb_h.status&CAM_AUTOSNS_VALID)) { u_int8_t _sense[18]; u_int32_t resid=ccb.csio.resid; memset(_sense,0,sizeof(_sense)); operator[](0) = 0x03; // REQUEST SENSE ccb.csio.cdb_io.cdb_bytes[4] = sizeof(_sense); ccb.csio.cdb_len = 6; ccb.csio.ccb_h.flags |= CAM_DIR_IN|CAM_DIS_AUTOSENSE; ccb.csio.data_ptr = _sense; ccb.csio.dxfer_len = sizeof(_sense); ccb.csio.sense_len = 0; ret = cam_send_ccb(cam, &ccb); ccb.csio.resid = resid; if (ret<0) return -1; if ((ccb.ccb_h.status&CAM_STATUS_MASK) != CAM_REQ_CMP) return errno=EIO,-1; memcpy(sense,_sense,sizeof(_sense)); } ret = ERRCODE(sense); if (ret == 0) ret = -1; else CREAM_ON_ERRNO(sense); return ret; } int umount(int f=-1) { struct stat fsb,msb; struct statfs *mntbuf; int ret=0,mntsize,i; if (f==-1) f=fd; if (fstat (f,&fsb) < 0) return -1; if ((mntsize=getmntinfo(&mntbuf,MNT_NOWAIT))==0)return -1; for (i=0;i<mntsize;i++) { if (stat (mntbuf[i].f_mntfromname,&msb) < 0) continue; if (msb.st_rdev == fsb.st_rdev) { ret=unmount (mntbuf[i].f_mntonname,0); break; } } return ret; }#define RELOAD_NEVER_NEEDED // according to Matthew Dillon int is_reload_needed () { return 0; }};#elif defined(__sun) || defined(sun)//// Licensing terms for commercial distribution for Solaris are to be// settled with Inserve Technology, 舦鋑en 6, 412 50 G諸EBORG, Sweden,// tel. +46-(0)31-86 87 88, see http://www.inserve.se/ for further// details.//#include <volmgt.h>extern "C" int _dev_unmount(char *); // VolMgt ON Consolidation Private API#include <sys/param.h>#include <sys/scsi/impl/uscsi.h>#include <sys/mount.h>#include <sys/mnttab.h>#include <sys/wait.h>#include <sys/cdio.h>#include <sys/utsname.h>#include <sys/dklabel.h>#include <sys/dkio.h>typedef enum { NONE=0, READ=USCSI_READ, WRITE=USCSI_WRITE } Direction;class Scsi_Command {private: int fd,autoclose; char *filename; struct uscsi_cmd ucmd; unsigned char cdb[16], _sense[18];public: Scsi_Command() { fd=-1, autoclose=1; filename=NULL; } Scsi_Command(int f) { fd=f, autoclose=0; filename=NULL; } Scsi_Command(void*f){ fd=(long)f, autoclose=0; filename=NULL; } ~Scsi_Command() { if (fd>=0 && autoclose) close(fd),fd=-1; if (filename) free(filename),filename=NULL; } int associate (const char *file,const struct stat *ref=NULL) { class autofree { private: char *ptr; public: autofree() { ptr=NULL; } ~autofree() { if (ptr) free(ptr); } char *operator=(char *str) { return ptr=str; } operator char *() { return ptr; } } volname,device; struct stat sb; int v; if ((v=volmgt_running())) { if ((volname=volmgt_symname ((char *)file))) { if ((device=media_findname (volname)) == NULL) return 0; } else if ((device=media_findname ((char *)file))==NULL) return 0; } else device=strdup(file); fd=open (device,O_RDONLY|O_NONBLOCK); if (fd<0) return 0; if (fstat(fd,&sb) < 0) return 0; if (!S_ISCHR(sb.st_mode)) { errno=ENOTTY; return 0; } if (ref && (!S_ISCHR(ref->st_mode) || ref->st_rdev!=sb.st_rdev)) { errno=ENXIO; return 0; } filename=strdup(device); return 1; } unsigned char &operator[] (size_t i) { if (i==0) { memset (&ucmd,0,sizeof(ucmd)); memset (cdb,0,sizeof(cdb)); memset (_sense,0,sizeof(_sense)); ucmd.uscsi_cdb = (caddr_t)cdb; ucmd.uscsi_rqbuf = (caddr_t)_sense; ucmd.uscsi_rqlen = sizeof(_sense); ucmd.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_ISOLATE | USCSI_RQENABLE; ucmd.uscsi_timeout= 60; } ucmd.uscsi_cdblen = i+1; return cdb[i]; } unsigned char &operator()(size_t i) { return _sense[i]; } unsigned char *sense() { return _sense; } void timeout(int i) { ucmd.uscsi_timeout=i; } size_t residue() { return ucmd.uscsi_resid; } int transport(Direction dir=NONE,void *buf=NULL,size_t sz=0) { int ret=0; ucmd.uscsi_bufaddr = (caddr_t)buf; ucmd.uscsi_buflen = sz; ucmd.uscsi_flags |= dir; if (ioctl(fd,USCSICMD,&ucmd)) { if (errno==EIO && _sense[0]==0) // USB seems to be broken... { size_t residue=ucmd.uscsi_resid; memset(cdb,0,sizeof(cdb)); cdb[0]=0x03; // REQUEST SENSE cdb[4]=sizeof(_sense); ucmd.uscsi_cdblen = 6; ucmd.uscsi_bufaddr = (caddr_t)_sense; ucmd.uscsi_buflen = sizeof(_sense); ucmd.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_ISOLATE | USCSI_READ; ucmd.uscsi_timeout = 1; ret = ioctl(fd,USCSICMD,&ucmd); ucmd.uscsi_resid = residue; if (ret) return -1; } ret = ERRCODE(_sense); if (ret==0) ret=-1; //else CREAM_ON_ERRNO(_sense); } return ret; } // mimics umount(2), therefore inconsistent return values int umount(int f=-1) { struct stat fsb,msb; struct mnttab mb; FILE *fp; pid_t pid,rpid; int ret=0,i,rval; if (f==-1) f=fd; if (fstat (f,&fsb) < 0) return -1; if ((fp=fopen (MNTTAB,"r")) == NULL) return -1; while ((i=getmntent (fp,&mb)) != -1) { if (i != 0) continue; // ignore corrupted lines if (stat (mb.mnt_special,&msb) < 0) continue; // also corrupted? if (msb.st_rdev == fsb.st_rdev) { if (_dev_unmount (mb.mnt_special)) break; { struct utsname uts; if (uname (&uts)>=0 && strcmp(uts.release,"5.8")>=0) { // M-m-m-m-m! Solaris 8 or later... ret = ::umount (mb.mnt_special); break; } } ret = -1; if ((pid = fork()) == (pid_t)-1) break; if (pid == 0) execl ("/usr/sbin/umount","umount",mb.mnt_mountp,NULL); while (1) { rpid = waitpid (pid,&rval,0); if (rpid == (pid_t)-1) { if (errno==EINTR) continue; else break; } else if (rpid != pid) { errno = ECHILD; break; } if (WIFEXITED(rval)) { if (WEXITSTATUS(rval) == 0) ret=0; else errno=EBUSY; // most likely break; } else if (WIFSTOPPED(rval) || WIFCONTINUED(rval)) continue; else { errno = ENOLINK; // some phony errno break; } } break; } } fclose (fp); return ret; } int is_reload_needed () { struct dk_minfo mi; struct dk_allmap pt; if (ioctl (fd,DKIOCGMEDIAINFO,&mi) < 0) return 1; memset (&pt,0,sizeof(pt)); pt.dka_map[2].dkl_nblk = mi.dki_capacity*(mi.dki_lbsize/DEV_BSIZE); pt.dka_map[0] = pt.dka_map[2]; if (ioctl (fd,DKIOCSAPART,&pt) < 0) return 1; return 0; }};#elif defined(__hpux)//// Copyright (C) 2003 Hewlett-Packard Development Company, L.P.// // 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//// =====================================================================//// The code targets 11i/11.11 and later, but it might just work on// 11.0 as well. For further information contact following HP office//// Hewlett-Packard Company// 3404 E Harmony Road// Fort Collins, CO 80528 USA//#include <strings.h>#include <sys/scsi.h>#include <mntent.h>#include <sys/mknod.h>typedef enum { NONE=0, READ=SCTL_READ, WRITE=0 } Direction;class Scsi_Command {private: int fd; int autoclose; char *filename; struct sctl_io cmd;public: Scsi_Command() { fd=-1, autoclose=1; filename=NULL; } Scsi_Command(int f) { fd=f, autoclose=0; filename=NULL; } Scsi_Command(void*f){ fd=(long)f, autoclose=0; filename=NULL; } ~Scsi_Command() { if (fd>=0 && autoclose) close(fd),fd=-1; if (filename) free(filename),filename=NULL; } int associate (const char *file,const struct stat *ref=NULL) { struct stat sb; fd=open (file,O_RDONLY|O_NONBLOCK); if (fd < 0) return 0; if (fstat(fd,&sb) < 0) return 0; if (!S_ISCHR(sb.st_mode)) { errno=EINVAL; return 0; } // shall we check for DIOC_DESCRIBE here? if (ref && (!S_ISCHR(ref->st_mode) || ref->st_rdev!=sb.st_rdev)) { errno=ENXIO; return 0; } filename=strdup(file); return 1; } unsigned char &operator[] (size_t i) { if (i==0) { bzero (&cmd,sizeof(struct sctl_io)); cmd.max_msecs=30*1000; } cmd.cdb_length = i+1; return cmd.cdb[i]; } unsigned char &sense(size_t i) { return cmd.sense[i]; } unsigned char *sense() { return cmd.sense; } void timeout(int i) { cmd.max_msecs=i*1000; } size_t residue() { return cmd.data_length-cmd.data_xfer; } int transport(Direction dir=NONE,void *buf=NULL,size_t sz=0) { const char *err = NULL; cmd.data = buf; cmd.data_length = sz; cmd.flags = dir; if (ioctl (fd,SIOC_IO,&cmd) != 0) return -1; if (cmd.cdb_status == S_GOOD) return 0; errno = EIO; switch (cmd.cdb_status) { case SCTL_INVALID_REQUEST: err = "SCTL_INVALID_REQUEST"; break; case SCTL_SELECT_TIMEOUT: err = "SCTL_SELECT_TIMEOUT"; break; case SCTL_INCOMPLETE: err = "SCTL_INCOMPLETE"; break; case SCTL_POWERFAIL: err = "SCTL_POWERFAIL"; break; default: err = NULL; break; } if (err != NULL) { fprintf (stderr,":-( FAIL: command failed with %s.\n",err); return -1; } switch (cmd.cdb_status & 0xff) { case S_CHECK_CONDITION: if (cmd.sense_status==S_GOOD && cmd.sense_xfer!=0) { CREAM_ON_ERRNO_NAKED(cmd.sense) // CREAM_ON_ERRNO // provokes PA-RISC // compiler bug... return ERRCODE(cmd.sense); } else fprintf (stderr,":-( FAIL: S_CHECK_CONDITION status, " "but no sense data?\n"); break; case S_BUSY: fprintf (stderr,":-( FAIL: S_BUSY condition?\n"); errno = EAGAIN; break; default: fprintf (stderr,":-( FAIL: unknown cdb_status=0x%x\n", cmd.cdb_status); break; } return -1; } // for now we only detect if media is mounted... int umount(int f=-1) { struct stat fsb,msb; struct mntent *mb; FILE *fp; int ret=0; char bdev[32]; dev_t m; if (f==-1) f=fd; if (fstat (f,&fsb) < 0) return -1; if ((fp=setmntent (MNT_MNTTAB,"r")) == NULL) return -1; m=minor(fsb.st_rdev); sprintf(bdev,"/dev/dsk/c%ut%ud%x",(m>>16)&0xFF,(m>>12)&0xF,(m>>8)&0xF); if (stat (bdev,&fsb) < 0) return -1; while ((mb=getmntent (fp))!=NULL) { if (stat (mb->mnt_fsname,&msb) < 0) continue; // corrupted line? if (msb.st_rdev == fsb.st_rdev) { errno=EBUSY; ret=-1; break; } } endmntent (fp); return ret; } int is_reload_needed () { return 1; }};#elif defined(__sgi)//// Not necessarily relevant IRIX notes.//// Information about UDF support seems to be contradictory. Some manuals// maintain that UDF writing is supported for DVD-RAM and hard disk, but// the only mention of UDF in IRIX release notes is "6.5.18 introduces// read-only support for the UDF filesystems format." If UDF writing is// supported, then it was implemented presumably in 6.5.21. DVD-RAM// writing at block device level was most likely introduced by then too.//// IRIX doesn't provide access to files larger than 2GB on ISO9660.// That's because ISO9660 is implemented as NFSv2 user-land server,// and 2GB limit is implied by NFSv2 protocol.//#ifdef PRIVATE#undef PRIVATE // <sys/dsreq.h> conflicts with <sys/mman.h>?#endif#include <sys/dsreq.h>#ifdef PRIVATE#undef PRIVATE // <sys/dsreq.h> conflicts with <sys/mman.h>?#endif#include <mntent.h>#include <sys/wait.h>#include <poll.h>#include <sys/attributes.h>#include <sys/param.h>#include <mediad.h>typedef enum { NONE=0, READ=DSRQ_READ, WRITE=DSRQ_WRITE } Direction;class Scsi_Command {private: int fd,autoclose; char *filename; dsreq_t req; unsigned char cdb[16], _sense[18];public: Scsi_Command() { fd=-1, autoclose=1; filename=NULL; } Scsi_Command(int f) { fd=f, autoclose=0; filename=NULL; } Scsi_Command(void*f){ fd=(long)f, autoclose=0; filename=NULL; } ~Scsi_Command() { if (fd>=0 && autoclose) close(fd),fd=-1; if (filename) free(filename),filename=NULL; } int associate (const char *file,const struct stat *ref=NULL) { struct stat sb; char hw_path[MAXPATHLEN]; int hw_len=sizeof(hw_path)-1; if (attr_get(file,"_devname",hw_path,&hw_len,0)) return 0; if (hw_len>=sizeof(hw_path)) hw_len=sizeof(hw_path)-1; // paranoia hw_path[hw_len]='\0'; if (ref) { // hw_path is maintained by kernel through hwgfs and // I assume it's not subject to race conditions... if (stat(hw_path,&sb)) return 0; if (!S_ISCHR(ref->st_mode) || ref->st_rdev!=sb.st_rdev) { errno=ENXIO; return 0; } } if (strcmp(hw_path+strlen(hw_path)-5,"/scsi")) { char *s=strstr(hw_path,"/disk/"); if (s==NULL) { errno=EINVAL; return 0; } strcpy (s,"/scsi"); } fd=open (hw_path,O_RDONLY|O_NONBLOCK); if (fd<0) return 0; if (fstat(fd,&sb) < 0) return 0; if (!S_ISCHR(sb.st_mode)) { errno=ENOTTY; return 0; } filename=strdup(file); return 1; } unsigned char &operator[] (size_t i) { if (i==0) { memset (&req,0,sizeof(req)); memset (cdb,0,sizeof(cdb)); memset (_sense,0,sizeof(_sense)); req.ds_cmdbuf = (caddr_t)cdb; req.ds_sensebuf = (caddr_t)_sense;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -