/*
* Utility routines
*
* This code was written by Peter Lawthers, and placed in the public
* domain for use by DMAPI implementors and app writers.
*
* Standard disclaimer:
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdarg.h>
#include <lib/hsm.h>
#ifdef linux
#include <string.h>
#include <time.h>
#define S_IAMB (S_IRWXU|S_IRWXG|S_IRWXO)
#endif
#define S_MASK (S_ISUID|S_ISGID|S_ISVTX|S_IAMB)
extern char *Progname;
extern int errno;
void err_msg(char *, ...);
void errno_msg(char *, ...);
struct ev_name_to_value ev_names[] = {
{ "DM_EVENT_CANCEL", DM_EVENT_CANCEL },
{ "DM_EVENT_MOUNT", DM_EVENT_MOUNT },
{ "DM_EVENT_PREUNMOUNT", DM_EVENT_PREUNMOUNT },
{ "DM_EVENT_UNMOUNT", DM_EVENT_UNMOUNT },
{ "DM_EVENT_DEBUT", DM_EVENT_DEBUT },
{ "DM_EVENT_CREATE", DM_EVENT_CREATE },
{ "DM_EVENT_CLOSE", DM_EVENT_CLOSE },
{ "DM_EVENT_POSTCREATE", DM_EVENT_POSTCREATE },
{ "DM_EVENT_REMOVE", DM_EVENT_REMOVE },
{ "DM_EVENT_POSTREMOVE", DM_EVENT_POSTREMOVE },
{ "DM_EVENT_RENAME", DM_EVENT_RENAME },
{ "DM_EVENT_POSTRENAME", DM_EVENT_POSTRENAME },
{ "DM_EVENT_LINK", DM_EVENT_LINK },
{ "DM_EVENT_POSTLINK", DM_EVENT_POSTLINK },
{ "DM_EVENT_SYMLINK", DM_EVENT_SYMLINK },
{ "DM_EVENT_POSTSYMLINK", DM_EVENT_POSTSYMLINK },
{ "DM_EVENT_READ", DM_EVENT_READ },
{ "DM_EVENT_WRITE", DM_EVENT_WRITE },
{ "DM_EVENT_TRUNCATE", DM_EVENT_TRUNCATE },
{ "DM_EVENT_ATTRIBUTE", DM_EVENT_ATTRIBUTE },
{ "DM_EVENT_DESTROY", DM_EVENT_DESTROY },
{ "DM_EVENT_NOSPACE", DM_EVENT_NOSPACE },
{ "DM_EVENT_USER", DM_EVENT_USER }
};
int ev_namecnt = sizeof(ev_names) / sizeof(ev_names[0]);
dm_eventtype_t
ev_name_to_value(
char *name)
{
int i;
for (i = 0; i < ev_namecnt; i++) {
if (!strcmp(name, ev_names[i].name))
return(ev_names[i].value);
}
return(DM_EVENT_INVALID);
}
char *
ev_value_to_name(
dm_eventtype_t event)
{
static char buffer[100];
int i;
for (i = 0; i < ev_namecnt; i++) {
if (event == ev_names[i].value)
return(ev_names[i].name);
}
sprintf(buffer, "Unknown Event Number %d\n", event);
return(buffer);
}
struct rt_name_to_value rt_names[] = {
{ "DM_RIGHT_NULL", DM_RIGHT_NULL },
{ "DM_RIGHT_SHARED", DM_RIGHT_SHARED },
{ "DM_RIGHT_EXCL", DM_RIGHT_EXCL }
};
int rt_namecnt = sizeof(rt_names) / sizeof(rt_names[0]);
int
rt_name_to_value(
char *name,
dm_right_t *rightp)
{
int i;
for (i = 0; i < rt_namecnt; i++) {
if (!strcmp(name, rt_names[i].name)) {
*rightp = rt_names[i].value;
return(0);
}
}
return(1);
}
char *
rt_value_to_name(
dm_right_t right)
{
int i;
for (i = 0; i < rt_namecnt; i++) {
if (right == rt_names[i].value)
return(rt_names[i].name);
}
return(NULL);
}
/*
* Convert a handle from (possibly) binary to ascii.
*/
void
hantoa(
void *hanp,
size_t hlen,
char *handle_str)
{
int i;
u_char *cp;
cp = (u_char *)hanp;
for (i=0;i<hlen; i++) {
sprintf(handle_str, "%.2x", *cp++);
handle_str += 2;
}
*handle_str = '\0'; /* Null-terminate to make it printable */
}
/*
* Convert a handle from ascii back to it's native binary representation
*/
int
atohan(
char *handle_str,
void **hanpp,
size_t *hlenp)
{
u_char handle[HANDLE_LEN];
char cur_char[3];
int i = 0;
u_long num;
if (strlen(handle_str) > HANDLE_LEN * 2){
return(EBADF);
}
while (*handle_str && *(handle_str + 1)) {
if (i == HANDLE_LEN){
return(EBADF);
}
cur_char[0] = *handle_str;
cur_char[1] = *(handle_str + 1);
cur_char[2] = '\0';
num = strtol(cur_char, (char **)0, 16);
handle[i++] = num & 0xff;
handle_str += 2;
}
if (*handle_str){
return(EBADF);
}
*hlenp = i;
if ((*hanpp = malloc(*hlenp)) == NULL)
return(ENOMEM);
memcpy(*hanpp, handle, *hlenp);
return(0);
}
int
opaque_to_handle(
char *name,
void **hanpp,
size_t *hlenp)
{
if (atohan(name, hanpp, hlenp)) {
/* not a handle */
} else if (dm_handle_is_valid(*hanpp, *hlenp) == DM_FALSE) {
dm_handle_free(*hanpp, *hlenp);
/* not a handle */
} else {
return(0);
}
/* Perhaps it is a pathname */
if (dm_path_to_handle(name, hanpp, hlenp)) {
return(errno);
}
return(0);
}
void
print_handle(
void *hanp,
size_t hlen)
{
char handle_str[HANDLE_STR];
if (hlen > HANDLE_LEN) {
printf("-- invalid hlen length %d --\n", hlen);
return;
}
printf("print_handle: ");
printf("%d\t", hlen);
hantoa(hanp, hlen, handle_str);
printf("%s\n ", handle_str);
}
void
print_victim(
void *hanp,
size_t hlen,
dm_off_t fsize)
{
char handle_str[HANDLE_STR];
if (hlen > HANDLE_LEN) {
printf("-- invalid length --\n");
return;
}
printf("%d\t", hlen);
hantoa(hanp, hlen, handle_str);
printf("%s ", handle_str);
printf("\t%lld \n", fsize);
}
/*
* Print out a simple error message, and include the errno
* string with it.
*/
void
errno_msg(char *fmt, ...)
{
va_list ap;
int old_errno;
old_errno = errno;
fprintf(stderr, "%s: ", Progname);
va_start(ap, fmt );
vfprintf(stderr, fmt, ap);
va_end(ap);
errno = old_errno;
perror("\n\tError");
}
/*
* Print out a simple error message
*/
void
err_msg(char *fmt, ...)
{
va_list ap;
fprintf(stderr, "%s: ", Progname);
va_start(ap, fmt );
vfprintf(stderr, fmt, ap);
va_end(ap);
}
/*
* Initialize the interface to the DMAPI
*/
int
setup_dmapi(dm_sessid_t *sidp)
{
char *cp;
if (dm_init_service(&cp) == -1) {
err_msg("%s/%d: Can't init dmapi", __FILE__, __LINE__);
return(1);
}
if (strcmp(cp, DM_VER_STR_CONTENTS)) {
err_msg("%s/%d: Compiled for a different version", __FILE__, __LINE__);
return(1);
}
find_test_session(sidp);
return(0);
}
/*
* Get the file's change indicator
*/
int
get_dmchange(
dm_sessid_t sid,
void *hanp,
size_t hlen,
dm_token_t token,
u_int *change_start)
{
int error;
dm_stat_t statbuf;
error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_CFLAG, &statbuf);
if (error == -1) {
errno_msg("%s/%d: Can't stat file (%d)", __FILE__, __LINE__, errno);
return(1);
}
*change_start = statbuf.dt_change;
return(0);
}
/*
* Write a file's data to the staging file. We write the file out
* in 4meg chunks.
*/
int
save_filedata(
dm_sessid_t sid,
void *hanp,
size_t hlen,
int stg_fd,
dm_size_t fsize)
{
char *filebuf;
int i, nbufs;
int retval;
dm_ssize_t nread, lastbuf;
ssize_t nwrite;
dm_off_t off;
nbufs = fsize / CHUNKSIZE;
off = 0;
retval = 0;
filebuf = malloc(CHUNKSIZE);
if (filebuf == NULL) {
err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__);
goto out;
}
for (i = 0; i<nbufs; i++) {
nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
(dm_ssize_t)CHUNKSIZE, filebuf);
if (nread != CHUNKSIZE) {
#ifdef __sgi
errno_msg("%s/%d: invis read err: got %lld, expected %lld, buf %d",
#else
errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
#endif
__FILE__, __LINE__,
nread, (dm_ssize_t)CHUNKSIZE, i);
retval = 1;
goto out;
}
off += nread;
nwrite = write(stg_fd, filebuf, CHUNKSIZE);
if (nwrite != CHUNKSIZE) {
errno_msg("%s/%d: write err %d, expected %d, buf %d",
__FILE__, __LINE__,
nwrite, CHUNKSIZE, i);
retval = 1;
goto out;
}
}
lastbuf = fsize % CHUNKSIZE;
nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
(dm_ssize_t)lastbuf, filebuf);
if (nread != lastbuf) {
#ifdef __sgi
errno_msg("%s/%d: invis read error- got %lld, expected %lld, last buf",
#else
errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
#endif
__FILE__, __LINE__,
nread, lastbuf);
retval = 1;
goto out;
}
nwrite = write(stg_fd, filebuf, (int)lastbuf);
if (nwrite != lastbuf) {
#ifdef __sgi
errno_msg("%s/%d: write error %d, expected %lld, last buffer",
#else
errno_msg("%s/%d: write error %d, expected %d, last buffer",
#endif
__FILE__, __LINE__,
nwrite, lastbuf);
retval = 1;
}
out:
if (filebuf)
free(filebuf);
close(stg_fd);
return(retval);
}
/*
* Read a file's data from the staging file.
* Since we only have the staging file handle (not a file descriptor)
* we use dm_read_invis() to read the data.
*
* We stage the entire file in, regardless of how much was asked for,
* starting at the faulting offset.
*/
int
restore_filedata(
dm_sessid_t sid,
void *hanp,
size_t hlen,
dm_token_t token,
void *stg_hanp,
size_t stg_hlen,
dm_off_t off)
{
char *filebuf;
int i, nbufs;
int error, retval;
dm_ssize_t nread, nwrite, lastbuf;
dm_off_t fsize;
dm_stat_t dm_statbuf;
error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_STAT,
&dm_statbuf);
if (error == -1) {
errno_msg("%s/%d: Can't get dm stats of file (%d)", __FILE__, __LINE__, errno);
return(1);
}
fsize = dm_statbuf.dt_size;
nbufs = fsize / CHUNKSIZE;
retval = 0;
filebuf = malloc(CHUNKSIZE);
if (filebuf == NULL) {
err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__);
goto out;
}
for (i = 0; i<nbufs; i++) {
nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN,
off, (dm_ssize_t)CHUNKSIZE, filebuf);
if (nread != CHUNKSIZE) {
errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
__FILE__, __LINE__,
nread, CHUNKSIZE, i);
retval = 1;
goto out;
}
nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, nread,
filebuf);
if (nwrite != nread) {
errno_msg("%s/%d: write error -got %d, expected %d, buf %d",
__FILE__, __LINE__,
nwrite, nread, i);
retval = 1;
goto out;
}
off += CHUNKSIZE;
}
lastbuf = fsize % CHUNKSIZE;
nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN, off,
(dm_ssize_t)lastbuf, filebuf);
if (nread != lastbuf) {
errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
__FILE__, __LINE__,
nread, lastbuf);
retval = 1;
goto out;
}
nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, lastbuf, filebuf);
if (nwrite != lastbuf) {
errno_msg("%s/%d: write error - got %d, expected %d, last buffer",
__FILE__, __LINE__,
nwrite, lastbuf);
retval = 1;
}
out:
if (filebuf)
free(filebuf);
return(retval);
}
extern mode_t
field_to_mode(
mode_t mode)
{
switch (mode & S_IFMT) {
case S_IFBLK:
return(S_IFBLK);
case S_IFREG:
return(S_IFREG);
case S_IFDIR:
return(S_IFDIR);
case S_IFCHR:
return(S_IFCHR);
case S_IFIFO:
return(S_IFIFO);
case S_IFLNK:
return(S_IFLNK);
case S_IFSOCK:
return(S_IFSOCK);
default:
return(0);
}
}
extern int
validate_state(
dm_stat_t *dmstat,
char *pathname,
int report_errors)
{
struct stat statb;
int errors = 0;
/* Get the stat block for the file. */
if (lstat(pathname, &statb)) {
perror("stat failed");
exit(1);
}
/* Compare its fields against the dm_stat_t structure. */
if (dmstat->dt_dev != statb.st_dev) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_dev 0x%x, "
"statb.st_dev 0x%x\n", dmstat->dt_dev,
statb.st_dev);
}
errors++;
}
if (dmstat->dt_ino != statb.st_ino) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_ino %llx, "
#if defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32)
"statb.st_ino %llx\n",
#else
"statb.st_ino %x\n",
#endif
dmstat->dt_ino, statb.st_ino);
}
errors++;
}
if ((dmstat->dt_mode & S_IFMT) != field_to_mode(statb.st_mode)) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_mode (mode) %s, "
"statb.st_mode (mode) %s\n",
mode_to_string(dmstat->dt_mode),
mode_to_string(field_to_mode(statb.st_mode)));
}
errors++;
}
if ((dmstat->dt_mode & S_MASK) != (statb.st_mode & S_MASK)) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_mode (perm) 0%o, "
"statb.st_mode (perm) 0%o\n",
dmstat->dt_mode & S_MASK,
statb.st_mode & S_MASK);
}
errors++;
}
if (dmstat->dt_nlink != statb.st_nlink) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_nlink %d, "
"statb.st_nlink %d\n", dmstat->dt_nlink,
statb.st_nlink);
}
errors++;
}
if (dmstat->dt_uid != statb.st_uid) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_uid %d, "
"statb.st_uid %d\n", dmstat->dt_uid,
statb.st_uid);
}
errors++;
}
if (dmstat->dt_gid != statb.st_gid) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_gid %d, "
"statb.st_gid %d\n", dmstat->dt_gid,
statb.st_gid);
}
errors++;
}
if (dmstat->dt_rdev != statb.st_rdev) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_rdev 0x%x, "
"statb.st_rdev 0x%x\n", dmstat->dt_rdev,
statb.st_rdev);
}
errors++;
}
if (dmstat->dt_size != statb.st_size) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_size %lld, "
#if defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32)
"statb.st_size %lld\n",
#else
"statb.st_size %d\n",
#endif
dmstat->dt_size, statb.st_size);
}
errors++;
}
if (dmstat->dt_atime != statb.st_atime) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_atime %d, "
"statb.st_atime %d\n", dmstat->dt_atime,
statb.st_atime);
}
errors++;
}
if (dmstat->dt_mtime != statb.st_mtime) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_mtime %d, "
"statb.st_mtime %d\n", dmstat->dt_mtime,
statb.st_mtime);
}
errors++;
}
if (dmstat->dt_ctime != statb.st_ctime) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_ctime %d, "
"statb.st_ctime %d\n", dmstat->dt_ctime,
statb.st_ctime);
}
errors++;
}
if (dmstat->dt_dtime != statb.st_ctime) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_dtime %d, "
"statb.st_ctime %d\n", dmstat->dt_dtime,
statb.st_ctime);
}
errors++;
}
if (dmstat->dt_blksize != statb.st_blksize) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_blksize %d, "
"statb.st_blksize %d\n", dmstat->dt_blksize,
statb.st_blksize);
}
errors++;
}
if (dmstat->dt_blocks != statb.st_blocks) {
if (report_errors) {
fprintf(stdout, "ERROR:dmstat->dt_blocks %lld, "
#if defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32)
"statb.st_blocks %lld\n",
#else
"statb.st_blocks %d\n",
#endif
dmstat->dt_blocks, statb.st_blocks);
}
errors++;
}
if (errors && report_errors)
fprintf(stdout, "There were %d differences\n", errors);
return(errors);
}
extern char *
date_to_string(
time_t timeval)
{
static char buffer[21];
char *tmstr;
if (timeval == (time_t)0) {
strcpy(buffer, "0");
} else {
tmstr = asctime(localtime(&timeval));
tmstr += 4;
strncpy(buffer, tmstr, 20);
buffer[20] = '\0';
}
return(buffer);
}
extern char *
mode_to_string(
mode_t mode)
{
static char buffer[256];
switch (mode & S_IFMT) {
case S_IFBLK:
return("S_IFBLK");
case S_IFREG:
return("S_IFREG");
case S_IFDIR:
return("S_IFDIR");
case S_IFCHR:
return("S_IFCHR");
case S_IFIFO:
return("S_IFIFO");
case S_IFLNK:
return("S_IFLNK");
case S_IFSOCK:
return("S_IFSOCK");
default:
sprintf(buffer, "Invalid mode 0%o", mode & S_IFMT);
return(buffer);
}
}
extern char *
emask_to_string(
dm_eventset_t emask)
{
static char buffer[256];
char *name;
int len = 0;
int i;
for (i = 0; i < 32; i++) {
if (!DMEV_ISSET(i, emask))
continue;
switch (i) {
case DM_EVENT_CREATE:
name = "DM_EVENT_CREATE";
break;
case DM_EVENT_POSTCREATE:
name = "DM_EVENT_POSTCREATE";
break;
case DM_EVENT_REMOVE:
name = "DM_EVENT_REMOVE";
break;
case DM_EVENT_POSTREMOVE:
name = "DM_EVENT_POSTREMOVE";
break;
case DM_EVENT_RENAME:
name = "DM_EVENT_RENAME";
break;
case DM_EVENT_POSTRENAME:
name = "DM_EVENT_POSTRENAME";
break;
case DM_EVENT_LINK:
name = "DM_EVENT_LINK";
break;
case DM_EVENT_POSTLINK:
name = "DM_EVENT_POSTLINK";
break;
case DM_EVENT_SYMLINK:
name = "DM_EVENT_SYMLINK";
break;
case DM_EVENT_POSTSYMLINK:
name = "DM_EVENT_POSTSYMLINK";
break;
case DM_EVENT_READ:
name = "DM_EVENT_READ";
break;
case DM_EVENT_WRITE:
name = "DM_EVENT_WRITE";
break;
case DM_EVENT_TRUNCATE:
name = "DM_EVENT_TRUNCATE";
break;
case DM_EVENT_ATTRIBUTE:
name = "DM_EVENT_ATTRIBUTE";
break;
case DM_EVENT_DESTROY:
name = "DM_EVENT_DESTROY";
break;
default:
fprintf(stderr, "Unknown event type %d\n", i);
exit(1);
}
sprintf(buffer + len, "%c%s", (len ? '|' : '('), name);
len = strlen(buffer);
}
if (len == 0) {
sprintf(buffer, "(none)");
} else {
sprintf(buffer + len, ")");
}
return(buffer);
}
#if defined(__sgi) || defined(linux)
extern char *
xflags_to_string(
u_int xflags)
{
static char buffer[256];
int len = 0;
if (xflags & ~(DM_XFLAG_REALTIME|DM_XFLAG_PREALLOC|DM_XFLAG_HASATTR)) {
sprintf(buffer, "Invalid xflags 0%o", xflags);
return(buffer);
}
if (xflags & DM_XFLAG_REALTIME) {
sprintf(buffer + len, "%cREALTIME", (len ? '|' : '('));
len = strlen(buffer);
}
if (xflags & DM_XFLAG_PREALLOC) {
sprintf(buffer + len, "%cPREALLOC", (len ? '|' : '('));
len = strlen(buffer);
}
if (xflags & DM_XFLAG_HASATTR) {
sprintf(buffer + len, "%cHASATTR", (len ? '|' : '('));
len = strlen(buffer);
}
if (len == 0) {
sprintf(buffer, "(none)");
} else {
sprintf(buffer + len, ")");
}
return(buffer);
}
#endif
extern void
print_state(
dm_stat_t *dmstat)
{
/* Print all the stat block fields. */
fprintf(stdout, "dt_dev 0x%x\n", dmstat->dt_dev);
fprintf(stdout, "dt_ino %llx\n", dmstat->dt_ino);
fprintf(stdout, "dt_mode (type) %s\n",
mode_to_string(dmstat->dt_mode));
fprintf(stdout, "dt_mode (perm) 0%o\n", dmstat->dt_mode & S_MASK);
fprintf(stdout, "dt_nlink %d\n", dmstat->dt_nlink);
fprintf(stdout, "dt_uid %d\n", dmstat->dt_uid);
fprintf(stdout, "dt_gid %d\n", dmstat->dt_gid);
fprintf(stdout, "dt_rdev 0x%x\n", dmstat->dt_rdev);
fprintf(stdout, "dt_size %lld\n", dmstat->dt_size);
fprintf(stdout, "dt_atime %s\n",
date_to_string(dmstat->dt_atime));
fprintf(stdout, "dt_mtime %s\n",
date_to_string(dmstat->dt_mtime));
fprintf(stdout, "dt_ctime %s\n",
date_to_string(dmstat->dt_ctime));
fprintf(stdout, "dt_blksize %d\n", dmstat->dt_blksize);
fprintf(stdout, "dt_blocks %lld\n", dmstat->dt_blocks);
#if defined(__sgi) || defined(linux)
fprintf(stdout, "dt_xfs_igen %d\n", dmstat->dt_xfs_igen);
fprintf(stdout, "dt_xfs_xflags %s\n",
xflags_to_string(dmstat->dt_xfs_xflags));
fprintf(stdout, "dt_xfs_extsize %d\n", dmstat->dt_xfs_extsize);
fprintf(stdout, "dt_xfs_extents %d\n", dmstat->dt_xfs_extents);
fprintf(stdout, "dt_xfs_aextents %d\n", dmstat->dt_xfs_aextents);
#endif
fputc('\n', stdout);
/* Print all other fields. */
fprintf(stdout, "emask %s\n",
emask_to_string(dmstat->dt_emask));
fprintf(stdout, "nevents %d\n", dmstat->dt_nevents);
fprintf(stdout, "pmanreg %d\n", dmstat->dt_pmanreg);
fprintf(stdout, "pers %d\n", dmstat->dt_pers);
fprintf(stdout, "dt_dtime %s\n",
date_to_string(dmstat->dt_dtime));
fprintf(stdout, "change %d\n", dmstat->dt_change);
}
extern void
print_line(
dm_stat_t *dmstat)
{
fprintf(stdout, "0x%x|", dmstat->dt_dev);
fprintf(stdout, "%llx|", dmstat->dt_ino);
fprintf(stdout, "%s|", mode_to_string(dmstat->dt_mode));
fprintf(stdout, "0%o|", dmstat->dt_mode & S_MASK);
fprintf(stdout, "%d|", dmstat->dt_nlink);
fprintf(stdout, "%d|", dmstat->dt_uid);
fprintf(stdout, "%d|", dmstat->dt_gid);
fprintf(stdout, "0x%x|", dmstat->dt_rdev);
fprintf(stdout, "%lld|", dmstat->dt_size);
fprintf(stdout, "%s|", date_to_string(dmstat->dt_atime));
fprintf(stdout, "%s|", date_to_string(dmstat->dt_mtime));
fprintf(stdout, "%s|", date_to_string(dmstat->dt_ctime));
fprintf(stdout, "%d|", dmstat->dt_blksize);
fprintf(stdout, "%lld|", dmstat->dt_blocks);
#ifdef __sgi
fprintf(stdout, "%d|", dmstat->dt_xfs_igen);
fprintf(stdout, "%s|", xflags_to_string(dmstat->dt_xfs_xflags));
fprintf(stdout, "%d|", dmstat->dt_xfs_extsize);
fprintf(stdout, "%d|", dmstat->dt_xfs_extents);
fprintf(stdout, "%d|", dmstat->dt_xfs_aextents);
#endif
/* Print all other fields. */
fprintf(stdout, "%s|", emask_to_string(dmstat->dt_emask));
fprintf(stdout, "%d|", dmstat->dt_nevents);
fprintf(stdout, "%d|", dmstat->dt_pmanreg);
fprintf(stdout, "%d|", dmstat->dt_pers);
fprintf(stdout, "%s|", date_to_string(dmstat->dt_dtime));
fprintf(stdout, "%d", dmstat->dt_change);
fputc('\n', stdout);
}