line source
/******************************************************************************
* Flash File System (ffs)
* Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
*
* ffs test core
*
* $Id: test.c 1.43.1.105.1.7 Thu, 18 Dec 2003 10:50:52 +0100 tsj $
*
******************************************************************************/
#include "ffs/ffs.h"
#include "ffs/board/tffs.h"
#include "ffs/board/core.h"
#include "ffs/board/tmffs.h"
#include "ffs/board/ffstrace.h"
#define COMPILE_ON_WIN32 1
#if (COMPILE_ON_WIN32 == 0)
#include "ffs/board/pcm.h"
#endif
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdarg.h>
#include "ffs/board/win32/getopt.h"
#include <errno.h>
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#endif //nWIN32
#ifndef WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif //nWIN32
extern char *ffs_strerror(effs_t error);
/******************************************************************************
* Prototypes and Globals
******************************************************************************/
static void main_args(int argc, char *argv[]);
static void main_usage(void);
static long arg_long_get(char *s);
#ifndef WIN32
static int ffs_server(char type);
#endif //nWIN32
char *arg_imagename = "image"; // flash image file to use for test
char *arg_test = "all"; // default test case to run
int arg_keepgoing = 0; // keep going on error
int arg_removeimage = 0; // remove image file first
char arg_server = 0;
char arg_pctm = 1;
int arg_trmask = TrTest; // trace mask
int arg_trspaces = 2; // indentation multiplier
/******************************************************************************
* Globals and Main
******************************************************************************/
int main(int argc, char *argv[])
{
int result;
main_args(argc, argv);
tr_init(arg_trmask, arg_trspaces, NULL );
if (arg_server == 't' || arg_server == 'u') {
#ifdef WIN32
fprintf(stdout, "FFS_server not supported in WIN32");
#else //WIN32
result = ffs_server(arg_server);
#endif //WIN32
}
else {
test_init(arg_keepgoing);
result = test_run(arg_test);
test_exit();
fprintf(stdout, "TEST TOTAL cases failed: %d\n", result);
if (result > 0)
fprintf(stderr, "TEST TOTAL cases failed: %d\n", result);
}
exit(0);
}
/******************************************************************************
* Command line parsing
******************************************************************************/
static void main_args_debug(char *optarg)
{
char sign;
unsigned int mask;
while (*optarg) {
sign = '+';
mask = 0;
if (*optarg == '+' || *optarg == '-')
sign = *optarg++;
if (*optarg) {
switch (*optarg) {
case 't': mask = TrTest; break;
case 'x': mask = TrTestHigh; break;
case 'y': mask = TrTestLow; break;
case 'b': mask = TrBstat; break;
case 'a': mask = TrApi; break;
case 'f': mask = TrFsck; break;
case 'F': mask = TrFsckLow; break;
case 'o': mask = TrObject; break;
case 'i': mask = TrIReclaim; break;
case 'd': mask = TrDReclaim; break;
case 'r': mask = TrReclaimLow; break;
case 'w': mask = TrDrvWrite; break;
case 'e': mask = TrDrvErase; break;
case 'j': mask = TrJournal; break;
case 'h': mask = TrUtil; break;
case 's': mask = TrServer; break;
case '?': mask = TrTrace; break;
}
switch (*optarg) {
case '*':
arg_trmask = TrAll &
// ~(TrTrace|TrTmffs|TrDrvWrite|TrDrvErase|TrJournal|TrUtil|TrBstat);
~(TrTrace|TrDrvWrite|TrDrvErase|TrJournal|TrUtil|TrBstat);
break;
default:
if (sign == '+')
arg_trmask |= mask;
else
arg_trmask &= ~mask;
break;
}
optarg++;
}
}
printf("arg_trmask = 0x%X\n", arg_trmask);
}
static void main_usage(void)
{
printf("Usage: ffs [OPTIONS...]\n"
"\n"
/* $Format: "\"Revision $ProjectVersion$, \""$ */
"Revision 5.53, "
__DATE__ ".\n"
"\n"
"OPTIONS:\n"
" -c <tcase> Semi-colon separated list of test cases to run.\n"
" Each test case name can be suffixed with one or more\n"
" numerical parameter(s).\n"
" Default is 'all'.\n"
" -f <n> Flash image file name. Default is 'image'.\n"
" -l List all test cases\n"
" -t <char> Trace mask in human format. Same as '-t <char>'.\n"
" Default is 't'.\n"
" * = All\n"
" t = Test\n"
" x = TestHigh\n"
" y = TestLow\n"
" b = Bstat\n"
" a = Api\n"
" f = Fsck\n"
" F = FsckLow\n"
" i = IReclaim\n"
" d = DReclaim\n"
" r = ReclaimLow\n"
" j = Journalling\n"
" w = DrvWrite\n"
" e = DrvErase\n"
" h = Helper/Utility Functions\n"
" s = FFS Server\n"
" 0 = None\n"
" -d i<n> Trace indentation multiplier. Default is 4.\n"
" -d m<n> Trace mask. Default is 0.\n"
" -d s<n> Trace indentation multiplier (spaces). Default is 4.\n"
" -s <char> Start as an FFS server, using either TCP or UDP:\n"
" t = tcp (default)\n"
" u = udp\n"
" -k Keep going on error\n"
" -r Remove flash image file first\n"
" -h Display this help\n");
exit(0);
}
static void main_args(int argc, char *argv[])
{
char c;
while ( (c = getopt(argc, argv, "c:f:krls:t:d:h")) != -1)
{
switch (c)
{
case 'c': arg_test = optarg; break;
case 'f': arg_imagename = optarg; break;
case 'k': arg_keepgoing = 1; break;
case 'r': arg_removeimage = 1; break;
case 'l': test_listall(); exit(0); break;
case 's': arg_server = *optarg; break;
case 't':
main_args_debug(optarg);
break;
case 'd':
switch(*optarg) {
case 's': arg_trspaces = arg_long_get(optarg); break;
case 'm': arg_trmask = arg_long_get(optarg); break;
}
break;
case 'h': main_usage(); break;
default:
main_usage();
}
}
}
static long arg_long_get(char *s)
{
long value;
char *endp;
errno = 0;
value = strtol(optarg, &endp, 0);
if (errno == ERANGE || *endp != 0) {
fprintf(stderr, "Invalid command line argument value: '%s'", s);
exit(1);
}
return value;
}
/******************************************************************************
* Globals and Main
******************************************************************************/
#ifndef WIN32
void server_error(char *msg)
{
perror(msg);
exit(1);
}
#define FFS_SERVER_PORT (21588)
#define INBUF_SIZE (2 * 65536)
#define OUTBUF_SIZE (2 * 65536)
static int ffs_server(char type)
{
char inbuf[INBUF_SIZE], *inbufp;
char outbuf[OUTBUF_SIZE], *outbufp;
int insize, outsize;
int error;
struct sockaddr_in myaddr;
struct sockaddr_in clientaddr;
int myfd, clientfd, addr_len;
error = ffs_initialize();
if (type == 'u')
{
// Code for using UDP datagrams
/* get an internet domain socket */
if ((myfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
server_error("socket()");
tr(TR_FUNC, TrServer, "socket()\n");
/* complete the socket structure */
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(FFS_SERVER_PORT);
/* bind the socket to the port number */
if (bind(myfd, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1)
server_error("bind()");
tr(TR_FUNC, TrServer, "bind(%d)\n", FFS_SERVER_PORT);
tr(TR_FUNC, TrServer,
"FFS UDP/IP server Waiting for client requests...\n");
for (;;)
{
addr_len = sizeof(struct sockaddr);
if ((insize = recvfrom(myfd, inbuf, sizeof(inbuf), 0,
(struct sockaddr *) &clientaddr,
&addr_len)) < 0)
server_error("recvfrom()");
tr(TR_FUNC, TrServer, "recv() %d bytes from %s\n",
insize, inet_ntoa(clientaddr.sin_addr));
outsize = tm_ffs(outbuf, OUTBUF_SIZE, inbuf, insize);
if(sendto(myfd, outbuf, outsize, 0,
(struct sockaddr *) &clientaddr,
sizeof(struct sockaddr)) < 0)
server_error("sendto()");
tr(TR_FUNC, TrServer, "send(%d)\n", outsize);
}
close(clientfd);
close(myfd);
}
else
{
// Code for using TCP/IP
/* get an internet domain socket */
if ((myfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
server_error("socket()");
tr(TR_FUNC, TrServer, "socket()\n");
/* complete the socket structure */
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(FFS_SERVER_PORT);
/* bind the socket to the port number */
if (bind(myfd, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1)
server_error("bind()");
tr(TR_FUNC, TrServer, "bind(%d)\n", FFS_SERVER_PORT);
/* show that we are willing to listen */
if (listen(myfd, 5) == -1)
server_error("listen()");
tr(TR_FUNC, TrServer, "listen()\n");
error = 0;
while (error == 0 || error == ESHUTDOWN)
{
tr(TR_FUNC, TrServer,
"FFS TCP/IP server waiting for client connection...\n");
if ((clientfd = accept(myfd, 0, 0)) < 0)
server_error("accept()");
tr(TR_FUNC, TrServer, "accept()\n");
error = 0;
while (error == 0)
{
inbufp = inbuf;
outbufp = outbuf;
if ((insize = read(clientfd, inbufp, sizeof(inbuf))) < 0) {
if (errno == ESHUTDOWN) {
error = ESHUTDOWN;
continue;
}
else {
server_error("recv()");
}
}
tr(TR_FUNC, TrServer, "recv() %d bytes\n", insize);
if (insize == 1 && inbuf[0] == 0)
break;
if (arg_pctm) {
inbufp++;
insize--;
outbufp = outbuf;
*outbufp++ = 0x70;
*outbufp++ = 0x00;
}
outsize = tm_ffs(outbufp, OUTBUF_SIZE, inbufp, insize);
if (arg_pctm) {
outsize += 2;
}
if (write(clientfd, outbuf, outsize) < 0)
server_error("send()");
tr(TR_FUNC, TrServer, "send(%d)\n", outsize);
}
close(clientfd);
}
close(myfd);
}
return(0);
}
#endif //nWIN32
/******************************************************************************
* Prototypes and Globals
******************************************************************************/
void test_fatal_printf(char *format, ...)
{
va_list args;
static char buf[1024];
va_start(args, format);
vsprintf(buf, format, args);
fprintf(stderr, "%s", buf);
exit(1);
}