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); }
/*************************************************************************** * 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 */
/* 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; }
/* * 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); }
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); }
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)); } }
void cfe_sleep(int ticks) { int64_t timer; TIMER_SET(timer,ticks); while (!TIMER_EXPIRED(timer)) { POLL(); } }
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; }
/*************************************************************************** * 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 */
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); }
/* 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)); } }
/* Backward space file */ static int BackwardSpace(usd_handle_t fid, int count) { POLL(); if (isafile) { return (0); } else { return (ForkIoctl(fid, USDTAPE_BSF, count)); } }
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; }
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; }
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); }
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; }
/* 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); }
/*************************************************************************** * 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 */
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; }
/*************************************************************************** * 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 */
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); }
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; }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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); }