/*
 * adfGetDirEnt
 *
 */
struct List* adfGetDirEnt(struct Volume* vol, SECTNUM nSect )
{
    return adfGetRDirEnt(vol, nSect, FALSE);
}
Exemple #2
0
int main(int argc, char* argv[])
{
    int i, j;
    BOOL rflag, lflag, xflag, cflag, vflag, sflag, dflag, pflag, qflag;
    struct List* files, *rtfiles;
    char *devname, *dirname;
    char strbuf[80];
    unsigned char *extbuf;
    int vInd, dInd, fInd, aInd;
    BOOL nextArg;

    struct Device *dev;
    struct Volume *vol;
    struct List *list, *cell;
    int volNum;
    BOOL true = TRUE;

    if (argc<2) {
        help();
        exit(0);
    }

    rflag = lflag = cflag = vflag = sflag = dflag = pflag = qflag = FALSE;
    vInd = dInd = fInd = aInd = -1;
    xflag = TRUE;
    dirname = NULL;
    devname = NULL;
    files = rtfiles = NULL;
    volNum = 0;

    fprintf(stderr,"unADF v%s : a unzip like for .ADF files, powered by ADFlib (v%s - %s)\n\n",
        UNADF_VERSION, adfGetVersionNumber(),adfGetVersionDate());

    /* parse options */
    i=1;
    while(i<argc) {
        if (argv[i][0]=='-') {
            j=1;
            nextArg = FALSE;
            while(j<(int)strlen(argv[i]) && !nextArg) {
                switch(argv[i][j]) {
                case 'v':
                    vflag = TRUE;
                    if ((i+1)<(argc-1)) {
                        i++;
                        nextArg = TRUE;
                        errno = 0;
                        volNum = atoi(argv[i]);
                        if (errno!=0 || volNum<0) {
                            fprintf(stderr,"invalid volume number, aborting.\n");
                            exit(1);
                        }
                    }
                    else
                        fprintf(stderr,"no volume number, -v option ignored.\n");
                    break;
                case 'l': 
                    lflag = TRUE;
                    xflag = FALSE;
                    break;
                case 's': 
                    sflag = TRUE;
                    break;
                case 'c': 
                    cflag = TRUE;
                    break;
                case 'r':
                    rflag = TRUE;
                    break;
                case 'd':
                    if (devname!=NULL && xflag && (i+1)==(argc-1)) {
                        i++;
                        dirname = argv[i];
                        if (dirname[strlen(dirname)-1]==DIRSEP)
                            dirname[strlen(dirname)-1]='\0';
                        nextArg = TRUE;
                        dflag = TRUE;
                    }
                    break;
                case 'p':
                    if (xflag) {
                        fprintf(stderr,"sending files to pipe.\n");
                        pflag = TRUE;
                        qflag = TRUE;
                    }
                    else
                        fprintf(stderr,"-p option must be used with extraction, ignored.\n");
                    break;
                case 'h':
                default:
                    help();
                    exit(0);
                } /* switch */
            j++;
            } /* while */
        } /* if */
        else {
			/* the last non option string is taken as a filename */
            if (devname==NULL) /* if the device name has been already given */
                devname = argv[i];
            else {
                if (xflag) {
                    if (rtfiles==NULL)
                        rtfiles = files = newCell(NULL, (void*)argv[i]);
                    else
                        files = newCell(files, (void*)argv[i]);
                }
                else
                    fprintf(stderr,"Must be used with extraction, ignored.\n");
            }
        }
        i++;
    } /* while */

    extbuf =(unsigned char*)malloc(EXTBUFL*sizeof(char));
    if (!extbuf) { fprintf(stderr,"malloc error\n"); exit(1); }

    /* initialize the library */
    adfEnvInitDefault();

    dev = adfMountDev( devname,TRUE );
    if (!dev) {
        sprintf(strbuf,"Can't mount the dump device '%s'.\n", devname);
        fprintf(stderr, strbuf);
        adfEnvCleanUp(); exit(1);
    }
    if (!qflag)
        printDev(dev);

    if (volNum>=dev->nVol) {
        fprintf(stderr,"This device has only %d volume(s), aborting.\n",dev->nVol);
        exit(1);
    }

    vol = adfMount(dev, volNum, TRUE);
    if (!vol) {
        adfUnMountDev(dev);
        fprintf(stderr, "Can't mount the volume\n");
        adfEnvCleanUp(); exit(1);
    }

    if (!qflag) {
        printVol(vol, volNum);
        putchar('\n');
    }

    if (cflag && isDIRCACHE(vol->dosType) && lflag) {
        adfChgEnvProp(PR_USEDIRC,&true);
        if (!qflag)
            puts("Using dir cache blocks.");
    }

    if (lflag) {
        if (!rflag) {
            cell = list = adfGetDirEnt(vol,vol->curDirPtr);
            while(cell) {
                printEnt(vol,cell->content,"", sflag);
                cell = cell->next;
            }
            adfFreeDirList(list);
        } else {
            cell = list = adfGetRDirEnt(vol,vol->curDirPtr,TRUE);
            printTree(vol,cell,"", sflag);
            adfFreeDirList(list);
        }
    }else if (xflag) {
        if (rtfiles!=NULL) {
            files = rtfiles;
            while(files!=NULL) {
                if (dirname!=NULL)
                    processFile(vol, (char*)files->content, dirname, extbuf, pflag, qflag);
                else
                    processFile(vol, (char*)files->content, "", extbuf, pflag, qflag);
                files = files->next;
            }
            freeList(rtfiles);
        }
        else {
            cell = list = adfGetRDirEnt(vol,vol->curDirPtr,TRUE);
            if (dirname==NULL)
                extractTree(vol, cell, "", extbuf, pflag, qflag);
            else
                extractTree(vol, cell, dirname, extbuf, pflag, qflag);
            adfFreeDirList(list);
        }
    }
    else
        help();

    free(extbuf);

    adfUnMount(vol);
    adfUnMountDev(dev);

    adfEnvCleanUp();

    return(0);
}
/*
 * adfGetRDirEnt
 *
 */
