Пример #1
0
static afs_int32
rewindFile(struct butm_tapeInfo *info)
{
    struct progress *p;
    afs_int32 code = 0;
    afs_int32 error;

    p = (struct progress *)info->tmRock;

    POLL();

    error = Rewind(p->fid);

    POLL();

    if (error) {
	info->status |= BUTM_STATUS_SEEKERROR;
	ERROR_EXIT(BUTM_IOCTL);
    }

    info->position = (isafile ? 0 : 1);
    info->kBytes = info->nBytes = 0;
    info->nFiles = info->nRecords = 0;
    p->reading = p->writing = 0;

  error_exit:
    if (error)
	info->error = error;
    return (code);
}
Пример #2
0
/***************************************************************************
 * Function Name: read_post_data
 * Description  : This function reads HTTP POST data which is the contents of
 *                a new image to write to flash memory.
 * Returns      : UPLOAD_OK - all data read
 *                UPLOAD_PENDING - not all data read
 *                UPLOAD_TCP_ERROR - TCP error
 ***************************************************************************/
static char read_post_data( int s, unsigned char *post_data_start,
    int content_length, int *post_data_idx_ptr )
{
    char ret = UPLOAD_PENDING;
    int post_data_idx = *post_data_idx_ptr;
    int len;

    do
    {
        len = tcp_recv( s, post_data_start + post_data_idx,
            content_length - post_data_idx );
        post_data_idx += len;
        POLL();
        cfe_web_listen( &g_listen_idx );
    } while( len > 0 && post_data_idx < content_length );

    *post_data_idx_ptr = post_data_idx;

    if( len < 0 )
    {
        console_log("web error: TCP read error receiving post data.");
        ret = UPLOAD_TCP_ERROR;
    }
    else
        if( post_data_idx == content_length )
            ret = UPLOAD_OK;

    return( ret );
} /* read_post_data */
Пример #3
0
/* Read a SW filemark, verify that it is a SW filemark, then skip to the next
 * HW filemark. If the read of the SW filemark shows it's an EOF, then
 * ignore that the SW filemark is not there and return 0 (found the SW filemark
 * missing with some 3.1 dumps).
 */
static afs_int32
file_ReadFileEnd(struct butm_tapeInfo *info)
{
    afs_int32 code = 0;
    afs_int32 blockType;

    if (info->debug)
	printf("butm: Read filemark end\n");

    POLL();
    info->error = 0;

    code = check(info, READ_OP);
    if (code)
	ERROR_EXIT(code);
    if (!READS || WRITES)
	ERROR_EXIT(BUTM_BADOP);

    info->status &= ~BUTM_STATUS_EOF;

    code = ReadTapeBlock(info, tapeBlock, &blockType);
    if (code)
	ERROR_EXIT(code);

    if ((blockType != BLOCK_FMEND) && (blockType != BLOCK_EOF))
	ERROR_EXIT(BUTM_BADBLOCK);

  error_exit:
    return code;
}
Пример #4
0
/*
 * Write the end-of-dump marker.
 */
