#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include "libhammer.h"
libhammer_fsinfo_t
libhammer_get_fsinfo(const char *path)
{
struct hammer_pseudofs_data *pfs_od;
struct hammer_ioc_pseudofs_rw pfs;
struct hammer_ioc_info info;
libhammer_pfsinfo_t pip;
libhammer_fsinfo_t fip;
int error = 0;
int fd;
if ((fd = open(path, O_RDONLY)) < 0)
return NULL;
fip = _libhammer_malloc(sizeof(*fip));
TAILQ_INIT(&fip->list_pseudo);
if ((ioctl(fd, HAMMERIOC_GET_INFO, &info)) < 0) {
libhammer_free_fsinfo(fip);
close(fd);
return NULL;
}
snprintf(fip->vol_name, TXTLEN, "%s", info.vol_label);
fip->vol_fsid = info.vol_fsid;
fip->version = info.version;
fip->nvolumes = info.nvolumes;
fip->rootvol = info.rootvol;
fip->inodes = info.inodes;
fip->bigblocks = info.bigblocks;
fip->freebigblocks = info.freebigblocks;
fip->rsvbigblocks = info.rsvbigblocks;
bzero(&pfs, sizeof(pfs));
pfs.pfs_id = 0;
pfs.ondisk = _libhammer_malloc(sizeof(*pfs_od));
pfs.bytes = sizeof(struct hammer_pseudofs_data);
while(error == 0) {
error = ioctl(fd, HAMMERIOC_SCAN_PSEUDOFS, &pfs);
if (error == 0 && !hammer_is_pfs_deleted(pfs.ondisk)) {
pip = _libhammer_malloc(sizeof(*pip));
pfs_od = pfs.ondisk;
pip->ismaster = hammer_is_pfs_master(pfs_od);
pip->version = fip->version;
pip->pfs_id = pfs.pfs_id;
pip->mirror_flags = pfs_od->mirror_flags;
pip->beg_tid = pfs_od->sync_beg_tid;
pip->end_tid = pfs_od->sync_end_tid;
pip->mountedon =
libhammer_find_pfs_mount(&pfs_od->unique_uuid);
if (fip->version < 3) {
libhammer_compat_old_snapcount(pip);
} else {
TAILQ_INIT(&pip->list_snap);
if (libhammer_pfs_get_snapshots(fip, pip) < 0)
pip->snapcount = 0;
}
TAILQ_INSERT_TAIL(&fip->list_pseudo, pip, entries);
}
pfs.pfs_id++;
}
free(pfs.ondisk);
close (fd);
return (fip);
}
void
libhammer_free_fsinfo(libhammer_fsinfo_t fip)
{
struct libhammer_pfsinfo *pfstmp;
while(!TAILQ_EMPTY(&fip->list_pseudo)) {
pfstmp = TAILQ_FIRST(&fip->list_pseudo);
libhammer_pfs_free_snapshots(pfstmp);
if (pfstmp->mountedon)
free(pfstmp->mountedon);
TAILQ_REMOVE(&fip->list_pseudo, pfstmp, entries);
free(pfstmp);
}
free(fip);
}