aboutsummaryrefslogtreecommitdiff
path: root/tests/checkfs/checkfs.c
blob: 3224d2b996b34fdde695995d3025362e81009edb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
/*

 * Copyright Daniel Industries.
 *
 * Created by: Vipin Malik (vipin.malik@daniel.com)
 *
 * This code is released under the GPL version 2. See the file COPYING
 * for more details.
 *
 * Software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing rights and
 * limitations under the Licence.

  This program opens files in progression (file00001, file00002 etc),
  upto MAX_NUM_FILES and checks their CRC. If a file is not found or the
  CRC does not match it stops it's operation.

  Everything is logged in a logfile called './logfile'.

  If everything is ok this program sends a signal, via com1, to the remote
  power control box to power cycle this computer.

  This program then proceeds to create new files file0....file<MAX_NUM_FILES>
  in a endless loop and checksum each before closing them.

  STRUCTURE OF THE FILES:
  The fist int is the size of the file in bytes.
  The last 2 bytes are the CRC for the entire file.
  There is random data in between.

  The files are opened in the current dir.

  $Id: checkfs.c,v 1.8 2005/11/07 11:15:17 gleixner Exp $
  $Log: checkfs.c,v $
  Revision 1.8  2005/11/07 11:15:17  gleixner
  [MTD / JFFS2] Clean up trailing white spaces

  Revision 1.7  2001/06/21 23:04:17  dwmw2
  Initial import to MTD CVS

  Revision 1.6  2001/06/08 22:26:05  vipin
  Split the modbus comm part of the program (that sends the ok to pwr me down
  message) into another file "comm.c"

  Revision 1.5  2001/06/08 21:29:56  vipin
  fixed small issue with write() checking for < 0 instead of < (bytes to be written).
  Now it does the latter (as it should).

  Revision 1.4  2001/05/11 22:29:40  vipin
  Added a test to check and err out if the first int in file (which tells us
  how many bytes there are in the file) is zero. This will prevent a corrupt
  file with zero's in it from passing the crc test.

  Revision 1.3  2001/05/11 21:33:54  vipin
  Changed to use write() rather than fwrite() when creating new file. Additionally,
  and more important, it now does a single write() for the entire data. This will
  enable us to use this program to test for power fail *data* reliability when
  writing over an existing file, specially on powr fail "safe" file systems as
  jffs/jffs2. Also added a new cmdline parameter "-e" that specifies the max # of
  errors that can be tolerated. This should be set to ZERO to test for the above,
  as old data should be reliabily maintained if the newer write never "took" before
  power failed. If the write did succeed, then the newer data will have its own
  CRC in place when it gets checked => hence no error. In theory at least!


  Revision 1.2  2001/05/11 19:27:33  vipin
  Added cmd line args to change serial port, and specify max size of
  random files created. Some cleanup. Added -Wall to Makefile.

  Revision 1.1  2001/05/11 16:06:28  vipin
  Importing checkfs (the power fail test program) into CVS. This was
  originally done for NEWS. NEWS had a lot of version, this is
  based off the last one done for NEWS. The "makefiles" program
  is run once initially to create the files in the current dir.
  "checkfs" is then run on every powerup to check consistancy
  of the files. See checkfs.c for more details.


*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "common.h"



extern int do_pwr_dn(int fd, int cycleCnt);

#define CMDLINE_PORT "-p"
#define CMDLINE_MAXFILEBYTES "-s"
#define CMDLINE_MAXERROR "-e"
#define CMDLINE_HELPSHORT "-?"
#define CMDLINE_HELPLONG "--help"


int CycleCount;

char SerialDevice[255] = "/dev/ttyS0"; /* default, can be changed
                                        through cmd line. */

#define MAX_INTS_ALLOW 100000 /* max # of int's in the file written.
                                 Statis limit to size struct. */
float FileSizeMax = 1024.0; /*= (file size in bytes), MUST be float*/

int MaxErrAllowed = 1; /* default, can ge changed thru cmd line*/


