📄 dvd+rw-format.cpp
字号:
/* * DVD盧W format 4.10 by Andy Polyakov <appro@fy.chalmers.se>. * * Use-it-on-your-own-risk, GPL bless... * * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/. * * Revision history: * * 2.0: * - deploy "IMMED" bit in "FORMAT UNIT"; * 2.1: * - LP64 fix; * - USB workaround; * 3.0: * - C++-fication for better portability; * - SYSV signals for better portability; * - -lead-out option for improved DVD+RW compatibility; * - tested with SONY DRU-500A; * 4.0: * - support for DVD-RW formatting and blanking, tool name becomes * overloaded... * 4.1: * - re-make it work under Linux 2.2 kernel; * 4.2: * - attempt to make DVD-RW Quick Format truly quick, upon release * is verified to work with Pioneer DVR-x05; * - media reload is moved to growisofs where is actually belongs; * 4.3: * - -blank to imply -force; * - reject -blank in DVD+RW context and -lead-out in DVD-RW; * 4.4: * - support for -force=full in DVD-RW context; * - ask unit to perform OPC if READ DISC INFORMATION doesn't return * any OPC descriptors; * 4.5: * - increase timeout for OPC, NEC multi-format derivatives might * require more time to fulfill the OPC procedure; * 4.6: * - -force to ignore error from READ DISC INFORMATION; * - -force was failing under FreeBSD with 'unable to unmount'; * - undocumented -gui flag to ease progress indicator parsing for * GUI front-ends; * 4.7: * - when formatting DVD+RW, Pioneer DVR-x06 remained unaccessible for * over 2 minutes after dvd+rw-format exited and user was frustrated * to poll the unit himself, now dvd+rw-format does it for user; * 4.8: * - DVD-RW format fails if preceeded by dummy recording; * - make sure we talk to MMC unit, be less intrusive; * - unify error reporting; * - permit for -lead-out even for blank DVD+RW, needed(?) for SANYO * derivatives; * 4.9: * - permit for DVD-RW blank even if format descriptors are not present; * 4.10: * - add support for DVD-RAM; */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#include <signal.h>#include <setjmp.h>#include <sys/wait.h>#include <errno.h>#include "transport.hxx"static void usage (char *prog){ fprintf (stderr,"- usage: %s [-force[=full]] [-lead-out|-blank[=full]]\n" " [-ssa[=none|default|max]] /dev/cdrom\n",prog), exit(1);}static volatile int *progress;static const char *gui_action=NULL;extern "C" void alarm_handler (int no){ static int i=0,len=1,old_progress=0; static const char *str = "|/-\\",*backspaces="\b\b\b\b\b\b\b\b\b\b"; int new_progress = *progress; if (gui_action) { fprintf (stderr,"* %s %.1f%%\n",gui_action, 100.0*new_progress/65536.0); alarm(3); return; } if (new_progress != old_progress) len = fprintf (stderr,"%.*s%.1f%%",len,backspaces, 100.0*new_progress/65536.0) - len, old_progress = new_progress; else fprintf (stderr,"\b%c",str[i]), i++, i&=3; alarm(1);}int main (int argc, char *argv[]){ Scsi_Command cmd; unsigned char formats[260],dinfo[32],inq[128]; char *dev=NULL,*p; unsigned int capacity,lead_out,mmc_profile,err; int force=0,full=0,compat=0,blank=0,ssa=0,do_opc=0,gui=0,len,i; pid_t pid; fprintf (stderr,"* DVD盧W/-RAM format utility by <appro@fy.chalmers.se>, " "version 4.10.\n"); for (i=1;i<argc;i++) { if (*argv[i] == '-') if (argv[i][1] == 'f') // -format|-force { force = 1; if ((p=strchr(argv[i],'=')) && p[1]=='f') full=1; } else if (argv[i][1] == 'l') // -lead-out force = compat = 1; else if (argv[i][1] == 'b') // -blank { blank=0x11; if ((p=strchr(argv[i],'=')) && p[1]=='f') blank=0x10; force=1; } else if (argv[i][1] == 's') // -ssa { force=ssa=1; if ((p=strchr(argv[i],'='))) { if (p[1]=='n') ssa=-1; // =none else if (p[1]=='d') ssa=2; // =default else if (p[3]=='x') ssa=3; // =max else ssa=0; // invalid } } else if (argv[i][1] == 'g') gui=1; else usage(argv[0]); else if (*argv[i] == '/') dev = argv[i]; else usage (argv[0]); } if (dev==NULL) usage (argv[0]); if (!cmd.associate(dev)) fprintf (stderr,":-( unable to open(\"%s\"): ",dev), perror (NULL), exit(1); cmd[0] = 0x12; // INQUIRY cmd[4] = 36; cmd[5] = 0; if ((err=cmd.transport(READ,inq,36))) sperror ("INQUIRY",err), exit (1); if ((inq[0]&0x1F) != 5) fprintf (stderr,":-( not an MMC unit!\n"), exit (1); cmd[0] = 0x46; // GET CONFIGURATION cmd[8] = 8; cmd[9] = 0; if ((err=cmd.transport(READ,formats,8))) sperror ("GET CONFIGURATION",err), exit (1); mmc_profile = formats[6]<<8|formats[7]; if (mmc_profile!=0x1A && mmc_profile!=0x14 && mmc_profile!=0x13 && mmc_profile!=0x12) fprintf (stderr,":-( mounted media doesn't appear to be " "DVD盧W or DVD-RAM\n"), exit (1); /* * First figure out how long the actual list is. Problem here is * that (at least Linux) USB units absolutely insist on accurate * cgc.buflen and you can't just set buflen to arbitrary value * larger than actual transfer length. */ int once=1; do { cmd[0] = 0x23; // READ FORMAT CAPACITIES cmd[8] = 4; cmd[9] = 0; if ((err=cmd.transport(READ,formats,4))) { if (err==0x62800 && once) // "MEDIUM MAY HAVE CHANGED" { cmd[0] = 0; // TEST UNIT READY cmd[5] = 0; cmd.transport(); // just swallow it... continue; } sperror ("READ FORMAT CAPACITIES",err), exit (1); } } while (once--); len = formats[3]; if (len&7 || len<8) fprintf (stderr,":-( allocation length isn't sane\n"), exit(1); cmd[0] = 0x23; // READ FORMAT CAPACITIES cmd[7] = (4+len)>>8; // now with real length... cmd[8] = (4+len)&0xFF; cmd[9] = 0; if ((err=cmd.transport(READ,formats,4+len))) sperror ("READ FORMAT CAPACITIES",err), exit (1); if (len != formats[3]) fprintf (stderr,":-( parameter length inconsistency\n"), exit(1); if (mmc_profile==0x1A) // DVD+RW { for (i=8;i<len;i+=8) // look for "DVD+RW Full" descriptor if ((formats [4+i+4]>>2) == 0x26) break; } else if (mmc_profile==0x12) // DVD-RAM { unsigned int v,ref; unsigned char *f,descr=0x01; int j; switch (ssa) { case -1: // no ssa for (ref=0,i=len,j=8;j<len;j+=8) { f = formats+4+j; if ((f[4]>>2) == 0x00) { v=f[0]<<24|f[1]<<16|f[2]<<8|f[3]; if (v>ref) ref=v,i=j; } } break; case 0: i=8; // just grab the first descriptor? break; case 1: // first ssa for (i=8;i<len;i+=8) if ((formats[4+i+4]>>2) == 0x01) break; break; case 2: // default ssa descr=0x00; case 3: // max ssa for (ref=0xFFFFFFFF,i=len,j=8;j<len;j+=8) { f = formats+4+j; if ((f[4]>>2) == descr) { v=f[0]<<24|f[1]<<16|f[2]<<8|f[3]; if (v<ref) ref=v,i=j; } } break; } } else // DVD-RW { int descr=full?0x10:0x15; for (i=8;i<len;i+=8) // look for "DVD-RW Quick" descriptor if ((formats [4+i+4]>>2) == descr) break; if (descr==0x15 && i==len) { fprintf (stderr,":-( failed to locate \"Quick Format\" descriptor.\n"); for (i=8;i<len;i+=8)// ... alternatively for "DVD-RW Full" if ((formats [4+i+4]>>2) == 0x10) break; } } if (i==len) { fprintf (stderr,":-( can't locate appropriate format descriptor\n"); if (blank) i=0; else exit(1); } capacity = 0; capacity |= formats[4+i+0], capacity <<= 8; capacity |= formats[4+i+1], capacity <<= 8; capacity |= formats[4+i+2], capacity <<= 8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -