get rid of EOL spaces
[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 #include <unistd.h> /* for fork/exec */
6 #include <sys/types.h> /* for wait */
7 #include <sys/wait.h> /* for wait */
8
9 #define __USE_GNU
10 #include <string.h> /* for making strcasestr happy */
11
12 #include "pnd_container.h"
13 #include "pnd_pxml.h"
14 #include "pnd_apps.h"
15 #include "pnd_pndfiles.h"
16
17 unsigned char pnd_pnd_seek_pxml ( FILE *f ) {
18   char *b;                // buffer
19   char *match;            // match within buffer
20   unsigned int len;       // length of file (not suporting 'big files' 2GB..)
21   unsigned int pos;       // current tape head
22   unsigned int readable;  // amount to read (for small files/chunks)
23
24   b = malloc ( PND_PXML_WINDOW_SIZE + 1 );
25
26   if ( ! b ) {
27     return ( 0 );
28   }
29
30   memset ( b, '\0', PND_PXML_WINDOW_SIZE + 1 );
31
32   // determine length of file
33   fseek ( f, 0, SEEK_END );
34   len = ftell ( f );
35   fseek ( f, 0, SEEK_SET );
36
37   /* ready to scan through the file, backwards
38    */
39
40   // easy case or no?
41   if ( len <= PND_PXML_WINDOW_SIZE ) {
42     pos = 0;
43     readable = len;
44   } else {
45     pos = len - PND_PXML_WINDOW_SIZE;
46     readable = PND_PXML_WINDOW_SIZE;
47   }
48
49   while ( 1 ) {
50
51     //printf ( "find pxml; pos %u readable %u\n", pos, readable );
52
53     // seek into this blocks position
54     fseek ( f, pos, SEEK_SET );
55
56     // read
57     fread ( b, 1, readable, f );
58
59     // find the head tag here? now, there are serious heavy duty algorithyms for locating
60     // strings within an arbitrary buffer. Thats needs to be done. This is the worst
61     // performing brute force strategy here.
62     if ( ( match = pnd_match_binbuf ( b, readable, PXML_TAGHEAD ) ) ) {
63       fseek ( f, pos + ( match - b ), SEEK_SET );
64       //printf ( "  match found at %u\n", pos + ( match - b ) );
65       free ( b );
66       return ( 1 );
67     }
68
69     // no match, so we need to back up another chunk; if we can't
70     // back up that much, we're on our last check. if we can't back
71     // up at all, we've already been here and time to fail
72     if ( pos == 0 ) {
73       break; // done, FAIL
74
75     } else if ( pos > PND_PXML_WINDOW_FRACTIONAL ) { // lots of space to back-seek
76       pos -= PND_PXML_WINDOW_FRACTIONAL;
77       readable = PND_PXML_WINDOW_SIZE;
78
79       // at some point when back-seeking, we just give up; we could seek through
80       // whole file (and if someone has gone and broken a pnd-file, the behaviour is
81       // 'undefined' .. but lets be kind in case that guy then distributes the broken
82       // file around. So we backseek to a point, but stop after xKB backwards?
83       if ( len - pos > (500*1024) ) {
84         break;
85       }
86
87     } else { // can only backseek less than the window-size
88       readable = PND_PXML_WINDOW_SIZE - pos;
89       memset ( b + pos, '\0', PND_PXML_WINDOW_SIZE - pos );
90       pos = 0;
91     }
92
93   } // while
94
95   // exeunt, with alarums
96   free ( b );
97   return ( 0 );
98 }
99
100 unsigned char pnd_pnd_accrue_pxml ( FILE *f, char *target, unsigned int maxlen ) {
101   char inbuf [ 1024 ]; // TBD: love all these assumptions? noob!
102   char *insert = target;
103   unsigned int l;
104
105   while ( fgets ( inbuf, 1023, f ) ) {
106
107     // copy inbuf onto end of target
108 #if 1
109     strncpy ( insert, inbuf, maxlen );
110     // reduce counter for max size so we can avoid buffer overruns
111     l = strlen ( inbuf );
112     maxlen -= l; // reduce
113     insert += l; // increment
114 #else
115     strncat ( target, inbuf, maxlen );
116 #endif
117
118     if ( strcasestr ( inbuf, PXML_TAGFOOT ) ) {
119       return ( 1 );
120     }
121
122   } // while
123
124   return ( 0 );
125 }
126
127 char *pnd_match_binbuf ( char *haystack, unsigned int maxlen, char *needle ) {
128   char *end = haystack + maxlen - strlen ( needle );
129   unsigned int needlelen = strlen ( needle );
130
131   while ( haystack < end ) {
132
133     if ( isprint(*haystack) ) {
134
135       if ( strncasecmp ( haystack, needle, needlelen ) == 0 ) {
136         //printf ( "haystack %s\n", haystack );
137         return ( haystack );
138       }
139
140     }
141
142     haystack += 1;
143   }
144
145   return ( NULL );
146 }
147
148 static unsigned char pnd_pnd_mountie ( char *pndrun, char *fullpath, char *unique_id, unsigned char do_mount ) {
149   char *argv [ 20 ];
150   int f;
151
152   if ( ! pndrun ) {
153     return ( 0 );
154   }
155
156   if ( ! fullpath ) {
157     return ( 0 );
158   }
159
160   if ( ! unique_id ) {
161     return ( 0 );
162   }
163
164 #if 0
165   printf ( "  runscript: %s\n", pndrun );
166   printf ( "  path: %s\n", fullpath );
167   printf ( "  id: %s\n", unique_id );
168 #endif
169
170   memset ( argv, '\0', sizeof(char*) * 20 );
171
172   // normal stuff
173   f = 0;
174   argv [ f++ ] = pndrun;
175   argv [ f++ ] = "-p";
176   argv [ f++ ] = fullpath;
177   argv [ f++ ] = "-b";
178   argv [ f++ ] = unique_id;
179
180   // mount-only
181   if ( do_mount ) {
182     argv [ f++ ] = "-m";
183   } else {
184     argv [ f++ ] = "-u";
185   }
186
187   // finish
188   argv [ f++ ] = NULL; // for execv
189
190   // debug
191 #if 0
192   int i;
193   for ( i = 0; i < f; i++ ) {
194     printf ( "exec's argv %u [ %s ]\n", i, argv [ i ] );
195   }
196 #endif
197
198   // invoke it!
199
200   if ( ( f = fork() ) < 0 ) {
201     // error forking
202   } else if ( f > 0 ) {
203     // parent
204   } else {
205     // child, do it
206     execv ( pndrun, argv );
207   }
208
209   // wait until mountscript actually completes
210   int status = 0;
211   waitpid ( f, &status, 0 /* options */ );
212
213   return ( 1 );
214 }
215
216 unsigned char pnd_pnd_mount ( char *pndrun, char *fullpath, char *unique_id ) {
217   return ( pnd_pnd_mountie ( pndrun, fullpath, unique_id, 1 ) );
218 }
219
220 unsigned char pnd_pnd_unmount ( char *pndrun, char *fullpath, char *unique_id ) {
221   return ( pnd_pnd_mountie ( pndrun, fullpath, unique_id, 0 ) );
222 }