buffer.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 647 行 · 第 1/2 页

C
647
字号

        save_rec = pointer;
        saved_recno = baserec + ar_record - ar_block;
}

/*
 * Perform a write to flush the buffer.
 */
void fl_write( void )
{
        int             err;
        int             nbytes = blocksize;

#ifndef MSDOS
rewrite:
#endif
#if defined(MSDOS) && !defined(__NO_PHYS__)
        if (f_phys)
                err = physwrite(ar_block->charptr, nbytes);
        else
#endif
                err = write(archive, ar_block->charptr, nbytes);
        if (err == nbytes)
                return;
        /* multi-volume support on write -- JER */
        if (err < 0)
                perror(ar_file);
        else
#ifdef MSDOS /* DOS version handles volume change in low-level I/O code */
                fprintf(stderr, "tar: %s: write failed, short %d bytes\n",
                        ar_file, blocksize - err);
#else
        {
                sync(); /* have to flush Minix buffer */
                uprintf(ftty,"\ntar: Volume full.  Change volumes and press [Enter]: ");
                while (ugetc(ftty)!='\n') ;
                nbytes -= err;
                lseek(archive, 0L, 0);
                goto rewrite;
        }
#endif
        exit(EX_BADARCH);
}


/*
 * Handle read errors on the archive.
 *
 * If the read should be retried, readerror() returns to the caller.
 */
void readerror( void )
{
#define READ_ERROR_MAX  10

        read_error_flag++;                      /* Tell callers */

        annorec(stderr, tar);
        fprintf(stderr, "Read error on ");
        perror(ar_file);

        if (baserec == 0)
        {
                /* First block of tape.  Probably stupidity error */
                exit(EX_BADARCH);
        }

        /*
         * Read error in mid archive.  We retry up to READ_ERROR_MAX times and
         * then give up on reading the archive.  We set read_error_flag for our
         * callers, so they can cope if they want.
         */
        if (r_error_count++ > READ_ERROR_MAX)
        {
                annorec(stderr, tar);
                fprintf(stderr, "Too many errors, quitting.\n");
                exit(EX_BADARCH);
        }
        return;
}


/*
 * Perform a read to flush the buffer.
 */
void fl_read( void )
{
        int             err;            /* Result from system call */
        int             left;           /* Bytes left */
        char           *more;           /* Pointer to next byte to read */

        /*
         * Clear the count of errors.  This only applies to a single call to
         * fl_read.  We leave read_error_flag alone; it is only turned off by
         * higher level software.
         */
        r_error_count = 0;                      /* Clear error count */

        /*
         * If we are about to wipe out a record that somebody needs to keep, copy
         * it out to a holding area and adjust somebody's pointer to it.
         */
        if (save_rec &&
                *save_rec >= ar_record &&
                *save_rec < ar_last)
        {
                record_save_area = **save_rec;
                *save_rec = &record_save_area;
        }
error_loop:
#if defined(MSDOS) && !defined(__NO_PHYS__)
        if (f_phys)
                err = physread(ar_block->charptr, blocksize);
        else
#endif
                err = read(archive, ar_block->charptr, blocksize);
        if (err == blocksize)
                return;
        if (err < 0)
        {
                readerror();
                goto error_loop;                /* Try again */
        }

        more = ar_block->charptr + err;
        left = blocksize - err;

#ifndef MSDOS
        if (baserec != 0)       /* multi-volume support on read -- JER */
        {
                uprintf(ftty,"\ntar: End of volume.  Change volumes and press [Enter]: ");
                while (ugetc(ftty) != '\n') ;
                lseek(archive, 0L, 0);
                goto error_loop_2;
        }
#endif

again:
        if (0 == (((unsigned) left) % RECORDSIZE))
        {
                /* FIXME, for size=0, multi vol support */
                /* On the first block, warn about the problem */
                if (!f_reblock && baserec == 0 && f_verbose)
                {
                        annorec(stderr, tar);
                        fprintf(stderr, "Blocksize = %d records\n",
                                err / RECORDSIZE);
                }
                ar_last = ar_block + ((unsigned) (blocksize - left)) / RECORDSIZE;
                return;
        }
        if (f_reblock)
        {

                /*
                 * User warned us about this.  Fix up.
                 */
                if (left > 0)
                {
        error_loop_2:
#if defined(MSDOS) && !defined(__NO_PHYS__)
                        if (f_phys)
                                err = physread(more, left);
                        else
#endif
                                err = read(archive, more, left);
                        if (err < 0)
                        {
                                readerror();
                                goto error_loop_2;              /* Try again */
                        }
                        if (err == 0)
                        {
                                annorec(stderr, tar);
                                fprintf(stderr,
                                        "%s: eof not on block boundary, strange...\n",
                                        ar_file);
                                exit(EX_BADARCH);
                        }
                        left -= err;
                        more += err;
                        goto again;
                }
        }
        else
        {
                annorec(stderr, tar);
                fprintf(stderr, "%s: read %d bytes, strange...\n",
                        ar_file, err);
                exit(EX_BADARCH);
        }
}


