File: [Development] / xfs-cmds / xfsprogs / io / pread.c (download)
Revision 1.17, Mon Apr 25 13:21:46 2005 UTC (12 years, 5 months ago) by hch
Branch: MAIN
Changes since 1.16: +1 -1
lines
GCC4 signedness fixes
cvtnum and init_cvtnum take unsigned paramaters now
|
/*
* Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#include <xfs/libxfs.h>
#include <ctype.h>
#include "command.h"
#include "input.h"
#include "init.h"
#include "io.h"
static cmdinfo_t pread_cmd;
static void
pread_help(void)
{
printf(_(
"\n"
" reads a range of bytes in a specified block size from the given offset\n"
"\n"
" Example:\n"
" 'pread -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n"
"\n"
" Reads a segment of the currently open file, optionally dumping it to the\n"
" standard output stream (with -v option) for subsequent inspection.\n"
" The reads are performed in sequential blocks starting at offset, with the\n"
" blocksize tunable using the -b option (default blocksize is 4096 bytes).\n"
"\n"));
}
void *buffer;
ssize_t highwater;
ssize_t buffersize;
int
alloc_buffer(
ssize_t bsize,
int uflag,
unsigned int seed)
{
if (bsize > highwater) {
if (buffer)
free(buffer);
buffer = memalign(pagesize, bsize);
if (!buffer) {
perror("memalign");
highwater = buffersize = 0;
return -1;
}
highwater = bsize;
}
buffersize = bsize;
if (!uflag)
memset(buffer, seed, buffersize);
return 0;
}
void
dump_buffer(
off64_t offset,
ssize_t len)
{
int i, j;
char *p;
for (i = 0, p = (char *)buffer; i < len; i += 16) {
char *s = p;
printf("%08llx: ", (unsigned long long)offset + i);
for (j = 0; j < 16 && i + j < len; j++, p++)
printf("%02x ", *p);
printf(" ");
for (j = 0; j < 16 && i + j < len; j++, s++) {
if (isalnum((int)*s))
printf("%c", *s);
else
printf(".");
}
printf("\n");
}
}
int
read_buffer(
int fd,
off64_t offset,
long long count,
long long *total,
int verbose,
int onlyone)
{
ssize_t bytes, bytes_requested;
int ops = 0;
*total = 0;
while (count > 0) {
bytes_requested = min(count, buffersize);
bytes = pread64(fd, buffer, bytes_requested, offset);
if (bytes == 0)
break;
if (bytes < 0) {
perror("pread64");
return -1;
}
ops++;
if (verbose)
dump_buffer(offset, bytes);
*total += bytes;
if (onlyone || bytes < bytes_requested)
break;
offset += bytes;
count -= bytes;
}
return ops;
}
static int
pread_f(
int argc,
char **argv)
{
off64_t offset;
long long count, total;
unsigned int blocksize, sectsize;
struct timeval t1, t2;
char s1[64], s2[64], ts[64];
int Cflag, uflag, vflag;
int c;
Cflag = uflag = vflag = 0;
init_cvtnum(&blocksize, §size);
while ((c = getopt(argc, argv, "b:Cuv")) != EOF) {
switch (c) {
case 'b':
blocksize = cvtnum(blocksize, sectsize, optarg);
if (blocksize < 0) {
printf(_("non-numeric bsize -- %s\n"), optarg);
return 0;
}
break;
case 'C':
Cflag = 1;
break;
case 'u':
uflag = 1;
break;
case 'v':
vflag = 1;
break;
default:
return command_usage(&pread_cmd);
}
}
if (optind != argc - 2)
return command_usage(&pread_cmd);
offset = cvtnum(blocksize, sectsize, argv[optind]);
if (offset < 0) {
printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
return 0;
}
optind++;
count = cvtnum(blocksize, sectsize, argv[optind]);
if (count < 0) {
printf(_("non-numeric length argument -- %s\n"), argv[optind]);
return 0;
}
if (alloc_buffer(blocksize, uflag, 0xabababab) < 0)
return 0;
gettimeofday(&t1, NULL);
if ((c = read_buffer(file->fd, offset, count, &total, vflag, 0)) < 0)
return 0;
gettimeofday(&t2, NULL);
t2 = tsub(t2, t1);
/* Finally, report back -- -C gives a parsable format */
timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
if (!Cflag) {
cvtstr((double)total, s1, sizeof(s1));
cvtstr(tdiv((double)total, t2), s2, sizeof(s2));
printf(_("read %lld/%lld bytes at offset %lld\n"),
total, count, (long long)offset);
printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
s1, c, ts, s2, tdiv((double)c, t2));
} else {/* bytes,ops,time,bytes/sec,ops/sec */
printf("%lld,%d,%s,%.3f,%.3f\n",
total, c, ts,
tdiv((double)total, t2), tdiv((double)c, t2));
}
return 0;
}
void
pread_init(void)
{
pread_cmd.name = _("pread");
pread_cmd.altname = _("r");
pread_cmd.cfunc = pread_f;
pread_cmd.argmin = 2;
pread_cmd.argmax = -1;
pread_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
pread_cmd.args = _("[-b bs] [-v] off len");
pread_cmd.oneline = _("reads a number of bytes at a specified offset");
pread_cmd.help = pread_help;
add_command(&pread_cmd);
}