/* Needed for CRC generation/checking */
static const unsigned short crc_ccitt_table[] = {
    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};


/*
  Set's up the Linux serial port. Must be passed string to device to
  open. Parameters are fixed to 9600,e,1

  [A possible enhancement to this program would be to pass these
  parameters via the command line.]

  Returns file descriptor to open port. Use this fd to write to port
  and close it later, when done.
*/
int setupSerial (const char *dev) {
    int i, fd;
    struct termios tios;

    fd = open(dev,O_RDWR | O_NDELAY );
    if (fd < 0) {
        fprintf(stderr, "%s: %s\n", dev, strerror(errno));
        exit(1);
    }
    if (tcgetattr(fd, &tios) < 0) {
        fprintf(stderr, "Could not get terminal attributes: %s", strerror(errno));
        exit(1);
    }

    tios.c_cflag =
        CS7 |
        CREAD |			// Enable Receiver
        HUPCL |			// Hangup after close
        CLOCAL |                // Ignore modem control lines
        PARENB;			// Enable parity (even by default)



    tios.c_iflag      = IGNBRK; // Ignore break
    tios.c_oflag      = 0;
    tios.c_lflag      = 0;
    for(i = 0; i < NCCS; i++) {
        tios.c_cc[i] = '\0';           // no special characters
    }
    tios.c_cc[VMIN] = 1;
    tios.c_cc[VTIME] = 0;

    cfsetospeed (&tios, B9600);
    cfsetispeed (&tios, B9600);

    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
        fprintf(stderr, "Could not set attributes: ,%s", strerror(errno));
        exit(1);
    }
    return fd;
}





//A portion of this code was taken from the AX.25 HDLC packet driver
//in LINUX. Once I test and have a better understanding of what
//it is doing, it will be better commented.

//For now one can speculate that the CRC routine always expects the
//CRC to calculate out to 0xf0b8 (the hardcoded value at the end)
//and returns TRUE if it is and FALSE if it doesn't.
//Why don't people document better!!!!
int check_crc_ccitt(char *filename)
{
    FILE *fp;
    FILE *logfp;
    unsigned short crc = 0xffff;
    int len;
    char dataByte;
    int retry;
    char done;

    fp =   fopen(filename,"rb");
    if(!fp){
        logfp = fopen("logfile","a"); /*open for appending only.*/
        fprintf(logfp, "Verify checksum:Error! Cannot open filename passed for verify checksum: %s\n",filename);
        fclose(logfp);
        return FALSE;
    }


    /*the first int contains an int that is the length of the file in long.*/
    if(fread(&len, sizeof(int), 1, fp) != 1){
        logfp = fopen("logfile","a"); /*open for appending only.*/
        fprintf(logfp, "verify checksum:Error reading from file: %s\n", filename);
        fclose(fp);
        fclose(logfp);
        return FALSE;
    }

    /* printf("Checking %i bytes for CRC in \"%s\".\n", len, filename); */

    /* Make sure that we did not read 0 as the number of bytes in file. This
       check prevents a corrupt file with zero's in it from passing the
       CRC test. A good file will always have some data in it. */
    if(len == 0)
    {

        logfp = fopen("logfile","a"); /*open for appending only.*/
        fprintf(logfp, "verify checksum: first int claims there are 0 data in file. Error!: %s\n", filename);
        fclose(fp);
        fclose(logfp);
        return FALSE;
    }


    rewind(fp);
    len+=2; /*the file has two extra bytes at the end, it's checksum. Those
              two MUST also be included in the checksum calculation.
            */

    for (;len>0;len--){
        retry=5; /*retry 5 times*/
        done = FALSE;
        while(!done){
            if(fread(&dataByte, sizeof(char), 1, fp) != 1){
                retry--;
            }else{
                done = TRUE;
            }
            if(retry == 0){
                done = TRUE;
            }
        }
        if(!retry){
            logfp = fopen("logfile","a"); /*open for appending only.*/
            fprintf(logfp, "Unexpected end of file: %s\n", filename);
            fprintf(logfp, "...bytes left to be read %i.\n",len);
            fclose(logfp);
            fclose(fp);
            return FALSE;
        }
        crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ dataByte) & 0xff];
    }
    fclose(fp);
    if( (crc & 0xffff) != 0xf0b8){
        /*printf("The CRC of read file:%x\n", crc); */
        return FALSE;
    }
    return TRUE;
}/*end check_crc_ccitt() */



