Make the on-disk format of .dat files produced by strfile(8)

architecture independent.  Besides the fixed-width types in
the header, the offsets are now stored as 64-bit off_t (also
in big endian format).

Tested on:	i386, amd64, sparc64, ia64
This commit is contained in:
Ruslan Ermilov 2005-02-17 18:06:37 +00:00
parent f812d8f8c6
commit be2ff1d140
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=142022
7 changed files with 109 additions and 101 deletions

View File

@ -3,7 +3,8 @@
PROG= fortune
MAN= fortune.6
CFLAGS+=-DDEBUG -Wall -I${.CURDIR}/../strfile
WARNS?= 2
CFLAGS+=-DDEBUG -I${.CURDIR}/../strfile
.include <bsd.prog.mk>

View File

@ -49,8 +49,7 @@ static const char sccsid[] = "@(#)fortune.c 8.1 (Berkeley) 5/31/93";
__FBSDID("$FreeBSD$");
# include <sys/stat.h>
# include <arpa/inet.h>
# include <sys/endian.h>
# include <dirent.h>
# include <fcntl.h>
@ -74,7 +73,7 @@ __FBSDID("$FreeBSD$");
# define CPERS 20 /* # of chars for each sec */
# define SLEN 160 /* # of chars in short fortune */
# define POS_UNKNOWN ((long) -1) /* pos for file unknown */
# define POS_UNKNOWN ((uint32_t) -1) /* pos for file unknown */
# define NO_PROB (-1) /* no prob specified for file */
# ifdef DEBUG
@ -88,7 +87,7 @@ __FBSDID("$FreeBSD$");
typedef struct fd {
int percent;
int fd, datfd;
long pos;
uint32_t pos;
FILE *inf;
char *name;
char *path;
@ -119,7 +118,7 @@ char *Fortbuf = NULL; /* fortune buffer for -m */
int Fort_len = 0;
long Seekpts[2]; /* seek pointers to fortunes */
off_t Seekpts[2]; /* seek pointers to fortunes */
FILEDESC *File_list = NULL, /* Head of file list */
*File_tail = NULL; /* Tail of file list */
@ -230,7 +229,7 @@ FILEDESC *fp;
char line[BUFSIZ];
open_fp(fp);
(void) fseek(fp->inf, Seekpts[0], 0);
(void) fseeko(fp->inf, Seekpts[0], 0);
for (Fort_len = 0; fgets(line, sizeof line, fp->inf) != NULL &&
!STR_ENDSTRING(line, fp->tbl); Fort_len++) {
if (fp->tbl.str_flags & STR_ROTATED)
@ -265,7 +264,7 @@ fortlen()
nchar = (int)(Seekpts[1] - Seekpts[0]);
else {
open_fp(Fortfile);
(void) fseek(Fortfile->inf, Seekpts[0], 0);
(void) fseeko(Fortfile->inf, Seekpts[0], 0);
nchar = 0;
while (fgets(line, sizeof line, Fortfile->inf) != NULL &&
!STR_ENDSTRING(line, Fortfile->tbl))
@ -955,17 +954,17 @@ get_fort()
if (fp->next != NULL) {
sum_noprobs(fp);
choice = random() % Noprob_tbl.str_numstr;
DPRINTF(1, (stderr, "choice = %d (of %ld) \n", choice,
DPRINTF(1, (stderr, "choice = %d (of %u) \n", choice,
Noprob_tbl.str_numstr));
while (choice >= fp->tbl.str_numstr) {
choice -= fp->tbl.str_numstr;
fp = fp->next;
DPRINTF(1, (stderr,
" skip \"%s\", %ld (choice = %d)\n",
" skip \"%s\", %u (choice = %d)\n",
fp->name, fp->tbl.str_numstr,
choice));
}
DPRINTF(1, (stderr, "using \"%s\", %ld\n", fp->name,
DPRINTF(1, (stderr, "using \"%s\", %u\n", fp->name,
fp->tbl.str_numstr));
}
get_tbl(fp);
@ -980,8 +979,8 @@ get_fort()
(void) lseek(fp->datfd,
(off_t) (sizeof fp->tbl + fp->pos * sizeof Seekpts[0]), 0);
read(fp->datfd, Seekpts, sizeof Seekpts);
Seekpts[0] = ntohl(Seekpts[0]);
Seekpts[1] = ntohl(Seekpts[1]);
Seekpts[0] = be64toh(Seekpts[0]);
Seekpts[1] = be64toh(Seekpts[1]);
}
/*
@ -1007,15 +1006,15 @@ FILEDESC *parent;
else {
get_tbl(parent);
choice = random() % parent->tbl.str_numstr;
DPRINTF(1, (stderr, " choice = %d (of %ld)\n",
DPRINTF(1, (stderr, " choice = %d (of %u)\n",
choice, parent->tbl.str_numstr));
for (fp = parent->child; choice >= fp->tbl.str_numstr;
fp = fp->next) {
choice -= fp->tbl.str_numstr;
DPRINTF(1, (stderr, "\tskip %s, %ld (choice = %d)\n",
DPRINTF(1, (stderr, "\tskip %s, %u (choice = %d)\n",
fp->name, fp->tbl.str_numstr, choice));
}
DPRINTF(1, (stderr, " using %s, %ld\n", fp->name,
DPRINTF(1, (stderr, " using %s, %u\n", fp->name,
fp->tbl.str_numstr));
return fp;
}
@ -1106,7 +1105,7 @@ FILEDESC *fp;
}
if (++(fp->pos) >= fp->tbl.str_numstr)
fp->pos -= fp->tbl.str_numstr;
DPRINTF(1, (stderr, "pos for %s is %ld\n", fp->name, fp->pos));
DPRINTF(1, (stderr, "pos for %s is %ld\n", fp->name, (long)fp->pos));
}
/*
@ -1132,11 +1131,11 @@ FILEDESC *fp;
"fortune: %s corrupted\n", fp->path);
exit(1);
}
/* fp->tbl.str_version = ntohl(fp->tbl.str_version); */
fp->tbl.str_numstr = ntohl(fp->tbl.str_numstr);
fp->tbl.str_longlen = ntohl(fp->tbl.str_longlen);
fp->tbl.str_shortlen = ntohl(fp->tbl.str_shortlen);
fp->tbl.str_flags = ntohl(fp->tbl.str_flags);
/* fp->tbl.str_version = be32toh(fp->tbl.str_version); */
fp->tbl.str_numstr = be32toh(fp->tbl.str_numstr);
fp->tbl.str_longlen = be32toh(fp->tbl.str_longlen);
fp->tbl.str_shortlen = be32toh(fp->tbl.str_shortlen);
fp->tbl.str_flags = be32toh(fp->tbl.str_flags);
(void) close(fd);
}
else {
@ -1159,7 +1158,7 @@ STRFILE *tp;
{
tp->str_numstr = 0;
tp->str_longlen = 0;
tp->str_shortlen = ~((unsigned long)0);
tp->str_shortlen = ~0;
}
/*

View File

@ -36,7 +36,7 @@
.\" @(#)strfile.8 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
.Dd June 9, 1993
.Dd February 17, 2005
.Dt STRFILE 8
.Os
.Sh NAME
@ -52,28 +52,32 @@
.Nm unstr
.Ar source_file
.Sh DESCRIPTION
.Nm Strfile
The
.Nm
utility
reads a file containing groups of lines separated by a line containing
a single percent
.Ql \&%
.Ql %
sign and creates a data file which contains
a header structure and a table of file offsets for each group of lines.
This allows random access of the strings.
.Pp
The output file, if not specified on the command line, is named
.Ar source_file Ns Sy .dat .
.Ar source_file Ns Pa .dat .
.Pp
The options are as follows:
.Bl -tag -width "-c char"
.Bl -tag -width ".Fl c Ar char"
.It Fl C
Flag the file as containing comments.
This option cases the
.Dv STR_COMMENTS
bit in the header
.Ar str_flags
.Va str_flags
field to be set.
Comments are designated by two delimiter characters at the
beginning of the line, though strfile does not give any special
beginning of the line, though
.Nm
does not give any special
treatment to comment lines.
.It Fl c Ar char
Change the delimiting character from the percent sign to
@ -88,7 +92,7 @@ Any initial non-alphanumeric characters are ignored.
This option causes the
.Dv STR_ORDERED
bit in the header
.Ar str_flags
.Va str_flags
field to be set.
.It Fl r
Randomize access to the strings.
@ -96,7 +100,7 @@ Entries in the offset table will be randomly ordered.
This option causes the
.Dv STR_RANDOM
bit in the header
.Ar str_flags
.Va str_flags
field to be set.
.It Fl s
Run silently; do not give a summary message when finished.
@ -106,22 +110,23 @@ Note that each alphabetic character in the groups of lines is rotated
This option causes the
.Dv STR_ROTATED
bit in the header
.Ar str_flags
.Va str_flags
field to be set.
.El
.Pp
The format of the header is:
.Bd -literal
#define VERSION 1
unsigned long str_version; /* version number */
unsigned long str_numstr; /* # of strings in the file */
unsigned long str_longlen; /* length of longest string */
unsigned long str_shortlen; /* length of shortest string */
uint32_t str_version; /* version number */
uint32_t str_numstr; /* # of strings in the file */
uint32_t str_longlen; /* length of longest string */
uint32_t str_shortlen; /* length of shortest string */
#define STR_RANDOM 0x1 /* randomized pointers */
#define STR_ORDERED 0x2 /* ordered pointers */
#define STR_ROTATED 0x4 /* rot-13'd text */
unsigned long str_flags; /* bit field for flags */
char str_delim; /* delimiting character */
#define STR_COMMENTS 0x8 /* embedded comments */
uint32_t str_flags; /* bit field for flags */
char str_delim; /* delimiting character */
.Ed
.Pp
All fields are written in network byte order.
@ -144,7 +149,7 @@ is run and then using
.Nm unstr
to dump them out in the table order.
.Sh FILES
.Bl -tag -width strfile.dat -compact
.Bl -tag -width ".Pa strfile.dat" -compact
.It Pa strfile.dat
default output file.
.El

View File

@ -49,7 +49,7 @@ static const char sccsid[] = "@(#)strfile.c 8.1 (Berkeley) 5/31/93";
__FBSDID("$FreeBSD$");
# include <sys/param.h>
# include <arpa/inet.h>
# include <sys/endian.h>
# include <stdio.h>
# include <stdlib.h>
# include <ctype.h>
@ -91,9 +91,9 @@ __FBSDID("$FreeBSD$");
# define ALLOC(ptr,sz) { \
if (ptr == NULL) \
ptr = malloc((unsigned int) (CHUNKSIZE * sizeof *ptr)); \
ptr = malloc(CHUNKSIZE * sizeof *ptr); \
else if (((sz) + 1) % CHUNKSIZE == 0) \
ptr = realloc((void *) ptr, ((unsigned int) ((sz) + CHUNKSIZE) * sizeof *ptr)); \
ptr = realloc(ptr, ((sz) + CHUNKSIZE) * sizeof *ptr); \
if (ptr == NULL) { \
fprintf(stderr, "out of space\n"); \
exit(1); \
@ -106,7 +106,7 @@ __FBSDID("$FreeBSD$");
typedef struct {
int first;
long pos;
off_t pos;
} STR;
static char *Infile = NULL, /* input file name */
@ -119,9 +119,9 @@ static int Oflag = FALSE; /* ordering flag */
static int Iflag = FALSE; /* ignore case flag */
static int Rflag = FALSE; /* randomize order flag */
static int Xflag = FALSE; /* set rotated bit */
static long Num_pts = 0; /* number of pointers/strings */
static uint32_t Num_pts = 0; /* number of pointers/strings */
static long *Seekpts;
static off_t *Seekpts;
static FILE *Sort_1, *Sort_2; /* pointers for sorting */
@ -129,7 +129,7 @@ static STRFILE Tbl; /* statistics table */
static STR *Firstch; /* first chars of each string */
static void add_offset(FILE *, long);
static void add_offset(FILE *, off_t);
static int cmp_str(const void *, const void *);
static int stable_collate_range_cmp(int, int);
static void do_order(void);
@ -150,9 +150,10 @@ int main(int ac, char *av[])
{
char *sp, dc;
FILE *inf, *outf;
long last_off, pos, *p;
unsigned long length;
int first, cnt;
off_t last_off, pos, *p;
size_t length;
int first;
uint32_t cnt;
char *nsp;
STR *fp;
static char string[257];
@ -178,24 +179,25 @@ int main(int ac, char *av[])
*/
Tbl.str_longlen = 0;
Tbl.str_shortlen = ~((unsigned long) 0);
Tbl.str_shortlen = 0xffffffff;
Tbl.str_delim = dc;
Tbl.str_version = VERSION;
first = Oflag;
add_offset(outf, ftell(inf));
add_offset(outf, ftello(inf));
last_off = 0;
do {
sp = fgets(string, 256, inf);
if (sp == NULL || (sp[0] == dc && sp[1] == '\n')) {
pos = ftell(inf);
length = pos - last_off - (sp ? strlen(sp) : 0);
pos = ftello(inf);
length = (size_t)(pos - last_off) -
(sp != NULL ? strlen(sp) : 0);
last_off = pos;
if (!length)
if (length == 0)
continue;
add_offset(outf, pos);
if (Tbl.str_longlen < length)
if ((size_t)Tbl.str_longlen < length)
Tbl.str_longlen = length;
if (Tbl.str_shortlen > length)
if ((size_t)Tbl.str_shortlen > length)
Tbl.str_shortlen = length;
first = Oflag;
}
@ -236,24 +238,24 @@ int main(int ac, char *av[])
if (Num_pts == 2)
puts("There was 1 string");
else
printf("There were %ld strings\n", Num_pts - 1);
printf("Longest string: %lu byte%s\n", Tbl.str_longlen,
printf("There were %u strings\n", Num_pts - 1);
printf("Longest string: %u byte%s\n", Tbl.str_longlen,
Tbl.str_longlen == 1 ? "" : "s");
printf("Shortest string: %lu byte%s\n", Tbl.str_shortlen,
printf("Shortest string: %u byte%s\n", Tbl.str_shortlen,
Tbl.str_shortlen == 1 ? "" : "s");
}
rewind(outf);
Tbl.str_version = htonl(Tbl.str_version);
Tbl.str_numstr = htonl(Tbl.str_numstr);
Tbl.str_longlen = htonl(Tbl.str_longlen);
Tbl.str_shortlen = htonl(Tbl.str_shortlen);
Tbl.str_flags = htonl(Tbl.str_flags);
Tbl.str_version = htobe32(Tbl.str_version);
Tbl.str_numstr = htobe32(Tbl.str_numstr);
Tbl.str_longlen = htobe32(Tbl.str_longlen);
Tbl.str_shortlen = htobe32(Tbl.str_shortlen);
Tbl.str_flags = htobe32(Tbl.str_flags);
(void) fwrite((char *) &Tbl, sizeof Tbl, 1, outf);
if (STORING_PTRS) {
for (p = Seekpts, cnt = Num_pts; cnt--; ++p)
*p = htonl(*p);
(void) fwrite((char *) Seekpts, sizeof *Seekpts, (int) Num_pts, outf);
*p = htobe64(*p);
(void) fwrite(Seekpts, sizeof *Seekpts, (size_t) Num_pts, outf);
}
(void) fclose(outf);
exit(0);
@ -329,13 +331,13 @@ void usage()
*/
void add_offset(fp, off)
FILE *fp;
long off;
off_t off;
{
long net;
off_t beoff;
if (!STORING_PTRS) {
net = htonl(off);
fwrite(&net, 1, sizeof net, fp);
beoff = htobe64(off);
fwrite(&beoff, 1, sizeof beoff, fp);
} else {
ALLOC(Seekpts, Num_pts + 1);
Seekpts[Num_pts] = off;
@ -349,13 +351,13 @@ long off;
*/
void do_order()
{
int i;
long *lp;
uint32_t i;
off_t *lp;
STR *fp;
Sort_1 = fopen(Infile, "r");
Sort_2 = fopen(Infile, "r");
qsort((char *) Firstch, (int) Tbl.str_numstr, sizeof *Firstch, cmp_str);
qsort(Firstch, (size_t) Tbl.str_numstr, sizeof *Firstch, cmp_str);
i = Tbl.str_numstr;
lp = Seekpts;
fp = Firstch;
@ -402,8 +404,8 @@ const void *s1, *s2;
if ((r = stable_collate_range_cmp(c1, c2)) != 0)
return (r);
(void) fseek(Sort_1, p1->pos, 0);
(void) fseek(Sort_2, p2->pos, 0);
(void) fseeko(Sort_1, p1->pos, 0);
(void) fseeko(Sort_2, p2->pos, 0);
n1 = FALSE;
n2 = FALSE;
@ -441,9 +443,9 @@ const void *s1, *s2;
*/
void randomize()
{
int cnt, i;
long tmp;
long *sp;
uint32_t cnt, i;
off_t tmp;
off_t *sp;
srandomdev();

View File

@ -37,20 +37,22 @@
*/
/* $FreeBSD$ */
#include <sys/types.h>
#define STR_ENDSTRING(line,tbl) \
(((unsigned char)(line)[0]) == (tbl).str_delim && (line)[1] == '\n')
typedef struct { /* information table */
#define VERSION 1
unsigned long str_version; /* version number */
unsigned long str_numstr; /* # of strings in the file */
unsigned long str_longlen; /* length of longest string */
unsigned long str_shortlen; /* length of shortest string */
uint32_t str_version; /* version number */
uint32_t str_numstr; /* # of strings in the file */
uint32_t str_longlen; /* length of longest string */
uint32_t str_shortlen; /* length of shortest string */
#define STR_RANDOM 0x1 /* randomized pointers */
#define STR_ORDERED 0x2 /* ordered pointers */
#define STR_ROTATED 0x4 /* rot-13'd text */
#define STR_COMMENTS 0x8 /* embedded comments */
unsigned long str_flags; /* bit field for flags */
unsigned char stuff[4]; /* long aligned space */
uint32_t str_flags; /* bit field for flags */
unsigned char stuff[4]; /* 64-bit aligned space */
#define str_delim stuff[0] /* delimiting character */
} STRFILE;

View File

@ -3,6 +3,7 @@
PROG= unstr
NO_MAN=
CFLAGS+=-Wall -I${.CURDIR}/../strfile
WARNS?= 3
CFLAGS+= -I${.CURDIR}/../strfile
.include <bsd.prog.mk>

View File

@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$");
*/
# include <sys/param.h>
# include <arpa/inet.h>
# include <sys/endian.h>
# include <stdio.h>
# include <ctype.h>
# include <stdlib.h>
@ -75,12 +75,10 @@ char *Infile, /* name of input file */
FILE *Inf, *Dataf;
void getargs(), order_unstr();
void getargs(char *[]), order_unstr(STRFILE *);
/* ARGSUSED */
int main(ac, av)
int ac;
char **av;
int main(int ac, char **av)
{
static STRFILE tbl; /* description table */
@ -94,11 +92,11 @@ char **av;
exit(1);
}
(void) fread((char *) &tbl, sizeof tbl, 1, Dataf);
tbl.str_version = ntohl(tbl.str_version);
tbl.str_numstr = ntohl(tbl.str_numstr);
tbl.str_longlen = ntohl(tbl.str_longlen);
tbl.str_shortlen = ntohl(tbl.str_shortlen);
tbl.str_flags = ntohl(tbl.str_flags);
tbl.str_version = be32toh(tbl.str_version);
tbl.str_numstr = be32toh(tbl.str_numstr);
tbl.str_longlen = be32toh(tbl.str_longlen);
tbl.str_shortlen = be32toh(tbl.str_shortlen);
tbl.str_flags = be32toh(tbl.str_flags);
if (!(tbl.str_flags & (STR_ORDERED | STR_RANDOM))) {
fprintf(stderr, "nothing to do -- table in file order\n");
exit(1);
@ -125,14 +123,14 @@ char *av[];
void order_unstr(tbl)
STRFILE *tbl;
{
int i;
uint32_t i;
char *sp;
long pos;
char buf[BUFSIZ];
off_t pos;
char buf[BUFSIZ];
for (i = 0; i < tbl->str_numstr; i++) {
(void) fread((char *) &pos, 1, sizeof pos, Dataf);
(void) fseek(Inf, ntohl(pos), 0);
(void) fread(&pos, 1, sizeof pos, Dataf);
(void) fseeko(Inf, be64toh(pos), 0);
if (i != 0)
(void) printf("%c\n", Delimch);
for (;;) {