mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
Add DMAPI tests for dm_get_bulkall and dm_get_bulkattr
Test for dm_get_bulkall.
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* October 1, 2003: Dean Roehrich
|
||||
* - Adapted to test dm_get_bulkall, from migfind.c.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <lib/hsm.h>
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, optopt, opterr;
|
||||
char *Progname;
|
||||
|
||||
extern void err_msg(char *, ...);
|
||||
extern void errno_msg(char *, ...);
|
||||
|
||||
int setup_dmapi(dm_sessid_t *);
|
||||
int scan_fs(dm_sessid_t, void *, size_t, dm_attrname_t*, size_t,
|
||||
int, int);
|
||||
void usage(char *);
|
||||
|
||||
void
|
||||
usage(
|
||||
char *prog)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s ", prog);
|
||||
fprintf(stderr, " <-a attrname> [-b bufsz] [-v] [-q]");
|
||||
fprintf(stderr, " filesystem\n");
|
||||
}
|
||||
|
||||
#define V_PRINT 0x01
|
||||
#define V_VERBOSE 0x02
|
||||
|
||||
int
|
||||
main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
{
|
||||
|
||||
int c;
|
||||
int error;
|
||||
char *fsname;
|
||||
dm_sessid_t sid;
|
||||
void *fs_hanp;
|
||||
size_t fs_hlen;
|
||||
dm_attrname_t dmattr;
|
||||
size_t bufsz = 65536;
|
||||
dm_size_t ret;
|
||||
int extras = 0;
|
||||
int verbose = V_PRINT;
|
||||
|
||||
Progname = argv[0];
|
||||
memset(&dmattr, 0, sizeof(dmattr));
|
||||
|
||||
while ((c = getopt(argc, argv, "a:b:evq")) != EOF) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
if (strlen(optarg) > (DM_ATTR_NAME_SIZE-1)){
|
||||
printf("Arg for -a too long\n");
|
||||
exit(1);
|
||||
}
|
||||
strcpy((char*)dmattr.an_chars, optarg);
|
||||
break;
|
||||
case 'b':
|
||||
bufsz = atoi(optarg);
|
||||
break;
|
||||
case 'e':
|
||||
extras++;
|
||||
break;
|
||||
case 'v':
|
||||
verbose |= V_VERBOSE;
|
||||
break;
|
||||
case 'q':
|
||||
verbose &= ~V_PRINT;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage(Progname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (optind >= argc) {
|
||||
usage(Progname);
|
||||
exit(1);
|
||||
}
|
||||
if (dmattr.an_chars[0] == '\0') {
|
||||
usage(Progname);
|
||||
exit(1);
|
||||
}
|
||||
fsname = argv[optind];
|
||||
|
||||
/*
|
||||
* Now we have our filesystem name and possibly a size threshold
|
||||
* to look for. Init the dmapi, and get a filesystem handle so
|
||||
* we can scan the filesystem
|
||||
*/
|
||||
error = setup_dmapi(&sid);
|
||||
if (error)
|
||||
exit(1);
|
||||
|
||||
if (dm_path_to_fshandle(fsname, &fs_hanp, &fs_hlen) == -1) {
|
||||
errno_msg("Can't get filesystem handle");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if( dm_get_config(fs_hanp, fs_hlen, DM_CONFIG_BULKALL, &ret) ||
|
||||
(ret != DM_TRUE)) {
|
||||
printf("Kernel does not have dm_get_bulkall\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the attributes of all files in the filesystem
|
||||
*/
|
||||
error = scan_fs(sid, fs_hanp, fs_hlen, &dmattr, bufsz, extras, verbose);
|
||||
if (error)
|
||||
exit(1);
|
||||
|
||||
|
||||
/*
|
||||
* We're done, so we can shut down our session.
|
||||
*/
|
||||
if (dm_destroy_session(sid) == -1) {
|
||||
errno_msg("Can't close session");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
my_print_victim(
|
||||
void *hanp,
|
||||
size_t hlen,
|
||||
dm_xstat_t *xbuf,
|
||||
dm_stat_t *sbuf,
|
||||
int extras,
|
||||
int verbose)
|
||||
{
|
||||
u_int attrlen;
|
||||
char *attrval;
|
||||
|
||||
if (hlen > HANDLE_LEN) {
|
||||
if (verbose & V_PRINT)
|
||||
printf("-- invalid length --\n");
|
||||
}
|
||||
else {
|
||||
char handle_str[HANDLE_STR];
|
||||
if (verbose & V_PRINT) {
|
||||
printf("%d\t", hlen);
|
||||
hantoa(hanp, hlen, handle_str);
|
||||
printf("%s ", handle_str);
|
||||
if (extras) {
|
||||
printf("size=%lld ",
|
||||
(int64_t)sbuf->dt_size);
|
||||
printf("ino=%lld ",
|
||||
(int64_t)sbuf->dt_ino);
|
||||
}
|
||||
}
|
||||
|
||||
attrval = DM_GET_VALUE(xbuf,
|
||||
dx_attrdata, char*);
|
||||
attrlen = DM_GET_LEN(xbuf,
|
||||
dx_attrdata);
|
||||
/* Hmmm, a hole in the dmapi spec.
|
||||
* No way to have a null pointer
|
||||
* for the value. No way to
|
||||
* distinguish between a zero-length
|
||||
* attribute value and not finding
|
||||
* the attribute in the first place.
|
||||
*
|
||||
* Punt. Since I cannot get a null
|
||||
* pointer for the value, let's look
|
||||
* at the length. If it's zero,
|
||||
* we'll say the attribute was
|
||||
* not found.
|
||||
*/
|
||||
if (verbose & V_PRINT) {
|
||||
if (attrlen) {
|
||||
printf("%d (%s)\n",
|
||||
attrlen,
|
||||
isalpha(attrval[0]) ? attrval : "");
|
||||
}
|
||||
else {
|
||||
printf("<none>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the attributes for all the files in a filesystem in bulk,
|
||||
* including the specified dmattr,
|
||||
* and print out the handles and dmattr values.
|
||||
*/
|
||||
int
|
||||
scan_fs(
|
||||
dm_sessid_t sid,
|
||||
void *fs_hanp,
|
||||
size_t fs_hlen,
|
||||
dm_attrname_t *dmattr,
|
||||
size_t buflen,
|
||||
int extras,
|
||||
int verbose)
|
||||
{
|
||||
u_int mask; /* attributes to scan for */
|
||||
dm_xstat_t *dm_xstatbuf, *xbuf; /* attributes buffer */
|
||||
dm_stat_t *sbuf;
|
||||
dm_attrloc_t locp; /* opaque location in fs */
|
||||
size_t rlenp; /* ret length of stat info */
|
||||
void *hanp; /* file handle */
|
||||
size_t hlen; /* file handle */
|
||||
int more; /* loop terminator */
|
||||
int error;
|
||||
|
||||
#ifdef VERITAS_21
|
||||
if (buflen > 65536)
|
||||
buflen= 65536;
|
||||
#endif
|
||||
dm_xstatbuf = (dm_xstat_t *)calloc(1, buflen);
|
||||
if (dm_xstatbuf == NULL) {
|
||||
err_msg("Can't get memory for stat buffer");
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the offset opaque offset cookie that
|
||||
* we use in successive calls to dm_get_bulkattr()
|
||||
*/
|
||||
error = dm_init_attrloc(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &locp);
|
||||
if (error == -1) {
|
||||
errno_msg("%s/%d: Can't initialize offset cookie (%d)", __FILE__, __LINE__, errno);
|
||||
free(dm_xstatbuf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set our stat mask so that we'll only get the normal stat(2)
|
||||
* info and the file's handle
|
||||
*/
|
||||
mask = DM_AT_HANDLE | DM_AT_STAT;
|
||||
do {
|
||||
more = dm_get_bulkall(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
|
||||
mask, dmattr, &locp, buflen,
|
||||
dm_xstatbuf, &rlenp);
|
||||
if (verbose & V_VERBOSE)
|
||||
fprintf(stderr, "BULKALL more=%d, rlen=%d\n", more, rlenp);
|
||||
if (more == -1) {
|
||||
errno_msg("%s/%d: Can't get bulkall for filesystem", __FILE__, __LINE__, errno);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk through the stat buffer and pull out files
|
||||
* that are of interest
|
||||
*
|
||||
* The stat buffer is variable length, so we must
|
||||
* use the DM_STEP_TO_NEXT macro to access each individual
|
||||
* dm_xstat_t structure in the returned buffer.
|
||||
*/
|
||||
xbuf = dm_xstatbuf;
|
||||
while (xbuf != NULL) {
|
||||
sbuf = &xbuf->dx_statinfo;
|
||||
if (S_ISREG(sbuf->dt_mode)) {
|
||||
hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
|
||||
hlen = DM_GET_LEN(sbuf, dt_handle);
|
||||
|
||||
my_print_victim(hanp, hlen, xbuf, sbuf,
|
||||
extras, verbose);
|
||||
}
|
||||
/* The sbuf has the offset to the next xbuf */
|
||||
xbuf = DM_STEP_TO_NEXT(sbuf, dm_xstat_t *);
|
||||
}
|
||||
} while (more == 1);
|
||||
|
||||
free(dm_xstatbuf);
|
||||
if (more == -1)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* October 2, 2003: Dean Roehrich
|
||||
* - Adapted to test dm_get_bulkattr + dm_get_dmattr, from migfind.c.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <lib/hsm.h>
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, optopt, opterr;
|
||||
char *Progname;
|
||||
|
||||
extern void print_victim(void *, size_t, dm_off_t);
|
||||
extern void err_msg(char *, ...);
|
||||
extern void errno_msg(char *, ...);
|
||||
|
||||
int setup_dmapi(dm_sessid_t *);
|
||||
int scan_fs(dm_sessid_t, void *, size_t, dm_attrname_t*,
|
||||
size_t, int);
|
||||
void usage(char *);
|
||||
|
||||
void
|
||||
usage(
|
||||
char *prog)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s ", prog);
|
||||
fprintf(stderr, " [-a attrname] [-b bufsz] [-v]");
|
||||
fprintf(stderr, " [-q] filesystem\n");
|
||||
}
|
||||
|
||||
#define V_PRINT 0x01
|
||||
#define V_VERBOSE 0x02
|
||||
|
||||
|
||||
int
|
||||
main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
{
|
||||
|
||||
int c;
|
||||
int error;
|
||||
char *fsname;
|
||||
dm_sessid_t sid;
|
||||
void *fs_hanp;
|
||||
size_t fs_hlen;
|
||||
dm_attrname_t dmattr;
|
||||
size_t bufsz = 65536;
|
||||
dm_attrname_t *dmattrp = NULL;
|
||||
int verbose = V_PRINT;
|
||||
|
||||
Progname = argv[0];
|
||||
memset(&dmattr, 0, sizeof(dmattr));
|
||||
|
||||
while ((c = getopt(argc, argv, "a:b:vq")) != EOF) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
if (strlen(optarg) > (DM_ATTR_NAME_SIZE-1)){
|
||||
printf("Arg for -a too long\n");
|
||||
exit(1);
|
||||
}
|
||||
strcpy((char*)dmattr.an_chars, optarg);
|
||||
dmattrp = &dmattr;
|
||||
break;
|
||||
case 'b':
|
||||
bufsz = atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
verbose |= V_VERBOSE;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
verbose &= ~V_PRINT;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
usage(Progname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (optind >= argc) {
|
||||
usage(Progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fsname = argv[optind];
|
||||
|
||||
/*
|
||||
* Now we have our filesystem name and possibly a size threshold
|
||||
* to look for. Init the dmapi, and get a filesystem handle so
|
||||
* we can scan the filesystem
|
||||
*/
|
||||
error = setup_dmapi(&sid);
|
||||
if (error)
|
||||
exit(1);
|
||||
|
||||
if (dm_path_to_fshandle(fsname, &fs_hanp, &fs_hlen) == -1) {
|
||||
errno_msg("Can't get filesystem handle");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Get the attributes of all files in the filesystem
|
||||
*/
|
||||
error = scan_fs(sid, fs_hanp, fs_hlen, dmattrp, bufsz, verbose);
|
||||
if (error)
|
||||
exit(1);
|
||||
|
||||
|
||||
/*
|
||||
* We're done, so we can shut down our session.
|
||||
*/
|
||||
if (dm_destroy_session(sid) == -1) {
|
||||
errno_msg("Can't close session");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
my_print_victim(
|
||||
dm_sessid_t sid,
|
||||
void *hanp,
|
||||
size_t hlen,
|
||||
dm_attrname_t *dm_attrp,
|
||||
int verbose)
|
||||
{
|
||||
size_t rlen;
|
||||
size_t buflen = 10000;
|
||||
char buf[buflen];
|
||||
|
||||
if (hlen > HANDLE_LEN) {
|
||||
if (verbose & V_PRINT)
|
||||
printf("-- invalid length --\n");
|
||||
}
|
||||
else {
|
||||
char handle_str[HANDLE_STR];
|
||||
if (verbose & V_PRINT) {
|
||||
printf("%d\t", hlen);
|
||||
hantoa(hanp, hlen, handle_str);
|
||||
printf("%s ", handle_str);
|
||||
}
|
||||
|
||||
if (dm_get_dmattr(sid, hanp, hlen, DM_NO_TOKEN, dm_attrp,
|
||||
buflen, (char*)buf, &rlen)) {
|
||||
if (verbose & V_PRINT) {
|
||||
if( errno == E2BIG ){
|
||||
printf("E2BIG\n");
|
||||
}
|
||||
else if (errno == ENOMEM){
|
||||
printf("ENOMEM\n");
|
||||
}
|
||||
else {
|
||||
printf("<none>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (verbose & V_PRINT) {
|
||||
if( isalpha(buf[0]) )
|
||||
printf("(%s)\n", buf);
|
||||
else
|
||||
printf("<len=%d>\n",rlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the attributes for all the files in a filesystem in bulk,
|
||||
* and print out the handles and sizes of any that meet our target
|
||||
* criteria.
|
||||
*
|
||||
* We are not interested in file names; if we were, then we would
|
||||
* have to do a dm_get_dirattrs() on each directroy, then use
|
||||
* dm_handle_to_path() to get the pathname.
|
||||
*/
|
||||
int
|
||||
scan_fs(
|
||||
dm_sessid_t sid,
|
||||
void *fs_hanp,
|
||||
size_t fs_hlen,
|
||||
dm_attrname_t *dmattrp,
|
||||
size_t buflen,
|
||||
int verbose)
|
||||
{
|
||||
u_int mask; /* attributes to scan for */
|
||||
dm_stat_t *dm_statbuf, *sbuf; /* attributes buffer */
|
||||
dm_attrloc_t locp; /* opaque location in fs */
|
||||
size_t rlenp; /* ret length of stat info */
|
||||
void *hanp; /* file handle */
|
||||
size_t hlen; /* file handle */
|
||||
int more; /* loop terminator */
|
||||
int error;
|
||||
|
||||
|
||||
#ifdef VERITAS_21
|
||||
if (buflen > 65536)
|
||||
buflen = 65536;
|
||||
#endif
|
||||
dm_statbuf = (dm_stat_t *)calloc(1, buflen);
|
||||
if (dm_statbuf == NULL) {
|
||||
err_msg("Can't get memory for stat buffer");
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the offset opaque offset cookie that
|
||||
* we use in successive calls to dm_get_bulkattr()
|
||||
*/
|
||||
error = dm_init_attrloc(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &locp);
|
||||
if (error == -1) {
|
||||
errno_msg("%s/%d: Can't initialize offset cookie (%d)", __FILE__, __LINE__, errno);
|
||||
free(dm_statbuf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set our stat mask so that we'll only get the normal stat(2)
|
||||
* info and the file's handle
|
||||
*/
|
||||
mask = DM_AT_HANDLE | DM_AT_STAT;
|
||||
do {
|
||||
more = dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
|
||||
mask, &locp, buflen, dm_statbuf, &rlenp);
|
||||
if (verbose & V_VERBOSE)
|
||||
fprintf(stderr, "BULKATTR more=%d, rlen=%d\n", more, rlenp);
|
||||
if (more == -1) {
|
||||
errno_msg("%s/%d: Can't get bulkattr for filesystem", __FILE__, __LINE__, errno);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk through the stat buffer and pull out files
|
||||
* that are of interest
|
||||
*
|
||||
* The stat buffer is variable length, so we must
|
||||
* use the DM_STEP_TO_NEXT macro to access each individual
|
||||
* dm_stat_t structure in the returned buffer.
|
||||
*/
|
||||
sbuf = dm_statbuf;
|
||||
while (sbuf != NULL) {
|
||||
if (S_ISREG(sbuf->dt_mode)) {
|
||||
hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
|
||||
hlen = DM_GET_LEN(sbuf, dt_handle);
|
||||
|
||||
if (dmattrp) {
|
||||
my_print_victim(sid, hanp, hlen,
|
||||
dmattrp, verbose);
|
||||
}
|
||||
else if (verbose & V_PRINT){
|
||||
print_victim(hanp, hlen, sbuf->dt_size);
|
||||
}
|
||||
}
|
||||
sbuf = DM_STEP_TO_NEXT(sbuf, dm_stat_t *);
|
||||
}
|
||||
} while (more == 1);
|
||||
|
||||
free(dm_statbuf);
|
||||
if (more == -1)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user