Clean up some consistent confusion between "dev" and "rdev."

Mostly, these were being used correctly even though a lot of
variables and function names were mis-named.

In the process, I found and fixed a couple of latent bugs and
added a guard against adding an archive to itself.
This commit is contained in:
kientzle 2004-06-27 18:38:13 +00:00
parent 34ed55636f
commit 7cfb61a9b9
12 changed files with 176 additions and 101 deletions

View File

@ -339,16 +339,9 @@ archive_entry_new(void)
*/
dev_t
archive_entry_devmajor(struct archive_entry *entry)
archive_entry_dev(struct archive_entry *entry)
{
return (major(entry->ae_stat.st_rdev));
}
dev_t
archive_entry_devminor(struct archive_entry *entry)
{
return (minor(entry->ae_stat.st_rdev));
return (entry->ae_stat.st_dev);
}
void
@ -403,13 +396,18 @@ archive_entry_hardlink(struct archive_entry *entry)
return (aes_get_mbs(&entry->ae_hardlink));
}
ino_t
archive_entry_ino(struct archive_entry *entry)
{
return (entry->ae_stat.st_ino);
}
mode_t
archive_entry_mode(struct archive_entry *entry)
{
return (entry->ae_stat.st_mode);
}
time_t
archive_entry_mtime(struct archive_entry *entry)
{
@ -434,6 +432,24 @@ archive_entry_pathname_w(struct archive_entry *entry)
return (aes_get_wcs(&entry->ae_pathname));
}
dev_t
archive_entry_rdev(struct archive_entry *entry)
{
return (entry->ae_stat.st_rdev);
}
dev_t
archive_entry_rdevmajor(struct archive_entry *entry)
{
return (major(entry->ae_stat.st_rdev));
}
dev_t
archive_entry_rdevminor(struct archive_entry *entry)
{
return (minor(entry->ae_stat.st_rdev));
}
int64_t
archive_entry_size(struct archive_entry *entry)
{
@ -472,24 +488,6 @@ archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
entry->ae_stat = *st;
}
void
archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
{
dev_t d;
d = entry->ae_stat.st_rdev;
entry->ae_stat.st_rdev = makedev(m, minor(d));
}
void
archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
{
dev_t d;
d = entry->ae_stat.st_rdev;
entry->ae_stat.st_rdev = makedev( major(d), m);
}
void
archive_entry_set_fflags(struct archive_entry *entry,
unsigned long set, unsigned long clear)
@ -572,6 +570,24 @@ archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
aes_copy_wcs(&entry->ae_pathname, name);
}
void
archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
{
dev_t d;
d = entry->ae_stat.st_rdev;
entry->ae_stat.st_rdev = makedev(m, minor(d));
}
void
archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
{
dev_t d;
d = entry->ae_stat.st_rdev;
entry->ae_stat.st_rdev = makedev( major(d), m);
}
void
archive_entry_set_size(struct archive_entry *entry, int64_t s)
{

View File

@ -66,18 +66,21 @@ struct archive_entry *archive_entry_new(void);
* Retrieve fields from an archive_entry.
*/
dev_t archive_entry_devmajor(struct archive_entry *);
dev_t archive_entry_devminor(struct archive_entry *);
dev_t archive_entry_dev(struct archive_entry *);
const char *archive_entry_fflags_text(struct archive_entry *);
void archive_entry_fflags(struct archive_entry *,
unsigned long *set, unsigned long *clear);
const char *archive_entry_gname(struct archive_entry *);
const char *archive_entry_hardlink(struct archive_entry *);
ino_t archive_entry_ino(struct archive_entry *);
mode_t archive_entry_mode(struct archive_entry *);
time_t archive_entry_mtime(struct archive_entry *);
long archive_entry_mtime_nsec(struct archive_entry *);
const char *archive_entry_pathname(struct archive_entry *);
const wchar_t *archive_entry_pathname_w(struct archive_entry *);
dev_t archive_entry_rdev(struct archive_entry *);
dev_t archive_entry_rdevmajor(struct archive_entry *);
dev_t archive_entry_rdevminor(struct archive_entry *);
int64_t archive_entry_size(struct archive_entry *);
const struct stat *archive_entry_stat(struct archive_entry *);
const char *archive_entry_symlink(struct archive_entry *);
@ -91,8 +94,6 @@ const char *archive_entry_uname(struct archive_entry *);
*/
void archive_entry_copy_stat(struct archive_entry *, const struct stat *);
void archive_entry_set_devmajor(struct archive_entry *, dev_t);
void archive_entry_set_devminor(struct archive_entry *, dev_t);
void archive_entry_set_fflags(struct archive_entry *,
unsigned long set, unsigned long clear);
/* Returns pointer to start of first invalid token, or NULL if none. */
@ -109,6 +110,8 @@ void archive_entry_set_link(struct archive_entry *, const char *);
void archive_entry_set_mode(struct archive_entry *, mode_t);
void archive_entry_set_pathname(struct archive_entry *, const char *);
void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
void archive_entry_set_size(struct archive_entry *, int64_t);
void archive_entry_set_symlink(struct archive_entry *, const char *);
void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);

