Beispiel #1
0
static PyObject *
CD_addcallback(cdparserobject *self, PyObject *args)
{
	int type;
	PyObject *func, *funcarg;

	/* XXX - more work here */
	if (!PyArg_ParseTuple(args, "iOO:addcallback", &type, &func, &funcarg))
		return NULL;

	if (type < 0 || type >= NCALLBACKS) {
		PyErr_SetString(PyExc_TypeError, "argument out of range");
		return NULL;
	}

#ifdef CDsetcallback
	CDaddcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback,
		      (void *) self);
#else
	CDsetcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback,
		      (void *) self);
#endif
	Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
	Py_INCREF(func);
	self->ob_cdcallbacks[type].ob_cdcallback = func;
	Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
	Py_INCREF(funcarg);
	self->ob_cdcallbacks[type].ob_cdcallbackarg = funcarg;

/*
	if (type == cd_audio) {
		sigfpe_[_UNDERFL].repls = _ZERO;
		handle_sigfpes(_ON, _EN_UNDERFL, NULL,
		                        _ABORT_ON_ERROR, NULL);
	}
*/

	Py_INCREF(Py_None);
	return Py_None;
}
Beispiel #2
0
int main(int argc, char **argv) 
{
  iso_primary_descriptor_type  ipd;
  char *dev = default_dev;
  char vendor[9],model[17],rev[5];
  unsigned char reply[1024];
  char tmpstr[255];
  int replylen=sizeof(reply);
  int trackno = 0;
  int info_only = 0;
  unsigned char *buffer;
  int buffersize = READBLOCKS*BLOCKSIZE;
  int start,stop,imagesize=0,tracksize=0;
  int counter = 0;
  long readsize = 0;
  long imagesize_bytes = 0;
  int drive_block_size, init_bsize;
  int force_mode = 0;
  int scanbus_mode = 0;
  int dump_start, dump_count;
  MD5_CTX *MD5; 
  char digest[16],digest_text[33];
  int md5_mode = 0;
  int opt_index = 0;
  int audio_track = 0;
  int readblocksize = BLOCKSIZE;
  int file_format = AF_FILE_AIFFC;
#ifdef IRIX
  CDPARSER *cdp = CDcreateparser();
  CDFRAME  cdframe;
#endif
  int dev_type;
  int i,c,o;
  int len;
  int start_time,cur_time,kbps;

  if (rcsid); 

  MD5 = malloc(sizeof(MD5_CTX));
  buffer=(unsigned char*)malloc(READBLOCKS*AUDIOBLOCKSIZE);
  if (!buffer || !MD5) die("No memory");

  if (argc<2) die("parameter(s) missing\n"
	          "Try '%s --help' for more information.\n",PRGNAME);

 
  /* parse command line parameters */
  while(1) {
    if ((c=getopt_long(argc,argv,"SMmvhid:",long_options,&opt_index))
	== -1) break;
    switch (c) {
    case 'a':
      file_format=AF_FILE_AIFF;
      break;
    case 'A':
      file_format=AF_FILE_AIFFC;
      break;
    case 'v':
      verbose_mode=1;
      break;
    case 'h':
      p_usage();
      break;
    case 'd':
      dev=strdup(optarg);
      break;
    case 't':
      if (sscanf(optarg,"%d",&trackno)!=1) trackno=0;
      break;
    case 'i':
      info_only=1; 
      break;
    case 'c':
      if (sscanf(optarg,"%d,%d",&dump_start,&dump_count)!=2)
	die("invalid parameters");
      dump_mode=1;
      break;
#ifdef IRIX
    case 'C':
      if (sscanf(optarg,"%d,%d",&dump_start,&dump_count)!=2)
	die("invalid parameters");
      dump_mode=2;
      break;
#endif
    case 'f':
      if (sscanf(optarg,"%d",&force_mode)!=1) die("invalid parameters");
      if (force_mode<1 || force_mode >2) {
	die("invalid parameters");
      }
      break;
    case 'm':
      md5_mode=1;
      break;
    case 'M':
      md5_mode=2;
      break;
    case 's':
      audio_mode=1;
      break;
    case 'S':
      scanbus_mode=1;
      break;
    case 'V':
      printf(PRGNAME " "  VERSION "  " HOST_TYPE
	     "\nCopyright (c) Timo Kokkonen, 1997-1998.\n\n"); 
      exit(0);
      break;

    case '?':
      break;

    default:
      die("error parsing parameters");

    }
  }


  if (!info_only) {
    if (md5_mode==2) outfile=fopen("/dev/null","w");
    else outfile=fopen(argv[optind],"w");
    if (!outfile) {
      if (argv[optind]) die("cannot open output file '%s'",argv[optind]);
      info_only=1;
    }
  }

  printf("readiso(9660) " VERSION "\n");

  /* open the scsi device */
  if (scsi_open(dev)) die("error opening scsi device '%s'",dev); 

  if (scanbus_mode) {
    printf("\n");
    scan_bus();
    exit(0);
  }
  
  memset(reply,0,sizeof(reply));
  if ((dev_type=inquiry(vendor,model,rev))<0) 
    die("error accessing scsi device");

  if (verbose_mode) {
    printf("device:   %s\n",dev);
    printf("Vendor:   %s\nModel:    %s\nRevision: %s\n",vendor,model,rev);
  }

  if ( (dev_type&0x1f) != 0x5 ) {
    die("Device doesn't seem to be a CD-ROM!");
  }

#ifdef IRIX
  if (strcmp(vendor,"TOSHIBA")) {
    warn("NOTE! Audio track reading probably not supported on this device.\n");
  }
#endif

  test_ready();
  if (test_ready()!=0) {
    sleep(2);
    if (test_ready()!=0)  die("device not ready");
  }

  fprintf(stderr,"Initializing...\n");
  if (audio_mode) {
#ifdef IRIX
    audioport=ALopenport("readiso","w",0);
    if (!audioport) {
      warn("Cannot initialize audio.");
      audio_mode=0;
    }
#else
    audio_mode=0;
#endif
  }


#ifdef IRIX
  /* Make sure we get sane underflow exception handling */
  sigfpe_[_UNDERFL].repls = _ZERO;
  handle_sigfpes(_ON, _EN_UNDERFL, NULL, _ABORT_ON_ERROR, NULL);
#endif

  /* set_removable(1); */

#if 0
  replylen=255;
  if (mode_sense10(reply,&replylen)==0) {
    printf("replylen=%d blocks=%d blocklen=%d\n",replylen,
	   V3(&reply[8+1]),V3(&reply[8+5]));
    PRINT_BUF(reply,replylen);
  }
  replylen=255; /* sizeof(reply); */
  if (mode_sense(reply,&replylen)==0) {
    printf("replylen=%d blocks=%d blocklen=%d\n",replylen,
	   V3(&reply[4+1]),V3(&reply[4+5]));
    PRINT_BUF(reply,replylen);
  }
#endif

  if (dump_mode==2) init_bsize=AUDIOBLOCKSIZE;
  else init_bsize=BLOCKSIZE;

  start_stop(0);

  if ( (drive_block_size=get_block_size()) < 0 ) {
    warn("cannot get current block size");
    drive_block_size=init_bsize;
  }

  if (drive_block_size != init_bsize) {
    mode_select(init_bsize,(dump_mode==2?0x82:0x00));
    drive_block_size=get_block_size();
    if (drive_block_size!=init_bsize) warn("cannot set drive block size.");
  }

  start_stop(1);

  if (dump_mode && !info_only) {
#ifdef IRIX
    CDFRAME buf;
    if (dump_mode==2) {
      if (cdp) {
	CDaddcallback(cdp, cd_audio, (CDCALLBACKFUNC)playaudio, 0);
      } else die("No audioparser");
    }
#endif
    fprintf(stderr,"Dumping %d sector(s) starting from LBA=%d\n",
	    dump_count,dump_start);
    for (i=dump_start;i<dump_start+dump_count;i++) {
      len=buffersize;
      read_10(i,1,buffer,&len);
      if (len<init_bsize) break;

#ifdef IRIX
      if (dump_mode==2) {
	memcpy(&buf,buffer,CDDA_BLOCKSIZE);
	CDparseframe(cdp,&buf);
      }
#endif
	
      fwrite(buffer,len,1,outfile); 
      fprintf(stderr,".");
    }
    fprintf(stderr,"\ndone.\n");
    
    goto quit;
  }


  fprintf(stderr,"Reading disc TOC...");
  replylen=sizeof(reply);
  read_toc(reply,&replylen,verbose_mode);
  printf("\n");

  if (trackno==0) { /* try to find first data track */
    for (i=0;i<(reply[3]-reply[2]+1);i++) {
      o=4+i*8;
      if (reply[o+1]&DATA_TRACK) { trackno=i+1; break; }
    }
    if (trackno==0) die("No data track(s) found.");
  }

  fprintf(stderr,"Reading track %d...\n",trackno); 

  if ( (trackno < reply[2]) || (trackno > reply[3]) )
    die("Invalid track specified.");
    
  if ( ((reply[(trackno-1)*8+4+1]&DATA_TRACK)==0) ) {
    fprintf(stderr,"Not a data track.\n");
    mode_select(AUDIOBLOCKSIZE,0x82);
    if (mode_sense(reply,&replylen)!=0) die("cannot get sense data");
    drive_block_size=V3(&reply[9]);
    fprintf(stderr,"Selecting CD-DA mode, output file format: %s\n",
	    file_format==AF_FILE_AIFFC?"AIFFC":"AIFF");
    audio_track=1;
  } else {
    audio_track=0;
  }


  start=V4(&reply[(trackno-1)*8+4+4]);
  stop=V4(&reply[(trackno)*8+4+4]);
  tracksize=abs(stop-start);
  /* if (verbose_mode) printf("Start LBA=%d\nStop  LBA=%d\n",start,stop); */

  len=buffersize;
  read_10(start-0,1,buffer,&len);
  /* PRINT_BUF(buffer,32); */

  
  if (!audio_track) {
    /* read the iso9660 primary descriptor */
    fprintf(stderr,"Reading ISO9660 primary descriptor...\n");
    len=buffersize;
    read_10(start+16,1,buffer,&len);
    if (len<sizeof(ipd)) die("cannot read iso9660 primary descriptor.");
    memcpy(&ipd,buffer,sizeof(ipd));
    
    imagesize=ISONUM(ipd.volume_space_size);
    
    /* we should really check here if we really got a valid primary 
       descriptor or not... */
    if ( (imagesize>(stop-start)) || (imagesize<1) ) {
      fprintf(stderr,"\aInvalid ISO primary descriptor!!!\n");
      if (!info_only) fprintf(stderr,"Copying entire track to image file.\n");
      force_mode=2;
    }
    
    if (force_mode==1) {} /* use size from ISO primary descriptor */
    else if (force_mode==2) imagesize=tracksize; /* use size from TOC */
    else {
      if (  ( (tracksize-imagesize) > MAX_DIFF_ALLOWED ) || 
	    ( imagesize > tracksize )  )   {
	fprintf(stderr,"ISO primary descriptor has suspicious volume size"
		" (%d blocks)\n",imagesize);
	imagesize=tracksize;
	fprintf(stderr,
		"Using track size from TOC record (%d blocks) instead.\n", 
		imagesize);
	fprintf(stderr,
		"(option -f can be used to override this behaviour.)\n");
      }
    }

    imagesize_bytes=imagesize*BLOCKSIZE;
    

    if (verbose_mode||info_only) {
      printf("ISO9660 image info:\n");
      printf("Type:              %02xh\n",ipd.type[0]);  
      ISOGETSTR(tmpstr,ipd.id,5);
      printf("ID:                %s\n",tmpstr);
      printf("Version:           %u\n",ipd.version[0]);
      ISOGETSTR(tmpstr,ipd.system_id,32);
      printf("System id:         %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.volume_id,32);
      printf("Volume id:         %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.volume_set_id,128);
      if (strlen(tmpstr)>0) printf("Volume set id:     %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.publisher_id,128);
      if (strlen(tmpstr)>0) printf("Publisher id:      %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.preparer_id,128);
      if (strlen(tmpstr)>0) printf("Preparer id:       %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.application_id,128);
      if (strlen(tmpstr)>0) printf("Application id:    %s\n",tmpstr);
      ISOGETDATE(tmpstr,ipd.creation_date);
      printf("Creation date:     %s\n",tmpstr);
      ISOGETDATE(tmpstr,ipd.modification_date);
      if (!NULLISODATE(ipd.modification_date)) 
	printf("Modification date: %s\n",tmpstr);
      ISOGETDATE(tmpstr,ipd.expiration_date);
      if (!NULLISODATE(ipd.expiration_date))
	printf("Expiration date:   %s\n",tmpstr);
      ISOGETDATE(tmpstr,ipd.effective_date);
      if (!NULLISODATE(ipd.effective_date))
	printf("Effective date:    %s\n",tmpstr);
      
      printf("Image size:        %02d:%02d:%02d, %d blocks (%ld bytes)\n",
	      LBA_MIN(ISONUM(ipd.volume_space_size)),
	      LBA_SEC(ISONUM(ipd.volume_space_size)),
	      LBA_FRM(ISONUM(ipd.volume_space_size)),
	      ISONUM(ipd.volume_space_size),
	      (long)ISONUM(ipd.volume_space_size)*BLOCKSIZE
	     );
      printf("Track size:        %02d:%02d:%02d, %d blocks (%ld bytes)\n",
	      LBA_MIN(tracksize),
	      LBA_SEC(tracksize),
	      LBA_FRM(tracksize),
	      tracksize,
	      (long)tracksize*BLOCKSIZE
	     );
    }
  } else { 
#ifdef IRIX
    /* if reading audio track */
    imagesize=tracksize;
    imagesize_bytes=imagesize*CDDA_DATASIZE;
    buffersize = READBLOCKS*AUDIOBLOCKSIZE;
    readblocksize = AUDIOBLOCKSIZE;

    if (cdp) {
      CDaddcallback(cdp, cd_audio, (CDCALLBACKFUNC)playaudio, 0);
    } else die("No audioparser");
    
    fclose(outfile);
    aiffsetup=AFnewfilesetup();
    AFinitrate(aiffsetup,AF_DEFAULT_TRACK,44100.0); /* 44.1 kHz */
    AFinitfilefmt(aiffsetup,file_format);           /* set file format */
    AFinitchannels(aiffsetup,AF_DEFAULT_TRACK,2);   /* stereo */
    AFinitsampfmt(aiffsetup,AF_DEFAULT_TRACK,
		  AF_SAMPFMT_TWOSCOMP,16);          /* 16bit */
    aiffoutfile=AFopenfile(argv[optind],"w",aiffsetup);
    if (!aiffoutfile) die("Cannot open target file (%s).",argv[optind]);
#endif
  }

  /* read the image */

  if (md5_mode) MD5Init(MD5);

  if (!info_only) {
    start_time=(int)time(NULL);
    fprintf(stderr,"Reading %s (%ldMb)...\n",
	    audio_track?"audio track":"ISO9660 image",
	    imagesize_bytes/(1024*1024));

    do {
      len=buffersize;
      if(readsize/readblocksize+READBLOCKS>imagesize) {
	read_10(start+counter,imagesize-readsize/readblocksize,buffer,&len);
      }
      else
	read_10(start+counter,READBLOCKS,buffer,&len);
      if ((counter%(1024*1024/readblocksize))<READBLOCKS) {
	cur_time=(int)time(NULL);
	if ((cur_time-start_time)>0) {
	  kbps=(readsize/1024)/(cur_time-start_time);
	} else {
	  kbps=0;
	}
	
	fprintf(stderr,"%3dM of %dM read. (%d kb/s)         \r",
		counter/512,imagesize/512,kbps);
      }
      counter+=READBLOCKS;
      readsize+=len;
      if (!audio_track) {
	fwrite(buffer,len,1,outfile);
      } else {
#ifdef IRIX
	/* audio track */
	for(i=0;i<(len/CDDA_BLOCKSIZE);i++) {
	  CDparseframe(cdp,(CDFRAME*)&buffer[i*CDDA_BLOCKSIZE]);
	}
#endif
      }
      if (md5_mode) MD5Update(MD5,buffer,(readsize>imagesize_bytes?
				       len-(readsize-imagesize_bytes):len) );
    } while (len==readblocksize*READBLOCKS&&readsize<imagesize*readblocksize);
    
    fprintf(stderr,"\n");
    if (!audio_track) {
      if (readsize > imagesize_bytes) 
	ftruncate(fileno(outfile),imagesize_bytes);
      if (readsize < imagesize_bytes) 
	fprintf(stderr,"Image not complete!\n");
      else fprintf(stderr,"Image complete.\n");
      fclose(outfile);
    } else {
#ifdef IRIX
      AFclosefile(aiffoutfile);
#endif
    }
  }

  if (md5_mode && !info_only) {
    MD5Final((unsigned char*)digest,MD5);
    md2str((unsigned char*)digest,digest_text);
    fprintf(stderr,"MD5 (%s) = %s\n",(md5_mode==2?"'image'":argv[optind]),
	    digest_text);
  }

 quit:
  start_stop(0);
  /* set_removable(1); */

  /* close the scsi device */
  scsi_close();

  return 0;
}