static afs_int32
file_WriteEODump(struct butm_tapeInfo *info)
{
    afs_int32 code = 0;

    if (info->debug)
	printf("butm: Write filemark EOD\n");

    POLL();
    info->error = 0;

    code = check(info, WRITE_OP);
    if (code)
	ERROR_EXIT(code);
    if (READS || WRITES)
	ERROR_EXIT(BUTM_BADOP);

    code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_EOD);
    if (code)
	ERROR_EXIT(code);

    info->status |= BUTM_STATUS_EOD;

  error_exit:
    return (code);
}
Пример #5
0
static afs_int32
file_ReadFileBegin(struct butm_tapeInfo *info)
{
    afs_int32 code = 0;
    afs_int32 blockType;

    if (info->debug)
	printf("butm: Read filemark begin\n");

    POLL();
    info->error = 0;

    code = check(info, READ_OP);
    if (code)
	ERROR_EXIT(code);
    if (READS || WRITES)
	ERROR_EXIT(BUTM_BADOP);

    code = ReadTapeBlock(info, tapeBlock, &blockType);
    if (code)
	ERROR_EXIT(code);

    if (blockType != BLOCK_FMBEGIN) {
	if (blockType == BLOCK_EOD)
	    ERROR_EXIT(BUTM_EOD);	/* EODump label */
	if (blockType == BLOCK_LABEL)
	    ERROR_EXIT(BUTM_LABEL);	/* Tape label */
	ERROR_EXIT(BUTM_BADBLOCK);	/* Other */
    }

  error_exit:
    return (code);
}
Пример #6
0
static int est_ssl_read (SSL *ssl, unsigned char *buf, int buf_max,
                       int sock_read_timeout) 
{
    int timeout;
    int read_fd;
    int rv;
    struct pollfd pfd;
    
    /*
     * load up the timeval struct to be passed to the select
     */
    timeout = sock_read_timeout * 1000;

    read_fd = SSL_get_fd(ssl);
    pfd.fd = read_fd;
    pfd.events = POLLIN;
    pfd.revents = 0;

    errno = 0;
    rv = POLL(&pfd, 1, timeout);
    if (rv == 0) {
        EST_LOG_ERR("Socket poll timeout.  No data received from server.");
        return -1;
    } else if ( rv == -1) {
        EST_LOG_ERR("Socket read failure. errno = %d", errno);
        return -1;
    } else {
        return (SSL_read(ssl, buf, buf_max));
    }
}
Пример #7
0
void cfe_sleep(int ticks)
{
    int64_t timer;

    TIMER_SET(timer,ticks);
    while (!TIMER_EXPIRED(timer)) {	
	POLL();
	}
}
Пример #8
0
static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
{
    pcconsole_t *softc = ctx->dev_softc;

    POLL();

    inpstat->inp_status = (softc->kbd_in != softc->kbd_out);

    return 0;
}
Пример #9
0
/***************************************************************************
 * Function Name: cfe_web_poll
 * Description  : The entry point function that is called in the background
 *                at polled intervals.  It listens for and processes HTTP
 *                requests.
 * Returns      : None.
 ***************************************************************************/
