Cleaning up files
[tpg/acess2.git] / Usermode / Libraries / liburi.so_src / main.c
1 /*
2  * Acess2 - URI Parser and opener
3  * By John Hodge (thePowersGang)
4  */
5 #include <acess/sys.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <uri.h>
11
12 // === STRUCTURES ===
13 struct sURIFile
14 {
15          int    Handle;
16          int    Mode;
17         tURIHandler     *Handler;
18          int    CurBlockOffset;
19         char    Buffer[];
20 };
21
22 // === PROTOTYPES ===
23  int    SoMain(void);
24 tURI    *URI_Parse(const char *String);
25 tURIFile        *URI_MakeHandle(int Mode, int Handle, tURIHandler *Handler);
26 tURIFile        *URI_Open(int Mode, tURI *URI);
27 size_t  URI_Read(tURIFile *File, size_t Bytes, void *Buffer);
28 size_t  URI_Write(tURIFile *File, size_t Bytes, void *Buffer);
29 void    URI_Close(tURIFile *File);
30 // --- file:/// handler
31  int    URI_file_Open(char *Host, int Port, char *Path, int Mode);
32 size_t  URI_file_Read(int Handle, size_t Bytes, void *Buffer);
33 size_t  URI_file_Write(int Handle, size_t Bytes, void *Buffer);
34 void    URI_file_Close(int Handle);
35
36 // === CONSTANTS ===
37 // Builtin URI protocol handlers
38 tURIHandler     caBuiltinHandlers[] = {
39         {"file", 0, URI_file_Open, URI_file_Close, URI_file_Read, URI_file_Write}
40 };
41 #define NUM_BUILTIN_HANDLERS    (sizeof(caBuiltinHandlers)/sizeof(caBuiltinHandlers[0]))
42
43 // === CODE ===
44 int SoMain(void)
45 {
46         return 0;
47 }
48
49 tURI *URI_Parse(const char *String)
50 {
51         const char      *tmp = String;
52         tURI    *ret;
53          int    protolen;
54         
55         if(!String)     return NULL;
56         
57         protolen = 0;
58         while( isalpha(*tmp) )  tmp++, protolen++;
59         
60         // true URI
61         if(tmp[0] == ':' && tmp[1] == '/' && tmp[2] == '/')
62         {
63                  int    hostlen, portlen, pathlen;
64                 tmp += 3;       // Eat '://'
65                 ret = malloc(sizeof(tURI) + strlen(String) - 2);
66                 
67                 ret->Proto = (char*)ret + sizeof(tURI);
68                 memcpy(ret->Proto, String, protolen);
69                 ret->Proto[protolen] = '\0';
70                 
71                 ret->Host = ret->Proto + protolen + 1;
72                 hostlen = 0;
73                 
74                 // IPv6
75                 if( *tmp == '[' )
76                 {
77                         tmp ++;
78                         while( *tmp != ']' ) {
79                                 ret->Host[hostlen] = *tmp;
80                                 tmp ++;
81                                 hostlen ++;
82                         }
83                         tmp ++;
84                         ret->Host[hostlen] = '\0';
85                 }
86                 // IPv4/DNS
87                 else
88                 {
89                         while( *tmp != '/' && *tmp != ':' )
90                         {
91                                 ret->Host[hostlen] = *tmp;
92                                 tmp ++;
93                                 hostlen ++;
94                         }
95                         ret->Host[hostlen] = '\0';
96                 }
97                 
98                 // Port
99                 if( *tmp == ':' ) {
100                         ret->PortStr = ret->Host + hostlen + 1;
101                         tmp ++;
102                         portlen = 0;
103                         while(isalpha(*tmp) || isdigit(*tmp))
104                         {
105                                 ret->PortStr[portlen] = *tmp;
106                                 portlen ++;
107                                 tmp ++;
108                         }
109                         ret->PortStr[portlen] = '\0';
110                         
111                         ret->PortNum = atoi(ret->PortStr);
112                         if(!ret->PortNum && !(ret->PortStr[0] == '0' && portlen == 1) )
113                         {
114                                 // error!
115                                 ret->Path = NULL;
116                                 return ret;
117                         }
118                 }
119                 else {
120                         ret->PortStr = NULL;
121                         ret->PortNum = -1;
122                 }
123                 
124                 if(*tmp == '\0')
125                 {
126                         ret->Path = NULL;
127                         return ret;
128                 }
129                 
130                 // TODO: What to do on a parse error
131                 if(*tmp != '/') {
132                         ret->Path = NULL;
133                         return ret;
134                 }
135                 
136                 if(ret->PortStr)
137                         ret->Path = ret->PortStr + portlen + 1;
138                 else
139                         ret->Path = ret->Host + hostlen + 1;
140                 
141                 tmp ++;
142                 pathlen = 0;
143                 while(*tmp)
144                 {
145                         ret->Path[pathlen] = *tmp;
146                         tmp ++;
147                         pathlen ++;
148                 }
149                 
150                 return ret;
151         }
152         else
153         {
154 //              char    *cwd;
155 //               int    retlen;
156                 
157                 // Path
158                 // TODO: What to do?
159                 // Probably return file:///<path>
160                 // but should I get the CWD and use append that?
161                 ret = malloc( sizeof(tURI) + strlen(String) + 1 );
162                 ret->Path = (char*)ret + sizeof(tURI);
163                 strcpy(ret->Path, String);
164                 ret->Proto = "file";
165                 ret->Host = NULL;
166                 ret->PortNum = 0;
167                 ret->PortStr = NULL;
168                 return ret;
169         }
170 }
171
172 tURIFile *URI_MakeHandle(int Mode, int Handle, tURIHandler *Handler)
173 {
174         tURIFile        *ret;
175         
176         ret = malloc(sizeof(tURIFile)+Handler->BlockSize);
177         if(!ret)        return NULL;
178         
179         ret->Handle = Handle;
180         ret->Mode = Mode;
181         ret->Handler = Handler;
182         ret->CurBlockOffset = 0;
183         
184         return ret;
185 }
186
187 tURIFile *URI_Open(int Mode, tURI *URI)
188 {
189         tURIHandler     *handler;
190         tURIFile        *ret;
191          int    handle;
192          int    i;
193         
194         if(!URI)
195                 return NULL;
196         
197         for( i = 0; i < NUM_BUILTIN_HANDLERS; i ++ )
198         {
199                 if(strcmp(URI->Proto, caBuiltinHandlers[i].Name) == 0)
200                         break;
201         }
202         
203         if( i == NUM_BUILTIN_HANDLERS )
204         {
205                 // TODO: Dynamics
206                 printf("URI_Open: Warning - Unknown URI handler\n");
207                 return NULL;
208         }
209         else
210                 handler = &caBuiltinHandlers[i];
211         
212         printf("URI_Open: handler->Open = %p\n", handler->Open);
213         
214         handle = handler->Open(URI->Host, URI->PortNum, URI->Path, Mode);
215         printf("URI_Open: handle = %i\n", handle);
216         if(handle == -1)        return NULL;
217         
218         printf("URI_MakeHandle(Mode=%i, handle=%i, handler=%p)\n",
219                 Mode, handle, handler);
220         ret = URI_MakeHandle(Mode, handle, handler);
221         if(!ret) {
222                 handler->Close( handle );
223                 return NULL;
224         }
225         return ret;
226 }
227
228 /**
229  * \brief Read from a URI file
230  */
231 size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer)
232 {
233         size_t  rem = Bytes;
234         void    *buf = Buffer;
235         size_t  tmp;
236         
237         printf("URI_Read(File=%p, Bytes=%u, Buffer=%p)\n",
238                 File, Bytes, Buffer);
239         
240         if(!File || !Buffer)    return -1;
241         if(Bytes == 0)  return 0;
242         
243         if( !(File->Mode & URI_MODE_READ) )     return -1;
244         
245         // Read from cache if avaliable
246         if(File->Handler->BlockSize && File->CurBlockOffset)
247         {
248                  int    avail;
249                 
250                 avail = File->Handler->BlockSize - File->CurBlockOffset;
251                 
252                 if(avail >= Bytes) {
253                         memcpy(Buffer, File->Buffer, Bytes);
254                         File->CurBlockOffset += Bytes;
255                         File->CurBlockOffset %= File->Handler->BlockSize;
256                         return Bytes;
257                 }
258                 
259                 rem -= avail;
260                 memcpy(Buffer, File->Buffer, avail);
261                 File->CurBlockOffset = 0;
262                 buf += avail;
263         }
264         
265         
266         if( File->Handler->BlockSize )
267         {
268                 // Read whole blocks
269                 while( rem >= File->Handler->BlockSize )
270                 {
271                         tmp = File->Handler->Read( File->Handle, File->Handler->BlockSize, buf );
272                         if(tmp < File->Handler->BlockSize)
273                                 return Bytes - rem - tmp;
274                         buf += File->Handler->BlockSize;
275                 }
276                 
277                 // Read the trailing part
278                 if(rem)
279                 {
280                         File->Handler->Read( File->Handle, File->Handler->BlockSize, File->Buffer );
281                         memcpy( buf, File->Buffer, rem );
282                         File->CurBlockOffset += rem;
283                 }
284                 return Bytes;
285         }
286         
287         return File->Handler->Read( File->Handle, Bytes, Buffer );
288 }
289
290 /**
291  * \brief Write to a URI file
292  */
293
294
295 // ====
296 // Builtin Handlers
297 // ====
298 int URI_file_Open(char *Host, int Port, char *Path, int Mode)
299 {
300          int    smode = 0;
301         if(Mode & URI_MODE_READ)        smode |= OPENFLAG_READ;
302         if(Mode & URI_MODE_WRITE)       smode |= OPENFLAG_WRITE;
303         
304         printf("URI_file_Open: open('%s', 0x%x)\n", Path, smode);
305         {
306                  int    ret;
307                 ret = open(Path, smode);
308                 return ret;
309         }
310 }
311 size_t URI_file_Read(int Handle, size_t Bytes, void *Buffer)
312 {
313         printf("URI_file_Read: (Handle=%i, Bytes=%i, Buffer=%p)\n",
314                 Handle, Bytes, Buffer);
315         return read(Handle, Bytes, Buffer);
316 }
317 size_t URI_file_Write(int Handle, size_t Bytes, void *Buffer)
318 {
319         return write(Handle, Bytes, Buffer);
320 }
321 void URI_file_Close(int Handle)
322 {
323         close(Handle);
324 }

UCC git Repository :: git.ucc.asn.au