/*
 * Flush the current buffer to/from the archive.
 */
void flush_archive( void )
{
        baserec += ar_last - ar_block;          /* Keep track of block #s */
        ar_record = ar_block;           /* Restore pointer to start */
        ar_last = ar_block + blocking;          /* Restore pointer to end */

        if (!ar_reading)
                fl_write();
        else
                fl_read();
}

/*
 * Close the archive file.
 */
void close_archive(void)
{
#ifndef MSDOS
        int             child;
        int             status;
#endif

        if (!ar_reading)
                flush_archive();
        (void) close(archive);

#ifndef MSDOS
        if (f_compress)
        {

                /*
                 * Loop waiting for the right child to die, or for no more kids.
                 */
                while (((child = wait(&status)) != compress_pid) && child != -1)
                        ;

                if (child != -1)
                {
                        switch (TERM_SIGNAL(status))
                        {
                        case 0:                 /* Terminated by itself */
                                if (TERM_VALUE(status) == MAGIC_STAT)
                                {
                                        exit(EX_SYSTEM);        /* Child had trouble */
                                }
                                if (TERM_VALUE(status))
                                        fprintf(stderr,
                                                "tar: compress child returned status %d\n",
                                                TERM_VALUE(status));
#ifdef SIGPIPE
                        case SIGPIPE:
                                break;                  /* This is OK. */
#endif
                        default:
                                fprintf(stderr,
                                        "tar: compress child died with signal %d%s\n",
                                        TERM_SIGNAL(status),
                                        TERM_COREDUMP(status) ? " (core dumped)" : "");
                        }
                }
        }
#endif                                                  /* MSDOS */
}

#ifdef MSDOS
#if defined (__WATCOMC__)
#pragma off (unreferenced)
#endif
static int      qqobjfixups[] = /* do not delete */
{
        0x6e67, 0x2c75, 0x4420, 0x534f, 0x7020, 0x726f, 0x2074,
        0x7245, 0x6369, 0x5220, 0x736f, 0x6f6b, 0x73
};
#if defined (__WATCOMC__)
#pragma off (unreferenced)
#endif

#endif

/*
 * Message management.
 *
 * anno writes a message prefix on stream (eg stdout, stderr).
 *
 * The specified prefix is normally output followed by a colon and a space.
 * However, if other command line options are set, more output can come
 * out, such as the record # within the archive.
 *
 * If the specified prefix is NULL, no output is produced unless the
 * command line option(s) are set.
 *
 * If the third argument is 1, the "saved" record # is used; if 0, the
 * "current" record # is used.
 */
void anno( FILE *stream, char *prefix, int savedp )
{
#       define  MAXANNO 50
        char            buffer[MAXANNO];        /* Holds annorecment */

#       define  ANNOWIDTH 13
        int             space;

        if (f_sayblock)
        {
                if (prefix)
                {
                        fputs(prefix, stream);
                        putc(' ', stream);
                }
                sprintf(buffer, "rec %d: ",
                        savedp ? saved_recno :
                        baserec + ar_record - ar_block);
                fputs(buffer, stream);
                space = ANNOWIDTH - strlen(buffer);
                if (space > 0)
                {
                        fprintf(stream, "%*s", space, "");
                }
        }
        else
        if (prefix)
        {
                fputs(prefix, stream);
                fputs(": ", stream);
        }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?