/*************************************************************************** $RCSfile: ctfstool.cpp,v $ ------------------- cvs : $Id: ctfstool.cpp,v 1.11 2003/05/08 11:01:23 aquamaniac Exp $ begin : Mon Apr 22 2002 copyright : (C) 2002 by Martin Preuss email : martin@libchipcard.de **************************************************************************** * 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 * ****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif /* Internationalization */ #ifdef HAVE_GETTEXT_ENVIRONMENT # include # include # define I18N(m) gettext(m) #else # define I18N(m) m #endif #define I18NT(m) m #include #include #include #include #include #define k_BLOCKSIZE 2048 #define k_PRG "ctfstool" #define k_PRG_VERSION_INFO \ "ctfstool v0.4 (part of libchipcard v"k_CHIPCARD_VERSION_STRING")\n"\ "(c) 2002 Martin Preuss\n"\ "This program is free software licensed under GPL.\n"\ "See COPYING for details.\n" void usage() { fprintf(stdout, I18N("CTFSTool - A tool to manipulate files on a CTFileSystem hosted\n" " by a memory chip card.\n" "(c) 2002 Martin Preuss\n" "This library is free software; you can redistribute it and/or\n" "modify it under the terms of the GNU Lesser General Public\n" "License as published by the Free Software Foundation; either\n" "version 2.1 of the License, or (at your option) any later version.\n" "\n" "Usage:\n" k_PRG" COMMAND [ARGS] [-u USERNAME] [-p PASSWD] [-C CONFIGFILE]\n" k_PRG" format SIZE NAME - format medium with SIZE bytes and\n" " given NAME\n" k_PRG" scratch SIZE - overwrite SIZE bytes on the card\n" k_PRG" info - show statistical info about the card\n" k_PRG" ls DIR - show content of given dir on the card\n" k_PRG" mkdir DIR - create directory DIR on the card\n" k_PRG" rmdir PATH - remove empty folder PATH from the card\n" k_PRG" rm PATH - remove file PATH from the card\n" k_PRG" cat FILE - dump content of the given file on the card\n" " to stdout\n" k_PRG" read SRC DST - read a file from the card and store\n" " it locally\n" k_PRG" write SRC DST - store a local file on the card\n" k_PRG" mv OLD NEW - rename file/dir OLD to NEW. Both\n" " names may be in different paths. In \n" " this case the file will be moved.\n" "\nOptions:\n" " -u USER - use USER for authentification\n" " -p PASS - use PASS for authentification\n" " -h - show this help\n" " -V - show version information\n" " -v - be more verbous\n" " -C CONFIGFILE - configuration file to be used\n") ); } struct s_args { string username; // -u string password; // -p string configFile; // -C bool verbous; // -v list params; }; int checkArgs(s_args &args, int argc, char **argv) { int i; string tmp; args.verbous=false; args.configFile=CHIPCARDC_CFGFILE; i=1; while (i=argc) return 1; args.username=argv[i]; } else if (tmp=="-C") { i++; if (i>=argc) return 1; args.configFile=argv[i]; } else if (tmp=="-p") { i++; if (i>=argc) return 1; args.password=argv[i]; } else if (tmp=="-h" || tmp=="--help") { usage(); return -1; } else if (tmp=="-V" || tmp=="--version") { fprintf(stdout,k_PRG_VERSION_INFO); return -1; } else if (tmp=="-v") { args.verbous=true; } else // otherwise add param args.params.push_back(tmp); i++; } // while // that's it return 0; } int openCard(CTPointer &card, bool quiet=false) { CTPointer trader; CTError err; CTCard *cp; trader=new CTCardTrader(false, 0, 0, CHIPCARD_STATUS_INSERTED, CHIPCARD_STATUS_INSERTED | CHIPCARD_STATUS_LOCKED_BY_OTHER, CHIPCARD_STATUS_INSERTED); err=trader.ref().start(); if (!err.isOk()) { fprintf(stderr, I18N("Could not initialize trader")); return 2; } if (!quiet) fprintf(stderr, I18N("Please insert your card into any reader\n")); // get the card err=trader.ref().getNext(cp, 30); if (!err.isOk()) { if (err.code()==k_CTERROR_API && (err.subcode1()==CHIPCARD_ERROR_NO_TRANSPORT || err.subcode1()==CHIPCARD_ERROR_NO_REQUEST)) { fprintf(stderr, I18N("Service unreachable, maybe \"chipcardd\" is not running?\n") ); return 2; } fprintf(stderr,I18N("No card inserted within some seconds, aborting.\n")); return 2; } err=trader.ref().stop(); if (!err.isOk()) { fprintf(stderr, I18N("Could not stop trader")); return 2; } card=cp; if (card.ref().isProcessorCard()) { fprintf(stderr, I18N("Not a memory card")); return 3; } if (!quiet) fprintf(stderr,I18N("Card is inserted, working.\n")); return 0; } int formatMedium(s_args args){ CTPointer cardfs; CTPointer basecard; int msize; string name; CTError err; int rv; if (args.params.size()!=2) { usage(); return 1; } sscanf(args.params.front().c_str(),"%i",&msize); if (!msize) { fprintf(stderr,I18N("Bad size (%d).\n"),msize); return 1; } name=args.params.back(); try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; err=cardfs.ref().openCard(); if (!err.isOk()) { fprintf(stderr,"%s\n",err.errorString().c_str()); return 3; } err=cardfs.ref().createMedium(msize, name, args.username, args.password); if (!err.isOk()) throw err; } // try catch (CTError xerr) { fprintf(stderr,"Exception: %s\n",xerr.errorString().c_str()); return 3; } return 0; } int mkDir(s_args args){ CTPointer cardfs; CTPointer basecard; CTDirectory dir; string name; CTError err; int rv; if (args.params.size()!=1) { usage(); return 1; } name=args.params.front(); try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } dir=CTDirectory(cardfs,name); err=dir.createDirectory(); if (!err.isOk()) throw err; err=dir.closeDirectory(); if (!err.isOk()) throw err; err=cardfs.ref().unmountMedium(); if (!err.isOk()) throw err; } // try catch (CTError xerr) { fprintf(stderr,"Exception: %s\n",xerr.errorString().c_str()); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } return 0; } int rmDir(s_args args){ CTPointer cardfs; CTPointer basecard; CTDirectory dir; string name; CTError err; int rv; if (args.params.size()!=1) { usage(); return 1; } name=args.params.front(); try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } dir=CTDirectory(cardfs,name); err=dir.removeDirectory(); if (!err.isOk()) throw err; err=cardfs.ref().unmountMedium(); if (!err.isOk()) throw err; } // try catch (CTError xerr) { fprintf(stderr,"Exception: %s\n",xerr.errorString().c_str()); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } return 0; } int rmFile(s_args args){ CTPointer cardfs; CTPointer basecard; CTFile file; string name; CTError err; int rv; if (args.params.size()!=1) { usage(); return 1; } name=args.params.front(); try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } file=CTFile(cardfs,name); err=file.removeFile(); if (!err.isOk()) throw err; err=cardfs.ref().unmountMedium(); if (!err.isOk()) throw err; } // try catch (CTError xerr) { fprintf(stderr,"Exception: %s\n",xerr.errorString().c_str()); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } return 0; } int writeToCard(s_args args){ CTPointer cardfs; CTPointer basecard; CTFile cf; string sname; string dname; FILE *sf; char buffer[k_BLOCKSIZE]; int i; string tmp; CTError err; int bytesRead; int rv; if (args.params.size()!=2) { usage(); return 1; } sname=args.params.front(); dname=args.params.back(); // try to open the source file sf=fopen(sname.c_str(),"r"); if (!sf) { fprintf(stderr,I18N("Could not open %s (%s)\n"), sname.c_str(),strerror(errno)); return 2; } // mount medium, create detination file try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; cf=CTFile(cardfs,dname); err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } err=cf.createFile(); if (!err.isOk()) throw CTError("writeToCard",err); // actually copy file bytesRead=0; while (!feof(sf)) { // read from file i=fread(buffer,1,sizeof(buffer),sf); if (i<1) break; bytesRead+=i; if (args.verbous) fprintf(stderr, I18N("Bytes read: %d\r"), bytesRead); tmp.assign(buffer,i); // write to card err=cf.writeString(tmp); if (!err.isOk()) throw CTError("writeToCard",err); } // while if (args.verbous) fprintf(stderr,"\n"); // close destination file err=cf.closeFile(); if (!err.isOk()) throw CTError("writeToCard",err); // remove destination file on read error if (ferror(sf)) { fprintf(stderr,I18N("Error reading from %s (%s)\n"), sname.c_str(),strerror(errno)); //cf.ref().removeFile(); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } //cardfs.ref().purge(); // DEBUG if (args.verbous) fprintf(stderr, I18N("Now writing to the card, please wait.\n" "This may take some minutes depending on " "the data size,\n")); cardfs.ref().unmountMedium(); } // try catch (CTError xerr) { fprintf(stderr,"\nException: %s\n",xerr.errorString().c_str()); fclose(sf); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } if (fclose(sf)) { fprintf(stderr,I18N("Could not close %s (%s)\n"), sname.c_str(),strerror(errno)); return 2; } return 0; } int readFromCard(s_args args){ CTPointer cardfs; CTPointer basecard; CTFile cf; string sname; string dname; FILE *sf; int i; string tmp; CTError err; int bytesRead; int rv; if (args.params.size()!=2) { usage(); return 1; } sname=args.params.front(); dname=args.params.back(); // try to open the source file sf=fopen(dname.c_str(),"w+"); if (!sf) { fprintf(stderr,I18N("Could not open %s (%s)\n"), dname.c_str(),strerror(errno)); return 2; } // mount medium, create detination file cf=CTFile(cardfs,sname); try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; cf=CTFile(cardfs,sname); err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } err=cf.openFile(); if (!err.isOk()) throw err; // actually copy file bytesRead=0; while(1) { tmp=cf.readString(k_BLOCKSIZE); if (tmp.length()==0) break; bytesRead+=tmp.length(); if (args.verbous) fprintf(stderr, I18N("Bytes read: %d\r"), bytesRead); i=fwrite(tmp.data(),1,tmp.length(),sf); if (i!=(int)tmp.length()) { fprintf(stderr,I18N("Error writing to %s (%s)\n"), dname.c_str(),strerror(errno)); } } // while if (args.verbous) fprintf(stderr,"\n"); err=cf.closeFile(); if (!err.isOk()) throw err; cardfs.ref().unmountMedium(); } // try catch (CTError xerr) { fprintf(stderr,"\nException: %s\n",xerr.errorString().c_str()); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } if (fclose(sf)) { fprintf(stderr,I18N("Could not close %s (%s)\n"), sname.c_str(),strerror(errno)); return 2; } return 0; } int catFile(s_args args){ CTPointer cardfs; CTPointer basecard; CTFile cf; string sname; int i; string tmp; CTError err; int rv; if (args.params.size()!=1) { usage(); return 1; } sname=args.params.front(); // mount medium, create detination file try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; cf=CTFile(cardfs,sname); err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } err=cf.openFile(); if (!err.isOk()) throw err; // actually copy file while(1) { tmp=cf.readString(k_BLOCKSIZE); if (tmp.length()==0) break; i=fwrite(tmp.data(),1,tmp.length(),stdout); if (i!=(int)tmp.length()) { fprintf(stderr,I18N("Error writing to stdout (%s)\n"), strerror(errno)); } } // while if (args.verbous) fprintf(stderr,"\n"); err=cf.closeFile(); if (!err.isOk()) throw err; cardfs.ref().unmountMedium(); } // try catch (CTError xerr) { fprintf(stderr,"\nException: %s\n",xerr.errorString().c_str()); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } return 0; } int lsDir(s_args args){ CTPointer cardfs; CTPointer basecard; CTDirectory dir; CTDirEntry entry; string name; CTError err; string tmp; string fname; char acc[11]; int rv; if (args.params.size()!=1) { usage(); return 1; } fname=args.params.front(); acc[3]='-'; acc[6]='-'; acc[9]='-'; acc[10]=0; try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } dir=CTDirectory(cardfs,fname); err=dir.openDirectory(); if (!err.isOk()) throw err; err=dir.firstEntry(entry); while (err.isOk()) { if (entry.attributes() & CTDirEntry::Attr_USED) { //fprintf(stderr,"%s\n",entry.dump().c_str()); if (entry.attributes() & CTDirEntry::Attr_DIR) acc[0]='d'; else acc[0]='-'; if (entry.attributes() & CTDirEntry::Attr_READ) acc[1]='r'; else acc[1]='-'; if (entry.attributes() & CTDirEntry::Attr_WRITE) acc[2]='w'; else acc[2]='-'; acc[4]=acc[1]; acc[7]=acc[1]; acc[5]=acc[2]; acc[8]=acc[2]; tmp=acc; tmp+=" "; tmp+=CTMisc::num2string(entry.size(),"%5d"); tmp+=" "; tmp+=entry.name(); fprintf(stdout,"%s\n",tmp.c_str()); } err=dir.nextEntry(entry); } err=dir.closeDirectory(); if (!err.isOk()) throw err; err=cardfs.ref().unmountMedium(); if (!err.isOk()) throw err; } // try catch (CTError xerr) { fprintf(stderr,"Exception: %s\n",xerr.errorString().c_str()); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } return 0; } int info(s_args args){ CTPointer cardfs; CTPointer basecard; string name; CTError err; CTSuperBlock sb; float fl; int i; int rv; if (args.params.size()!=0) { usage(); return 1; } name=args.params.front(); try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } sb=cardfs.ref().superBlock(); printf(I18N("General information\n")); printf("------------------------------------------------------\n"); printf(I18N("Card Name : %s\n"),sb.mediumName().c_str()); printf(I18N("Card Size : %6d byte(s) in %d blocks\n"), sb.mediumSize(), cardfs.ref().blocks()); printf(I18N("Block Size : %6d byte(s)\n"), cardfs.ref().blockSize()); printf(I18N("Used Bytes : %6d byte(s) in %d blocks\n"), (cardfs.ref().blocks()-cardfs.ref().freeBlocks())* cardfs.ref().blockSize(), cardfs.ref().blocks()-cardfs.ref().freeBlocks()); printf(I18N("Free Bytes : %6d byte(s) in %d blocks\n"), cardfs.ref().freeBlocks()*cardfs.ref().blockSize(), cardfs.ref().freeBlocks()); printf(I18N("Medium Encrypted : ")); if (sb.isCrypted()) printf(I18N("Yes\n")); else printf(I18N("No\n")); printf(I18N("Write Protection : ")); if (sb.isReadOnly()) printf(I18N("Yes\n")); else printf(I18N("No\n")); printf(I18N("Statistical information\n")); printf("------------------------------------------------------\n"); i=sb.mediumSize()-cardfs.ref().blocks()*cardfs.ref().blockSize(); fl=i*100.0/sb.mediumSize(); printf(I18N("Overhead : %6.2f%% (%d bytes)\n"), fl,i); i=cardfs.ref().blocks()-cardfs.ref().freeBlocks(); fl=i*100.0/cardfs.ref().blocks(); printf(I18N("Medium Usage : %6.2f%%\n"), fl); err=cardfs.ref().unmountMedium(); if (!err.isOk()) throw err; } // try catch (CTError xerr) { fprintf(stderr,"Exception: %s\n",xerr.errorString().c_str()); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } return 0; } int scratchMedium(s_args args){ CTPointer card; CTPointer basecard; int s; int i; string tmp; CTError err; float fl; int rv; if (args.params.size()!=1) { usage(); return 1; } sscanf(args.params.front().c_str(),"%i",&s); if (!s || s%1024) { fprintf(stderr, I18N("Bad size (%d).\n" "The size must be multiple of 1024.\n") ,s); return 1; } try { rv=openCard(basecard); if (rv!=0) return rv; card=new CTMemoryCard(basecard.ref()); basecard=0; err=card.ref().openCard(); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } tmp=string(1024,(char)0); if (args.verbous) fprintf(stderr, I18N("Started scratching...\r")); for (i=0; i cardfs; CTPointer basecard; CTFile file; string oname; string nname; CTError err; int rv; if (args.params.size()!=2) { usage(); return 1; } oname=args.params.front(); nname=args.params.back(); try { rv=openCard(basecard); if (rv!=0) return rv; cardfs=new CTCardFS(basecard.ref()); basecard=0; err=cardfs.ref().mountMedium(args.username,args.password); if (!err.isOk()) { fprintf(stderr,I18N("Error: %s\n"),err.errorString().c_str()); return 3; } file=CTFile(cardfs,oname); err=file.renameFile(nname); if (!err.isOk()) throw err; err=cardfs.ref().unmountMedium(); if (!err.isOk()) throw err; } // try catch (CTError xerr) { fprintf(stderr,"Exception: %s\n",xerr.errorString().c_str()); cardfs.ref().purge(); cardfs.ref().unmountMedium(); return 3; } return 0; } int main(int argc, char **argv) { string cmd; s_args args; int rv; #ifdef HAVE_GETTEXT_ENVIRONMENT setlocale(LC_ALL,""); if (bindtextdomain("ctfstool", I18N_PATH)==0) { fprintf(stderr," Error bindtextdomain()\n"); } if (textdomain("ctfstool")==0) { fprintf(stderr," Error textdomain()\n"); } #endif rv=checkArgs(args,argc,argv); if (rv==-1) return 0; else if (rv) return rv; if (argc<2) { usage(); return 1; } if (args.params.empty()) { usage(); return 1; } cmd=args.params.front(); args.params.pop_front(); rv=ChipCard_Init(args.configFile.c_str(),0); if (rv!=CHIPCARD_SUCCESS) { fprintf(stderr, I18N("Error initializing libchipcard (%d), aborting.\n"),rv); return 2; } if (cmd=="format") rv=formatMedium(args); else if (cmd=="mkdir") rv=mkDir(args); else if (cmd=="rmdir") rv=rmDir(args); else if (cmd=="rm") rv=rmFile(args); else if (cmd=="ls") rv=lsDir(args); else if (cmd=="write") rv=writeToCard(args); else if (cmd=="read") rv=readFromCard(args); else if (cmd=="cat") rv=catFile(args); else if (cmd=="mv") rv=renameFile(args); else if (cmd=="info") rv=info(args); else if (cmd=="scratch") rv=scratchMedium(args); else { fprintf(stderr,I18N("Unknown command.\n")); usage(); rv=1; } ChipCard_Fini(); return rv; }