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