mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
3d3751a7b3
Eliminate build warnings reported on files located under these
subdirectories:
dmapi/src/common/cmd/
dmapi/src/common/lib/
dmapi/src/sample_hsm/
dmapi/src/simple/
Signed-off-by: Alex Elder <aelder@sgi.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
281 lines
6.6 KiB
C
281 lines
6.6 KiB
C
/*
|
|
* Simple utility to find all files above a certain size in
|
|
* a filesystem. The output is to stdout, and is of the form:
|
|
* filehandle length filehandle file size in bytes
|
|
*
|
|
* The list is not sorted in any way.
|
|
*
|
|
* 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 <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>
|
|
|
|
#define NUMLEN 16 /* arbitrary max len of input size */
|
|
#define MAX_K (((u_int)LONG_MAX) / 1024)
|
|
#define MAX_M (((u_int)LONG_MAX) / (1024*1024))
|
|
|
|
|
|
|
|
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_off_t);
|
|
int verify_size(char *, dm_off_t *);
|
|
void usage(char *);
|
|
|
|
void
|
|
usage(
|
|
char *prog)
|
|
{
|
|
fprintf(stderr, "Usage: %s ", prog);
|
|
fprintf(stderr, " [-s file threshold]");
|
|
fprintf(stderr, " filesystem\n");
|
|
}
|
|
|
|
/*
|
|
* Convert an input string on the form 10m or 128K to something reasonable
|
|
*/
|
|
int
|
|
verify_size(
|
|
char *str,
|
|
dm_off_t *sizep)
|
|
{
|
|
char *cp;
|
|
dm_off_t size;
|
|
|
|
if (strlen(str) > NUMLEN) {
|
|
printf("Size %s is invalid \n", str);
|
|
return(1);
|
|
}
|
|
|
|
size = strtol(str,0,0);
|
|
if (size < 0 || size >= LONG_MAX ) {
|
|
printf("Size %lld is invalid \n", (long long) size);
|
|
return(1);
|
|
}
|
|
|
|
cp = str;
|
|
while (isdigit(*cp))
|
|
cp++;
|
|
if (*cp == 'k' || *cp == 'K') {
|
|
if ( size >= (u_int) MAX_K) {
|
|
printf("Size %lld is invalid\n", (long long) size);
|
|
return(1);
|
|
}
|
|
size *= 1024;
|
|
} else if (*cp == 'm' || *cp == 'M') {
|
|
if ( size >= (u_int) MAX_M) {
|
|
printf("Size %lld is invalid\n", (long long) size);
|
|
return(1);
|
|
}
|
|
size *= (1024*1024);
|
|
}
|
|
*sizep = size;
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
int
|
|
main(
|
|
int argc,
|
|
char *argv[])
|
|
{
|
|
|
|
int c;
|
|
int error;
|
|
dm_off_t size;
|
|
char *fsname;
|
|
dm_sessid_t sid;
|
|
void *fs_hanp;
|
|
size_t fs_hlen;
|
|
char *sizep = "0";
|
|
|
|
|
|
Progname = argv[0];
|
|
size = 0;
|
|
|
|
while ((c = getopt(argc, argv, "s:")) != EOF) {
|
|
switch (c) {
|
|
case 's':
|
|
sizep = optarg;
|
|
break;
|
|
|
|
case '?':
|
|
default:
|
|
usage(Progname);
|
|
exit(1);
|
|
}
|
|
}
|
|
if (optind >= argc) {
|
|
usage(Progname);
|
|
exit(1);
|
|
}
|
|
/*
|
|
* Verify the input size string is legit
|
|
*/
|
|
error = verify_size(sizep, &size);
|
|
if (error)
|
|
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, size);
|
|
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);
|
|
|
|
}
|
|
|
|
/*
|
|
* 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_off_t target_size)
|
|
{
|
|
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 */
|
|
size_t buflen; /* length of stat buffer */
|
|
void *hanp; /* file handle */
|
|
size_t hlen; /* file handle */
|
|
int more; /* loop terminator */
|
|
int error;
|
|
|
|
|
|
/*
|
|
* Size the stat buffer to return info on 1K files at a time
|
|
*/
|
|
buflen = sizeof(dm_stat_t) * 1024;
|
|
#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 (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) &&
|
|
sbuf->dt_size >= target_size) {
|
|
hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
|
|
hlen = DM_GET_LEN(sbuf, dt_handle);
|
|
|
|
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);
|
|
}
|
|
|