void cfe_web_poll(void *x)
{
    static int first_time = 1;
    static int in_cfe_web_poll = 0;

    PSOCKET_INFO si;
    int i;

    if( in_cfe_web_poll == 0 )
    {
        in_cfe_web_poll = 1;

        /* If this is the first time that this function was called, initialize
         * the socket info data array.
         */
        if( first_time == 1 )
        {
            first_time = 0;
            for( i = 0, si = g_socket_info; i < NUM_SOCKETS; i++, si++ )
            {
                si->s = SOCKET_CLOSED;
                si->state = HTTP_READ_FIRST_HDR;
                si->web_buf_idx = 0;
                si->post_content_length = 0;
            }
        }

        /* Check the connection state of each socket. */
        for( i = 0, si = g_socket_info; i < NUM_SOCKETS; i++, si++ )
        {
            cfe_web_listen( &g_listen_idx );
            if( si->s >= 0 )
            {
                int connflag;
                tcp_status( si->s, &connflag, NULL, NULL );
                if( connflag == TCPSTATUS_CONNECTED )
                {
                    cfe_web_bg_process( si );
                    POLL();
                }
                else
                    if( connflag == TCPSTATUS_NOTCONN )
                    {
                        console_log("web warning: Unexpected TCP disconnect.");
                        tcp_close(si->s);
                        si->s = SOCKET_CLOSED;
                        si->state = HTTP_READ_FIRST_HDR;
                        si->web_buf_idx = 0;
                    }
            }
        }

        in_cfe_web_poll = 0;
    }
} /* cfe_web_poll */
Пример #10
0
static afs_int32
file_Dismount(struct butm_tapeInfo *info)
{
    struct progress *p;
    afs_int32 code = 0, error = 0;

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

    POLL();
    info->error = 0;

    code = check(info, READ_OP);
    if (code)
	ERROR_EXIT(code);

    p = (struct progress *)info->tmRock;

    (void)ShutdownAccess(p->fid);	/* for NT */

    /* close the device */
    if ((error = ForkClose(p->fid))) {
	printf("butm: Tape close failed. Error %d\n", errno);
    }

    POLL();

    if (error) {
	code = BUTM_DISMOUNTFAIL;
	info->status |= BUTM_STATUS_TAPEERROR;
    }

    config.mountId = 0;
    info->tmRock = 0;		/* mark it as closed - even if error on close */
    if (p)
	free(p);

  error_exit:
    if (error)
	info->error = error;
    return (code);
}
Пример #11
0
/* write end of file mark */
static int
WriteEOF(usd_handle_t fid, int count)
{
    POLL();

    if (isafile) {
	return (0);
    } else {
	return (ForkIoctl(fid, USDTAPE_WEOF, count));
    }
}
Пример #12
0
/* Backward space file */
static int
BackwardSpace(usd_handle_t fid, int count)
{
    POLL();

    if (isafile) {
	return (0);
    } else {
	return (ForkIoctl(fid, USDTAPE_BSF, count));
    }
}
Пример #13
0
static void console_readnum(int *num,unsigned char *ch)
{
    int total = 0;

    for (;;) {
	total = (total * 10) + (*ch - '0');
	while (console_read(ch,1) != 1) { POLL(); }
	if (!((*ch >= '0') && (*ch <= '9'))) break;
	}

    *num = total;
}
Пример #14
0
void * increment_counter(void *arg)
{
    int i = 0;

    threadId = (long)arg;
    init_uli(0);
    dprintLine("IC called: %d\n", threadId);
    /*
     * Setup ULI stack.
     */
    void *my_stack = (void *) malloc(4096);
    if(my_stack == NULL) {
      exit(1);
    }
    SETUPULI(my_stack);

    for (i = 0; i < 100; ++i)
    {
        POLL();
        mylock(&L);
        POLL();
        count++;
        POLL();
        myunlock(&L);
        POLL();
    }
    POLL();
    sleep(2);   // Sleep to give time for other threads to send messages
    POLL();
    pthread_exit(NULL);
    return NULL;
}
Пример #15
0
afs_int32
SeekFile(struct butm_tapeInfo *info, int count)
{
    afs_int32 code = 0;
    struct progress *p;
    afs_int32 error = 0;

    if (count == 0)
	ERROR_EXIT(0);
    p = (struct progress *)info->tmRock;

    if (isafile) {		/* no reason for seeking through a file */
	p->reading = p->writing = 0;
	return (0);
    }

    POLL();

    if (count > 0)
	error = ForwardSpace(p->fid, count);
    else
	error = BackwardSpace(p->fid, -count);

    POLL();

    if (error) {
	info->status |= BUTM_STATUS_SEEKERROR;
	ERROR_EXIT(BUTM_IOCTL);
    }

    info->position += count;
    incSize(info, (count * config.fileMarkSize));
    p = (struct progress *)info->tmRock;
    p->reading = p->writing = 0;

  error_exit:
    if (error)
	info->error = error;
    return (code);
}
Пример #16
0
void * increment_counter(void *arg)
{
    int cpu = get_myid();
    unsigned long myid = (unsigned long)pthread_self();
    //unsigned long myid = tno++;
    
    int i = 0;
    for (i = 0; i < 2; ++i)
    {
        POLL();
        mylock(&L);
        POLL();
        count++;
        POLL();
        myunlock(&L);
        POLL();
        sleep(interval);
                
    }
    POLL();
    sleep(2);   // Sleep to give time for other threads to send messages
    POLL();
    pthread_exit(NULL);
    return NULL;
}
Пример #17
0
/* Writes data out in block sizes of 16KB. Does destroy the data.
 * Assumes the data buffer has a space reserved at beginning for a blockMark.
 */
static afs_int32
file_WriteFileData(struct butm_tapeInfo *info, char *data, afs_int32 blocks, afs_int32 len)
{
    afs_int32 code = 0;
    int length;
    afs_int32 b;
    char *bstart;		/* Where block starts for a 16K block */
    char *dstart;		/* Where data  starts for a 16K block */

    if (info->debug)
	printf("butm: Write tape data - %u bytes\n", len);

    POLL();
    info->error = 0;

    code = check(info, WRITE_OP);
    if (code)
	ERROR_EXIT(code);
    if (!data || (len < 0))
	ERROR_EXIT(BUTM_BADARGUMENT);
    if (READS || !WRITES)
	ERROR_EXIT(BUTM_BADOP);

    b = 0;			/* start at block 0 */
    while (len > 0) {
	dstart = &data[b * BUTM_BLKSIZE];
	bstart = dstart - sizeof(struct blockMark);

	if (len < BUTM_BLKSIZE) {
	    memset(&dstart[len], 0, BUTM_BLKSIZE - len);
	    length = len;
	} else {
	    length = BUTM_BLKSIZE;
	}

	code = WriteTapeBlock(info, bstart, length, BLOCK_DATA);

	len -= length;

	/* If there are more blocks, step to next block */
	/* Otherwise, copy the data to beginning of last block */

	if (b < (blocks - 1))
	    b++;
	else if (len)
	    memcpy(&dstart[0], &dstart[BUTM_BLKSIZE], len);
    }

  error_exit:
    return (code);
}
Пример #18
0
/***************************************************************************
 * Function Name: cfe_web_listen
 * Description  : This function checks to see if TCP listen can be issued
 *                on the HTTP port and issues the listen if it can.
 * Returns      : None.
 ***************************************************************************/
