Minor cleanup of the standard read/write I/O modules:
* Use public API, don't access struct archive directly. (People should be able to copy these into their applications as a template for custom I/O callbacks.) * Set "skip" only for regular files. ("skip" allows the low-level library to catch attempts to add an archive to itself or extract over itself.) * Simplify the write_open functions by just calling stat() at the beginning. Somehow, these functions had acquired some complex logic that tried to avoid the stat() call but never succeeded. MFC after: 10 days
This commit is contained in:
parent
c3b11d8213
commit
b2ba9b4e04
@ -89,8 +89,8 @@ file_open(struct archive *a, void *client_data)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
a->skip_file_dev = st.st_dev;
|
||||
a->skip_file_ino = st.st_ino;
|
||||
if (S_ISREG(st.st_mode))
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
@ -110,9 +110,10 @@ file_open(struct archive *a, void *client_data)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (fstat(mine->fd, &st) == 0) {
|
||||
/* Set dev/ino of archive file so extract won't overwrite. */
|
||||
a->skip_file_dev = st.st_dev;
|
||||
a->skip_file_ino = st.st_ino;
|
||||
/* If we're reading a file from disk, ensure that we don't
|
||||
overwrite it with an extracted file. */
|
||||
if (S_ISREG(st.st_mode))
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
/* Remember mode so close can decide whether to flush. */
|
||||
mine->st_mode = st.st_mode;
|
||||
} else {
|
||||
|
@ -110,9 +110,10 @@ file_open(struct archive *a, void *client_data)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (fstat(mine->fd, &st) == 0) {
|
||||
/* Set dev/ino of archive file so extract won't overwrite. */
|
||||
a->skip_file_dev = st.st_dev;
|
||||
a->skip_file_ino = st.st_ino;
|
||||
/* If we're reading a file from disk, ensure that we don't
|
||||
overwrite it with an extracted file. */
|
||||
if (S_ISREG(st.st_mode))
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
/* Remember mode so close can decide whether to flush. */
|
||||
mine->st_mode = st.st_mode;
|
||||
} else {
|
||||
|
@ -74,44 +74,35 @@ static int
|
||||
file_open(struct archive *a, void *client_data)
|
||||
{
|
||||
struct write_fd_data *mine;
|
||||
struct stat st, *pst;
|
||||
struct stat st;
|
||||
|
||||
pst = NULL;
|
||||
mine = (struct write_fd_data *)client_data;
|
||||
|
||||
if (fstat(mine->fd, &st) != 0) {
|
||||
archive_set_error(a, errno, "Couldn't stat fd %d", mine->fd);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a regular file, don't add it to itself.
|
||||
*/
|
||||
if (S_ISREG(st.st_mode))
|
||||
archive_write_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
|
||||
/*
|
||||
* If client hasn't explicitly set the last block handling,
|
||||
* then set it here: If the output is a block or character
|
||||
* device, pad the last block, otherwise leave it unpadded.
|
||||
* then set it here.
|
||||
*/
|
||||
if (mine->fd >= 0 && a->bytes_in_last_block < 0) {
|
||||
/* Last block will be fully padded. */
|
||||
if (fstat(mine->fd, &st) == 0) {
|
||||
pst = &st;
|
||||
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ||
|
||||
S_ISFIFO(st.st_mode))
|
||||
archive_write_set_bytes_in_last_block(a, 0);
|
||||
else
|
||||
archive_write_set_bytes_in_last_block(a, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mine->fd == 1) {
|
||||
if (a->bytes_in_last_block < 0) /* Still default? */
|
||||
if (archive_write_get_bytes_in_last_block(a) < 0) {
|
||||
/* If the output is a block or character device, fifo,
|
||||
* or stdout, pad the last block, otherwise leave it
|
||||
* unpadded. */
|
||||
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ||
|
||||
S_ISFIFO(st.st_mode) || (mine->fd == 1))
|
||||
/* Last block will be fully padded. */
|
||||
archive_write_set_bytes_in_last_block(a, 0);
|
||||
}
|
||||
|
||||
if (mine->fd < 0) {
|
||||
archive_set_error(a, errno, "Failed to open");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (pst == NULL && fstat(mine->fd, &st) == 0)
|
||||
pst = &st;
|
||||
if (pst == NULL) {
|
||||
archive_set_error(a, errno, "Couldn't stat fd %d", mine->fd);
|
||||
return (ARCHIVE_FATAL);
|
||||
else
|
||||
archive_write_set_bytes_in_last_block(a, 1);
|
||||
}
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
|
@ -88,53 +88,42 @@ file_open(struct archive *a, void *client_data)
|
||||
{
|
||||
int flags;
|
||||
struct write_file_data *mine;
|
||||
struct stat st, *pst;
|
||||
struct stat st;
|
||||
|
||||
pst = NULL;
|
||||
mine = (struct write_file_data *)client_data;
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
|
||||
/*
|
||||
* Open the file.
|
||||
*/
|
||||
if (mine->filename[0] != '\0') {
|
||||
mine->fd = open(mine->filename, flags, 0666);
|
||||
|
||||
/*
|
||||
* If client hasn't explicitly set the last block
|
||||
* handling, then set it here: If the output is a
|
||||
* block or character device, pad the last block,
|
||||
* otherwise leave it unpadded.
|
||||
*/
|
||||
if (mine->fd >= 0 && a->bytes_in_last_block < 0) {
|
||||
if (fstat(mine->fd, &st) == 0) {
|
||||
pst = &st;
|
||||
if (S_ISCHR(st.st_mode) ||
|
||||
S_ISBLK(st.st_mode) ||
|
||||
S_ISFIFO(st.st_mode))
|
||||
/* Pad last block. */
|
||||
archive_write_set_bytes_in_last_block(a, 0);
|
||||
else
|
||||
/* Don't pad last block. */
|
||||
archive_write_set_bytes_in_last_block(a, 1);
|
||||
}
|
||||
if (mine->fd < 0) {
|
||||
archive_set_error(a, errno, "Failed to open '%s'",
|
||||
mine->filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* NULL filename is stdout.
|
||||
*/
|
||||
mine->fd = 1;
|
||||
if (a->bytes_in_last_block < 0) /* Still default? */
|
||||
/* Last block will be fully padded. */
|
||||
/* By default, pad archive when writing to stdout. */
|
||||
if (archive_write_get_bytes_in_last_block(a) < 0)
|
||||
archive_write_set_bytes_in_last_block(a, 0);
|
||||
}
|
||||
|
||||
if (mine->fd < 0) {
|
||||
archive_set_error(a, errno, "Failed to open '%s'",
|
||||
mine->filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (pst == NULL && fstat(mine->fd, &st) == 0)
|
||||
pst = &st;
|
||||
if (pst == NULL) {
|
||||
archive_set_error(a, errno, "Couldn't stat '%s'",
|
||||
mine->filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
/*
|
||||
* Set up default last block handling.
|
||||
*/
|
||||
if (archive_write_get_bytes_in_last_block(a) < 0) {
|
||||
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ||
|
||||
S_ISFIFO(st.st_mode))
|
||||
/* Pad last block when writing to device or FIFO. */
|
||||
archive_write_set_bytes_in_last_block(a, 0);
|
||||
else
|
||||
/* Don't pad last block otherwise. */
|
||||
archive_write_set_bytes_in_last_block(a, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -142,10 +131,8 @@ file_open(struct archive *a, void *client_data)
|
||||
* itself. If it's a device file, it's okay to add the device
|
||||
* entry to the output archive.
|
||||
*/
|
||||
if (S_ISREG(pst->st_mode)) {
|
||||
a->skip_file_dev = pst->st_dev;
|
||||
a->skip_file_ino = pst->st_ino;
|
||||
}
|
||||
if (S_ISREG(st.st_mode))
|
||||
archive_write_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -88,53 +88,42 @@ file_open(struct archive *a, void *client_data)
|
||||
{
|
||||
int flags;
|
||||
struct write_file_data *mine;
|
||||
struct stat st, *pst;
|
||||
struct stat st;
|
||||
|
||||
pst = NULL;
|
||||
mine = (struct write_file_data *)client_data;
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
|
||||
/*
|
||||
* Open the file.
|
||||
*/
|
||||
if (mine->filename[0] != '\0') {
|
||||
mine->fd = open(mine->filename, flags, 0666);
|
||||
|
||||
/*
|
||||
* If client hasn't explicitly set the last block
|
||||
* handling, then set it here: If the output is a
|
||||
* block or character device, pad the last block,
|
||||
* otherwise leave it unpadded.
|
||||
*/
|
||||
if (mine->fd >= 0 && a->bytes_in_last_block < 0) {
|
||||
if (fstat(mine->fd, &st) == 0) {
|
||||
pst = &st;
|
||||
if (S_ISCHR(st.st_mode) ||
|
||||
S_ISBLK(st.st_mode) ||
|
||||
S_ISFIFO(st.st_mode))
|
||||
/* Pad last block. */
|
||||
archive_write_set_bytes_in_last_block(a, 0);
|
||||
else
|
||||
/* Don't pad last block. */
|
||||
archive_write_set_bytes_in_last_block(a, 1);
|
||||
}
|
||||
if (mine->fd < 0) {
|
||||
archive_set_error(a, errno, "Failed to open '%s'",
|
||||
mine->filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* NULL filename is stdout.
|
||||
*/
|
||||
mine->fd = 1;
|
||||
if (a->bytes_in_last_block < 0) /* Still default? */
|
||||
/* Last block will be fully padded. */
|
||||
/* By default, pad archive when writing to stdout. */
|
||||
if (archive_write_get_bytes_in_last_block(a) < 0)
|
||||
archive_write_set_bytes_in_last_block(a, 0);
|
||||
}
|
||||
|
||||
if (mine->fd < 0) {
|
||||
archive_set_error(a, errno, "Failed to open '%s'",
|
||||
mine->filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (pst == NULL && fstat(mine->fd, &st) == 0)
|
||||
pst = &st;
|
||||
if (pst == NULL) {
|
||||
archive_set_error(a, errno, "Couldn't stat '%s'",
|
||||
mine->filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
/*
|
||||
* Set up default last block handling.
|
||||
*/
|
||||
if (archive_write_get_bytes_in_last_block(a) < 0) {
|
||||
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ||
|
||||
S_ISFIFO(st.st_mode))
|
||||
/* Pad last block when writing to device or FIFO. */
|
||||
archive_write_set_bytes_in_last_block(a, 0);
|
||||
else
|
||||
/* Don't pad last block otherwise. */
|
||||
archive_write_set_bytes_in_last_block(a, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -142,10 +131,8 @@ file_open(struct archive *a, void *client_data)
|
||||
* itself. If it's a device file, it's okay to add the device
|
||||
* entry to the output archive.
|
||||
*/
|
||||
if (S_ISREG(pst->st_mode)) {
|
||||
a->skip_file_dev = pst->st_dev;
|
||||
a->skip_file_ino = pst->st_ino;
|
||||
}
|
||||
if (S_ISREG(st.st_mode))
|
||||
archive_write_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user