/*
  Sends "OK to power me down" message to the remote
  power cycling box, via the serial port.
  Also updates the num power cycle count in a local
  file.
  This file "./cycleCnt" must be present. This is
  initially (and once) created by the separate "makefiles.c"
  program.
*/
void send_pwrdn_ok(void){

    int fd;
    FILE *cyclefp;
    int cycle_fd;

    cyclefp =   fopen("cycleCnt","rb");
    if(!cyclefp){
        printf("expecting file \"cycleCnt\". Cannot continue.\n");
        exit(1);
    }
    if(fread(&CycleCount, sizeof(CycleCount),1,cyclefp) != 1){
        fprintf(stderr, "Error! Unexpected end of file cycleCnt.\n");
        exit(1);
    }
    fclose(cyclefp);

    CycleCount++;

    /*now write this puppy back*/
    cyclefp  = fopen("cycleCnt","wb");
    cycle_fd = fileno(cyclefp);
    if(!cyclefp){
        fprintf(stderr, "Error! cannot open file for write:\"cycleCnt\". Cannot continue.\n");
        exit(1);
    }
    if(fwrite(&CycleCount, sizeof(CycleCount), 1,cyclefp) !=1){
        fprintf(stderr, "Error writing to file cycleCnt. Cannot continue.\n");
        exit(1);
    }
    if(fdatasync(cycle_fd)){
        fprintf(stderr, "Error! cannot sync file buffer with disk.\n");
        exit(1);
    }

    fclose(cyclefp);
    (void)sync();

    printf("\n\n Sending Power down command to the remote box.\n");
    fd = setupSerial(SerialDevice);

    if(do_pwr_dn(fd, CycleCount) < 0)
    {
        fprintf(stderr, "Error sending power down command.\n");
        exit(1);
    }

    close(fd);
}//end send_pwrnd_ok()




/*
  Appends 16bit CRC at the end of numBytes long buffer.
  Make sure buf, extends at least 2 bytes beyond.
 */
void appendChecksum(char *buf, int numBytes){

    unsigned short crc = 0xffff;
    int index = 0;

    /* printf("Added CRC (2 bytes) to %i bytes.\n", numBytes); */

    for (; numBytes > 0; numBytes--){

        crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ buf[index++]) & 0xff];
    }
    crc ^= 0xffff;
    /*printf("The CRC: %x\n\n", crc);*/

    buf[index++] = crc;
    buf[index++] = crc >> 8;



}/*end checksum()*/