View File

@ -48,6 +48,11 @@ struct archive {
unsigned state;
struct archive_entry *entry;
uid_t user_uid; /* UID of current user. */
/* Dev/ino of the archive being read/written. */
dev_t skip_file_dev;
ino_t skip_file_ino;
/* Utility: Pointer to a block of nulls. */
const char *nulls;
@ -62,8 +67,6 @@ struct archive {
off_t read_data_output_offset;
size_t read_data_remaining;
uid_t user_uid; /* UID of current user. */
/* Callbacks to open/read/write/close archive stream. */
archive_open_callback *client_opener;
archive_read_callback *client_reader;

View File

@ -625,13 +625,13 @@ archive_read_extract_device(struct archive *a, struct archive_entry *entry,
unlink(archive_entry_pathname(entry));
r = mknod(archive_entry_pathname(entry), mode,
archive_entry_stat(entry)->st_rdev);
archive_entry_rdev(entry));
/* Might be a non-existent parent dir; try fixing that. */
if (r != 0 && errno == ENOENT) {
mkdirpath(a, archive_entry_pathname(entry));
r = mknod(archive_entry_pathname(entry), mode,
archive_entry_stat(entry)->st_rdev);
archive_entry_rdev(entry));
}
if (r != 0) {
@ -654,7 +654,7 @@ archive_read_extract_char_device(struct archive *a,
{
mode_t mode;
mode = (archive_entry_stat(entry)->st_mode & ~S_IFMT) | S_IFCHR;
mode = (archive_entry_mode(entry) & ~S_IFMT) | S_IFCHR;
return (archive_read_extract_device(a, entry, flags, mode));
}
@ -664,7 +664,7 @@ archive_read_extract_block_device(struct archive *a,
{
mode_t mode;
mode = (archive_entry_stat(entry)->st_mode & ~S_IFMT) | S_IFBLK;
mode = (archive_entry_mode(entry) & ~S_IFMT) | S_IFBLK;
return (archive_read_extract_device(a, entry, flags, mode));
}

View File

@ -55,8 +55,8 @@ struct archive_entry_header_ustar {
char version[2]; /* For POSIX: "00" */
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char rdevmajor[8];
char rdevminor[8];
char prefix[155];
};
@ -81,8 +81,8 @@ struct archive_entry_header_gnutar {
char magic[8]; /* "ustar \0" (note blank/blank/null at end) */
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char rdevmajor[8];
char rdevminor[8];
char atime[12];
char ctime[12];
char offset[12];
@ -313,7 +313,7 @@ archive_read_format_tar_bid(struct archive *a)
/* Not a valid mode; bail out here. */
return (0);
}
/* TODO: Sanity test uid/gid/size/mtime/devmajor/devminor fields. */
/* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */
return (bid);
}
@ -932,8 +932,8 @@ header_ustar(struct archive *a, struct tar *tar, struct archive_entry *entry,
/* Parse out device numbers only for char and block specials. */
if (header->typeflag[0] == '3' || header->typeflag[0] == '4') {
st->st_rdev = makedev(
tar_atol(header->devmajor, sizeof(header->devmajor)),
tar_atol(header->devminor, sizeof(header->devminor)));
tar_atol(header->rdevmajor, sizeof(header->rdevmajor)),
tar_atol(header->rdevminor, sizeof(header->rdevminor)));
}
tar->entry_bytes_remaining = st->st_size;
@ -1070,9 +1070,9 @@ pax_attribute(struct archive_entry *entry, struct stat *st,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
else if (wcscmp(key, L"SCHILY.devmajor")==0)
st->st_rdev = makedev(tar_atol10(value, wcslen(value)),
minor(st->st_dev));
minor(st->st_rdev));
else if (wcscmp(key, L"SCHILY.devminor")==0)
st->st_rdev = makedev(major(st->st_dev),
st->st_rdev = makedev(major(st->st_rdev),
tar_atol10(value, wcslen(value)));
else if (wcscmp(key, L"SCHILY.fflags")==0)
archive_entry_copy_fflags_text_w(entry, value);
@ -1234,8 +1234,8 @@ header_gnutar(struct archive *a, struct tar *tar, struct archive_entry *entry,
/* Parse out device numbers only for char and block specials */
if (header->typeflag[0] == '3' || header->typeflag[0] == '4')
st->st_rdev = makedev (
tar_atol(header->devmajor, sizeof(header->devmajor)),
tar_atol(header->devminor, sizeof(header->devminor)));
tar_atol(header->rdevmajor, sizeof(header->rdevmajor)),
tar_atol(header->rdevminor, sizeof(header->rdevminor)));
else
st->st_rdev = 0;
@ -1333,7 +1333,7 @@ gnu_parse_sparse_data(struct archive *a, struct tar *tar,
* all of the standard numeric fields. This is a significant limitation
* in practice:
* = file size is limited to 8GB
* = devmajor and devminor are limited to 21 bits
* = rdevmajor and rdevminor are limited to 21 bits
* = uid/gid are limited to 21 bits
*
* There are two workarounds for this:

View File

@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include "archive.h"
#include "archive_entry.h"
#include "archive_private.h"
extern char **environ;
@ -186,6 +187,12 @@ archive_write_header(struct archive *a, struct archive_entry *entry)
if (a->state & ARCHIVE_STATE_DATA)
((a->format_finish_entry)(a));
if (archive_entry_dev(entry) == a->skip_file_dev &&
archive_entry_ino(entry) == a->skip_file_ino) {
archive_set_error(a, 0, "Can't add archive to itself.");
return (ARCHIVE_WARN);
}
/* Format and write header. */
ret = ((a->format_write_header)(a, entry));

View File

@ -64,8 +64,9 @@ static int
file_open(struct archive *a, void *client_data)
{
struct write_fd_data *mine;
struct stat st;
struct stat st, *pst;
pst = NULL;
mine = client_data;
/*
@ -75,12 +76,14 @@ file_open(struct archive *a, void *client_data)
*/
if (mine->fd >= 0 && a->bytes_in_last_block < 0) {
/* Last block will be fully padded. */
fstat(mine->fd, &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 (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) {
@ -94,6 +97,13 @@ file_open(struct archive *a, void *client_data)
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);
}
return (ARCHIVE_OK);
}

View File

@ -76,8 +76,9 @@ file_open(struct archive *a, void *client_data)
{
int flags;
struct write_file_data *mine;
struct stat st;
struct stat st, *pst;
pst = NULL;
mine = client_data;
flags = O_WRONLY | O_CREAT | O_TRUNC;
@ -91,13 +92,17 @@ file_open(struct archive *a, void *client_data)
* otherwise leave it unpadded.
*/
if (mine->fd >= 0 && a->bytes_in_last_block < 0) {
/* Last block will be fully padded. */
fstat(mine->fd, &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 (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);
}
}
} else {
mine->fd = 1;
@ -112,6 +117,17 @@ file_open(struct archive *a, void *client_data)
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);
}
a->skip_file_dev = pst->st_dev;
a->skip_file_ino = pst->st_ino;
return (ARCHIVE_OK);
}

View File

@ -76,8 +76,9 @@ file_open(struct archive *a, void *client_data)
{
int flags;
struct write_file_data *mine;
struct stat st;
struct stat st, *pst;
pst = NULL;
mine = client_data;
flags = O_WRONLY | O_CREAT | O_TRUNC;
@ -91,13 +92,17 @@ file_open(struct archive *a, void *client_data)
* otherwise leave it unpadded.
*/
if (mine->fd >= 0 && a->bytes_in_last_block < 0) {
/* Last block will be fully padded. */
fstat(mine->fd, &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 (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);
}
}
} else {
mine->fd = 1;
@ -112,6 +117,17 @@ file_open(struct archive *a, void *client_data)
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);
}
a->skip_file_dev = pst->st_dev;
a->skip_file_ino = pst->st_ino;
return (ARCHIVE_OK);
}

View File

@ -446,26 +446,28 @@ archive_write_pax_header(struct archive *a,
/*
* POSIX/SUSv3 doesn't provide a standard key for large device
* numbers. I use the same keys here that Joerg Schilling used for
* 'star.' No doubt, other implementations use other keys. Note that
* there's no reason we can't write the same information into a number
* of different keys.
* numbers. I use the same keys here that Joerg Schilling
* used for 'star.' (Which, somewhat confusingly, are called
* "devXXX" even though they code "rdev" values.) No doubt,
* other implementations use other keys. Note that there's no
* reason we can't write the same information into a number of
* different keys.
*
* Of course, this is only needed for block or char device entries.
*/
if (S_ISBLK(st_main->st_mode) ||
S_ISCHR(st_main->st_mode)) {
/*
* If devmajor is too large, add 'SCHILY.devmajor' to
* If rdevmajor is too large, add 'SCHILY.devmajor' to
* extended attributes.
*/
dev_t devmajor, devminor;
devmajor = major(st_main->st_rdev);
devminor = minor(st_main->st_rdev);
if (devmajor >= (1 << 18)) {
dev_t rdevmajor, rdevminor;
rdevmajor = major(st_main->st_rdev);
rdevminor = minor(st_main->st_rdev);
if (rdevmajor >= (1 << 18)) {
add_pax_attr_int(&(pax->pax_header), "SCHILY.devmajor",
devmajor);
archive_entry_set_devmajor(entry_main, (1 << 18) - 1);
rdevmajor);
archive_entry_set_rdevmajor(entry_main, (1 << 18) - 1);
need_extension = 1;
}
@ -473,10 +475,10 @@ archive_write_pax_header(struct archive *a,
* If devminor is too large, add 'SCHILY.devminor' to
* extended attributes.
*/
if (devminor >= (1 << 18)) {
if (rdevminor >= (1 << 18)) {
add_pax_attr_int(&(pax->pax_header), "SCHILY.devminor",
devminor);
archive_entry_set_devminor(entry_main, (1 << 18) - 1);
rdevminor);
archive_entry_set_rdevminor(entry_main, (1 << 18) - 1);
need_extension = 1;
}
}
@ -558,6 +560,8 @@ archive_write_pax_header(struct archive *a,
"SCHILY.acl.default", wp);
/* Include star-compatible metadata info. */
/* Note: "SCHILY.dev{major,minor}" are NOT the
* major/minor portions of "SCHILY.dev". */
add_pax_attr_int(&(pax->pax_header), "SCHILY.dev",
st_main->st_dev);
add_pax_attr_int(&(pax->pax_header), "SCHILY.ino",

View File

@ -275,13 +275,13 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
break;
case S_IFCHR:
shar_printf(a, "mknod %s c %d %d\n", name,
archive_entry_devmajor(entry),
archive_entry_devminor(entry));
archive_entry_rdevmajor(entry),
archive_entry_rdevminor(entry));
break;
case S_IFBLK:
shar_printf(a, "mknod %s b %d %d\n", name,
archive_entry_devmajor(entry),
archive_entry_devminor(entry));
archive_entry_rdevmajor(entry),
archive_entry_rdevminor(entry));
break;
default:
return (ARCHIVE_WARN);

View File

@ -65,10 +65,10 @@ struct archive_entry_header_ustar {
char version[2]; /* For POSIX: "00" */
char uname[32];
char gname[32];
char devmajor[6];
char devmajor_padding[2];
char devminor[6];
char devminor_padding[2];
char rdevmajor[6];
char rdevmajor_padding[2];
char rdevminor[6];
char rdevminor_padding[2];
char prefix[155];
char padding[12];
};
@ -90,8 +90,8 @@ static const struct archive_entry_header_ustar template_header = {
{ '0', '0' }, /* version */
{ }, /* uname */
{ }, /* gname */
{ "000000" }, { ' ', '\0' }, /* devmajor, space-null termination */
{ "000000" }, { ' ', '\0' }, /* devminor, space-null termination */
{ "000000" }, { ' ', '\0' }, /* rdevmajor, space-null termination */
{ "000000" }, { ' ', '\0' }, /* rdevminor, space-null termination */
{ }, /* prefix */
{ } /* padding */
};
@ -289,15 +289,15 @@ __archive_write_format_header_ustar(struct archive *a, char buff[512],
}
if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) {
if (format_octal(major(st->st_rdev), h->devmajor,
sizeof(h->devmajor))) {
if (format_octal(major(st->st_rdev), h->rdevmajor,
sizeof(h->rdevmajor))) {
archive_set_error(a, ERANGE,
"Major device number too large");
ret = ARCHIVE_WARN;
}
if (format_octal(minor(st->st_rdev), h->devminor,
sizeof(h->devminor))) {
if (format_octal(minor(st->st_rdev), h->rdevminor,
sizeof(h->rdevminor))) {
archive_set_error(a, ERANGE,
"Minor device number too large");
ret = ARCHIVE_WARN;