コード例 #1
0
ファイル: cmd_tar.c プロジェクト: Nevor/upmc-sash-project
/*
 * Read a tar file and extract or list the specified files within it.
 * If the list is empty than all files are extracted or listed.
 */
static void
readTarFile(int fileCount, const char ** fileTable)
{
	const char *	cp;
	int		cc;
	int		inCc;
	int		blockSize;
	char		buf[BUF_SIZE];

	skipFileFlag = FALSE;
	badHeader = FALSE;
	warnedRoot = FALSE;
	eofFlag = FALSE;
	inHeader = TRUE;
	inCc = 0;
	dataCc = 0;
	outFd = -1;
	blockSize = sizeof(buf);
	cp = buf;

	/*
	 * Open the tar file for reading.
	 */
	tarFd = open(tarName, O_RDONLY);

	if (tarFd < 0)
	{
		perror(tarName);

		return;
	}

	/*
	 * Read blocks from the file until an end of file header block
	 * has been seen.  (A real end of file from a read is an error.)
	 */
	while (!intFlag && !eofFlag)
	{
		/*
		 * Read the next block of data if necessary.
		 * This will be a large block if possible, which we will
		 * then process in the small tar blocks.
		 */
		if (inCc <= 0)
		{
			cp = buf;
			inCc = fullRead(tarFd, buf, blockSize);

			if (inCc < 0)
			{
				perror(tarName);

				goto done;
			}

			if (inCc == 0)
			{
				fprintf(stderr,
					"Unexpected end of file from \"%s\"",
					tarName);

				goto done;
			}
		}

		/*
		 * If we are expecting a header block then examine it.
		 */
		if (inHeader)
		{
			readHeader((const TarHeader *) cp, fileCount, fileTable);

			cp += TAR_BLOCK_SIZE;
			inCc -= TAR_BLOCK_SIZE;

			continue;
		}

		/*
		 * We are currently handling the data for a file.
		 * Process the minimum of the amount of data we have available
		 * and the amount left to be processed for the file.
		 */
		cc = inCc;

		if (cc > dataCc)
			cc = dataCc;

		readData(cp, cc);

		/*
		 * If the amount left isn't an exact multiple of the tar block
		 * size then round it up to the next block boundary since there
		 * is padding at the end of the file.
		 */
		if (cc % TAR_BLOCK_SIZE)
			cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);

		cp += cc;
		inCc -= cc;
	}

	/*
	 * Check for an interrupt.
	 */
	if (intFlag)
		fprintf(stderr, "Interrupted - aborting\n");


done:
	/*
	 * Close the tar file if needed.
	 */
	if ((tarFd >= 0) && (close(tarFd) < 0))
		perror(tarName);

	/*
	 * Close the output file if needed.
	 * This is only done here on a previous error and so no
	 * message is required on errors.
	 */
	if (outFd >= 0)
		(void) close(outFd);
}
コード例 #2
0
ファイル: cmd_tar.c プロジェクト: Nevor/upmc-sash-project
/*
 * Save a regular file to the tar file.
 */
static void
saveRegularFile(const char * fileName, const struct stat * statbuf)
{
	BOOL		sawEof;
	int		fileFd;
	int		cc;
	int		dataCount;
	long		fullDataCount;
	char		data[TAR_BLOCK_SIZE * 16];

	/*
	 * Open the file for reading.
	 */
	fileFd = open(fileName, O_RDONLY);

	if (fileFd < 0)
	{
		perror(fileName);

		return;
	}

	/*
	 * Write out the header for the file.
	 */
	writeHeader(fileName, statbuf);

	/*
	 * Write the data blocks of the file.
	 * We must be careful to write the amount of data that the stat
	 * buffer indicated, even if the file has changed size.  Otherwise
	 * the tar file will be incorrect.
	 */
	fullDataCount = statbuf->st_size;
	sawEof = FALSE;

	while (!intFlag && (fullDataCount > 0))
	{
		/*
		 * Get the amount to write this iteration which is
		 * the minumum of the amount left to write and the
		 * buffer size.
		 */
		dataCount = sizeof(data);

		if (dataCount > fullDataCount)
			dataCount = (int) fullDataCount;

		/*
		 * Read the data from the file if we haven't seen the
		 * end of file yet.
		 */
		cc = 0;

		if (!sawEof)
		{
			cc = fullRead(fileFd, data, dataCount);

			if (cc < 0)
			{
				perror(fileName);

				(void) close(fileFd);
				errorFlag = TRUE;

				return;
			}

			/*
			 * If the file ended too soon, complain and set
			 * a flag so we will zero fill the rest of it.
			 */
			if (cc < dataCount)
			{
				fprintf(stderr,
					"%s: Short read - zero filling",
					fileName);

				sawEof = TRUE;
			}
		}

		/*
		 * Zero fill the rest of the data if necessary.
		 */
		if (cc < dataCount)
			memset(data + cc, 0, dataCount - cc);

		/*
		 * Write the buffer to the TAR file.
		 */
		writeTarBlock(data, dataCount);

		fullDataCount -= dataCount;
	}

	/*
	 * Close the file.
	 */
	if (close(fileFd) < 0)
		fprintf(stderr, "%s: close: %s\n", fileName, strerror(errno));
}
コード例 #3
0
static sys_return_t
sud_get_common (az_allocid_t allocid, const char *name,
                char *buf, size_t len, uint64_t expectedRevision)
{
    char fname[256];
    int rv = 0;
    ssize_t sz = 0;
    int fd;
    int flags;

    assert (len >= 8);

    snprintf (fname, sizeof(fname)-1, "%s/%ld/%s", SUD_DIR, allocid, name);

    flags = OPEN_RDONLY_FLAGS;
    fd = MY_OPEN (fname, flags, 0);
    if (fd < 0) {
        // Handle the normal case of an invalid allocid being requested.
        if (errno == ENOENT) {
            return SYSERR_NOT_FOUND;
        }

        // All other errors are catastrophic.
        perror ("open");
        syslog (LOG_ERR, "ERROR: sud open");
        assert (0);
    }

    // Read in the revision number first.
    sz = fullRead (fd, buf, 8);
    if (sz != 8) {
        perror ("read 1");
        syslog (LOG_ERR, "ERROR: sud read 1");
        assert (0);
    }

    uint64_t actualRevision = *((uint64_t *) buf);
    if (expectedRevision != actualRevision) {
        // This is a normal condition.  Return an error and allow the 
        // caller to try again with a different expectedRevision.

        rv = MY_CLOSE (fd);
        if (rv < 0) {
            perror ("close");
            syslog (LOG_ERR, "ERROR: sud close");
        }

        return SYSERR_INVALID_STATE;
    }

    // Read the remainder of the record after the revision number.
    sz = fullRead (fd, buf+8, len-8);
    if ((size_t)sz != (len-8)) {
        perror ("read 2");
        syslog (LOG_ERR, "ERROR: sud read 2");
        assert (0);
    }

    rv = MY_CLOSE (fd);
    if (rv < 0) {
        perror ("close");
        syslog (LOG_ERR, "ERROR: sud close");
    }

    return SYSERR_NONE;
}