blob: 4ca9e7d8f841cf758f9e1ceb1033907caf7f535e [file] [log] [blame]
/*
* Copyright (c) 2000-2001 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Directory attributes are written on tape during the directory dump phase,
* which precedes the non-dir dump phase. The directory attributes cannot be
* restored, however, until all of the non-dir files have been restored
* (directory timestamps would be wrong, directory inherit flags would
* interfere, etc.) These routines allow the directory attributes to be stored
* on disk when they are read from the dump stream so that they can be applied
* at a later time.
*/
#include <xfs/xfs.h>
#include <xfs/jdm.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <assert.h>
#include <string.h>
#include "config.h"
#include "types.h"
#include "util.h"
#include "mlog.h"
#include "global.h"
#include "drive.h"
#include "media.h"
#include "content.h"
#include "content_inode.h"
#include "dirattr.h"
#include "openutil.h"
#include "mmap.h"
/* Create a file, try to reserve space for it, and return the fd. */
int
create_filled_file(
const char *pathname,
off64_t size)
{
struct flock64 fl = {
.l_len = size,
};
int fd;
int ret;
(void)unlink(pathname);
fd = open(pathname, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd < 0)
return fd;
ret = ioctl(fd, XFS_IOC_RESVSP64, &fl);
if (ret && errno != ENOTTY)
mlog(MLOG_VERBOSE | MLOG_NOTE,
_("attempt to reserve %lld bytes for %s using %s failed: %s (%d)\n"),
size, pathname, "XFS_IOC_RESVSP64",
strerror(errno), errno);
return fd;
}
/* structure definitions used locally ****************************************/
/* node handle limits
*/
#ifdef DIRATTRCHK
/* macros for manipulating dirattr handles when handle consistency
* checking is enabled. the upper bits of a handle will be loaded
* with a handle checksum.
*/
#define HDLSUMCNT 4
#define HDLSUMSHIFT (NBBY * sizeof (dah_t) - HDLSUMCNT)
#define HDLSUMLOMASK ((1 << HDLSUMCNT) - 1)
#define HDLSUMMASK (HDLSUMLOMASK << HDLSUMSHIFT)
#define HDLDIXCNT HDLSUMSHIFT
#define HDLDIXMASK ((1 << HDLDIXCNT) - 1)
#define HDLGETSUM(h) ((uint16_t) \
(((int)h >> HDLSUMSHIFT) \
& \
HDLSUMLOMASK))
#define HDLGETDIX(h) ((dix_t)((int)h & HDLDIXMASK))
#define HDLMKHDL(s, d) ((dah_t)((((int)s << HDLSUMSHIFT)\
& \
HDLSUMMASK) \
| \
((int)d & HDLDIXMASK)))
#define DIX_MAX ((off64_t)HDLDIXMASK)
/* each dirattr will hold two check fields: a handle checksum, and unique
* pattern, to differentiate a valid dirattr from random file contents.
*/
#define DIRATTRUNQ 0xa116
#else /* DIRATTRCHK */
#define DIX_MAX (((off64_t)1 \
<< \
((off64_t)NBBY \
* \
(off64_t)sizeof(dah_t))) \
- \
(off64_t)2) /* 2 to avoid DAH_NULL */
#endif /* DIRATTRCHK */
/* dirattr definition
*/
struct dirattr {
#ifdef DIRATTRCHK
uint16_t d_unq;
uint16_t d_sum;
#endif /* DIRATTRCHK */
mode_t d_mode;
uid_t d_uid;
gid_t d_gid;
time32_t d_atime;
time32_t d_mtime;
time32_t d_ctime;
uint32_t d_xflags;
uint32_t d_extsize;
uint32_t d_projid;
uint32_t d_dmevmask;
uint32_t d_dmstate;
off64_t d_extattroff;
};
typedef struct dirattr dirattr_t;
#define DIRATTR_EXTATTROFFNULL ((off64_t)OFF64MAX)
/* dirattr persistent context definition
*/
struct dirattr_pers {
off64_t dp_appendoff;
};
typedef struct dirattr_pers dirattr_pers_t;
#define DIRATTR_PERS_SZ pgsz
/* dirattr transient context definition
*/
#define DIRATTR_BUFSIZE 32768
struct dirattr_tran {
char *dt_pathname;
int dt_fd;
bool_t dt_at_endpr;
dah_t dt_cachedh;
dirattr_t dt_cached_dirattr;
size_t dt_off;
char dt_buf[DIRATTR_BUFSIZE];
char *dt_extattrpathname;
int dt_extattrfd;
bool_t dt_extattrfdbadpr;
};
typedef struct dirattr_tran dirattr_tran_t;
/* a dirattr is identified internally by its index into the backing store.
* this index is the offset of the dirattr (relative to the end of the dirattr
* persistent state hdr) into the backing store divided by the size of a
* dirattr. a special index is reserved to represent the null index. a type
* is defined for dirattr index (dix_t). it is a 64 bit signed for direct use
* in the lseek64 system call.
*/
typedef off64_t dix_t;
#define DIX2OFF(dix) ((off64_t)(dix * (off64_t)sizeof(dirattr_t) \
+ \
(off64_t)DIRATTR_PERS_SZ))
#define OFF2DIX(doff) ((dix_t)((doff - (off64_t)DIRATTR_PERS_SZ) \
/ \
(off64_t)sizeof(dirattr_t)))
/* declarations of externally defined global symbols *************************/
extern size_t pgsz;
/* forward declarations of locally defined static functions ******************/
static void dirattr_get(dah_t);
static void dirattr_cacheflush(void);
#ifdef DIRATTRCHK
static uint16_t calcdixcum(dix_t dix);
#endif /* DIRATTRCHK */
/* definition of locally defined global variables ****************************/
/* definition of locally defined static variables *****************************/
static char *dirattrfile = "dirattr";
static char *dirextattrfile = "dirextattr";
static dirattr_tran_t *dtp = 0;
static dirattr_pers_t *dpp = 0;
/* definition of locally defined global functions ****************************/
bool_t
dirattr_init(char *hkdir, bool_t resume, uint64_t dircnt)
{
if (dtp) {
return BOOL_TRUE;
}
/* sanity checks
*/
assert(sizeof(dirattr_pers_t) <= DIRATTR_PERS_SZ);
assert(!dtp);
assert(!dpp);
/* allocate and initialize context
*/
dtp = (dirattr_tran_t *)calloc(1, sizeof(dirattr_tran_t));
assert(dtp);
dtp->dt_cachedh = DAH_NULL;
dtp->dt_fd = -1;
dtp->dt_extattrfd = -1;
/* generate a string containing the pathname of the dirattr file
*/
dtp->dt_pathname = open_pathalloc(hkdir, dirattrfile, 0);
/* open the dirattr file
*/
if (resume) {
/* open existing file
*/
dtp->dt_fd = open(dtp->dt_pathname, O_RDWR);
if (dtp->dt_fd < 0) {
mlog(MLOG_NORMAL | MLOG_ERROR, _(
"could not find directory attributes file %s: "
"%s\n"),
dtp->dt_pathname,
strerror(errno));
return BOOL_FALSE;
}
} else {
dtp->dt_fd = create_filled_file(dtp->dt_pathname,
DIRATTR_PERS_SZ + (dircnt * sizeof(struct dirattr)));
if (dtp->dt_fd < 0) {
mlog(MLOG_NORMAL | MLOG_ERROR, _(
"could not create directory attributes file %s: "
"%s\n"),
dtp->dt_pathname,
strerror(errno));
return BOOL_FALSE;
}
}
/* mmap the persistent descriptor
*/
assert(!(DIRATTR_PERS_SZ % pgsz));
dpp = (dirattr_pers_t *)mmap_autogrow(DIRATTR_PERS_SZ,
dtp->dt_fd,
(off_t)0);
assert(dpp);
if (dpp == (dirattr_pers_t *)-1) {
mlog(MLOG_NORMAL | MLOG_ERROR, _(
"unable to map %s: %s\n"),
dtp->dt_pathname,
strerror(errno));
return BOOL_FALSE;
}
/* initialize persistent state
*/
if (!resume) {
dpp->dp_appendoff = (off64_t)DIRATTR_PERS_SZ;
}
/* initialize transient state
*/
dtp->dt_at_endpr = BOOL_FALSE;
/* calculate the dir extattr pathname, and set the fd to -1.
* file will be created on demand.
*/
dtp->dt_extattrpathname = open_pathalloc(hkdir, dirextattrfile, 0);
dtp->dt_extattrfd = -1;
dtp->dt_extattrfdbadpr = BOOL_FALSE;
if (resume) {
(void)unlink(dtp->dt_extattrpathname);
}
return BOOL_TRUE;
}
void
dirattr_cleanup(void)
{
/* REFERENCED */
int rval;
if (!dtp) {
return;
}
if (dpp) {
rval = munmap((void *)dpp, DIRATTR_PERS_SZ);
assert(!rval);
dpp = 0;
}
if (dtp->dt_fd >= 0) {
(void)close(dtp->dt_fd);
dtp->dt_fd = -1;
}
if (dtp->dt_pathname) {
(void)unlink(dtp->dt_pathname);
free((void *)dtp->dt_pathname);
}
if (dtp->dt_extattrfd >= 0) {
(void)close(dtp->dt_extattrfd);
dtp->dt_extattrfd = -1;
}
if (dtp->dt_extattrpathname) {
(void)unlink(dtp->dt_extattrpathname);
free((void *)dtp->dt_extattrpathname);
}
free((void *)dtp);
dtp = 0;
}
dah_t
dirattr_add(filehdr_t *fhdrp)
{
dirattr_t dirattr;
off64_t oldoff;
dix_t dix;
#ifdef DIRATTRCHK
uint16_t sum;
#endif /* DIRATTRCHK */
dah_t dah;
/* sanity checks
*/
assert(dtp);
assert(dpp);
/* make sure file pointer is positioned to write at end of file
*/
if (!dtp->dt_at_endpr) {
off64_t newoff;
newoff = lseek64(dtp->dt_fd, dpp->dp_appendoff, SEEK_SET);
if (newoff == (off64_t)-1) {
mlog(MLOG_NORMAL | MLOG_ERROR, _(
"lseek of dirattr failed: %s\n"),
strerror(errno));
return DAH_NULL;
}
assert(dpp->dp_appendoff == newoff);
dtp->dt_at_endpr = BOOL_TRUE;
}
if (dtp->dt_off + sizeof(dirattr_t) > sizeof(dtp->dt_buf)) {
if (dirattr_flush() != RV_OK) {
return DAH_NULL;
}
}
/* calculate the index of this dirattr
*/
oldoff = dpp->dp_appendoff;
dix = OFF2DIX(oldoff);
assert(dix <= DIX_MAX);
/* populate a dirattr
*/
dirattr.d_mode = (mode_t)fhdrp->fh_stat.bs_mode;
dirattr.d_uid = (uid_t)fhdrp->fh_stat.bs_uid;
dirattr.d_gid = (gid_t)fhdrp->fh_stat.bs_gid;
dirattr.d_atime = (time32_t)fhdrp->fh_stat.bs_atime.tv_sec;
dirattr.d_mtime = (time32_t)fhdrp->fh_stat.bs_mtime.tv_sec;
dirattr.d_ctime = (time32_t)fhdrp->fh_stat.bs_ctime.tv_sec;
dirattr.d_xflags = fhdrp->fh_stat.bs_xflags;
dirattr.d_extsize = (uint32_t)fhdrp->fh_stat.bs_extsize;
dirattr.d_projid = bstat_projid(&(fhdrp->fh_stat));
dirattr.d_dmevmask = fhdrp->fh_stat.bs_dmevmask;
dirattr.d_dmstate = (uint32_t)fhdrp->fh_stat.bs_dmstate;
#ifdef DIRATTRCHK
dirattr.d_unq = DIRATTRUNQ;
sum = calcdixcum(dix);
dirattr.d_sum = sum;
#endif /* DIRATTRCHK */
dirattr.d_extattroff = DIRATTR_EXTATTROFFNULL;
/* write the entry into our buffer
*/
memcpy(dtp->dt_buf + dtp->dt_off, (void *)&dirattr, sizeof(dirattr_t));
dtp->dt_off += sizeof(dirattr_t);
/* update the next write offset
*/
assert(dpp->dp_appendoff <= OFF64MAX - (off64_t)sizeof(dirattr_t));
dpp->dp_appendoff += (off64_t)sizeof(dirattr_t);
#ifdef DIRATTRCHK
dah = HDLMKHDL(sum, dix);
#else /* DIRATTRCHK */
dah = (dah_t)dix;
#endif /* DIRATTRCHK */
return dah;
}
void
dirattr_addextattr(dah_t dah, extattrhdr_t *ahdrp)
{
off64_t oldoff;
off64_t off;
off64_t seekoff;
off64_t nulloff;
int nread;
int nwritten;
/* pull the selected dir attributes into the cache
*/
dirattr_get(dah);
/* open/create extended attributes file if not yet done
*/
if (dtp->dt_extattrfd < 0) {
if (dtp->dt_extattrfdbadpr) {
return;
}
dtp->dt_extattrfd = open(dtp->dt_extattrpathname,
O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR);
if (dtp->dt_extattrfd < 0) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not open/create directory "
"extended attributes file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
}
/* seek to the end of the dir extattr list
*/
off = dtp->dt_cached_dirattr.d_extattroff;
oldoff = DIRATTR_EXTATTROFFNULL;
while (off != DIRATTR_EXTATTROFFNULL) {
seekoff = lseek64(dtp->dt_extattrfd, off, SEEK_SET);
if (seekoff < 0) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not seek to into extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
assert(seekoff == off);
oldoff = off;
nread = read(dtp->dt_extattrfd,
(void *)&off,
sizeof(off));
if (nread != (int)sizeof(off)) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not read extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
}
/* append the extended attributes
*/
off = lseek64(dtp->dt_extattrfd, 0, SEEK_END);
if (off < 0) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not seek to end of extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
nulloff = DIRATTR_EXTATTROFFNULL;
nwritten = write(dtp->dt_extattrfd,
(void *)&nulloff,
sizeof(nulloff));
if (nwritten != (int)sizeof(nulloff)) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not write extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
nwritten = write(dtp->dt_extattrfd, (void *)ahdrp, ahdrp->ah_sz);
if (nwritten != (int)(ahdrp->ah_sz)) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not write at end of extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
/* fill in the offset of the extended attributes into the
* linked list
*/
if (oldoff == DIRATTR_EXTATTROFFNULL) {
dtp->dt_cached_dirattr.d_extattroff = off;
dirattr_cacheflush();
} else {
seekoff = lseek64(dtp->dt_extattrfd, oldoff, SEEK_SET);
if (seekoff < 0) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not seek to into extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
assert(seekoff == oldoff);
nwritten = write(dtp->dt_extattrfd,
(void *)&off,
sizeof(off));
if (nwritten != (int)sizeof(off)) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not write extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
}
}
bool_t
dirattr_cb_extattr(dah_t dah,
bool_t (*cbfunc)(extattrhdr_t *ahdrp,
void *ctxp),
extattrhdr_t *ahdrp,
void *ctxp)
{
off64_t off;
/* pull the selected dir attributes into the cache
*/
dirattr_get(dah);
/* open/create extended attributes file if not yet done
*/
if (dtp->dt_extattrfd < 0) {
if (dtp->dt_extattrfdbadpr) {
return BOOL_TRUE;
}
dtp->dt_extattrfd = open(dtp->dt_extattrpathname,
O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR);
if (dtp->dt_extattrfd < 0) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not open/create directory "
"extended attributes file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
}
/* walk through the dirattr list for this dah
*/
off = dtp->dt_cached_dirattr.d_extattroff;
while (off != DIRATTR_EXTATTROFFNULL) {
off64_t seekoff;
int nread;
off64_t nextoff;
size_t recsz;
bool_t ok;
/* seek to the extattr
*/
seekoff = lseek64(dtp->dt_extattrfd, off, SEEK_SET);
if (seekoff < 0) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not seek to into extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
assert(seekoff == off);
/* peel off the next offset
*/
nread = read(dtp->dt_extattrfd,
(void *)&nextoff,
sizeof(nextoff));
if (nread != (int)sizeof(nextoff)) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not read extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
/* read the extattr hdr
*/
nread = read(dtp->dt_extattrfd,
(void *)ahdrp,
EXTATTRHDR_SZ);
if (nread != EXTATTRHDR_SZ) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not read extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
/* read the remainder of the extattr
*/
recsz = (size_t)ahdrp->ah_sz;
assert(recsz >= EXTATTRHDR_SZ);
nread = read(dtp->dt_extattrfd,
(void *)&ahdrp[1],
recsz - EXTATTRHDR_SZ);
if (nread != (int)(recsz - EXTATTRHDR_SZ)) {
mlog(MLOG_NORMAL | MLOG_WARNING, _(
"could not read extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror(errno),
errno);
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
/* call the callback func
*/
ok = (*cbfunc)(ahdrp, ctxp);
if (!ok) {
return BOOL_FALSE;
}
/* go th the next one
*/
off = nextoff;
}
return BOOL_TRUE;
}
void
dirattr_update(dah_t dah, filehdr_t *fhdrp)
{
dix_t dix;
#ifdef DIRATTRCHK
uint16_t sum;
#endif /* DIRATTRCHK */
off64_t argoff;
off64_t newoff;
dirattr_t dirattr;
int nwritten;
/* sanity checks
*/
assert(dtp);
assert(dpp);
assert(dah != DAH_NULL);
#ifdef DIRATTRCHK
sum = HDLGETSUM(dah);
dix = HDLGETDIX(dah);
#else /* DIRATTRCHK */
dix = (dix_t)dah;
#endif /* DIRATTRCHK */
assert(dix >= 0);
assert(dix <= DIX_MAX);
argoff = DIX2OFF(dix);
assert(argoff >= 0);
assert(argoff >= (off64_t)DIRATTR_PERS_SZ);
assert(argoff <= dpp->dp_appendoff - (off64_t)sizeof(dirattr_t));
#ifdef DIRATTRCHK
dirattr_get(dah);
assert(dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ);
assert(dtp->dt_cached_dirattr.d_sum == sum);
#endif /* DIRATTRCHK */
if (dtp->dt_at_endpr && dtp->dt_off) {
if (dirattr_flush() != RV_OK) {
assert(0);
return;
}
}
/* seek to the dirattr
*/
newoff = lseek64(dtp->dt_fd, argoff, SEEK_SET);
if (newoff == (off64_t)-1) {
mlog(MLOG_NORMAL, _(
"lseek of dirattr failed: %s\n"),
strerror(errno));
assert(0);
}
assert(newoff == argoff);
/* populate a dirattr
*/
dirattr.d_mode = (mode_t)fhdrp->fh_stat.bs_mode;
dirattr.d_uid = (uid_t)fhdrp->fh_stat.bs_uid;
dirattr.d_gid = (gid_t)fhdrp->fh_stat.bs_gid;
dirattr.d_atime = (time32_t)fhdrp->fh_stat.bs_atime.tv_sec;
dirattr.d_mtime = (time32_t)fhdrp->fh_stat.bs_mtime.tv_sec;
dirattr.d_ctime = (time32_t)fhdrp->fh_stat.bs_ctime.tv_sec;
dirattr.d_xflags = fhdrp->fh_stat.bs_xflags;
dirattr.d_extsize = (uint32_t)fhdrp->fh_stat.bs_extsize;
dirattr.d_projid = bstat_projid(&(fhdrp->fh_stat));
dirattr.d_dmevmask = fhdrp->fh_stat.bs_dmevmask;
dirattr.d_dmstate = (uint32_t)fhdrp->fh_stat.bs_dmstate;
dirattr.d_extattroff = DIRATTR_EXTATTROFFNULL;
/* write the dirattr
*/
nwritten = write(dtp->dt_fd, (void *)&dirattr, sizeof(dirattr));
if ((size_t)nwritten != sizeof(dirattr)) {
mlog(MLOG_NORMAL, _(
"update of dirattr failed: %s\n"),
strerror(errno));
assert(0);
}
dtp->dt_at_endpr = BOOL_FALSE;
dtp->dt_cachedh = dah;
}
/* ARGSUSED */
void
dirattr_del(dah_t dah)
{
}
mode_t
dirattr_get_mode(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_mode;
}
uid_t
dirattr_get_uid(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_uid;
}
uid_t
dirattr_get_gid(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_gid;
}
time32_t
dirattr_get_atime(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_atime;
}
time32_t
dirattr_get_mtime(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_mtime;
}
time32_t
dirattr_get_ctime(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_ctime;
}
uint32_t
dirattr_get_xflags(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_xflags;
}
uint32_t
dirattr_get_extsize(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_extsize;
}
uint32_t
dirattr_get_projid(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_projid;
}
uint32_t
dirattr_get_dmevmask(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_dmevmask;
}
uint32_t
dirattr_get_dmstate(dah_t dah)
{
dirattr_get(dah);
return dtp->dt_cached_dirattr.d_dmstate;
}
rv_t
dirattr_flush()
{
ssize_t nwritten;
/* sanity checks
*/
assert (dtp);
if (dtp->dt_off) {
/* write the accumulated dirattr entries
*/
nwritten = write(dtp->dt_fd, (void *)dtp->dt_buf, dtp->dt_off);
if (nwritten != dtp->dt_off) {
if (nwritten < 0) {
mlog(MLOG_NORMAL | MLOG_ERROR,
_("write of dirattr buffer failed: %s\n"),
strerror(errno));
} else {
mlog(MLOG_NORMAL | MLOG_ERROR,
_("write of dirattr buffer failed: "
"expected to write %ld, actually "
"wrote %ld\n"), dtp->dt_off, nwritten);
}
assert(0);
return RV_UNKNOWN;
}
dtp->dt_off = 0;
}
return RV_OK;
}
/* definition of locally defined static functions ****************************/
static void
dirattr_get(dah_t dah)
{
dix_t dix;
off64_t argoff;
off64_t newoff;
int nread;
#ifdef DIRATTRCHK
uint16_t sum;
#endif /* DIRATTRCHK */
/* sanity checks
*/
assert(dtp);
assert(dpp);
assert(dah != DAH_NULL);
/* if we are already holding this dirattr in cache,
* just return
*/
if (dtp->dt_cachedh == dah) {
return;
}
#ifdef DIRATTRCHK
sum = HDLGETSUM(dah);
dix = HDLGETDIX(dah);
#else /* DIRATTRCHK */
dix = (dix_t)dah;
#endif /* DIRATTRCHK */
assert(dix >= 0);
assert(dix <= DIX_MAX);
argoff = DIX2OFF(dix);
assert(argoff >= 0);
assert(argoff >= (off64_t)DIRATTR_PERS_SZ);
assert(argoff <= dpp->dp_appendoff - (off64_t)sizeof(dirattr_t));
if (dtp->dt_at_endpr && dtp->dt_off) {
if (dirattr_flush() != RV_OK) {
assert(0);
return;
}
}
/* seek to the dirattr
*/
newoff = lseek64(dtp->dt_fd, argoff, SEEK_SET);
if (newoff == (off64_t)-1) {
mlog(MLOG_NORMAL, _(
"lseek of dirattr failed: %s\n"),
strerror(errno));
assert(0);
}
assert(newoff == argoff);
/* read the dirattr
*/
nread = read(dtp->dt_fd,
(void *)&dtp->dt_cached_dirattr,
sizeof(dtp->dt_cached_dirattr));
if ((size_t)nread != sizeof(dtp->dt_cached_dirattr)) {
mlog(MLOG_NORMAL, _(
"read of dirattr failed: %s\n"),
strerror(errno));
assert(0);
}
#ifdef DIRATTRCHK
assert(dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ);
assert(dtp->dt_cached_dirattr.d_sum == sum);
#endif /* DIRATTRCHK */
dtp->dt_at_endpr = BOOL_FALSE;
dtp->dt_cachedh = dah;
}
static void
dirattr_cacheflush(void)
{
dah_t dah;
dix_t dix;
#ifdef DIRATTRCHK
uint16_t sum;
#endif /* DIRATTRCHK */
off64_t argoff;
off64_t newoff;
int nwritten;
/* sanity checks
*/
assert(dtp);
assert(dpp);
/* if nothing in the cache, ignore
*/
dah = dtp->dt_cachedh;
assert(dah != DAH_NULL);
if (dah == DAH_NULL) {
return;
}
#ifdef DIRATTRCHK
sum = HDLGETSUM(dah);
dix = HDLGETDIX(dah);
#else /* DIRATTRCHK */
dix = (dix_t)dah;
#endif /* DIRATTRCHK */
#ifdef DIRATTRCHK
assert(dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ);
assert(dtp->dt_cached_dirattr.d_sum == sum);
#endif /* DIRATTRCHK */
assert(dix >= 0);
assert(dix <= DIX_MAX);
argoff = DIX2OFF(dix);
assert(argoff >= 0);
assert(argoff >= (off64_t)DIRATTR_PERS_SZ);
assert(argoff <= dpp->dp_appendoff - (off64_t)sizeof(dirattr_t));
/* seek to the dirattr
*/
newoff = lseek64(dtp->dt_fd, argoff, SEEK_SET);
if (newoff == (off64_t)-1) {
mlog(MLOG_NORMAL, _(
"lseek of dirattr failed: %s\n"),
strerror(errno));
assert(0);
}
assert(newoff == argoff);
/* write the dirattr
*/
nwritten = write(dtp->dt_fd,
(void *)&dtp->dt_cached_dirattr,
sizeof(dtp->dt_cached_dirattr));
if ((size_t)nwritten != sizeof(dtp->dt_cached_dirattr)) {
mlog(MLOG_NORMAL, _(
"flush of dirattr failed: %s\n"),
strerror(errno));
assert(0);
}
dtp->dt_at_endpr = BOOL_FALSE;
}
#ifdef DIRATTRCHK
static uint16_t
calcdixcum(dix_t dix)
{
uint16_t sum;
ix_t nibcnt;
ix_t nibix;
assert((sizeof(dah_t) / HDLSUMCNT) * HDLSUMCNT == sizeof(dah_t));
nibcnt = (sizeof(dah_t) / HDLSUMCNT) - 1;
sum = 0;
for (nibix = 0; nibix < nibcnt; nibix++) {
sum += (uint16_t)(dix & HDLSUMLOMASK);
dix >>= HDLSUMCNT;
}
sum = (uint16_t)((~sum + 1) & HDLSUMLOMASK);
return sum;
}
#endif /* DIRATTRCHK */