static void cfe_web_listen( int *listen_idx_ptr )
{
    static int port = SERVER_PORT;

    int listen_idx = *listen_idx_ptr;
    PSOCKET_INFO si = &g_socket_info[listen_idx];

    /* If a TCP socket has been opened, check its connection status. */
    if( si->s >= 0 )
    {
        int connflag;
        tcp_status( si->s, &connflag, NULL, NULL );

        /* If the socket is connection, set the next socket index to listen for
         * a TCP connection.
         */
        if( connflag == TCPSTATUS_CONNECTED )
        {
            listen_idx = (listen_idx + 1) % NUM_SOCKETS;
            si = &g_socket_info[listen_idx];
        }
    }

    /* If the TCP socket has not been opened, open it and listen for a TCP
     * connection.
     */
    if( si->s == SOCKET_CLOSED )
    {
        /* Open the socket in non-blocking mode. */
        POLL();
        if( (si->s = tcp_socket()) >= 0 )
        {
            console_log("web info: Waiting for connection on socket %d.", si->s);
            if( tcp_listen(si->s, port) != 0 )
                console_log("web error: listen error on %d.", si->s);
        }
        else
        {
            console_log("web error %d: Could not create TCP socket.", si->s);
            si->s = SOCKET_CLOSED;
        }
    }

    *listen_idx_ptr = listen_idx;
} /* cfe_web_listen */
Пример #19
0
static int
bcm1250_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
{
    bcm1250_t *softc = ctx->dev_softc;
    physaddr_t arg_p = softc->mailbox + 0;
    physaddr_t cmd_p = softc->mailbox + 4;
    chunk_desc code;
    uint32_t cmd;
    int64_t timer;
    int res;
    
    /* Note: This code assumes that PTR_TO_PHYS gives a PCI memory space
       address that is accessible via our BAR4 or BAR5 */

    code.addr = PTR_TO_PHYS((uint8_t *)buffer->buf_ptr);
    code.len  = buffer->buf_length;

    cmd = 0x1;      /* load */
    if (!elf_header((uint8_t *)buffer->buf_ptr)) {
	/* No recognizable elf seal, so assume compressed. */
	cmd |= 0x2;
	}

    phys_write32(arg_p | MBOX_SET_BIT, PTR_TO_PHYS(&code));
    phys_write32(cmd_p | MBOX_SET_BIT, cmd);     /* load */

    /* Wait for handshake */

    res = CFE_ERR_TIMEOUT;
    TIMER_SET(timer, 5*CFE_HZ);
    while (!TIMER_EXPIRED(timer)) {
        if ((phys_read32(cmd_p) & 0x3) == 0) {
	    softc->downloaded = 1;
	    buffer->buf_retlen = 0;
	    /* Note that the result code need not be translated only
               because we are assuming a CFE in the device that is
               compatible with us. */
	    res = (int)phys_read32(arg_p);
	    break;
	    }
	POLL();
	}

    return res;
}
Пример #20
0
/***************************************************************************
 * Function Name: cfe_web_tcp_send
 * Description  : Sends data on a TCP non blocking connection and waits for
 *                it to finish.
 * Returns      : > 0 - bytes send, < 0 - TCP error
 ***************************************************************************/
