Date: Thu, 11 Sep 2014 17:08:12 -0700 From: William Orr <will@worrbase.com> To: freebsd-current@freebsd.org Subject: Re: Inconsistent behavior with dd(1) Message-ID: <5412396C.1070304@worrbase.com> In-Reply-To: <53FC11C8.5050803@worrbase.com> References: <3C86F281-D618-4B93-BBA3-2DA33AC407EC@worrbase.com> <CAOtMX2ikYhyCS0WW178Pn_Ug2pzYQWrNfAvWkJt=f%2BwEdHY3dg@mail.gmail.com> <20140816173439.GZ83475@funkthat.com> <53F24D60.4080107@worrbase.com> <53FC11C8.5050803@worrbase.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --TtDSoreIoo6TL953mAev6FNls70kAmBdP Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hey, any thoughts on this? Does it need more work? Can it get merged? On 08/25/2014 09:49 PM, William Orr wrote: > On 8/18/14 12:00 PM, William Orr wrote: >> Reply inline. >> >> On 08/16/2014 10:34 AM, John-Mark Gurney wrote: >>> Alan Somers wrote this message on Fri, Aug 15, 2014 at 10:42 -0600: >>>> On Thu, Aug 14, 2014 at 11:55 PM, William Orr <will@worrbase.com> >>>> wrote: >>>>> Hey, >>>>> >>>>> I found some inconsistent behavior with dd(1) when it comes to >>>>> specifying arguments in -CURRENT. >>>>> >>>>> [ worr on terra ] ( ~ ) % dd if=3D/dev/zero of=3D/dev/null >>>>> count=3D18446744073709551616 >>>>> dd: count: Result too large >>>>> [ worr on terra ] ( ~ ) % dd if=3D/dev/zero of=3D/dev/null >>>>> count=3D18446744073709551617 >>>>> dd: count: Result too large >>>>> [ worr on terra ] ( ~ ) % dd if=3D/dev/zero of=3D/dev/null >>>>> count=3D18446744073709551615 >>>>> dd: count cannot be negative >>>>> [ worr on terra ] ( ~ ) % dd if=3D/dev/zero of=3D/dev/null >>>>> count=3D-18446744073709551615 >>>>> 1+0 records in >>>>> 1+0 records out >>>>> 512 bytes transferred in 0.000373 secs (1373071 bytes/sec) >>>>> [ worr on terra ] ( ~ ) % dd if=3D/dev/zero of=3D/dev/null count=3D= -1 >>>>> dd: count cannot be negative >>>>> >>>>> ??? >>>>> >>>>> Any chance someone has the time and could take a look? >>>>> https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D191263 >>>>> >>>>> Thanks, >>>>> William Orr >>>>> >>>>> ??? >>>> >>>> IMHO, this is a bug in strtouq(3), not in dd(1). Why should it pars= e >>>> negative numbers at all, when there is stroq(3) for that purpose? T= he >>>> standard is clear that it must, though. Oddly enough, stroq would >>>> probably not accept -18446744073709551615, even though strtouq does.= >>>> Specific comments on your patch below: >>>> >>>> >>>>> Here???s the patch: >>>>> >>>>> Index: bin/dd/args.c >>>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>>> --- bin/dd/args.c (revision 267712) >>>>> +++ bin/dd/args.c (working copy) >>>>> @@ -186,46 +186,31 @@ >>>>> static void >>>>> f_bs(char *arg) >>>>> { >>>>> - uintmax_t res; >>>>> - >>>>> - res =3D get_num(arg); >>>>> - if (res < 1 || res > SSIZE_MAX) >>>>> - errx(1, "bs must be between 1 and %jd", >>>>> (intmax_t)SSIZE_MAX); >>>>> - in.dbsz =3D out.dbsz =3D (size_t)res; >>>>> + in.dbsz =3D out.dbsz =3D get_num(arg); >>>>> + if (in.dbsz < 1 || out.dbsz < 1) >>>> Why do you need to check both in and out? Aren't they the same? >>>> Also, you eliminated the check for overflowing SSIZE_MAX. That's no= t >>>> ok, because these values get passed to places that expect signed >>>> numbers, for example in dd.c:303. >>> The type of dbsz is size_t, so really: >>> >>>>> + errx(1, "bs must be between 1 and %ju", >>>>> (uintmax_t)-1); >>> This should be SIZE_MAX, except there isn't a define for this? So ma= ybe >>> the code really should be: >>> (uintmax_t)(size_t)-1 >>> >>> to get the correct value for SIZE_MAX... >>> >>> Otherwise on systems that uintmax_t is >32bits and size_t is 32bits, >>> the error message will be wrong... >> Yes, this should probably be SIZE_MAX rather than that cast. Same with= >> the others >> >>>>> } >>>>> >>>>> static void >>>>> f_cbs(char *arg) >>>>> { >>>>> - uintmax_t res; >>>>> - >>>>> - res =3D get_num(arg); >>>>> - if (res < 1 || res > SSIZE_MAX) >>>>> - errx(1, "cbs must be between 1 and %jd", >>>>> (intmax_t)SSIZE_MAX); >>>>> - cbsz =3D (size_t)res; >>>>> + cbsz =3D get_num(arg); >>>>> + if (cbsz < 1) >>>>> + errx(1, "cbs must be between 1 and %ju", >>>>> (uintmax_t)-1); >>>>> } >>>> Again, you eliminated the check for SSIZE_MAX, but cbsz must be sign= ed. >>> What do you mean by this? cbsz is size_t which is unsigned... >> I believe he's referring to this use of cbsz/in.dbsz/out.dbsz: >> >> https://svnweb.freebsd.org/base/head/bin/dd/dd.c?revision=3D265698&vie= w=3Dmarkup#l171 >> >> >> Really, this is more wrong since there is math inside of a malloc(3) >> call without any overflow handling. By virtue of making this max out a= t >> a ssize_t, it becomes more unlikely that you'll have overflow. >> >> This math should probably be done ahead of time with proper overflow >> handling. I'll include that in my next patch, if there's no objection.= >> >> I don't see any other reason why in.dbsz, out.dbsz or cbsz should be >> signed, but it's very possible that I didn't look hard enough. >> >>> Again, the cast above is wrong... Maybe we should add a SIZE_MAX >>> define so we don't have to see the double cast... >>> >>>>> static void >>>>> f_count(char *arg) >>>>> { >>>>> - intmax_t res; >>>>> - >>>>> - res =3D (intmax_t)get_num(arg); >>>>> - if (res < 0) >>>>> - errx(1, "count cannot be negative"); >>>>> - if (res =3D=3D 0) >>>>> - cpy_cnt =3D (uintmax_t)-1; >>>> This is a special case. See dd_in(). I think that eliminating this= >>>> special case will have the unintended effect of breaking count=3D0. >>>> >>>>> - else >>>>> - cpy_cnt =3D (uintmax_t)res; >>>>> + cpy_cnt =3D get_num(arg); >>>>> } >>>>> >>>>> static void >>>>> f_files(char *arg) >>>>> { >>>>> - >>> Don't eliminate these blank lines.. they are intentional per style(9)= : >>> /* Insert an empty line if the function has no local >>> variables. */ >>> >>>>> files_cnt =3D get_num(arg); >>>>> if (files_cnt < 1) >>>>> - errx(1, "files must be between 1 and %jd", >>>>> (uintmax_t)-1); >>>>> + errx(1, "files must be between 1 and %ju", >>>>> (uintmax_t)-1); >>>> Good catch. >>>> >>>>> } >>>>> >>>>> static void >>>>> @@ -241,14 +226,10 @@ >>>>> static void >>>>> f_ibs(char *arg) >>>>> { >>>>> - uintmax_t res; >>>>> - >>>>> if (!(ddflags & C_BS)) { >>>>> - res =3D get_num(arg); >>>>> - if (res < 1 || res > SSIZE_MAX) >>>>> - errx(1, "ibs must be between 1 and %jd", >>>>> - (intmax_t)SSIZE_MAX); >>>>> - in.dbsz =3D (size_t)res; >>>>> + in.dbsz =3D get_num(arg); >>>>> + if (in.dbsz < 1) >>>>> + errx(1, "ibs must be between 1 and %ju", >>>>> (uintmax_t)-1); >>>> Again, you eliminated the check for SSIZE_MAX, but dbsz must be sign= ed. >>> If dbsz must be signed, we should change it's definition to ssize_t >>> instead of size_t... Can you point to the line that says this? >>> >>> In investigating this, it looks like we may have a bug in ftruncate i= n >>> that out.offset * out.dbsz may overflow and return incorrect results.= =2E. >>> We should probably check that the output (cast to off_t) is greater t= han >>> both the inputs before calling ftruncate... This is safe as both are= >>> unsigned... >> Yeah, there probably ought to be integer overflow handling here as wel= l. >> >>>>> } >>>>> } >>>>> >>>>> @@ -262,14 +243,10 @@ >>>>> static void >>>>> f_obs(char *arg) >>>>> { >>>>> - uintmax_t res; >>>>> - >>>>> if (!(ddflags & C_BS)) { >>>>> - res =3D get_num(arg); >>>>> - if (res < 1 || res > SSIZE_MAX) >>>>> - errx(1, "obs must be between 1 and %jd", >>>>> - (intmax_t)SSIZE_MAX); >>>>> - out.dbsz =3D (size_t)res; >>>>> + out.dbsz =3D get_num(arg); >>>>> + if (out.dbsz < 1) >>>>> + errx(1, "obs must be between 1 and %ju", >>>>> (uintmax_t)-1); >>>>> } >>>>> } >>>> Again, you eliminated the check for SSIZE_MAX, but dbsz must be sign= ed. >>>> >>>>> @@ -378,11 +355,14 @@ >>>>> uintmax_t num, mult, prevnum; >>>>> char *expr; >>>>> >>>>> + if (val[0] =3D=3D '-') >>>>> + errx(1, "%s: cannot be negative", oper); >>>>> + >>>> In general, I like this part of the diff. Every user of get_num >>>> checks for negative values, so why not move the check into get_num >>>> itself? But you changed it from a numeric check to a text check, an= d >>>> writing text parsers makes me nervous. I can't see any problems, >>>> though. >> Funnily enough this part of the diff was wrong. I didn't account for >> spaces, so I'll add that in my upcoming diff. >> >>>>> errno =3D 0; >>>>> num =3D strtouq(val, &expr, 0); >>>>> if (errno !=3D 0) /* Overflow or >>>>> underflow. */ >>>>> err(1, "%s", oper); >>>>> - >>>>> + >>>>> if (expr =3D=3D val) /* No valid >>>>> digits. */ >>>>> errx(1, "%s: illegal numeric value", oper); >>>>> >>>>> Index: bin/dd/dd.c >>>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>>> --- bin/dd/dd.c (revision 267712) >>>>> +++ bin/dd/dd.c (working copy) >>>>> @@ -284,8 +284,6 @@ >>>>> >>>>> for (;;) { >>>>> switch (cpy_cnt) { >>>>> - case -1: /* count=3D0 was >>>>> specified */ >>>>> - return; >>>> Again, I don't think this will do what you want it to do. Previousl= y, >>>> leaving count unspecified resulted in cpy_cnt being 0, and specifyin= g >>>> count=3D0 set cpy_cnt to -1. With your patch, setting count=3D0 wil= l have >>>> the same effect as leaving it unspecified. >> Nope. It didn't do what I wanted. I'll submit an updated diff with thi= s >> fixed as well as the other things I mentioned, provided there's no >> objection to my direction. >> >>>>> case 0: >>>>> break; >>>>> default: >>>>> >>>>> > Here is a new version of this patch. I've now changed the members of th= e > struct that are used as ssize_ts to ssize_ts, and have fixed casts > appropriately. I have also opted for strtoull over the deprecated > strtouq. I changed some struct members that were declared as uintmax_t'= s > to size_t's. >=20 > Any comments? Criticisms? Gross attacks on my character? >=20 > Index: args.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- args.c (revision 270645) > +++ args.c (working copy) > @@ -41,6 +41,7 @@ >=20 > #include <sys/types.h> >=20 > +#include <ctype.h> > #include <err.h> > #include <errno.h> > #include <inttypes.h> > @@ -171,8 +172,7 @@ > */ > if (in.offset > OFF_MAX / (ssize_t)in.dbsz || > out.offset > OFF_MAX / (ssize_t)out.dbsz) > - errx(1, "seek offsets cannot be larger than %jd", > - (intmax_t)OFF_MAX); > + errx(1, "seek offsets cannot be larger than %jd", OFF_MAX); > } >=20 > static int > @@ -186,37 +186,28 @@ > static void > f_bs(char *arg) > { > - uintmax_t res; >=20 > - res =3D get_num(arg); > - if (res < 1 || res > SSIZE_MAX) > - errx(1, "bs must be between 1 and %jd", (intmax_t)SSIZE_MAX); > - in.dbsz =3D out.dbsz =3D (size_t)res; > + in.dbsz =3D out.dbsz =3D get_num(arg); > + if (out.dbsz < 1 || out.dbsz > SSIZE_MAX) > + errx(1, "bs must be between 1 and %jd", SSIZE_MAX); > } >=20 > static void > f_cbs(char *arg) > { > - uintmax_t res; >=20 > - res =3D get_num(arg); > - if (res < 1 || res > SSIZE_MAX) > - errx(1, "cbs must be between 1 and %jd", (intmax_t)SSIZE_MAX);= > - cbsz =3D (size_t)res; > + cbsz =3D get_num(arg); > + if (cbsz < 1 || cbsz > SSIZE_MAX) > + errx(1, "cbs must be between 1 and %jd", SSIZE_MAX); > } >=20 > static void > f_count(char *arg) > { > - intmax_t res; >=20 > - res =3D (intmax_t)get_num(arg); > - if (res < 0) > - errx(1, "count cannot be negative"); > - if (res =3D=3D 0) > - cpy_cnt =3D (uintmax_t)-1; > - else > - cpy_cnt =3D (uintmax_t)res; > + cpy_cnt =3D get_num(arg); > + if (cpy_cnt =3D=3D 0) > + cpy_cnt =3D -1; > } >=20 > static void > @@ -225,7 +216,7 @@ >=20 > files_cnt =3D get_num(arg); > if (files_cnt < 1) > - errx(1, "files must be between 1 and %jd", (uintmax_t)-1); > + errx(1, "files must be between 1 and %ju", SIZE_MAX); > } >=20 > static void > @@ -241,14 +232,11 @@ > static void > f_ibs(char *arg) > { > - uintmax_t res; >=20 > if (!(ddflags & C_BS)) { > - res =3D get_num(arg); > - if (res < 1 || res > SSIZE_MAX) > - errx(1, "ibs must be between 1 and %jd", > - (intmax_t)SSIZE_MAX); > - in.dbsz =3D (size_t)res; > + in.dbsz =3D get_num(arg); > + if (in.dbsz < 1 || in.dbsz > SSIZE_MAX) > + errx(1, "ibs must be between 1 and %ju", SSIZE_MAX); > } > } >=20 > @@ -262,14 +250,11 @@ > static void > f_obs(char *arg) > { > - uintmax_t res; >=20 > if (!(ddflags & C_BS)) { > - res =3D get_num(arg); > - if (res < 1 || res > SSIZE_MAX) > - errx(1, "obs must be between 1 and %jd", > - (intmax_t)SSIZE_MAX); > - out.dbsz =3D (size_t)res; > + out.dbsz =3D get_num(arg); > + if (out.dbsz < 1 || out.dbsz > SSIZE_MAX) > + errx(1, "obs must be between 1 and %jd", SSIZE_MAX); > } > } >=20 > @@ -378,11 +363,17 @@ > uintmax_t num, mult, prevnum; > char *expr; >=20 > + while (isspace(val[0])) > + val++; > + > + if (val[0] =3D=3D '-') > + errx(1, "%s: cannot be negative", oper); > + > errno =3D 0; > - num =3D strtouq(val, &expr, 0); > + num =3D strtoull(val, &expr, 0); > if (errno !=3D 0) /* Overflow or underflow. */ > err(1, "%s", oper); > - > + > if (expr =3D=3D val) /* No valid digits. */ > errx(1, "%s: illegal numeric value", oper); >=20 > Index: conv.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- conv.c (revision 270645) > +++ conv.c (working copy) > @@ -133,7 +133,7 @@ > */ > ch =3D 0; > for (inp =3D in.dbp - in.dbcnt, outp =3D out.dbp; in.dbcnt;) { > - maxlen =3D MIN(cbsz, in.dbcnt); > + maxlen =3D MIN(cbsz, (size_t)in.dbcnt); > if ((t =3D ctab) !=3D NULL) > for (cnt =3D 0; cnt < maxlen && (ch =3D *inp++) !=3D '\n';= > ++cnt) > @@ -146,7 +146,7 @@ > * Check for short record without a newline. Reassemble the > * input block. > */ > - if (ch !=3D '\n' && in.dbcnt < cbsz) { > + if (ch !=3D '\n' && (size_t)in.dbcnt < cbsz) { > (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); > break; > } > @@ -228,7 +228,7 @@ > * translation has to already be done or we might not recognize th= e > * spaces. > */ > - for (inp =3D in.db; in.dbcnt >=3D cbsz; inp +=3D cbsz, in.dbcnt -=3D= cbsz) { > + for (inp =3D in.db; (size_t)in.dbcnt >=3D cbsz; inp +=3D cbsz, in.= dbcnt > -=3D cbsz) { > for (t =3D inp + cbsz - 1; t >=3D inp && *t =3D=3D ' '; --t) > ; > if (t >=3D inp) { > Index: dd.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- dd.c (revision 270645) > +++ dd.c (working copy) > @@ -168,10 +168,10 @@ > * record oriented I/O, only need a single buffer. > */ > if (!(ddflags & (C_BLOCK | C_UNBLOCK))) { > - if ((in.db =3D malloc(out.dbsz + in.dbsz - 1)) =3D=3D NULL) > + if ((in.db =3D malloc((size_t)out.dbsz + in.dbsz - 1)) =3D=3D = NULL) > err(1, "input buffer"); > out.db =3D in.db; > - } else if ((in.db =3D malloc(MAX(in.dbsz, cbsz) + cbsz)) =3D=3D NU= LL || > + } else if ((in.db =3D malloc(MAX((size_t)in.dbsz, cbsz) + cbsz)) =3D= =3D > NULL || > (out.db =3D malloc(out.dbsz + cbsz)) =3D=3D NULL) > err(1, "output buffer"); >=20 > @@ -343,7 +343,7 @@ > ++st.in_full; >=20 > /* Handle full input blocks. */ > - } else if ((size_t)n =3D=3D in.dbsz) { > + } else if ((size_t)n =3D=3D (size_t)in.dbsz) { > in.dbcnt +=3D in.dbrcnt =3D n; > ++st.in_full; >=20 > @@ -493,7 +493,7 @@ > outp +=3D nw; > st.bytes +=3D nw; >=20 > - if ((size_t)nw =3D=3D n && n =3D=3D out.dbsz) > + if ((size_t)nw =3D=3D n && n =3D=3D (size_t)out.dbsz) > ++st.out_full; > else > ++st.out_part; > Index: dd.h > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- dd.h (revision 270645) > +++ dd.h (working copy) > @@ -38,10 +38,9 @@ > typedef struct { > u_char *db; /* buffer address */ > u_char *dbp; /* current buffer I/O address */ > - /* XXX ssize_t? */ > - size_t dbcnt; /* current buffer byte count */ > - size_t dbrcnt; /* last read byte count */ > - size_t dbsz; /* block size */ > + ssize_t dbcnt; /* current buffer byte count */ > + ssize_t dbrcnt; /* last read byte count */ > + ssize_t dbsz; /* block size */ >=20 > #define ISCHR 0x01 /* character device (warn on short= ) */ > #define ISPIPE 0x02 /* pipe-like (see position.c) */ > @@ -57,13 +56,13 @@ > } IO; >=20 > typedef struct { > - uintmax_t in_full; /* # of full input blocks */ > - uintmax_t in_part; /* # of partial input blocks */ > - uintmax_t out_full; /* # of full output blocks */ > - uintmax_t out_part; /* # of partial output blocks */ > - uintmax_t trunc; /* # of truncated records */ > - uintmax_t swab; /* # of odd-length swab blocks */ > - uintmax_t bytes; /* # of bytes written */ > + size_t in_full; /* # of full input blocks */ > + size_t in_part; /* # of partial input blocks */ > + size_t out_full; /* # of full output blocks */ > + size_t out_part; /* # of partial output blocks */ > + size_t trunc; /* # of truncated records */ > + size_t swab; /* # of odd-length swab blocks */ > + size_t bytes; /* # of bytes written */ > struct timespec start; /* start time of dd */ > } STAT; >=20 > Index: position.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- position.c (revision 270645) > +++ position.c (working copy) > @@ -178,7 +178,7 @@ > n =3D write(out.fd, out.db, out.dbsz); > if (n =3D=3D -1) > err(1, "%s", out.name); > - if ((size_t)n !=3D out.dbsz) > + if (n !=3D out.dbsz) > errx(1, "%s: write failure", out.name); > } > break; >=20 > _______________________________________________ > freebsd-current@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-current > To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.o= rg" --TtDSoreIoo6TL953mAev6FNls70kAmBdP Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iQIcBAEBAgAGBQJUEjlxAAoJEOWIWopNkblksLIP/3qDVPRJBDFO0gO0+TG717IE ocee7AmUkjXxZz6+5TnB/ihA6JsY0A40kkQsbRId/Pe/lMz3wgx9SIckiX+oo3Xy Or625D8kbM6PjgepIQGBEb/HH/qqGeN/UQwF9OZMCPzEnGfeXXovD658rar5b4S6 FTIjdGJzAJGwjHnwM3XJJUcaWfJ1nRUF4gPlCl2TILnXf6fNNOV7X4CXGLklep/v ZIroeZjbWZjHDob3ZU7LCs2zhXgumyZXrT3bzAvxYgGQpo0IaMalSxd/7T9gG9/f GpFz9n7jGfbFW3hoeip58mHORXAW6vcWRFFFQnUiJNU10icugL/GIIPcp3IQ59aH K9G/gv26kSvvhmdYLVeAinvY3Bj9dwswqhUtVRFwHNeBM0xQPkGakZ0M8eJTepRk AIkMDQnb2r1UTwpUS+Vh++mSrgdMCUYkSaDb2jSCypVsDMV/ZJ6DHY/1NBuCELsu UYvWEw7zP47KTCCHgXY/SS7mwnRLsSkO525o39ugo+URXmLe1CQo5UgQEIAivHuU 8Ujn0WzkiTsJJh4+jdUXd/RaQFrDZTzQyfTZjNqSbIEwJ2savt/nT+weBiDxBJgj Vy98+cNrfLDfobAVe1ASDG/rQzfaxNBQgInCTXMQQQwAmvL6GfToC87fDNd5iift ldMTlZtREF1FVm3p8I/L =DLDx -----END PGP SIGNATURE----- --TtDSoreIoo6TL953mAev6FNls70kAmBdP--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5412396C.1070304>