Exemplo n.º 1
0
static int
WorkerBee(struct cmd_syndesc *as, void *arock)
{
    char *tapedev;
    struct tapeLabel *label;
    struct fileMark *fmark;
    afs_int32 fmtype;
    struct blockMark *bmark;
    afs_int32 isheader, isdatablock;
    char *data;
    char *tblock;
    afs_int32 code;
    struct volumeHeader *volheaderPtr = NULL;
    int eod = 1;
    int rc;
    char *nextblock;		/* We cycle through three tape blocks so we  */
    char *lastblock;		/* can trim off the volume trailer from the  */
    char *lastblock2;		/* end of each volume without having to back */
    char *tapeblock1;		/* up the output stream.                     */
    char *tapeblock2;
    char *tapeblock3;

    tapedev = as->parms[0].items->data;	/* -tape     */
    nrestore =
	(as->parms[1].items ? atol(as->parms[1].items->data) : 0x7fffffff);
    nskip = (as->parms[2].items ? atol(as->parms[2].items->data) : 0);
    if (as->parms[4].items)
	nskip = 0x7fffffff;	/* -scan     */
    outfile = (as->parms[3].items ? as->parms[3].items->data : 0);
    ask = (as->parms[5].items ? 0 : 1);	/* -noask    */
    printlabels = (as->parms[6].items ? 1 : 0);	/* -label    */
    printheaders = (as->parms[7].items ? 1 : 0);	/* -vheaders */
    verbose = (as->parms[8].items ? 1 : 0);	/* -verbose  */

    /* Open the tape device */
    rc = usd_Open(tapedev, USD_OPEN_RDONLY, 0, &fd);
    if (rc != 0) {
	printf("Failed to open tape device %s. Code = %d\n", tapedev, rc);
	exit(1);
    }

    /*
     * Initialize the tape block buffers
     */
    tapeblock1 = (char *)malloc(3 * 16384);
    if (tapeblock1 == NULL) {
	printf("Failed to allocate I/O buffers.\n");
	exit(1);
    }
    tapeblock2 = tapeblock1 + 16384;
    tapeblock3 = tapeblock2 + 16384;

    nextblock = tapeblock1;
    lastblock = NULL;
    lastblock2 = NULL;

    /* Read each tape block deciding what to do with it */
    do {			/* while ((nskip!=0) && (nrestore!=0)) */
	code = readblock(nextblock);
	if (code) {
	    if (!eod)
		fprintf(stderr, "Tape device read error: %d\n", code);
	    break;
	}
	isdatablock = 0;

	/* A data block can be either a volume header, volume trailer,
	 * or actual data from a dump.
	 */
	bmark = (struct blockMark *)nextblock;
	label = (struct tapeLabel *)nextblock;
	fmark = (struct fileMark *)nextblock;
	if (ntohl(bmark->magic) == BLOCK_MAGIC) {
	    if (verbose)
		printf("Data block\n");
	    isdatablock = 1;
	    isheader = 0;
	    data = &nextblock[sizeof(struct blockMark)];
	    if (strncmp(data, "H++NAME#", 8) == 0) {
		volheaderPtr = (struct volumeHeader *)data;
		printHeader(volheaderPtr, &isheader);
	    }
	    if (isheader) {
		code = openOutFile(volheaderPtr);
		nextblock = tapeblock1;
		lastblock = NULL;
		lastblock2 = NULL;
	    } else {
		if (lastblock2 != NULL) {
		    data = &lastblock2[sizeof(struct blockMark)];
		    bmark = (struct blockMark *)lastblock2;
		    writeData(data, ntohl(bmark->count));
		    tblock = lastblock2;
		} else if (lastblock != NULL) {
		    tblock = tapeblock2;
		} else {
		    tblock = tapeblock3;
		}
		lastblock2 = lastblock;
		lastblock = nextblock;
		nextblock = tblock;
	    }
	}

	/* Filemarks come in 3 forms: BEGIN, END, and EOD.
	 * There is no information stored in filemarks.
	 */
	else if (ntohl(fmark->magic) == FILE_MAGIC) {
	    fmtype = ntohl(fmark->nBytes);
	    if (fmtype == FILE_BEGIN) {
		if (verbose)
		    fprintf(stderr, "File mark volume begin\n");
	    } else if (fmtype == FILE_END) {
		if (verbose)
		    fprintf(stderr, "File mark volume end\n");
	    } else if (fmtype == FILE_EOD) {
		if (verbose)
		    fprintf(stderr, "File mark end-of-dump\n");
		eod = 1;
	    }
	}

	/* A dump label */
	else if (ntohl(label->magic) == TAPE_MAGIC) {
	    if (verbose)
		fprintf(stderr, "Dump label\n");
	    printLabel(label);
	    eod = 0;
	}

	else {
	    if (verbose) {
		fprintf(stderr, "Unrecognized tape block - end\n");
	    }
	}

	/* Anything other than a data block closes the out file.
	 * At this point nextblock contains the end of tape file mark,
	 * lastblock contains the last data block for the current volume,
	 * and lastblock2 contains the second to last block for the current
	 * volume. If the volume fits in a single block, lastblock2 will
	 * be NULL. Call writeLastBlocks to strip off the dump trailer before
	 * writing the last of the volume data to the dump file. The dump
	 * trailer may span block boundaries.
	 */
	if (!isdatablock && lastblock) {
	    writeLastBlocks(lastblock, lastblock2);
	    closeOutFile();
	    nextblock = tapeblock1;
	    lastblock = NULL;
	    lastblock2 = NULL;
	}
    } while ((nskip != 0) || (nrestore != 0));

    free(tapeblock1);

    return 0;
}
Exemplo n.º 2
0
int
openOutFile(struct volumeHeader *headerPtr)
{
    afs_int32 len;
    int ch;
    int rc;
    int oflag;
    int skip, first;
    afs_hyper_t size;

    /* If we were asked to skip this volume, then skip it */
    if (nskip) {
	nskip--;
	return 0;
    }
    /* Skip if we are not to restore any */
    if (!nrestore)
	return 0;

    /* Get the volume name and strip off the BK or RO extension */
    if (outfile) {
	strcpy(filename, outfile);
    } else {
	strcpy(filename, headerPtr->volumeName);
	len = strlen(filename);
	if ((len > 7) && (strcmp(".backup", filename + len - 7) == 0)) {
	    filename[len - 7] = 0;
	} else if ((len > 9)
		   && (strcmp(".readonly", filename + len - 9) == 0)) {
	    filename[len - 9] = 0;
	}
    }

    if (ask) {
	first = 1;
	skip = 0;
	printf("Press return to retreive volume %s (%u) to file %s; " "s"
	       " to skip\n", headerPtr->volumeName, headerPtr->volumeID,
	       filename);
	do {
	    ch = getchar();
	    if ((first == 1) && (ch == 's'))
		skip = 1;
	    if ((first == 1) && (ch == 'q'))
		exit(0);
	    first = 0;
	} while (ch != '\n');
	if (skip) {
	    printf("Will not restore volume %s\n", headerPtr->volumeName);
	    return 0;
	}
    } else {
	printf("Retrieve volume %s (%u) to file %s\n", headerPtr->volumeName,
	       headerPtr->volumeID, filename);
    }

    /* Should I append the date onto the end of the name? */

    /* Open the file to write to */
    if (headerPtr->contd == TC_VOLCONTD) {
	/* Continuation of dump */
	oflag = USD_OPEN_RDWR;
    } else {
	/* An all new dump */
	oflag = USD_OPEN_RDWR | USD_OPEN_CREATE;
    }
    rc = usd_Open(filename, oflag, 0664, &ofd);
    if (rc != 0) {
	fprintf(stderr, "Unable to open file %s. Skipping. Code = %d\n",
		filename, rc);
	nrestore--;
	return 0;
    }
    if (headerPtr->contd != TC_VOLCONTD) {
	hzero(size);
	rc = USD_IOCTL(ofd, USD_IOCTL_SETSIZE, &size);
	if (rc != 0) {
	    fprintf(stderr, "Unable to open file %s. Skipping. Code = %d\n",
		    filename, rc);
	    USD_CLOSE(ofd);
	    nrestore--;
	    return 0;
	}
    }
    ofdIsOpen = 1;
    return 0;
}
Exemplo n.º 3
0
static afs_int32
file_Mount(struct butm_tapeInfo *info, char *tape)
{
    struct progress *p;
    char filename[64];
    usd_handle_t fid;
    int xflags;
    afs_int32 code = 0, error = 0, rc = 0;

    if (!info || !tape)
	ERROR_EXIT(BUTM_BADARGUMENT);

    if (info->debug)
	printf("butm: Mount tape drive\n");

    POLL();
    info->error = 0;

    if (info->structVersion != BUTM_MAJORVERSION)
	ERROR_EXIT(BUTM_OLDINTERFACE);
    if (info->tmRock)
	ERROR_EXIT(BUTM_PARALLELMOUNTS);
    if (strlen(tape) >= sizeof(info->name))
	ERROR_EXIT(BUTM_BADARGUMENT);

    strcpy(info->name, tape);

    strcpy(filename, config.tapedir);	/* the name of the tape device */
    info->position = (isafile ? 0 : 1);
    info->kBytes = info->nBytes = 0;
    info->nRecords = info->nFiles = 0;
    info->recordSize = 0;
    info->tapeSize = config.tapeSize;
    info->coefBytes = 1;
    info->coefRecords = 0;
    info->coefFiles = sizeof(struct fileMark);
    info->simultaneousTapes = 1;
    info->status = 0;
    info->error = 0;
    info->flags = BUTM_FLAGS_SEQUENTIAL;

    xflags = 0;
    if (isafile) {
	xflags |= USD_OPEN_CREATE;
    } else {
	/*
	 * try to open in a child process first so nothing will
	 * time out should the process block because the device
	 * isn't ready.
	 */

	if (ForkOpen(filename)) {
	    ERROR_EXIT(BUTM_MOUNTFAIL);
	}
    }

    /* Now go ahead and open the tape drive for real */
    rc = usd_Open(filename, (USD_OPEN_RDWR | USD_OPEN_WLOCK | xflags), 0777,
		  &fid);
    if (rc != 0) {		/* try for lesser access */
	rc = usd_Open(filename, (USD_OPEN_RDONLY | USD_OPEN_RLOCK), 0, &fid);

	if (rc) {
	    error = rc;
	    ERROR_EXIT(BUTM_MOUNTFAIL);
	}
	info->flags |= BUTM_FLAGS_READONLY;
    }

    (void)PrepareAccess(fid);	/* for NT */

    p = malloc(sizeof(*p));
    info->tmRock = (char *)p;
    p->fid = fid;
    p->mountId = config.mountId = time(0);
    p->reading = p->writing = 0;

    TapeBlockSize = BUTM_BLOCKSIZE;	/* Initialize */

  error_exit:
    if (error)
	info->error = error;
    return (code);
}
Exemplo n.º 4
0
static int
ForkOpen(char *device)
{
    int rc;			/* return code from system calls */
    int i;			/* loop index */
    int pid;			/* process ID of child process */
    int status;			/* exit status of child process */
    int open_rc;		/* return code from open */
    int pipefd[2];		/* pipe for child return status */
    int forkflag;		/* flag set when ready to fork */
    usd_handle_t fd;		/* handle returned from open */

#ifdef AFS_PTHREAD_ENV
    forkflag = 0;		/* No need to fork if using pthreads */
#else
    forkflag = 1;
#endif

    /* create pipe for getting return code from child */
    if (forkflag) {
	rc = pipe(pipefd);
	if (rc < 0) {
	    printf("butm: Cannot create pipe for OPEN process. Error %d\n",
		   errno);
	    forkflag = 0;
	}
    }

    if (forkflag) {
	pid = fork();
	if (pid < 0) {
	    close(pipefd[0]);
	    close(pipefd[1]);
	    printf("butm: Cannot create child process for OPEN. Error %d\n",
		   errno);
	    forkflag = 0;
	}
    }

    if (!forkflag) {		/* problem starting child process */
	/*
	 *return success, the caller will discover any problems
	 * when it opens the device.
	 */
	open_rc = 0;
    } else if (pid == 0) {	/* child process */
	/* close all unneccessary file descriptors */
	for (i = 3; i < _POSIX_OPEN_MAX; i++) {
	    if (i != pipefd[1]) {
		close(i);
	    }
	}

	/* try the open */
	open_rc = usd_Open(device, USD_OPEN_RDONLY, 0, &fd);

	if (open_rc == 0) {
	    USD_CLOSE(fd);
	}

	/*
	 * Send the return code back to the parent.
	 * If this fails, there's nothing we can do, but we must test
	 * it in order to avoid complier warnings on some platforms.
	 */
	if (write(pipefd[1], &open_rc, sizeof(open_rc)) < 0)
	    ; /* don't care */

	exit(0);
    } else {			/* parent process */

	close(pipefd[1]);

	POLL();
	/* read the result from the child process */
	rc = read(pipefd[0], &open_rc, sizeof(open_rc));
	if (rc != sizeof(open_rc)) {
	    /* this is not a problem since we will reopen the device anyway */
	    printf("butm: No response from  OPEN process. Error %d\n", errno);
	    open_rc = 0;
	}

	close(pipefd[0]);

	/* get the completion status from the child process */
	rc = waitpid(pid, &status, 0);
	while (rc < 0 && errno == EINTR) {
	    rc = waitpid(pid, &status, 0);
	}
	if (rc < 0) {
	    printf("butm: Cannot get status of OPEN process. Error %d\n",
		   errno);
	} else if (status != 0) {
	    printf
		("butm: Unexpected OPEN process exit status 0x%04x. Error %d \n",
		 status, errno);
	}
	SLEEP(1);
    }

    return (open_rc);
}
Exemplo n.º 5
0
int
fileMarkSize(char *tapeDevice)
{
    afs_uint32 nFileMarks, nBlocks, nbfTape;
    double tpSize, fmSize;
    afs_uint32 bufferSize = 16384;
    usd_handle_t hTape;
    FILE *logFile;
    int count = 0;
    afs_uint32 countr;
    afs_int32 code = 0;

    code =
	usd_Open(tapeDevice, (USD_OPEN_RDWR | USD_OPEN_WLOCK), 0777, &hTape);
    if (code) {
	printf("Can't open tape device %s\n", tapeDevice);
	fflush(stdout);
	exit(1);
    }

    logFile = fopen("fms.log", "w+");
    if (logFile == NULL) {
	printf("Can't open log file\n");
	fflush(stdout);
	exit(1);
    }
    fprintf(logFile, "fms test started\n");
    fflush(logFile);

    code = rewindTape(hTape);
    if (code) {
	fprintf(logFile, "Can't rewind tape\n");
	fflush(logFile);
	ERROR(code);
    }

    /* measure capacity of tape */
    nbfTape = 0;
    countr = 0;
    while (1) {
	code = dataBlock(hTape, bufferSize);
	nbfTape++;
	count++;
	countr++;
	if (code)
	    break;

	if (count >= 5) {
	    count = 0;
	    printf("\rwrote block: %d", nbfTape);
	}

    }

    fprintf(logFile, "wrote %d blocks\n", nbfTape);
    fflush(logFile);
    printf("\rwrote %d blocks\n", nbfTape);
    printf("Finished data capacity test - rewinding\n");
    /* reset the tape device */
    code = USD_CLOSE(hTape);
    if (code) {
	fprintf(logFile, "Can't close tape device at end of pass 1\n");
	fflush(logFile);
	printf("Can't close tape device %s\n", tapeDevice);
	goto error_exit;
    }
    code =
	usd_Open(tapeDevice, (USD_OPEN_RDWR | USD_OPEN_WLOCK), 0777, &hTape);
    if (code) {
	fprintf(logFile, "Can't open tape device for pass 2\n");
	fflush(logFile);
	printf("Can't open tape device %s\n", tapeDevice);
	goto error_exit;
    }

    code = rewindTape(hTape);
    if (code) {
	fprintf(logFile, "Can't rewind tape\n");
	fflush(logFile);
	ERROR(code);
    }

    /* now measure file mark size */
    nFileMarks = 0;
    nBlocks = 0;
    count = 0;
    countr = 0;
    while (1) {
	code = dataBlock(hTape, bufferSize);
	nBlocks++;
	if (code)
	    break;
	code = fileMark(hTape);
	nFileMarks++;
	if (code)
	    break;
	count++;
	countr++;

	if (count >= 2) {
	    count = 0;
	    printf("\rwrote %d blocks, %d filemarks", nBlocks, nFileMarks);
	}

    }
    printf("\nFinished filemark test\n");
    tpSize = (double)nbfTape *(double)bufferSize;
    fmSize =
	(((double)nbfTape -
	  (double)nBlocks) * (double)bufferSize) / (double)nFileMarks;
    printf("Tape capacity is %.0f bytes\n", tpSize);
    printf("File marks are %.0f bytes\n", fmSize);
    fprintf(logFile, "Tape capacity is %.0f bytes\n", tpSize);
    fprintf(logFile, "File marks are %.0f bytes\n", fmSize);
    fflush(logFile);
    fclose(logFile);
  error_exit:
    USD_CLOSE(hTape);
    return (code);
}