Added first stab of pnd exec support
[pandora-libraries.git] / lib / pnd_pndfiles.c
1
2 #include <stdio.h> /* for FILE etc */
3 #include <stdlib.h> /* for malloc */
4 #include <ctype.h> /* for isprint */
5
6 #define __USE_GNU
7 #include <string.h> /* for making strcasestr happy */
8
9 #include "pnd_container.h"
10 #include "pnd_pxml.h"
11 #include "pnd_apps.h"
12 #include "pnd_pndfiles.h"
13
14 unsigned char pnd_pnd_seek_pxml ( FILE *f ) {
15   char *b;                // buffer
16   char *match;            // match within buffer
17   unsigned int len;       // length of file (not suporting 'big files' 2GB..)
18   unsigned int pos;       // current tape head
19   unsigned int readable;  // amount to read (for small files/chunks)
20
21   b = malloc ( PND_PXML_WINDOW_SIZE + 1 );
22
23   if ( ! b ) {
24     return ( 0 );
25   }
26
27   memset ( b, '\0', PND_PXML_WINDOW_SIZE + 1 );
28
29   // determine length of file
30   fseek ( f, 0, SEEK_END );
31   len = ftell ( f );
32   fseek ( f, 0, SEEK_SET );
33
34   /* ready to scan through the file, backwards
35    */
36
37   // easy case or no?
38   if ( len <= PND_PXML_WINDOW_SIZE ) {
39     pos = 0;
40     readable = len;
41   } else {
42     pos = len - PND_PXML_WINDOW_SIZE;
43     readable = PND_PXML_WINDOW_SIZE;
44   }
45
46   while ( 1 ) {
47
48     //printf ( "find pxml; pos %u readable %u\n", pos, readable );
49
50     // seek into this blocks position
51     fseek ( f, pos, SEEK_SET );
52
53     // read
54     fread ( b, 1, readable, f );
55
56     // find the head tag here? now, there are serious heavy duty algorithyms for locating
57     // strings within an arbitrary buffer. Thats needs to be done. This is the worst
58     // performing brute force strategy here.
59     if ( ( match = pnd_match_binbuf ( b, readable, PXML_TAGHEAD ) ) ) {
60       fseek ( f, pos + ( match - b ), SEEK_SET );
61       //printf ( "  match found at %u\n", pos + ( match - b ) );
62       free ( b );
63       return ( 1 );
64     }
65
66     // no match, so we need to back up another chunk; if we can't
67     // back up that much, we're on our last check. if we can't back
68     // up at all, we've already been here and time to fail
69     if ( pos == 0 ) {
70       break; // done, FAIL
71     } else if ( pos > PND_PXML_WINDOW_FRACTIONAL ) {
72       pos -= PND_PXML_WINDOW_FRACTIONAL;
73       readable = PND_PXML_WINDOW_SIZE;
74     } else {
75       readable = PND_PXML_WINDOW_SIZE - pos;
76       memset ( b + pos, '\0', PND_PXML_WINDOW_SIZE - pos );
77       pos = 0;
78     }
79
80   } // while
81
82   // exeunt, with alarums
83   free ( b );
84   return ( 0 );
85 }
86
87 unsigned char pnd_pnd_accrue_pxml ( FILE *f, char *target, unsigned int maxlen ) {
88   char inbuf [ 1024 ]; // TBD: love all these assumptions? noob!
89   char *insert = target;
90   unsigned int l;
91
92   while ( fgets ( inbuf, 1023, f ) ) {
93
94     // copy inbuf onto end of target
95 #if 1
96     strncpy ( insert, inbuf, maxlen );
97     // reduce counter for max size so we can avoid buffer overruns
98     l = strlen ( inbuf );
99     maxlen -= l; // reduce
100     insert += l; // increment
101 #else
102     strncat ( target, inbuf, maxlen );
103 #endif
104
105     if ( strcasestr ( inbuf, PXML_TAGFOOT ) ) {
106       return ( 1 );
107     }
108
109   } // while
110
111   return ( 0 );
112 }
113
114 char *pnd_match_binbuf ( char *haystack, unsigned int maxlen, char *needle ) {
115   char *end = haystack + maxlen - strlen ( needle );
116   unsigned int needlelen = strlen ( needle );
117
118   while ( haystack < end ) {
119
120     if ( isprint(*haystack) ) {
121
122       if ( strncasecmp ( haystack, needle, needlelen ) == 0 ) {
123         //printf ( "haystack %s\n", haystack );
124         return ( haystack );
125       }
126
127     }
128
129     haystack += 1;
130   }
131
132   return ( NULL );
133 }