static int cfe_web_tcp_send( int s, char *buf, int size )
{
    int i, len = 0;

    for( i = 0; i < size; i += len )
    {
        POLL();
        cfe_web_listen( &g_listen_idx );
        len = tcp_send( s, buf + i, size - i );
        if( len < 0 )
        {
            console_log("web error: TCP write error sending a web page.");
            break;
        }
    }

    return( len );
} /* cfe_web_tcp_send */
Пример #21
0
static afs_int32
file_ReadFileData(struct butm_tapeInfo *info, char *data, int len, int *nBytes)
{
    struct blockMark *bmark;
    afs_int32 code = 0;
    afs_int32 blockType;

    if (info->debug)
	printf("butm: Read tape data - %u bytes\n", len);

    POLL();
    info->error = 0;

    if (!nBytes)
	ERROR_EXIT(BUTM_BADARGUMENT);
    *nBytes = 0;

    code = check(info, READ_OP);
    if (code)
	ERROR_EXIT(code);
    if (!data || (len < 0) || (len > BUTM_BLKSIZE))
	ERROR_EXIT(BUTM_BADARGUMENT);
    if (!READS || WRITES)
	ERROR_EXIT(BUTM_BADOP);

    data -= sizeof(struct blockMark);
    code = ReadTapeBlock(info, data, &blockType);
    if (code)
	ERROR_EXIT(code);

    if (blockType != BLOCK_DATA) {
	if (blockType == BLOCK_EOF)
	    ERROR_EXIT(BUTM_EOF);
	if (blockType == BLOCK_FMEND)
	    ERROR_EXIT(BUTM_ENDVOLUME);
	ERROR_EXIT(BUTM_BADBLOCK);
    }

    bmark = (struct blockMark *)data;
    *nBytes = ntohl(bmark->count);	/* Size of data in buf */

  error_exit:
    return (code);
}
Пример #22
0
static int
sb1250_host_open(cfe_devctx_t *ctx)
{
    sb1250_host_t *softc = ctx->dev_softc;
    uint64_t *mbox_p = K1_PTR64 (A_IMR_REGISTER(0, R_IMR_MAILBOX_CPU));
    uint32_t *cmd_p = ((uint32_t *)mbox_p) + 1;
    uint32_t *arg_p = ((uint32_t *)mbox_p) + 0;
    physaddr_t desc_addr, data_addr;    /* in PCI full-access space */


    /* The caller has probably done this already. */
    while ((*cmd_p & 0x3) == 0) {
	POLL();    /* timeout might be good */
	}

    desc_addr = PCI_TO_CPU(*arg_p);
    data_addr = phys_read32(desc_addr);
    softc->pci_base = PCI_TO_CPU(data_addr);
    softc->limit = phys_read32(desc_addr + 4);

    return 0;
}
Пример #23
0
static afs_int32
file_WriteFileEnd(struct butm_tapeInfo *info)
{
    afs_int32 code = 0;

    if (info->debug)
	printf("butm: Write filemark end\n");

    POLL();
    info->error = 0;

    code = check(info, WRITE_OP);
    if (code)
	ERROR_EXIT(code);
    if (READS || !WRITES)
	ERROR_EXIT(BUTM_BADOP);

    code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_FMEND);

  error_exit:
    return (code);
}
Пример #24
0
static afs_int32
file_WriteFileBegin(struct butm_tapeInfo *info)
{
    afs_int32 code = 0;

    if (info->debug)
	printf("butm: Write filemark begin\n");

    POLL();

    code = check(info, WRITE_OP);
    if (code)
	ERROR_EXIT(code);

    code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_FMBEGIN);
    if (code)
	ERROR_EXIT(code);

    info->nFiles++;

  error_exit:
    return (code);
}
Пример #25
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);
}
Пример #26
0
static afs_int32
file_ReadLabel(struct butm_tapeInfo *info, struct butm_tapeLabel *label,
	       afs_int32 rewind)
{
    struct tapeLabel *tlabel;
    afs_int32 code = 0;
    afs_int32 blockType;

    if (info->debug)
	printf("butm: Read tape label\n");

    POLL();
    info->error = 0;

    code = check(info, READ_OP);
    if (code)
	ERROR_EXIT(code);
    if (READS || WRITES)
	ERROR_EXIT(BUTM_BADOP);

    if (rewind) {
	code = rewindFile(info);
	if (code)
	    ERROR_EXIT(code);	/* status is set so return */
    }

    /*
     * When appended labels were written, either 1 or 2 EOF marks may
     * have had to be skipped.  When reading a label, these EOF marks
     * must also be skipped. When an EOF is read, 0 bytes are returned
     * (refer to the write calls in file_WriteLabel routine).
     * ---------------------------------------------------------------- */
    code = ReadTapeBlock(info, tapeBlock, &blockType);
    if (!isafile && !rewind && (blockType == BLOCK_EOF))
	do {
	    code = ReadTapeBlock(info, tapeBlock, &blockType);
	    if (blockType != BLOCK_EOF)
		break;		/* didn't read an EOF */

	    code = ReadTapeBlock(info, tapeBlock, &blockType);
	} while (0);

    if (blockType == BLOCK_UNKNOWN)
	ERROR_EXIT(BUTM_NOLABEL);
    if (code)
	ERROR_EXIT(code);
    if (blockType != BLOCK_LABEL)
	ERROR_EXIT(BUTM_BADBLOCK);

    /* Copy label out
     * -------------- */
    if (label) {
	tlabel = (struct tapeLabel *)tapeBlock;
	memcpy(label, &tlabel->label, sizeof(struct butm_tapeLabel));
	label->structVersion = ntohl(label->structVersion);
	label->creationTime = ntohl(label->creationTime);
	label->expirationDate = ntohl(label->expirationDate);
	label->size = ntohl(label->size);
	label->dumpid = ntohl(label->dumpid);
	label->useCount = ntohl(label->useCount);

	info->tapeSize = label->size;	/* use size from label */
    }

  error_exit:
    return (code);
}
Пример #27
0
static int
ForkIoctl(usd_handle_t fd, int op, int count)
{
    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 ioctl_rc;		/* return code from ioctl call */
    int pipefd[2];		/* pipe for child return status */
    int forkflag;		/* flag set when ready to fork */
    usd_tapeop_t tapeop;	/* tape operation specification */
    int unixfd;

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

    /* initialize tape command structure */
    tapeop.tp_op = op;
    tapeop.tp_count = count;

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

    if (forkflag) {
	pid = fork();
	if (pid < 0) {
	    close(pipefd[0]);
	    close(pipefd[1]);
	    printf("butm:  Can't fork IOCTL process. Error %d\n", errno);
	    forkflag = 0;

	}
    }

    if (!forkflag) {		/* problem starting child process */
	/* do the ioctl anyway, it will probably work */
	ioctl_rc = USD_IOCTL(fd, USD_IOCTL_TAPEOPERATION, (void *)&tapeop);
    } else if (pid == 0) {	/* child process */
	/* close all unneccessary file descriptors */
	/* note: as painful as it is, we have to reach under the covers of
	 *       the usd package to implement this functionality.
	 */
	unixfd = (intptr_t)(fd->handle);

	for (i = 3; i < _POSIX_OPEN_MAX; i++) {
	    if (i != unixfd && i != pipefd[1]) {
		close(i);
	    }
	}

	/* do the ioctl call */
	ioctl_rc = USD_IOCTL(fd, USD_IOCTL_TAPEOPERATION, (void *)&tapeop);

	/*
	 * 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], &ioctl_rc, sizeof(int)) < 0)
	    ; /* don't care */

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

	close(pipefd[1]);
	POLL();
	/* read the result from the child process */
	rc = read(pipefd[0], &ioctl_rc, sizeof(int));
	if (rc != sizeof(int)) {
	    /* tape is now in unknown state */
	    printf("butm:  Can't determine IOCTL child status. Error %d\n",
		   errno);
	    ioctl_rc = EFAULT;
	}

	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:  Can't determine IOCTL child status. Error %d\n",
		   errno);
	} else if (status != 0) {
	    printf
		("butm: Unexpected IOCTL process status 0x%04x . Error %d\n",
		 status, errno);
	}
	SLEEP(1);
    }

    return (ioctl_rc);
}
Пример #28
0
static afs_int32
WriteTapeBlock(struct butm_tapeInfo *info,
	       char *buffer,     /* assumed to be 16384 bytes with data in it */
	       afs_int32 length, /* amount data in buffer */
	       afs_int32 blockType)
{
    afs_int32 code = 0, rc = 0;
    afs_uint32 wsize;
    struct tapeLabel *label;
    struct fileMark *fmark;
    struct blockMark *bmark;
    struct progress *p;
    afs_int32 error = 0;

    p = (struct progress *)info->tmRock;

    if (blockType == BLOCK_DATA) {	/* Data Block */
	if (length == 0)
	    ERROR_EXIT(0);
	bmark = (struct blockMark *)buffer;
	memset(bmark, 0, sizeof(struct blockMark));
	bmark->magic = htonl(BLOCK_MAGIC);
	bmark->count = htonl(length);
    } else if (blockType == BLOCK_FMBEGIN) {	/* Filemark - begin */
	fmark = (struct fileMark *)buffer;
	fmark->magic = htonl(FILE_MAGIC);
	fmark->nBytes = htonl(FILE_BEGIN);
    } else if (blockType == BLOCK_FMEND) {	/* Filemark - end */
	fmark = (struct fileMark *)buffer;
	fmark->magic = htonl(FILE_MAGIC);
	fmark->nBytes = htonl(FILE_FMEND);
    } else if (blockType == BLOCK_LABEL) {	/* Label */
	label = (struct tapeLabel *)buffer;
	label->magic = htonl(TAPE_MAGIC);
    } else if (blockType == BLOCK_EOD) {	/* Filemark - EOD mark */
	fmark = (struct fileMark *)buffer;
	fmark->magic = htonl(FILE_MAGIC);
	fmark->nBytes = htonl(FILE_EOD);
    }

    /* Write the tape block */
    /* -------------------- */
    rc = USD_WRITE(p->fid, buffer, BUTM_BLOCKSIZE, &wsize);
    if ((rc == 0) && (wsize > 0)) {
	incPosition(info, p->fid, wsize);	/* record whats written */
	p->writing++;
    }

    if (wsize != BUTM_BLOCKSIZE) {
	info->status |= BUTM_STATUS_WRITEERROR;
	if (rc != 0) {
	    error = rc;
	    ERROR_EXIT(BUTM_IO);
	} else
	    ERROR_EXIT(BUTM_EOT);
    }
    if (isafile)
	info->position++;

    /* Write trailing EOF marker for some block types */
    /* ---------------------------------------------- */
    if ((blockType == BLOCK_FMEND) || (blockType == BLOCK_LABEL)
	|| (blockType == BLOCK_EOD)) {

	POLL();
	error = WriteEOF(p->fid, 1);
	POLL();
	if (error) {
	    info->status |= BUTM_STATUS_WRITEERROR;
	    ERROR_EXIT(BUTM_IOCTL);
	}

	incSize(info, config.fileMarkSize);
	if (!isafile)
	    info->position++;
	p->writing = 0;
    }

  error_exit:
    if (error)
	info->error = error;
    return (code);
}
Пример #29
0
static afs_int32
file_WriteLabel(struct butm_tapeInfo *info, struct butm_tapeLabel *label,
		afs_int32 rewind)
{
    afs_int32 code = 0;
    afs_int32 fcode;
    struct tapeLabel *tlabel;
    struct progress *p;
    afs_int64 off;		/* offset */

    if (info->debug)
	printf("butm: Write tape label\n");

    POLL();
    info->error = 0;

    code = check(info, WRITE_OP);
    if (code)
	ERROR_EXIT(code);
    if (!label)
	ERROR_EXIT(BUTM_BADARGUMENT);
    if (label->structVersion != CUR_TAPE_VERSION)
	ERROR_EXIT(BUTM_OLDINTERFACE);

    if (rewind) {		/* Not appending, so rewind */
	code = rewindFile(info);
	if (code)
	    ERROR_EXIT(code);

	if (isafile) {
	    p = (struct progress *)info->tmRock;
	    off = 0;
	    code = USD_IOCTL(p->fid, USD_IOCTL_SETSIZE, &off);
	    if (code)
		ERROR_EXIT(BUTM_POSITION);
	}
    } else {
	if (READS || WRITES)
	    ERROR_EXIT(BUTM_BADOP);
    }

    /* Copy the label into the tape block
     * ---------------------------------- */
    memset(tapeBlock, 0, BUTM_BLOCKSIZE);

    if (!label->creationTime)
	label->creationTime = time(0);

    tlabel = (struct tapeLabel *)tapeBlock;
    memcpy(&tlabel->label, label, sizeof(struct butm_tapeLabel));
    tlabel->label.structVersion = htonl(CUR_TAPE_VERSION);
    tlabel->label.creationTime = htonl(tlabel->label.creationTime);
    tlabel->label.expirationDate = htonl(tlabel->label.expirationDate);
    tlabel->label.size = htonl(tlabel->label.size);
    tlabel->label.useCount = htonl(tlabel->label.useCount);
    tlabel->label.dumpid = htonl(tlabel->label.dumpid);

    /*
     * write the tape label - For appends, the write may need to skip
     * over 1 or 2 EOF marks that were written when tape was closed after
     * the last dump. Plus, some AIX tape drives require we try forwarding
     * over the last EOF and take an error before we can write the new label.
     * ---------------------------------------------------------------------- */
    code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_LABEL);
    if (!isafile && !rewind && (code == BUTM_IO))
	do {			/* do if write failed */
	    fcode = SeekFile(info, 1);	/* skip over the EOF */
	    if (fcode)
		break;		/* leave if error */

	    code =
		WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_LABEL);
	    if (code != BUTM_IO)
		break;		/* continue if write failed */

	    fcode = SeekFile(info, 1);	/* skip over the EOF */
	    if (fcode) {	/* retry 1 write if couldn't skip */
		code =
		    WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE,
				   BLOCK_LABEL);
		break;
	    }

	    code =
		WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_LABEL);
	    if (code != BUTM_IO)
		break;		/* continue if write failed */

	    fcode = SeekFile(info, 1);	/* skip over the EOF */
	    if (fcode) {	/* retry 1 write if couldn't skip */
		code =
		    WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE,
				   BLOCK_LABEL);
		break;
	    }
	    break;
	} while (0);

    /* clear the write error status a failed WriteTapeBlock may have produced */
    if (!code)
	info->status &= ~BUTM_STATUS_WRITEERROR;

  error_exit:
    return code;
}
Пример #30
0
static int
ForkClose(usd_handle_t fd)
{
    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 close_rc, parent_close_rc;	/* return codes from close */
    int pipefd[2];		/* pipe for child return status */
    int ctlpipe[2];		/* pipe for message to child */
    int forkflag;		/* flag set when ready to fork */
    int unixfd;

#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 CLOSE process. Error %d\n",
		   errno);
	    forkflag = 0;
	}
    }

    /* create pipe for notifying child when to close */
    if (forkflag) {
	rc = pipe(ctlpipe);
	if (rc < 0) {
	    close(pipefd[0]);
	    close(pipefd[1]);
	    printf("butm: Cannot create pipe for CLOSE  process. Error %d\n",
		   errno);
	    forkflag = 0;
	}
    }

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

    if (!forkflag) {		/* problem starting child process */
	close_rc = USD_CLOSE(fd);
	parent_close_rc = close_rc;
    } else if (pid == 0) {	/* child process */
	/* close all unneccessary file descriptors */
	/* note: as painful as it is, we have to reach under the covers of
	 *       the usd package to implement this functionality.
	 */
	unixfd = (intptr_t)(fd->handle);

	for (i = 3; i < _POSIX_OPEN_MAX; i++) {
	    if (i != unixfd && i != ctlpipe[0] && i != pipefd[1]) {
		close(i);
	    }
	}

	/*
	 * The parent writes the control pipe after it closes the device.
	 * We don't actually care about the read; we're just using it to
	 * block until the parent is ready.  But we must do something
	 * with the result, to avoid complier warnings on some platforms.
	 */
	if (read(ctlpipe[0], &close_rc, sizeof(int)) < 0)
	    ; /* don't care */
	close(ctlpipe[0]);

	/* do the close */
	close_rc = 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], &close_rc, sizeof(int)) < 0)
	    ; /* don't care */

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

	close(pipefd[1]);
	close(ctlpipe[0]);

	POLL();
	/*
	 * close the device, this should have no effect as long as the
	 * child has not closed
	 */

	parent_close_rc = USD_CLOSE(fd);

	/* notify the child to do its close */
	rc = write(ctlpipe[1], &close_rc, sizeof(int));	/* just send garbage */
	if (rc != sizeof(int)) {
	    printf("butm: Error communicating with CLOSE process. Error %d\n",
		   errno);
	}
	close(ctlpipe[1]);

	/* read the result from the child process */
	rc = read(pipefd[0], &close_rc, sizeof(int));
	if (rc != sizeof(int)) {
	    /* logging is enough, since we wrote a file mark the */
	    /* return code from the close doesn't really matter  */
	    printf("butm: No response from  CLOSE  process. Error %d\n",
		   errno);
	    close_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 CLOSE  process. Error %d\n",
		   errno);
	} else if (status != 0) {
	    printf
		("butm: Unexpected exit status 0x%04x from CLOSE  process. Error %d\n",
		 status, errno);
	}

	/* if either process received an error, then return an error */
	if (parent_close_rc < 0) {
	    close_rc = parent_close_rc;
	}
	SLEEP(1);
    }

    return (close_rc);
}