Added basic LED stuff to libpnd pnd_device
[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     } else if ( pos > PND_PXML_WINDOW_FRACTIONAL ) {
75       pos -= PND_PXML_WINDOW_FRACTIONAL;
76       readable = PND_PXML_WINDOW_SIZE;
77     } else {
78       readable = PND_PXML_WINDOW_SIZE - pos;
79       memset ( b + pos, '\0', PND_PXML_WINDOW_SIZE - pos );
80       pos = 0;
81     }
82
83   } // while
84
85   // exeunt, with alarums
86   free ( b );
87   return ( 0 );
88 }
89
90 unsigned char pnd_pnd_accrue_pxml ( FILE *f, char *target, unsigned int maxlen ) {
91   char inbuf [ 1024 ]; // TBD: love all these assumptions? noob!
92   char *insert = target;
93   unsigned int l;
94
95   while ( fgets ( inbuf, 1023, f ) ) {
96
97     // copy inbuf onto end of target
98 #if 1
99     strncpy ( insert, inbuf, maxlen );
100     // reduce counter for max size so we can avoid buffer overruns
101     l = strlen ( inbuf );
102     maxlen -= l; // reduce
103     insert += l; // increment
104 #else
105     strncat ( target, inbuf, maxlen );
106 #endif
107
108     if ( strcasestr ( inbuf, PXML_TAGFOOT ) ) {
109       return ( 1 );
110     }
111
112   } // while
113
114   return ( 0 );
115 }
116
117 char *pnd_match_binbuf ( char *haystack, unsigned int maxlen, char *needle ) {
118   char *end = haystack + maxlen - strlen ( needle );
119   unsigned int needlelen = strlen ( needle );
120
121   while ( haystack < end ) {
122
123     if ( isprint(*haystack) ) {
124
125       if ( strncasecmp ( haystack, needle, needlelen ) == 0 ) {
126         //printf ( "haystack %s\n", haystack );
127         return ( haystack );
128       }
129
130     }
131
132     haystack += 1;
133   }
134
135   return ( NULL );
136 }
137
138 static unsigned char pnd_pnd_mountie ( char *pndrun, char *fullpath, char *unique_id, unsigned char do_mount ) {
139   char *argv [ 20 ];
140   int f;
141
142   if ( ! pndrun ) {
143     return ( 0 );
144   }
145
146   if ( ! fullpath ) {
147     return ( 0 );
148   }
149
150   if ( ! unique_id ) {
151     return ( 0 );
152   }
153
154 #if 0
155   printf ( "  runscript: %s\n", pndrun );
156   printf ( "  path: %s\n", fullpath );
157   printf ( "  id: %s\n", unique_id );
158 #endif
159
160   memset ( argv, '\0', sizeof(char*) * 20 );
161
162   // normal stuff
163   f = 0;
164   argv [ f++ ] = pndrun;
165   argv [ f++ ] = "-p";
166   argv [ f++ ] = fullpath;
167   argv [ f++ ] = "-b";
168   argv [ f++ ] = unique_id;
169
170   // mount-only
171   if ( do_mount ) {
172     argv [ f++ ] = "-m";
173   } else {
174     argv [ f++ ] = "-u";
175   }
176
177   // finish
178   argv [ f++ ] = NULL; // for execv
179
180   // debug
181 #if 0
182   int i;
183   for ( i = 0; i < f; i++ ) {
184     printf ( "exec's argv %u [ %s ]\n", i, argv [ i ] );
185   }
186 #endif
187
188   // invoke it!
189
190   if ( ( f = fork() ) < 0 ) {
191     // error forking
192   } else if ( f > 0 ) {
193     // parent
194   } else {
195     // child, do it
196     execv ( pndrun, argv );
197   } 
198
199   // wait until mountscript actually completes
200   int status = 0;
201   wait ( &status );
202
203   return ( 1 );
204 }
205
206 unsigned char pnd_pnd_mount ( char *pndrun, char *fullpath, char *unique_id ) {
207   return ( pnd_pnd_mountie ( pndrun, fullpath, unique_id, 1 ) );
208 }
209
210 unsigned char pnd_pnd_unmount ( char *pndrun, char *fullpath, char *unique_id ) {
211   return ( pnd_pnd_mountie ( pndrun, fullpath, unique_id, 0 ) );
212 }