/*
  This guy make a new "random data file" with the filename
  passed to it. This file is checksummed with the checksum
  stored at the end. The first "int" in the file is the
  number of int's in it (this is needed to know how much
  data to read and checksum later).
*/
void make_new_file(char *filename){


    int dfd; /* data file descriptor */
    int rand_data;
    int data_size;
    int temp_size;
    int dataIndex = 0;
    int err;


    struct {
        int sizeInBytes; /* must be int */
        int dataInt[MAX_INTS_ALLOW+1]; /* how many int's can we write? */
    }__attribute((packed)) dataBuf;


    fprintf(stderr, "Creating File:%s. ", filename);

    if((dfd = open(filename, O_RDWR | O_CREAT | O_SYNC)) <= 0)
    {
        printf("Error! Cannot open file: %s\n",filename);
        perror("Error");
        exit(1);
    }

    /*now write a bunch of random binary data to the file*/
    /*first figure out how much data to write. That is random also.*/

    /*file should not be less than 5 ints long. (so that we have decent length files,
      that's all)*/
    while(
	((data_size = (int)(1+(int)((FileSizeMax/sizeof(int))*rand()/(RAND_MAX+1.0)))) < 5)
    );

    /* printf("Writing %i ints to the file.\n", data_size); */

    temp_size = data_size * sizeof(int);

    /* Make sure that all data is written in one go! This is important to
       check for reliability of file systems like JFFS/JFFS that purport to
       have "reliable" writes during powre fail.
     */

    dataBuf.sizeInBytes = temp_size;

    data_size--; /*one alrady written*/
    dataIndex = 0;

    while(data_size--){
        rand_data =  (int)(1 + (int)(10000.0*rand()/(RAND_MAX+1.0)));

        dataBuf.dataInt[dataIndex++] = rand_data;

    }

    /*now calculate the file checksum and append it to the end*/
    appendChecksum((char *)&dataBuf, dataBuf.sizeInBytes);

    /* Don't forget to increase the size of data written by the 2 chars of CRC at end.
     These 2 bytes are NOT included in the sizeInBytes field. */
    if((err = write(dfd, (void *)&dataBuf, dataBuf.sizeInBytes + sizeof(short))) <
       (dataBuf.sizeInBytes + sizeof(short))
    )
    {
        printf("Error writing data buffer to file. Written %i bytes rather than %i bytes.",
               err, dataBuf.sizeInBytes);
        perror("Error");
        exit(1);
    }

    /* Now that the data is (hopefully) safely written. I can truncate the file to the new
       length so that I can reclaim any unused space, if the older file was larger.
     */
    if(ftruncate(dfd, dataBuf.sizeInBytes + sizeof(short)) < 0)
    {
        perror("Error: Unable to truncate file.");
        exit(1);
    }


    close(dfd);


}//end make_new_file()



/*
  Show's help on stdout
 */
void printHelp(char **argv)
{
    printf("Usage:%s <options, defined below>\n", argv[0]);
    printf("%s </dev/ttyS0,1,2...>: Set com port to send ok to pwr dn msg on\n",
           CMDLINE_PORT);
    printf("%s <n>: Set Max size in bytes of each file to be created.\n",
           CMDLINE_MAXFILEBYTES);
    printf("%s <n>: Set Max errors allowed when checking all files for CRC on start.\n",
           CMDLINE_MAXERROR);
    printf("%s or %s: This Help screen.\n", CMDLINE_HELPSHORT,
           CMDLINE_HELPLONG);

}/* end printHelp()*/



void processCmdLine(int argc, char **argv)
{

    int cnt;

    /* skip past name of this program, process rest */
    for(cnt = 1; cnt < argc; cnt++)
    {
        if(strcmp(argv[cnt], CMDLINE_PORT) == 0)
        {
            strncpy(SerialDevice, argv[++cnt], sizeof(SerialDevice));
            continue;
        }else
            if(strcmp(argv[cnt], CMDLINE_MAXFILEBYTES) == 0)
            {
                FileSizeMax = (float)atoi(argv[++cnt]);
                if(FileSizeMax > (MAX_INTS_ALLOW*sizeof(int)))
                {
                    printf("Max file size allowed is %lu.\n",
                           MAX_INTS_ALLOW*sizeof(int));
                    exit(0);
                }

                continue;
            }else
                if(strcmp(argv[cnt], CMDLINE_HELPSHORT) == 0)
                {
                    printHelp(argv);
                    exit(0);

                }else
                    if(strcmp(argv[cnt], CMDLINE_HELPLONG) == 0)
                    {
                        printHelp(argv);
                        exit(0);
                    }else

                        if(strcmp(argv[cnt], CMDLINE_MAXERROR) == 0)
                        {
                            MaxErrAllowed = atoi(argv[++cnt]);
                        }
                        else
                        {
                            printf("Unknown cmd line option:%s\n", argv[cnt]);
                            printHelp(argv);
                            exit(0);

                        }
    }


}/* end processCmdLine() */





