int libhammer_pfs_get_snapshots(libhammer_fsinfo_t fip, libhammer_pfsinfo_t pip) { struct hammer_snapshot_data *snapdata = NULL; struct hammer_ioc_snapshot snap; libhammer_snapinfo_t sip; libhammer_pfsinfo_t pfs0; char *path = NULL; int ret = 0; int fd; u_int i; assert(pip != NULL); assert(fip != NULL); /* * Still need a path to open so, when not mounted, try * to figure out the PFS path access in order to open(2) * Note that this will fail for slave PFS that were created * with pfs-slave directive since they don't have any transaction * recorded and nlookup can't find them. For those we simply * return the error in the head structure of libhammer_pfsinfo_t * for the caller to handle the situation. */ pfs0 = libhammer_get_first_pfs(fip); if (pip->mountedon == NULL) libhammer_pfs_canonical_path(pfs0->mountedon, pip, &path); else path = strdup(pip->mountedon); if (path == NULL || (fd = open(path, O_RDONLY)) < 0) { pip->head.error = errno; ret = -1; goto out; } bzero(&snap, sizeof(snap)); /* * Loop while there are snapshots returned from the ioctl(2) call. * * For more information on how the snapshots are returned * to userland please check sys/vfs/hammer/hammer_ioctl.c */ do { if (ioctl(fd, HAMMERIOC_GET_SNAPSHOT, &snap) < 0) { pip->head.error = errno; ret = -1; close(fd); goto out; } for (i = 0; i < snap.count; i++) { snapdata = &snap.snaps[i]; sip = _libhammer_malloc(sizeof(*sip)); sip->tid = snapdata->tid; sip->ts = snapdata->ts; if (strlen(snapdata->label)) sprintf(sip->label, "%s", snapdata->label); else sip->label[0] = '\0'; TAILQ_INSERT_TAIL(&pip->list_snap, sip, entries); pip->snapcount++; } } while (snap.head.error == 0 && snap.count); close(fd); out: if (path) free(path); return (ret); }
libhammer_volinfo_t libhammer_get_volinfo(const char *path) { struct hammer_pseudofs_data *pfs_od; struct hammer_ioc_pfs_iterate pi; struct hammer_ioc_info info; libhammer_pfsinfo_t pfstmp; libhammer_volinfo_t hvi; int error = 0; int fd; if ((fd = open(path, O_RDONLY)) < 0) return NULL; hvi = _libhammer_malloc(sizeof(*hvi)); TAILQ_INIT(&hvi->list_pseudo); if ((ioctl(fd, HAMMERIOC_GET_INFO, &info)) < 0) { libhammer_free_volinfo(hvi); close(fd); return NULL; } /* Fill volume information */ snprintf(hvi->vol_name, TXTLEN, "%s", info.vol_name); hvi->vol_fsid = info.vol_fsid; hvi->version = info.version; hvi->nvolumes = info.nvolumes; hvi->inodes = info.inodes; hvi->bigblocks = info.bigblocks; hvi->freebigblocks = info.freebigblocks; hvi->rsvbigblocks = info.rsvbigblocks; bzero(&pi, sizeof(pi)); pi.ondisk = _libhammer_malloc(sizeof(*pfs_od)); while(error == 0) { error = ioctl(fd, HAMMERIOC_PFS_ITERATE, &pi); if (error == 0 && ((pi.head.flags & HAMMER_PFSD_DELETED) == 0)) { /* * XXX - In the case the path passed is on PFS#0 but it * is not the mountpoint itself, it could produce a * wrong type of PFS. */ pfstmp = _libhammer_malloc(sizeof(*pfstmp)); pfs_od = pi.ondisk; pfstmp->ismaster = (pfs_od->mirror_flags & HAMMER_PFSD_SLAVE) ? 0 : 1; if (pi.pos == 0) pfstmp->mountedon = strdup(path); else pfstmp->mountedon = libhammer_find_pfs_mount(pi.pos, hvi->vol_fsid, pfstmp->ismaster); /* * Fill in structs used in the library. We don't rely on * HAMMER own struct but we do fill our own. */ pfstmp->version = hvi->version; pfstmp->pfs_id = pi.pos; pfstmp->mirror_flags = pfs_od->mirror_flags; pfstmp->beg_tid = pfs_od->sync_beg_tid; pfstmp->end_tid = pfs_od->sync_end_tid; pfstmp->snapcount = count_snapshots(hvi->version, pfstmp->snapshots, pfstmp->mountedon, &pfstmp->head.error); TAILQ_INSERT_TAIL(&hvi->list_pseudo, pfstmp, entries); } pi.pos++; } free(pi.ondisk); close (fd); return (hvi); }