struct List* adfGetRDirEnt(struct Volume* vol, SECTNUM nSect, BOOL recurs )
{
    struct bEntryBlock entryBlk;
	struct List *cell, *head;
    int i;
    struct Entry *entry;
    SECTNUM nextSector;
    int32_t *hashTable;
    struct bEntryBlock parent;


    if (adfEnv.useDirCache && isDIRCACHE(vol->dosType))
        return (adfGetDirEntCache(vol, nSect, recurs ));


    if (adfReadEntryBlock(vol,nSect,&parent)!=RC_OK)
		return NULL;

    hashTable = parent.hashTable;
    cell = head = NULL;
    for(i=0; i<HT_SIZE; i++) {
        if (hashTable[i]!=0) {
             entry = (struct Entry *)calloc(1,sizeof(struct Entry));
             if (!entry) {
                 adfFreeDirList(head);
				 (*adfEnv.eFct)("adfGetDirEnt : malloc");
                 return NULL;
             }
             if (adfReadEntryBlock(vol, hashTable[i], &entryBlk)!=RC_OK) {
				 adfFreeDirList(head);
                 return NULL;
             }
             if (adfEntBlock2Entry(&entryBlk, entry)!=RC_OK) {
				 adfFreeDirList(head); return NULL;
             }
             entry->sector = hashTable[i];
	
             if (head==NULL)
                 head = cell = newCell(0, (void*)entry);
             else
                 cell = newCell(cell, (void*)entry);
             if (cell==NULL) {
                 adfFreeDirList(head); return NULL;
             }

             if (recurs && entry->type==ST_DIR)
                 cell->subdir = adfGetRDirEnt(vol,entry->sector,recurs);

             /* same hashcode linked list */
             nextSector = entryBlk.nextSameHash;
             while( nextSector!=0 ) {
                 entry = (struct Entry *)calloc(1,sizeof(struct Entry));
                 if (!entry) {
                     adfFreeDirList(head);
					 (*adfEnv.eFct)("adfGetDirEnt : malloc");
                     return NULL;
                 }
                 if (adfReadEntryBlock(vol, nextSector, &entryBlk)!=RC_OK) {
					 adfFreeDirList(head); return NULL;
                 }

                 if (adfEntBlock2Entry(&entryBlk, entry)!=RC_OK) {
					 adfFreeDirList(head);
                     return NULL;
                 }
                 entry->sector = nextSector;
	
                 cell = newCell(cell, (void*)entry);
                 if (cell==NULL) {
                     adfFreeDirList(head); return NULL;
                 }
				 
                 if (recurs && entry->type==ST_DIR)
                     cell->subdir = adfGetRDirEnt(vol,entry->sector,recurs);
				 
                 nextSector = entryBlk.nextSameHash;
             }
        }
    }

/*    if (parent.extension && isDIRCACHE(vol->dosType) )
        adfReadDirCache(vol,parent.extension);
*/
    return head;
}