PERFORCE change 82811 for review
Peter Wemm
peter at FreeBSD.org
Tue Aug 30 00:09:16 GMT 2005
http://perforce.freebsd.org/chv.cgi?CH=82811
Change 82811 by peter at peter_daintree on 2005/08/30 00:08:21
IFC @82810
Affected files ...
.. //depot/projects/hammer/bin/sh/sh.1#18 integrate
.. //depot/projects/hammer/lib/libc/string/strcspn.3#2 integrate
.. //depot/projects/hammer/lib/libc/string/strspn.3#2 integrate
.. //depot/projects/hammer/sys/dev/wi/if_wi.c#42 integrate
.. //depot/projects/hammer/sys/kern/uipc_mbuf.c#31 integrate
.. //depot/projects/hammer/sys/sys/mbuf.h#43 integrate
.. //depot/projects/hammer/tools/tools/recoverdisk/README#3 integrate
.. //depot/projects/hammer/tools/tools/recoverdisk/recoverdisk.c#4 integrate
Differences ...
==== //depot/projects/hammer/bin/sh/sh.1#18 (text+ko) ====
@@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
-.\" $FreeBSD: src/bin/sh/sh.1,v 1.104 2005/08/29 06:47:43 jcamou Exp $
+.\" $FreeBSD: src/bin/sh/sh.1,v 1.105 2005/08/29 21:28:12 jcamou Exp $
.\"
.Dd August 17, 2005
.Dt SH 1
@@ -426,7 +426,8 @@
.Pp
An alias name may be escaped in a command line, so that it is not
replaced by its alias value, by using quoting characters within or
-adjacent to the alias name. This is most often done by prefixing
+adjacent to the alias name.
+This is most often done by prefixing
an alias name with a backslash to execute a function, built-in, or
normal program with the same name.
See the
==== //depot/projects/hammer/lib/libc/string/strcspn.3#2 (text+ko) ====
@@ -34,7 +34,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)strcspn.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcspn.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strcspn.3,v 1.8 2005/08/29 20:41:58 garys Exp $
.\"
.Dd June 4, 1993
.Dt STRCSPN 3
@@ -63,6 +63,13 @@
.Em complement
of
.Fa charset ) .
+In other words, it computes the string array index in
+.Fa s
+of the first character of
+.Fa s
+which is also in
+.Fa charset ,
+else the index of the first null character.
.Sh RETURN VALUES
The
.Fn strcspn
==== //depot/projects/hammer/lib/libc/string/strspn.3#2 (text+ko) ====
@@ -34,7 +34,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)strspn.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strspn.3,v 1.8 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strspn.3,v 1.9 2005/08/29 20:41:58 garys Exp $
.\"
.Dd June 4, 1993
.Dt STRSPN 3
@@ -56,8 +56,15 @@
.Fa s
as long as the characters from
.Fa s
-occur in string
+occur in the null-terminated string
.Fa charset .
+In other words, it computes the string array index in
+.Fa s
+of the first character of
+.Fa s
+which is not in
+.Fa charset ,
+else the index of the first null character.
.Sh RETURN VALUES
The
.Fn strspn
==== //depot/projects/hammer/sys/dev/wi/if_wi.c#42 (text+ko) ====
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.188 2005/08/29 15:46:41 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.189 2005/08/29 20:06:02 scottl Exp $");
#define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
#define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
@@ -2444,7 +2444,6 @@
if (i == 0) {
device_printf(sc->sc_dev, "wi_cmd: busy bit won't clear.\n" );
sc->wi_gone = 1;
- count--;
return(ETIMEDOUT);
}
@@ -2468,7 +2467,6 @@
s = CSR_READ_2(sc, WI_STATUS);
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
if (s & WI_STAT_CMD_RESULT) {
- count--;
return(EIO);
}
break;
@@ -2476,7 +2474,6 @@
DELAY(WI_DELAY);
}
- count--;
if (i == WI_TIMEOUT) {
device_printf(sc->sc_dev,
"timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
==== //depot/projects/hammer/sys/kern/uipc_mbuf.c#31 (text+ko) ====
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/uipc_mbuf.c,v 1.149 2005/07/30 01:32:16 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/uipc_mbuf.c,v 1.152 2005/08/29 20:15:33 andre Exp $");
#include "opt_mac.h"
#include "opt_param.h"
@@ -270,6 +270,125 @@
}
/*
+ * Clean up mbuf (chain) from any tags and packet headers.
+ * If "all" is set then the first mbuf in the chain will be
+ * cleaned too.
+ */
+void
+m_demote(struct mbuf *m0, int all)
+{
+ struct mbuf *m;
+
+ for (m = all ? m0 : m0->m_next; m != NULL; m = m->m_next) {
+ if (m->m_flags & M_PKTHDR) {
+ m_tag_delete_chain(m, NULL);
+ m->m_flags &= ~M_PKTHDR;
+ bzero(&m->m_pkthdr, sizeof(struct pkthdr));
+ }
+ if (m->m_type & MT_HEADER)
+ m->m_type = MT_DATA;
+ if (m != m0 && m->m_nextpkt)
+ m->m_nextpkt = NULL;
+ m->m_flags = m->m_flags & (M_EXT|M_EOR|M_RDONLY|M_FREELIST);
+ }
+}
+
+/*
+ * Sanity checks on mbuf (chain).
+ * Returns 0 bad, 1 good, panic worse.
+ * sanitize, 0 run M_SANITY_ACTION, 1 garble things so they blow up later.
+ */
+int
+m_sanity(struct mbuf *m0, int sanitize)
+{
+ struct mbuf *m;
+ caddr_t a, b;
+ int pktlen = 0;
+
+#define M_SANITY_ACTION(s) return (0)
+/* #define M_SANITY_ACTION(s) panic("mbuf %p: " s, m) */
+
+ m = m0;
+ while (m) {
+ /*
+ * Basic pointer checks. If any of these fails then some
+ * unrelated kernel memory before or after us is trashed.
+ * No way to recover from that.
+ */
+ a = (m->m_flags & M_EXT ? m->m_ext.ext_buf :
+ (m->m_flags & M_PKTHDR ? (caddr_t)(&m->m_pktdat) :
+ (caddr_t)(&m->m_dat)) );
+ b = (caddr_t)(a + (m->m_flags & M_EXT ? m->m_ext.ext_size :
+ (m->m_flags & M_PKTHDR ? MHLEN : MLEN)));
+ if ((caddr_t)m->m_data < a)
+ M_SANITY_ACTION("m_data outside mbuf data range left");
+ if ((caddr_t)m->m_data > b)
+ M_SANITY_ACTION("m_data outside mbuf data range right");
+ if ((caddr_t)m->m_data + m->m_len > b)
+ M_SANITY_ACTION("m_data + m_len exeeds mbuf space");
+ if (m->m_flags & M_PKTHDR && m->m_pkthdr.header) {
+ if ((caddr_t)m->m_pkthdr.header < a ||
+ (caddr_t)m->m_pkthdr.header > b)
+ M_SANITY_ACTION("m_pkthdr.header outside mbuf data range");
+ }
+
+ /* m->m_nextpkt may only be set on first mbuf in chain. */
+ if (m != m0 && m->m_nextpkt) {
+ if (sanitize) {
+ m_freem(m->m_nextpkt);
+ m->m_nextpkt = (struct mbuf *)0xDEADC0DE;
+ } else
+ M_SANITY_ACTION("m->m_nextpkt on in-chain mbuf");
+ }
+
+ /* correct type correlations. */
+ if (m->m_type == MT_HEADER && !(m->m_flags & M_PKTHDR)) {
+ if (sanitize)
+ m->m_type = MT_DATA;
+ else
+ M_SANITY_ACTION("MT_HEADER set but not M_PKTHDR");
+ }
+
+ /* packet length (not mbuf length!) calculation */
+ if (m0->m_flags & M_PKTHDR)
+ pktlen += m->m_len;
+
+ /* m_tags may only be attached to first mbuf in chain. */
+ if (m != m0 && m->m_flags & M_PKTHDR &&
+ !SLIST_EMPTY(&m->m_pkthdr.tags)) {
+ if (sanitize) {
+ m_tag_delete_chain(m, NULL);
+ /* put in 0xDEADC0DE perhaps? */
+ }
+ else
+ M_SANITY_ACTION("m_tags on in-chain mbuf");
+ }
+
+ /* M_PKTHDR may only be set on first mbuf in chain */
+ if (m != m0 && m->m_flags & M_PKTHDR) {
+ if (sanitize) {
+ bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
+ m->m_flags &= ~M_PKTHDR;
+ /* put in 0xDEADCODE and leave hdr flag in */
+ } else
+ M_SANITY_ACTION("M_PKTHDR on in-chain mbuf");
+ }
+
+ m = m->m_next;
+ }
+ if (pktlen && pktlen != m0->m_pkthdr.len) {
+ if (sanitize)
+ m0->m_pkthdr.len = 0;
+ else
+ M_SANITY_ACTION("m_pkthdr.len != mbuf chain length");
+ }
+#undef M_SANITY_ACTION
+
+ return 1;
+}
+
+
+/*
* "Move" mbuf pkthdr from "from" to "to".
* "from" must have M_PKTHDR set, and "to" must be empty.
*/
@@ -439,6 +558,151 @@
}
/*
+ * Returns mbuf chain with new head for the prepending case.
+ * Copies from mbuf (chain) n from off for len to mbuf (chain) m
+ * either prepending or appending the data.
+ * The resulting mbuf (chain) m is fully writeable.
+ * m is destination (is made writeable)
+ * n is source, off is offset in source, len is len from offset
+ * dir, 0 append, 1 prepend
+ * how, wait or nowait
+ */
+
+static int
+m_bcopyxxx(void *s, void *t, u_int len)
+{
+ bcopy(s, t, (size_t)len);
+ return 0;
+}
+
+struct mbuf *
+m_copymdata(struct mbuf *m, struct mbuf *n, int off, int len,
+ int prep, int how)
+{
+ struct mbuf *mm, *x, *z;
+ caddr_t p;
+ int i, mlen, nlen = 0;
+ caddr_t buf[MLEN];
+
+ KASSERT(m != NULL && n != NULL, ("m_copymdata, no target or source"));
+ KASSERT(off >= 0, ("m_copymdata, negative off %d", off));
+ KASSERT(len >= 0, ("m_copymdata, negative len %d", len));
+ KASSERT(prep == 0 || prep == 1, ("m_copymdata, unknown direction %d", prep));
+
+ /* Make sure environment is sane. */
+ for (z = m; z != NULL; z = z->m_next) {
+ mlen += z->m_len;
+ if (!M_WRITABLE(z)) {
+ /* Make clusters writeable. */
+ if (z->m_flags & M_RDONLY)
+ return NULL; /* Can't handle ext ref. */
+ x = m_getcl(how, MT_DATA, 0);
+ if (!x)
+ return NULL;
+ bcopy(z->m_ext.ext_buf, x->m_ext.ext_buf, x->m_ext.ext_size);
+ p = x->m_ext.ext_buf + (z->m_data - z->m_ext.ext_buf);
+ MEXT_REM_REF(z); /* XXX */
+ z->m_data = p;
+ x->m_flags &= ~M_EXT;
+ (void)m_free(x);
+ }
+ }
+ mm = prep ? m : z;
+ for (z = n; z != NULL; z = z->m_next)
+ nlen += z->m_len;
+ if (len == M_COPYALL)
+ len = nlen - off;
+ if (off + len > nlen || len < 1)
+ return NULL;
+
+ /*
+ * Append/prepend the data. Allocating mbufs as necessary.
+ */
+ /* Shortcut if enough free space in first/last mbuf. */
+ if (!prep && M_TRAILINGSPACE(mm) >= len) {
+ m_apply(n, off, len, m_bcopyxxx, mtod(mm, caddr_t) +
+ mm->m_len);
+ mm->m_len += len;
+ mm->m_pkthdr.len += len;
+ return m;
+ }
+ if (prep && M_LEADINGSPACE(mm) >= len) {
+ mm->m_data = mtod(mm, caddr_t) - len;
+ m_apply(n, off, len, m_bcopyxxx, mtod(mm, caddr_t));
+ mm->m_len += len;
+ mm->m_pkthdr.len += len;
+ return mm;
+ }
+
+ /* Expand first/last mbuf to cluster if possible. */
+ if (!prep && !(mm->m_flags & M_EXT) && len > M_TRAILINGSPACE(mm)) {
+ bcopy(mm->m_data, &buf, mm->m_len);
+ m_clget(mm, how);
+ if (!(mm->m_flags & M_EXT))
+ return NULL;
+ bcopy(&buf, mm->m_ext.ext_buf, mm->m_len);
+ mm->m_data = mm->m_ext.ext_buf;
+ mm->m_pkthdr.header = NULL;
+ }
+ if (prep && !(mm->m_flags & M_EXT) && len > M_LEADINGSPACE(mm)) {
+ bcopy(mm->m_data, &buf, mm->m_len);
+ m_clget(mm, how);
+ if (!(mm->m_flags & M_EXT))
+ return NULL;
+ bcopy(&buf, (caddr_t *)mm->m_ext.ext_buf +
+ mm->m_ext.ext_size - mm->m_len, mm->m_len);
+ mm->m_data = (caddr_t)mm->m_ext.ext_buf +
+ mm->m_ext.ext_size - mm->m_len;
+ mm->m_pkthdr.header = NULL;
+ }
+
+ /* Append/prepend as many mbuf (clusters) as necessary to fit len. */
+ if (!prep && len > M_TRAILINGSPACE(mm)) {
+ if (!m_getm(mm, len - M_TRAILINGSPACE(mm), how, MT_DATA))
+ return NULL;
+ }
+ if (prep && len > M_LEADINGSPACE(mm)) {
+ if (!(z = m_getm(NULL, len - M_LEADINGSPACE(mm), how, MT_DATA)))
+ return NULL;
+ i = 0;
+ for (x = z; x != NULL; x = x->m_next) {
+ i += x->m_flags & M_EXT ? x->m_ext.ext_size :
+ (x->m_flags & M_PKTHDR ? MHLEN : MLEN);
+ if (!x->m_next)
+ break;
+ }
+ z->m_data += i - len;
+ m_move_pkthdr(mm, z);
+ x->m_next = mm;
+ mm = z;
+ }
+
+ /* Seek to start position in source mbuf. Optimization for long chains. */
+ while (off > 0) {
+ if (off < n->m_len)
+ break;
+ off -= n->m_len;
+ n = n->m_next;
+ }
+
+ /* Copy data into target mbuf. */
+ z = mm;
+ while (len > 0) {
+ KASSERT(z != NULL, ("m_copymdata, falling off target edge"));
+ i = M_TRAILINGSPACE(z);
+ m_apply(n, off, i, m_bcopyxxx, mtod(z, caddr_t) + z->m_len);
+ z->m_len += i;
+ /* fixup pkthdr.len if necessary */
+ if ((prep ? mm : m)->m_flags & M_PKTHDR)
+ (prep ? mm : m)->m_pkthdr.len += i;
+ off += i;
+ len -= i;
+ z = z->m_next;
+ }
+ return (prep ? mm : m);
+}
+
+/*
* Copy an entire packet, including header (which must be present).
* An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
* Note that the copy is read-only, because clusters are not copied,
==== //depot/projects/hammer/sys/sys/mbuf.h#43 (text+ko) ====
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* @(#)mbuf.h 8.5 (Berkeley) 2/19/95
- * $FreeBSD: src/sys/sys/mbuf.h,v 1.172 2005/07/30 01:32:16 sam Exp $
+ * $FreeBSD: src/sys/sys/mbuf.h,v 1.175 2005/08/29 20:15:33 andre Exp $
*/
#ifndef _SYS_MBUF_H_
@@ -573,10 +573,13 @@
void m_copyback(struct mbuf *, int, int, c_caddr_t);
void m_copydata(const struct mbuf *, int, int, caddr_t);
struct mbuf *m_copym(struct mbuf *, int, int, int);
+struct mbuf *m_copymdata(struct mbuf *, struct mbuf *,
+ int, int, int, int);
struct mbuf *m_copypacket(struct mbuf *, int);
void m_copy_pkthdr(struct mbuf *, struct mbuf *);
struct mbuf *m_copyup(struct mbuf *n, int len, int dstoff);
struct mbuf *m_defrag(struct mbuf *, int);
+void m_demote(struct mbuf *, int);
struct mbuf *m_devget(char *, int, int, struct ifnet *,
void (*)(char *, caddr_t, u_int));
struct mbuf *m_dup(struct mbuf *, int);
@@ -592,6 +595,7 @@
void m_print(const struct mbuf *, int);
struct mbuf *m_pulldown(struct mbuf *, int, int, int *);
struct mbuf *m_pullup(struct mbuf *, int);
+int m_sanity(struct mbuf *, int);
struct mbuf *m_split(struct mbuf *, int, int);
struct mbuf *m_uiotombuf(struct uio *, int, int, int);
==== //depot/projects/hammer/tools/tools/recoverdisk/README#3 (text+ko) ====
@@ -1,7 +1,7 @@
-$FreeBSD: src/tools/tools/recoverdisk/README,v 1.2 2005/02/07 11:26:53 obrien Exp $
+$FreeBSD: src/tools/tools/recoverdisk/README,v 1.3 2005/08/29 23:08:01 sobomax Exp $
-This is a small tool which will read an entire disk(partition) using
-1M blocks and optionally write the read data to a file or disk.
+This is a small tool which will read an entire disk(partition) or file
+using 1M blocks and optionally write the read data to a file or disk.
If a read error happens, the 1M block gets put on the end of the worklist
and will be retried with 64k blocksize.
@@ -20,3 +20,6 @@
touch myfloppy.flp
recoverdisk /dev/fd0 myfloppy.flp
+or recover a single file from the unreadable media:
+
+ recoverdisk /cdrom/file.avi file.avi
==== //depot/projects/hammer/tools/tools/recoverdisk/recoverdisk.c#4 (text+ko) ====
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $FreeBSD: src/tools/tools/recoverdisk/recoverdisk.c,v 1.4 2004/10/23 15:58:50 des Exp $
+ * $FreeBSD: src/tools/tools/recoverdisk/recoverdisk.c,v 1.5 2005/08/29 23:08:01 sobomax Exp $
*/
#include <stdio.h>
#include <stdint.h>
@@ -18,9 +18,11 @@
#include <unistd.h>
#include <sys/queue.h>
#include <sys/disk.h>
+#include <sys/stat.h>
#define BIGSIZE (1024 * 1024)
#define MEDIUMSIZE (64 * 1024)
+#define MINSIZE (512)
struct lump {
off_t start;
@@ -53,10 +55,11 @@
struct lump *lp;
off_t t, d;
size_t i, j;
- int error;
+ int error, flags;
u_char *buf;
- u_int sectorsize;
+ u_int sectorsize, minsize;
time_t t1, t2;
+ struct stat sb;
if (argc < 2)
@@ -68,22 +71,35 @@
fdr = open(argv[1], O_RDONLY);
if (fdr < 0)
err(1, "Cannot open read descriptor %s", argv[1]);
+
+ error = fstat(fdr, &sb);
+ if (error < 0)
+ err(1, "fstat failed");
+ flags = O_WRONLY;
+ if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
+ error = ioctl(fdr, DIOCGSECTORSIZE, §orsize);
+ if (error < 0)
+ err(1, "DIOCGSECTORSIZE failed");
+ minsize = sectorsize;
+
+ error = ioctl(fdr, DIOCGMEDIASIZE, &t);
+ if (error < 0)
+ err(1, "DIOCGMEDIASIZE failed");
+ } else {
+ sectorsize = 1;
+ t = sb.st_size;
+ minsize = MINSIZE;
+ flags |= O_CREAT | O_TRUNC;
+ }
+
if (argc > 2) {
- fdw = open(argv[2], O_WRONLY);
+ fdw = open(argv[2], flags, DEFFILEMODE);
if (fdw < 0)
err(1, "Cannot open write descriptor %s", argv[2]);
} else {
fdw = -1;
}
- error = ioctl(fdr, DIOCGSECTORSIZE, §orsize);
- if (error < 0)
- err(1, "DIOCGSECTORSIZE failed");
-
- error = ioctl(fdr, DIOCGMEDIASIZE, &t);
- if (error < 0)
- err(1, "DIOCGMEDIASIZE failed");
-
new_lump(0, t, 0);
d = 0;
@@ -100,7 +116,7 @@
if (lp->state == 1)
i = MEDIUMSIZE;
if (lp->state > 1)
- i = sectorsize;
+ i = minsize;
time(&t2);
if (t1 != t2 || lp->len < BIGSIZE) {
printf("\r%13jd %7zu %13jd %3d %13jd %13jd %.8f",
More information about the p4-projects
mailing list