int main(int argc, char **argv){

    FILE *logfp;
    int log_fd;
    char filename[30];
    short filenameCounter = 0;
    unsigned short counter;
    unsigned short numberFiles;
    char error = FALSE;
    short errorCnt = 0;
    time_t timep;
    char * time_string;
    unsigned int seed;


    numberFiles = MAX_NUM_FILES;

    if(argc >= 1)
    {
        processCmdLine(argc, argv);
    }


    /*
      First open MAX_NUM_FILES and make sure that the checksum is ok.
      Also make an intry into the logfile.
    */
    /* timestamp! */
    time(&timep);
    time_string = (char *)ctime((time_t *)&timep);

    /*start a new check, make a log entry and continue*/
    logfp = fopen("logfile","a"); /*open for appending only.*/
    log_fd = fileno(logfp);
    fprintf(logfp,"%s", time_string);
    fprintf(logfp,"Starting new check.\n");
    if(fdatasync(log_fd) == -1){
        fprintf(stderr,"Error! Cannot sync file data with disk.\n");
        exit(1);
    }

    fclose(logfp);
    (void)sync();

    /*
      Now check all random data files in this dir.
    */
    for(counter=0;counter<MAX_NUM_FILES;counter++){

        fprintf(stderr, "%i.", counter);

        /*create the filename in sequence. The number of files
          to check and the algorithm to create the filename is
          fixed and known in advance.*/
        sprintf(filename,"file%i",filenameCounter++);

        if(!check_crc_ccitt(filename)){
            /*oops, checksum does not match. Make an entry into the log file
              and decide if we can continue or not.*/
            fprintf(stderr, "crcError:%s ", filename);
            logfp = fopen("logfile","a"); /*open for appending only.*/
            log_fd = fileno(logfp);
            fprintf(logfp,"CRC error in file: %s\n", filename);
            if(fdatasync(log_fd) == -1){
                fprintf(stderr,"Error! Cannot sync file data with disk.\n");
                exit(1);
            }
            fclose(logfp);
            (void)sync();

            error = TRUE;
            errorCnt++;

            if(errorCnt > MaxErrAllowed){
                logfp = fopen("logfile","a"); /*open for appending only.*/
                log_fd = fileno(logfp);
                fprintf(logfp,"\nMax Error count exceed. Stopping!\n");
                if(fdatasync(log_fd) == -1){
                    fprintf(stderr,"Error! Cannot sync file data with disk.\n");
                    exit(1);
                }
                fclose(logfp);
                (void)sync();

                fprintf(stderr, "Too many errors. See \"logfile\".\n");
                exit(1);
            }/* if too many errors */

            /*we have decided to continue, however first repair this file
              so that we do not cumulate errors across power cycles.*/
            make_new_file(filename);
        }
    }//for

    /*all files checked, make a log entry and continue*/
    logfp = fopen("logfile","a"); /*open for appending only.*/
    log_fd = fileno(logfp);
    fprintf(logfp,"All files checked. Total errors found: %i\n\n", errorCnt);
    if(fdatasync(log_fd)){
        fprintf(stderr, "Error! cannot sync file buffer with disk.\n");
        exit(1);
    }

    fclose(logfp);
    (void)sync();

    /*now send a message to the remote power box and have it start a random
      pwer down timer after which power will be killed to this unit.
    */
    send_pwrdn_ok();

    /*now go into a forever loop of writing to files and CRC'ing them on
      a continious basis.*/

    /*start from a random file #*/
    /*seed rand based on the current time*/
    seed = (unsigned int)time(NULL);
    srand(seed);

    filenameCounter=(int)(1+(int)((float)(MAX_NUM_FILES-1)*rand()/(RAND_MAX+1.0)));

    while(1){

        for(;filenameCounter<MAX_NUM_FILES;filenameCounter++){

            /*create the filename in sequence*/
            sprintf(filename,"file%i",filenameCounter);
            make_new_file(filename);
        }
        filenameCounter = 0;
    }

    exit(0); /* though we will never reach here, but keeps the compiler happy*/
}/*end main()*/