mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
Align buffer for read() with flag O_DIRECT
This commit is contained in:
parent
de2f2c471b
commit
55518fa690
7 changed files with 124 additions and 34 deletions
6
CHANGES
6
CHANGES
|
@ -21,6 +21,12 @@ Corrections:
|
||||||
Mitigated race condition of quickly terminating SYSTEM or EXEC child
|
Mitigated race condition of quickly terminating SYSTEM or EXEC child
|
||||||
processes.
|
processes.
|
||||||
|
|
||||||
|
Option o-direct might require alignment of read/write buffer to, e.g.,
|
||||||
|
512 bytes, Socat now takes care of this when allocating the buffer.
|
||||||
|
With this fix read() succeeds, however, write() still might fail when
|
||||||
|
not writing complete pages.
|
||||||
|
Test: O_DIRECT
|
||||||
|
|
||||||
Porting:
|
Porting:
|
||||||
In gcc version 10 the default changed from -fcommon to -fno-common.
|
In gcc version 10 the default changed from -fcommon to -fno-common.
|
||||||
Consequently, linking filan and procan failed with error
|
Consequently, linking filan and procan failed with error
|
||||||
|
|
|
@ -69,6 +69,9 @@
|
||||||
/* Define if you have the socket function. */
|
/* Define if you have the socket function. */
|
||||||
#undef HAVE_SOCKET
|
#undef HAVE_SOCKET
|
||||||
|
|
||||||
|
/* Define if you have the posix_memalign function. */
|
||||||
|
#undef HAVE_PROTOTYPE_LIB_posix_memalign
|
||||||
|
|
||||||
/* Define if you have the strdup function. */
|
/* Define if you have the strdup function. */
|
||||||
#undef HAVE_PROTOTYPE_LIB_strdup
|
#undef HAVE_PROTOTYPE_LIB_strdup
|
||||||
|
|
||||||
|
|
|
@ -785,6 +785,7 @@ AC_CHECK_FUNCS(cfsetispeed cfgetispeed cfsetospeed cfgetospeed)
|
||||||
###################################
|
###################################
|
||||||
# check for prototype and existence of functions that return a pointer
|
# check for prototype and existence of functions that return a pointer
|
||||||
# defines in config.h: HAVE_PROTOTYPE_LIB_$1
|
# defines in config.h: HAVE_PROTOTYPE_LIB_$1
|
||||||
|
AC_CHECK_PROTOTYPE_LIB(posix_memalign)
|
||||||
AC_CHECK_PROTOTYPE_LIB(strdup)
|
AC_CHECK_PROTOTYPE_LIB(strdup)
|
||||||
AC_CHECK_PROTOTYPE_LIB(strerror)
|
AC_CHECK_PROTOTYPE_LIB(strerror)
|
||||||
AC_CHECK_PROTOTYPE_LIB(strstr)
|
AC_CHECK_PROTOTYPE_LIB(strstr)
|
||||||
|
@ -794,7 +795,6 @@ AC_CHECK_PROTOTYPE_LIB(memrchr)
|
||||||
AC_CHECK_PROTOTYPE_LIB(if_indextoname)
|
AC_CHECK_PROTOTYPE_LIB(if_indextoname)
|
||||||
AC_CHECK_PROTOTYPE_LIB(ptsname)
|
AC_CHECK_PROTOTYPE_LIB(ptsname)
|
||||||
|
|
||||||
|
|
||||||
AC_MSG_CHECKING(for long long)
|
AC_MSG_CHECKING(for long long)
|
||||||
AC_CACHE_VAL(sc_cv_type_longlong,
|
AC_CACHE_VAL(sc_cv_type_longlong,
|
||||||
[AC_TRY_COMPILE([],[long long s;],
|
[AC_TRY_COMPILE([],[long long s;],
|
||||||
|
|
73
socat.c
73
socat.c
|
@ -57,7 +57,7 @@ void socat_opt_hint(FILE *fd, char a, char b);
|
||||||
void socat_version(FILE *fd);
|
void socat_version(FILE *fd);
|
||||||
int socat(const char *address1, const char *address2);
|
int socat(const char *address1, const char *address2);
|
||||||
int _socat(void);
|
int _socat(void);
|
||||||
int cv_newline(unsigned char **buff, ssize_t *bytes, int lineterm1, int lineterm2);
|
int cv_newline(unsigned char *buff, ssize_t *bytes, int lineterm1, int lineterm2);
|
||||||
void socat_signal(int sig);
|
void socat_signal(int sig);
|
||||||
static int socat_sigchild(struct single *file);
|
static int socat_sigchild(struct single *file);
|
||||||
|
|
||||||
|
@ -708,7 +708,7 @@ int childleftdata(xiofile_t *xfd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
unsigned char **buff, size_t bufsiz, bool righttoleft);
|
unsigned char *buff, size_t bufsiz, bool righttoleft);
|
||||||
|
|
||||||
bool mayrd1; /* sock1 has read data or eof, according to poll() */
|
bool mayrd1; /* sock1 has read data or eof, according to poll() */
|
||||||
bool mayrd2; /* sock2 has read data or eof, according to poll() */
|
bool mayrd2; /* sock2 has read data or eof, according to poll() */
|
||||||
|
@ -765,8 +765,21 @@ int _socat(void) {
|
||||||
Error2("buffer size option (-b) to big - "F_Zu" (max is "F_Zu")", socat_opts.bufsiz, (SIZE_MAX-1)/2);
|
Error2("buffer size option (-b) to big - "F_Zu" (max is "F_Zu")", socat_opts.bufsiz, (SIZE_MAX-1)/2);
|
||||||
socat_opts.bufsiz = (SIZE_MAX-1)/2;
|
socat_opts.bufsiz = (SIZE_MAX-1)/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_PROTOTYPE_LIB_posix_memalign
|
||||||
|
/* Operations on files with flag O_DIRECT might need buffer alignment.
|
||||||
|
Without this, eg.read() fails with "Invalid argument" */
|
||||||
|
{
|
||||||
|
int _errno;
|
||||||
|
if ((_errno = Posix_memalign((void **)&buff, getpagesize(), 2*socat_opts.bufsiz+1)) != 0) {
|
||||||
|
Error1("posix_memalign(): %s", strerror(_errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* !HAVE_PROTOTYPE_LIB_posix_memalign */
|
||||||
buff = Malloc(2*socat_opts.bufsiz+1);
|
buff = Malloc(2*socat_opts.bufsiz+1);
|
||||||
if (buff == NULL) return -1;
|
if (buff == NULL) return -1;
|
||||||
|
#endif /* !HAVE_PROTOTYPE_LIB_posix_memalign */
|
||||||
|
|
||||||
if (socat_opts.logopt == 'm' && xioinqopt('l', NULL, 0) == 'm') {
|
if (socat_opts.logopt == 'm' && xioinqopt('l', NULL, 0) == 'm') {
|
||||||
Info("switching to syslog");
|
Info("switching to syslog");
|
||||||
|
@ -988,7 +1001,7 @@ int _socat(void) {
|
||||||
|
|
||||||
if (mayrd1 && maywr2) {
|
if (mayrd1 && maywr2) {
|
||||||
mayrd1 = false;
|
mayrd1 = false;
|
||||||
if ((bytes1 = xiotransfer(sock1, sock2, &buff, socat_opts.bufsiz, false))
|
if ((bytes1 = xiotransfer(sock1, sock2, buff, socat_opts.bufsiz, false))
|
||||||
< 0) {
|
< 0) {
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
closing = MAX(closing, 1);
|
closing = MAX(closing, 1);
|
||||||
|
@ -1020,7 +1033,7 @@ int _socat(void) {
|
||||||
|
|
||||||
if (mayrd2 && maywr1) {
|
if (mayrd2 && maywr1) {
|
||||||
mayrd2 = false;
|
mayrd2 = false;
|
||||||
if ((bytes2 = xiotransfer(sock2, sock1, &buff, socat_opts.bufsiz, true))
|
if ((bytes2 = xiotransfer(sock2, sock1, buff, socat_opts.bufsiz, true))
|
||||||
< 0) {
|
< 0) {
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
closing = MAX(closing, 1);
|
closing = MAX(closing, 1);
|
||||||
|
@ -1194,10 +1207,10 @@ static int
|
||||||
*/
|
*/
|
||||||
/* inpipe, outpipe must be single descriptors (not dual!) */
|
/* inpipe, outpipe must be single descriptors (not dual!) */
|
||||||
int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
unsigned char **buff, size_t bufsiz, bool righttoleft) {
|
unsigned char *buff, size_t bufsiz, bool righttoleft) {
|
||||||
ssize_t bytes, writt = 0;
|
ssize_t bytes, writt = 0;
|
||||||
|
|
||||||
bytes = xioread(inpipe, *buff, bufsiz);
|
bytes = xioread(inpipe, buff, bufsiz);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
XIO_RDSTREAM(inpipe)->eof = 2;
|
XIO_RDSTREAM(inpipe)->eof = 2;
|
||||||
|
@ -1215,7 +1228,7 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
/* handle escape char */
|
/* handle escape char */
|
||||||
if (XIO_RDSTREAM(inpipe)->escape != -1) {
|
if (XIO_RDSTREAM(inpipe)->escape != -1) {
|
||||||
/* check input data for escape char */
|
/* check input data for escape char */
|
||||||
unsigned char *ptr = *buff;
|
unsigned char *ptr = buff;
|
||||||
size_t ctr = 0;
|
size_t ctr = 0;
|
||||||
while (ctr < bytes) {
|
while (ctr < bytes) {
|
||||||
if (*ptr == XIO_RDSTREAM(inpipe)->escape) {
|
if (*ptr == XIO_RDSTREAM(inpipe)->escape) {
|
||||||
|
@ -1251,8 +1264,8 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
size_t j;
|
size_t j;
|
||||||
size_t N = 16;
|
size_t N = 16;
|
||||||
const unsigned char *end, *s, *t;
|
const unsigned char *end, *s, *t;
|
||||||
s = *buff;
|
s = buff;
|
||||||
end = (*buff)+bytes;
|
end = buff+bytes;
|
||||||
xioprintblockheader(stderr, bytes, righttoleft);
|
xioprintblockheader(stderr, bytes, righttoleft);
|
||||||
while (s < end) {
|
while (s < end) {
|
||||||
/*! prefix? */
|
/*! prefix? */
|
||||||
|
@ -1298,8 +1311,8 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
xioprintblockheader(stderr, bytes, righttoleft);
|
xioprintblockheader(stderr, bytes, righttoleft);
|
||||||
while (i < (size_t)bytes) {
|
while (i < (size_t)bytes) {
|
||||||
int c = (*buff)[i];
|
int c = buff[i];
|
||||||
if (i > 0 && (*buff)[i-1] == '\n')
|
if (i > 0 && buff[i-1] == '\n')
|
||||||
/*! prefix? */;
|
/*! prefix? */;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\a' : fputs("\\a", stderr); break;
|
case '\a' : fputs("\\a", stderr); break;
|
||||||
|
@ -1323,12 +1336,12 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
/* print prefix */
|
/* print prefix */
|
||||||
xioprintblockheader(stderr, bytes, righttoleft);
|
xioprintblockheader(stderr, bytes, righttoleft);
|
||||||
for (i = 0; i < bytes; ++i) {
|
for (i = 0; i < bytes; ++i) {
|
||||||
fprintf(stderr, " %02x", (*buff)[i]);
|
fprintf(stderr, " %02x", buff[i]);
|
||||||
}
|
}
|
||||||
fputc('\n', stderr);
|
fputc('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
writt = xiowrite(outpipe, *buff, bytes);
|
writt = xiowrite(outpipe, buff, bytes);
|
||||||
if (writt < 0) {
|
if (writt < 0) {
|
||||||
/* EAGAIN when nonblocking but a mandatory lock is on file.
|
/* EAGAIN when nonblocking but a mandatory lock is on file.
|
||||||
the problem with EAGAIN is that the read cannot be repeated,
|
the problem with EAGAIN is that the read cannot be repeated,
|
||||||
|
@ -1355,11 +1368,9 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
/* converts the newline characters (or character sequences) from the one
|
/* converts the newline characters (or character sequences) from the one
|
||||||
specified in lineterm1 to that of lineterm2. Possible values are
|
specified in lineterm1 to that of lineterm2. Possible values are
|
||||||
LINETERM_CR, LINETERM_CRNL, LINETERM_RAW.
|
LINETERM_CR, LINETERM_CRNL, LINETERM_RAW.
|
||||||
buff points to the malloc()'ed data, input and output. It may be subject to
|
bytes specifies the number of bytes input and output */
|
||||||
realloc(). bytes specifies the number of bytes input and output */
|
int cv_newline(unsigned char *buff, ssize_t *bytes,
|
||||||
int cv_newline(unsigned char **buff, ssize_t *bufsiz,
|
|
||||||
int lineterm1, int lineterm2) {
|
int lineterm1, int lineterm2) {
|
||||||
ssize_t *bytes = bufsiz;
|
|
||||||
/* must perform newline changes */
|
/* must perform newline changes */
|
||||||
if (lineterm1 <= LINETERM_CR && lineterm2 <= LINETERM_CR) {
|
if (lineterm1 <= LINETERM_CR && lineterm2 <= LINETERM_CR) {
|
||||||
/* no change in data length */
|
/* no change in data length */
|
||||||
|
@ -1369,23 +1380,23 @@ int cv_newline(unsigned char **buff, ssize_t *bufsiz,
|
||||||
} else {
|
} else {
|
||||||
from = '\r'; to = '\n';
|
from = '\r'; to = '\n';
|
||||||
}
|
}
|
||||||
z = *buff + *bytes;
|
z = buff + *bytes;
|
||||||
p = *buff;
|
p = buff;
|
||||||
while (p < z) {
|
while (p < z) {
|
||||||
if (*p == from) *p = to;
|
if (*p == from) *p = to;
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (lineterm1 == LINETERM_CRNL) {
|
} else if (lineterm1 == LINETERM_CRNL) {
|
||||||
/* buffer becomes shorter */
|
/* buffer might become shorter */
|
||||||
unsigned char to, *s, *t, *z;
|
unsigned char to, *s, *t, *z;
|
||||||
if (lineterm2 == LINETERM_RAW) {
|
if (lineterm2 == LINETERM_RAW) {
|
||||||
to = '\n';
|
to = '\n';
|
||||||
} else {
|
} else {
|
||||||
to = '\r';
|
to = '\r';
|
||||||
}
|
}
|
||||||
z = *buff + *bytes;
|
z = buff + *bytes;
|
||||||
s = t = *buff;
|
s = t = buff;
|
||||||
while (s < z) {
|
while (s < z) {
|
||||||
if (*s == '\r') {
|
if (*s == '\r') {
|
||||||
++s;
|
++s;
|
||||||
|
@ -1397,20 +1408,24 @@ int cv_newline(unsigned char **buff, ssize_t *bufsiz,
|
||||||
*t++ = *s++;
|
*t++ = *s++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*bufsiz = t - *buff;
|
*bytes = t - buff;
|
||||||
} else {
|
} else {
|
||||||
/* buffer becomes longer, must alloc another space */
|
/* buffer becomes longer (up to double length), must alloc another space */
|
||||||
unsigned char *buf2;
|
static unsigned char *buf2; /*! not threadsafe */
|
||||||
unsigned char from; unsigned char *s, *t, *z;
|
unsigned char from; unsigned char *s, *t, *z;
|
||||||
|
|
||||||
if (lineterm1 == LINETERM_RAW) {
|
if (lineterm1 == LINETERM_RAW) {
|
||||||
from = '\n';
|
from = '\n';
|
||||||
} else {
|
} else {
|
||||||
from = '\r';
|
from = '\r';
|
||||||
}
|
}
|
||||||
if ((buf2 = Malloc(2*socat_opts.bufsiz/*sic!*/+1)) == NULL) {
|
if (buf2 == NULL) {
|
||||||
|
if ((buf2 = Malloc(socat_opts.bufsiz)) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s = *buff; t = buf2; z = *buff + *bytes;
|
}
|
||||||
|
memcpy(buf2, buff, *bytes);
|
||||||
|
s = buf2; t = buff; z = buf2 + *bytes;
|
||||||
while (s < z) {
|
while (s < z) {
|
||||||
if (*s == from) {
|
if (*s == from) {
|
||||||
*t++ = '\r'; *t++ = '\n';
|
*t++ = '\r'; *t++ = '\n';
|
||||||
|
@ -1420,9 +1435,7 @@ int cv_newline(unsigned char **buff, ssize_t *bufsiz,
|
||||||
*t++ = *s++;
|
*t++ = *s++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(*buff);
|
*bytes = t - buff;;
|
||||||
*buff = buf2;
|
|
||||||
*bufsiz = t - buf2;;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
10
sycls.c
10
sycls.c
|
@ -23,6 +23,16 @@
|
||||||
|
|
||||||
#if WITH_SYCLS
|
#if WITH_SYCLS
|
||||||
|
|
||||||
|
#if HAVE_PROTOTYPE_LIB_posix_memalign
|
||||||
|
int Posix_memalign(void **memptr, size_t alignment, size_t size) {
|
||||||
|
int result;
|
||||||
|
Debug3("posix_memalign(%p, "F_Zu", F_Zu)", memptr, alignment, size);
|
||||||
|
result = posix_memalign(memptr, alignment, size);
|
||||||
|
Debug1("posix_memalign(...) -> %d", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_PROTOTYPE_LIB_posix_memalign */
|
||||||
|
|
||||||
mode_t Umask(mode_t mask) {
|
mode_t Umask(mode_t mask) {
|
||||||
mode_t result;
|
mode_t result;
|
||||||
int _errno;
|
int _errno;
|
||||||
|
|
2
sycls.h
2
sycls.h
|
@ -11,6 +11,7 @@ struct utsname;
|
||||||
struct flock;
|
struct flock;
|
||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
|
|
||||||
|
int Posix_memalign(void **memptr, size_t alignment, size_t size);
|
||||||
mode_t Umask(mode_t mask);
|
mode_t Umask(mode_t mask);
|
||||||
#endif /* WITH_SYCLS */
|
#endif /* WITH_SYCLS */
|
||||||
int Open(const char *pathname, int flags, mode_t mode);
|
int Open(const char *pathname, int flags, mode_t mode);
|
||||||
|
@ -175,6 +176,7 @@ void Add_history(const char *string);
|
||||||
|
|
||||||
#else /* !WITH_SYCLS */
|
#else /* !WITH_SYCLS */
|
||||||
|
|
||||||
|
#define Posix_memalign(m,a,s) posix_memalign(m,a,s)
|
||||||
#define Umask(m) umask(m)
|
#define Umask(m) umask(m)
|
||||||
#define Creat(p,m) creat(p,m)
|
#define Creat(p,m) creat(p,m)
|
||||||
#define Lseek(f,o,w) lseek(f,o,w)
|
#define Lseek(f,o,w) lseek(f,o,w)
|
||||||
|
|
58
test.sh
58
test.sh
|
@ -13614,7 +13614,7 @@ NAME=SCTP_SERVICENAME
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%socket%*|*%sctp%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%socket%*|*%sctp%*|*%$NAME%*)
|
||||||
TEST="$NAME: Service name resolution works with SCTP"
|
TEST="$NAME: Service name resolution works with SCTP"
|
||||||
# invoke socat with address SCTP4-CONNECT:$LOCALHOST:http; when this does fails with
|
# invoke socat with address SCTP4-CONNECT:$LOCALHOST:http; when this fails with
|
||||||
# "Connection refused", or does not fail at all, the test succeeded
|
# "Connection refused", or does not fail at all, the test succeeded
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! runssctp4 "$((PORT))" >/dev/null; then
|
elif ! runssctp4 "$((PORT))" >/dev/null; then
|
||||||
|
@ -13647,6 +13647,62 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# Test the o-direct option on reading
|
||||||
|
NAME=O_DIRECT
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%engine%*|*%file%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: echo via file with o-direct"
|
||||||
|
# Write data to a file and read it with options o-direct (and ignoreeof)
|
||||||
|
# When the data read is the same as the data written the test succeeded.
|
||||||
|
if ! eval $NUMCOND; then :;
|
||||||
|
elif ! testoptions o-direct >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}o-direct not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
else
|
||||||
|
tf="$td/test$N.file"
|
||||||
|
to="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="test$N $(date) $RANDOM"
|
||||||
|
$PRINTF "test $F_n $TEST... " $N
|
||||||
|
CMD="$TRACE $SOCAT $opts - $tf,o-direct,ignoreeof!!$tf"
|
||||||
|
echo "$da" |$CMD >"$to" 2>"$te"
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ] && grep -q "Invalid argument" "$te" && [ $UNAME = Linux ]; then
|
||||||
|
case $(stat -f /tmp/gerhard/ |grep -o "Type: [^[:space:]]*" |cut -c 7-) in
|
||||||
|
ext2/ext3|xfs|reiserfs)
|
||||||
|
$PRINTF "${FAILED}\n"
|
||||||
|
echo "$CMD" >&2
|
||||||
|
cat "$te" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N" ;;
|
||||||
|
*) $PRINTF "${YELLOW}inable file system${NORMAL}\n"
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N" ;;
|
||||||
|
esac
|
||||||
|
elif [ $rc -ne 0 ]; then
|
||||||
|
$PRINTF "${FAILED}:\n"
|
||||||
|
echo "$CMD" >&2
|
||||||
|
cat "$te" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
elif ! echo "$da" |diff - "$to" >$tdiff; then
|
||||||
|
$PRINTF "${FAILED}\n"
|
||||||
|
echo "$CMD" >&2
|
||||||
|
cat "$te" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi # command ok
|
||||||
|
fi ;; # NUMCOND, feats
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
#=================================================================================
|
#=================================================================================
|
||||||
# here come tests that might affect your systems integrity. Put normal tests
|
# here come tests that might affect your systems integrity. Put normal tests
|
||||||
|
|
Loading…
Reference in a new issue