17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <auth.h>
47dd7cddfSDavid du Colombier #include <fcall.h>
57dd7cddfSDavid du Colombier
67dd7cddfSDavid du Colombier /*
77dd7cddfSDavid du Colombier * caveat:
87dd7cddfSDavid du Colombier * this stuff is only meant to work for ascii databases
97dd7cddfSDavid du Colombier */
107dd7cddfSDavid du Colombier
117dd7cddfSDavid du Colombier typedef struct Fid Fid;
127dd7cddfSDavid du Colombier typedef struct Fs Fs;
137dd7cddfSDavid du Colombier typedef struct Quick Quick;
147dd7cddfSDavid du Colombier typedef struct Match Match;
157dd7cddfSDavid du Colombier typedef struct Search Search;
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier enum
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier OPERM = 0x3, /* mask of all permission types in open mode */
207dd7cddfSDavid du Colombier Nfidhash = 32,
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier /*
237dd7cddfSDavid du Colombier * qids
247dd7cddfSDavid du Colombier */
25*9a747e4fSDavid du Colombier Qroot = 1,
267dd7cddfSDavid du Colombier Qsearch = 2,
277dd7cddfSDavid du Colombier Qstats = 3,
287dd7cddfSDavid du Colombier };
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier /*
317dd7cddfSDavid du Colombier * boyer-moore quick string matching
327dd7cddfSDavid du Colombier */
337dd7cddfSDavid du Colombier struct Quick
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier char *pat;
367dd7cddfSDavid du Colombier char *up; /* match string for upper case of pat */
377dd7cddfSDavid du Colombier int len; /* of pat (and up) -1; used for fast search */
387dd7cddfSDavid du Colombier uchar jump[256]; /* jump index table */
397dd7cddfSDavid du Colombier int miss; /* amount to jump if we falsely match the last char */
407dd7cddfSDavid du Colombier };
417dd7cddfSDavid du Colombier extern void quickmk(Quick*, char*, int);
427dd7cddfSDavid du Colombier extern void quickfree(Quick*);
437dd7cddfSDavid du Colombier extern char* quicksearch(Quick*, char*, char*);
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier /*
467dd7cddfSDavid du Colombier * exact matching of a search string
477dd7cddfSDavid du Colombier */
487dd7cddfSDavid du Colombier struct Match
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier Match *next;
517dd7cddfSDavid du Colombier char *pat; /* null-terminated search string */
527dd7cddfSDavid du Colombier char *up; /* upper case of pat */
537dd7cddfSDavid du Colombier int len; /* length of both pat and up */
547dd7cddfSDavid du Colombier int (*op)(Match*, char*, char*); /* method for this partiticular search */
557dd7cddfSDavid du Colombier };
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier struct Search
587dd7cddfSDavid du Colombier {
597dd7cddfSDavid du Colombier Quick quick; /* quick match */
607dd7cddfSDavid du Colombier Match *match; /* exact matches */
617dd7cddfSDavid du Colombier int skip; /* number of matches to skip */
627dd7cddfSDavid du Colombier };
637dd7cddfSDavid du Colombier
647dd7cddfSDavid du Colombier extern char* searchsearch(Search*, char*, char*, int*);
657dd7cddfSDavid du Colombier extern Search* searchparse(char*, char*);
667dd7cddfSDavid du Colombier extern void searchfree(Search*);
677dd7cddfSDavid du Colombier
687dd7cddfSDavid du Colombier struct Fid
697dd7cddfSDavid du Colombier {
707dd7cddfSDavid du Colombier Lock;
717dd7cddfSDavid du Colombier Fid *next;
727dd7cddfSDavid du Colombier Fid **last;
737dd7cddfSDavid du Colombier uint fid;
747dd7cddfSDavid du Colombier int ref; /* number of fcalls using the fid */
757dd7cddfSDavid du Colombier int attached; /* fid has beed attached or cloned and not clunked */
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier int open;
787dd7cddfSDavid du Colombier Qid qid;
797dd7cddfSDavid du Colombier Search *search; /* search patterns */
807dd7cddfSDavid du Colombier char *where; /* current location in the database */
817dd7cddfSDavid du Colombier int n; /* number of bytes left in found item */
827dd7cddfSDavid du Colombier };
837dd7cddfSDavid du Colombier
84*9a747e4fSDavid du Colombier int dostat(int, uchar*, int);
857dd7cddfSDavid du Colombier void* emalloc(uint);
867dd7cddfSDavid du Colombier void fatal(char*, ...);
877dd7cddfSDavid du Colombier Match* mkmatch(Match*, int(*)(Match*, char*, char*), char*);
887dd7cddfSDavid du Colombier Match* mkstrmatch(Match*, char*);
897dd7cddfSDavid du Colombier char* nextsearch(char*, char*, char**, char**);
907dd7cddfSDavid du Colombier int strlook(Match*, char*, char*);
917dd7cddfSDavid du Colombier char* strndup(char*, int);
927dd7cddfSDavid du Colombier int tolower(int);
937dd7cddfSDavid du Colombier int toupper(int);
947dd7cddfSDavid du Colombier char* urlunesc(char*, char*);
957dd7cddfSDavid du Colombier void usage(void);
967dd7cddfSDavid du Colombier
977dd7cddfSDavid du Colombier struct Fs
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier Lock; /* for fids */
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier Fid *hash[Nfidhash];
102*9a747e4fSDavid du Colombier uchar statbuf[1024]; /* plenty big enough */
1037dd7cddfSDavid du Colombier };
1047dd7cddfSDavid du Colombier extern void fsrun(Fs*, int);
1057dd7cddfSDavid du Colombier extern Fid* getfid(Fs*, uint);
1067dd7cddfSDavid du Colombier extern Fid* mkfid(Fs*, uint);
1077dd7cddfSDavid du Colombier extern void putfid(Fs*, Fid*);
108*9a747e4fSDavid du Colombier extern char* fsversion(Fs*, Fcall*);
109*9a747e4fSDavid du Colombier extern char* fsauth(Fs*, Fcall*);
1107dd7cddfSDavid du Colombier extern char* fsattach(Fs*, Fcall*);
1117dd7cddfSDavid du Colombier extern char* fswalk(Fs*, Fcall*);
1127dd7cddfSDavid du Colombier extern char* fsopen(Fs*, Fcall*);
1137dd7cddfSDavid du Colombier extern char* fscreate(Fs*, Fcall*);
1147dd7cddfSDavid du Colombier extern char* fsread(Fs*, Fcall*);
1157dd7cddfSDavid du Colombier extern char* fswrite(Fs*, Fcall*);
1167dd7cddfSDavid du Colombier extern char* fsclunk(Fs*, Fcall*);
1177dd7cddfSDavid du Colombier extern char* fsremove(Fs*, Fcall*);
1187dd7cddfSDavid du Colombier extern char* fsstat(Fs*, Fcall*);
1197dd7cddfSDavid du Colombier extern char* fswstat(Fs*, Fcall*);
1207dd7cddfSDavid du Colombier
1217dd7cddfSDavid du Colombier char *(*fcalls[])(Fs*, Fcall*) =
1227dd7cddfSDavid du Colombier {
123*9a747e4fSDavid du Colombier [Tversion] fsversion,
1247dd7cddfSDavid du Colombier [Tattach] fsattach,
125*9a747e4fSDavid du Colombier [Tauth] fsauth,
1267dd7cddfSDavid du Colombier [Twalk] fswalk,
1277dd7cddfSDavid du Colombier [Topen] fsopen,
1287dd7cddfSDavid du Colombier [Tcreate] fscreate,
1297dd7cddfSDavid du Colombier [Tread] fsread,
1307dd7cddfSDavid du Colombier [Twrite] fswrite,
1317dd7cddfSDavid du Colombier [Tclunk] fsclunk,
1327dd7cddfSDavid du Colombier [Tremove] fsremove,
1337dd7cddfSDavid du Colombier [Tstat] fsstat,
1347dd7cddfSDavid du Colombier [Twstat] fswstat
1357dd7cddfSDavid du Colombier };
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier char Eperm[] = "permission denied";
1387dd7cddfSDavid du Colombier char Enotdir[] = "not a directory";
1397dd7cddfSDavid du Colombier char Enotexist[] = "file does not exist";
1407dd7cddfSDavid du Colombier char Eisopen[] = "file already open for I/O";
1417dd7cddfSDavid du Colombier char Einuse[] = "fid is already in use";
1427dd7cddfSDavid du Colombier char Enofid[] = "no such fid";
1437dd7cddfSDavid du Colombier char Enotopen[] = "file is not open";
1447dd7cddfSDavid du Colombier char Ebadsearch[] = "bad search string";
1457dd7cddfSDavid du Colombier
1467dd7cddfSDavid du Colombier Fs fs;
1477dd7cddfSDavid du Colombier char *database;
1487dd7cddfSDavid du Colombier char *edatabase;
149*9a747e4fSDavid du Colombier int messagesize = 8192+IOHDRSZ;
1507dd7cddfSDavid du Colombier void
main(int argc,char ** argv)1517dd7cddfSDavid du Colombier main(int argc, char **argv)
1527dd7cddfSDavid du Colombier {
153*9a747e4fSDavid du Colombier Dir *d;
1547dd7cddfSDavid du Colombier char buf[12], *mnt, *srv;
1557dd7cddfSDavid du Colombier int fd, p[2], n;
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier mnt = "/tmp";
1587dd7cddfSDavid du Colombier srv = nil;
1597dd7cddfSDavid du Colombier ARGBEGIN{
1607dd7cddfSDavid du Colombier case 's':
1617dd7cddfSDavid du Colombier srv = ARGF();
1627dd7cddfSDavid du Colombier mnt = nil;
1637dd7cddfSDavid du Colombier break;
1647dd7cddfSDavid du Colombier case 'm':
1657dd7cddfSDavid du Colombier mnt = ARGF();
1667dd7cddfSDavid du Colombier break;
1677dd7cddfSDavid du Colombier }ARGEND
1687dd7cddfSDavid du Colombier
169*9a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
170*9a747e4fSDavid du Colombier
1717dd7cddfSDavid du Colombier if(argc != 1)
1727dd7cddfSDavid du Colombier usage();
173*9a747e4fSDavid du Colombier d = nil;
1747dd7cddfSDavid du Colombier fd = open(argv[0], OREAD);
175*9a747e4fSDavid du Colombier if(fd < 0 || (d=dirfstat(fd)) == nil)
1767dd7cddfSDavid du Colombier fatal("can't open %s: %r", argv[0]);
177*9a747e4fSDavid du Colombier n = d->length;
178*9a747e4fSDavid du Colombier free(d);
1797dd7cddfSDavid du Colombier if(n == 0)
1807dd7cddfSDavid du Colombier fatal("zero length database %s", argv[0]);
1817dd7cddfSDavid du Colombier database = emalloc(n);
1827dd7cddfSDavid du Colombier if(read(fd, database, n) != n)
1837dd7cddfSDavid du Colombier fatal("can't read %s: %r", argv[0]);
1847dd7cddfSDavid du Colombier close(fd);
1857dd7cddfSDavid du Colombier edatabase = database + n;
1867dd7cddfSDavid du Colombier
1877dd7cddfSDavid du Colombier if(pipe(p) < 0)
1887dd7cddfSDavid du Colombier fatal("pipe failed");
1897dd7cddfSDavid du Colombier
1907dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOTEG|RFNAMEG)){
1917dd7cddfSDavid du Colombier case 0:
1927dd7cddfSDavid du Colombier fsrun(&fs, p[0]);
1937dd7cddfSDavid du Colombier exits(nil);
1947dd7cddfSDavid du Colombier case -1:
1957dd7cddfSDavid du Colombier fatal("fork failed");
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier if(mnt == nil){
1997dd7cddfSDavid du Colombier if(srv == nil)
2007dd7cddfSDavid du Colombier usage();
2017dd7cddfSDavid du Colombier fd = create(srv, OWRITE, 0666);
2027dd7cddfSDavid du Colombier if(fd < 0){
2037dd7cddfSDavid du Colombier remove(srv);
2047dd7cddfSDavid du Colombier fd = create(srv, OWRITE, 0666);
2057dd7cddfSDavid du Colombier if(fd < 0){
2067dd7cddfSDavid du Colombier close(p[1]);
2077dd7cddfSDavid du Colombier fatal("create of %s failed", srv);
2087dd7cddfSDavid du Colombier }
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier sprint(buf, "%d", p[1]);
2117dd7cddfSDavid du Colombier if(write(fd, buf, strlen(buf)) < 0){
2127dd7cddfSDavid du Colombier close(p[1]);
2137dd7cddfSDavid du Colombier fatal("writing %s", srv);
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier close(p[1]);
2167dd7cddfSDavid du Colombier exits(nil);
2177dd7cddfSDavid du Colombier }
2187dd7cddfSDavid du Colombier
219*9a747e4fSDavid du Colombier if(mount(p[1], -1, mnt, MREPL, "") < 0){
2207dd7cddfSDavid du Colombier close(p[1]);
2217dd7cddfSDavid du Colombier fatal("mount failed");
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier close(p[1]);
2247dd7cddfSDavid du Colombier exits(nil);
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier
2277dd7cddfSDavid du Colombier /*
2287dd7cddfSDavid du Colombier * execute the search
2297dd7cddfSDavid du Colombier * do a quick match,
2307dd7cddfSDavid du Colombier * isolate the line in which the occured,
2317dd7cddfSDavid du Colombier * and try all of the exact matches
2327dd7cddfSDavid du Colombier */
2337dd7cddfSDavid du Colombier char*
searchsearch(Search * search,char * where,char * end,int * np)2347dd7cddfSDavid du Colombier searchsearch(Search *search, char *where, char *end, int *np)
2357dd7cddfSDavid du Colombier {
2367dd7cddfSDavid du Colombier Match *m;
2377dd7cddfSDavid du Colombier char *s, *e;
2387dd7cddfSDavid du Colombier
2397dd7cddfSDavid du Colombier *np = 0;
2407dd7cddfSDavid du Colombier if(search == nil || where == nil)
2417dd7cddfSDavid du Colombier return nil;
2427dd7cddfSDavid du Colombier for(;;){
2437dd7cddfSDavid du Colombier s = quicksearch(&search->quick, where, end);
2447dd7cddfSDavid du Colombier if(s == nil)
2457dd7cddfSDavid du Colombier return nil;
2467dd7cddfSDavid du Colombier e = memchr(s, '\n', end - s);
2477dd7cddfSDavid du Colombier if(e == nil)
2487dd7cddfSDavid du Colombier e = end;
2497dd7cddfSDavid du Colombier else
2507dd7cddfSDavid du Colombier e++;
2517dd7cddfSDavid du Colombier while(s > where && s[-1] != '\n')
2527dd7cddfSDavid du Colombier s--;
2537dd7cddfSDavid du Colombier for(m = search->match; m != nil; m = m->next){
2547dd7cddfSDavid du Colombier if((*m->op)(m, s, e) == 0)
2557dd7cddfSDavid du Colombier break;
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier
2587dd7cddfSDavid du Colombier if(m == nil){
2597dd7cddfSDavid du Colombier if(search->skip > 0)
2607dd7cddfSDavid du Colombier search->skip--;
2617dd7cddfSDavid du Colombier else{
2627dd7cddfSDavid du Colombier *np = e - s;
2637dd7cddfSDavid du Colombier return s;
2647dd7cddfSDavid du Colombier }
2657dd7cddfSDavid du Colombier }
2667dd7cddfSDavid du Colombier
2677dd7cddfSDavid du Colombier where = e;
2687dd7cddfSDavid du Colombier }
2697dd7cddfSDavid du Colombier }
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier /*
2727dd7cddfSDavid du Colombier * parse a search string of the form
2737dd7cddfSDavid du Colombier * tag=val&tag1=val1...
2747dd7cddfSDavid du Colombier */
2757dd7cddfSDavid du Colombier Search*
searchparse(char * search,char * esearch)2767dd7cddfSDavid du Colombier searchparse(char *search, char *esearch)
2777dd7cddfSDavid du Colombier {
2787dd7cddfSDavid du Colombier Search *s;
2797dd7cddfSDavid du Colombier Match *m, *next, **last;
2807dd7cddfSDavid du Colombier char *tag, *val, *p;
2817dd7cddfSDavid du Colombier int ok;
2827dd7cddfSDavid du Colombier
2837dd7cddfSDavid du Colombier s = emalloc(sizeof *s);
2847dd7cddfSDavid du Colombier s->match = nil;
2857dd7cddfSDavid du Colombier
2867dd7cddfSDavid du Colombier /*
2877dd7cddfSDavid du Colombier * acording to the http spec,
2887dd7cddfSDavid du Colombier * repeated search queries are ingored.
2897dd7cddfSDavid du Colombier * the last search given is performed on the original object
2907dd7cddfSDavid du Colombier */
2917dd7cddfSDavid du Colombier while((p = memchr(s, '?', esearch - search)) != nil){
2927dd7cddfSDavid du Colombier search = p + 1;
2937dd7cddfSDavid du Colombier }
2947dd7cddfSDavid du Colombier while(search < esearch){
2957dd7cddfSDavid du Colombier search = nextsearch(search, esearch, &tag, &val);
2967dd7cddfSDavid du Colombier if(tag == nil)
2977dd7cddfSDavid du Colombier continue;
2987dd7cddfSDavid du Colombier
2997dd7cddfSDavid du Colombier ok = 0;
3007dd7cddfSDavid du Colombier if(strcmp(tag, "skip") == 0){
3017dd7cddfSDavid du Colombier s->skip = strtoul(val, &p, 10);
3027dd7cddfSDavid du Colombier if(*p == 0)
3037dd7cddfSDavid du Colombier ok = 1;
3047dd7cddfSDavid du Colombier }else if(strcmp(tag, "search") == 0){
3057dd7cddfSDavid du Colombier s->match = mkstrmatch(s->match, val);
3067dd7cddfSDavid du Colombier ok = 1;
3077dd7cddfSDavid du Colombier }
3087dd7cddfSDavid du Colombier free(tag);
3097dd7cddfSDavid du Colombier free(val);
3107dd7cddfSDavid du Colombier if(!ok){
3117dd7cddfSDavid du Colombier searchfree(s);
3127dd7cddfSDavid du Colombier return nil;
3137dd7cddfSDavid du Colombier }
3147dd7cddfSDavid du Colombier }
3157dd7cddfSDavid du Colombier
3167dd7cddfSDavid du Colombier if(s->match == nil){
3177dd7cddfSDavid du Colombier free(s);
3187dd7cddfSDavid du Colombier return nil;
3197dd7cddfSDavid du Colombier }
3207dd7cddfSDavid du Colombier
3217dd7cddfSDavid du Colombier /*
3227dd7cddfSDavid du Colombier * order the matches by probability of occurance
3237dd7cddfSDavid du Colombier * first cut is just by length
3247dd7cddfSDavid du Colombier */
3257dd7cddfSDavid du Colombier for(ok = 0; !ok; ){
3267dd7cddfSDavid du Colombier ok = 1;
3277dd7cddfSDavid du Colombier last = &s->match;
3287dd7cddfSDavid du Colombier for(m = *last; m && m->next; m = *last){
3297dd7cddfSDavid du Colombier if(m->next->len > m->len){
3307dd7cddfSDavid du Colombier next = m->next;
3317dd7cddfSDavid du Colombier m->next = next->next;
3327dd7cddfSDavid du Colombier next->next = m;
3337dd7cddfSDavid du Colombier *last = next;
3347dd7cddfSDavid du Colombier ok = 0;
3357dd7cddfSDavid du Colombier }
3367dd7cddfSDavid du Colombier last = &m->next;
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier /*
3417dd7cddfSDavid du Colombier * convert the best search into a fast lookup
3427dd7cddfSDavid du Colombier */
3437dd7cddfSDavid du Colombier m = s->match;
3447dd7cddfSDavid du Colombier s->match = m->next;
3457dd7cddfSDavid du Colombier quickmk(&s->quick, m->pat, 1);
3467dd7cddfSDavid du Colombier free(m->pat);
3477dd7cddfSDavid du Colombier free(m->up);
3487dd7cddfSDavid du Colombier free(m);
3497dd7cddfSDavid du Colombier return s;
3507dd7cddfSDavid du Colombier }
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier void
searchfree(Search * s)3537dd7cddfSDavid du Colombier searchfree(Search *s)
3547dd7cddfSDavid du Colombier {
3557dd7cddfSDavid du Colombier Match *m, *next;
3567dd7cddfSDavid du Colombier
3577dd7cddfSDavid du Colombier if(s == nil)
3587dd7cddfSDavid du Colombier return;
3597dd7cddfSDavid du Colombier for(m = s->match; m; m = next){
3607dd7cddfSDavid du Colombier next = m->next;
3617dd7cddfSDavid du Colombier free(m->pat);
3627dd7cddfSDavid du Colombier free(m->up);
3637dd7cddfSDavid du Colombier free(m);
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier quickfree(&s->quick);
3667dd7cddfSDavid du Colombier free(s);
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier
3697dd7cddfSDavid du Colombier char*
nextsearch(char * search,char * esearch,char ** tagp,char ** valp)3707dd7cddfSDavid du Colombier nextsearch(char *search, char *esearch, char **tagp, char **valp)
3717dd7cddfSDavid du Colombier {
3727dd7cddfSDavid du Colombier char *tag, *val;
3737dd7cddfSDavid du Colombier
3747dd7cddfSDavid du Colombier *tagp = nil;
3757dd7cddfSDavid du Colombier *valp = nil;
3767dd7cddfSDavid du Colombier for(tag = search; search < esearch && *search != '='; search++)
3777dd7cddfSDavid du Colombier ;
3787dd7cddfSDavid du Colombier if(search == esearch)
3797dd7cddfSDavid du Colombier return search;
3807dd7cddfSDavid du Colombier tag = urlunesc(tag, search);
3817dd7cddfSDavid du Colombier search++;
3827dd7cddfSDavid du Colombier for(val = search; search < esearch && *search != '&'; search++)
3837dd7cddfSDavid du Colombier ;
3847dd7cddfSDavid du Colombier val = urlunesc(val, search);
3857dd7cddfSDavid du Colombier if(search != esearch)
3867dd7cddfSDavid du Colombier search++;
3877dd7cddfSDavid du Colombier *tagp = tag;
3887dd7cddfSDavid du Colombier *valp = val;
3897dd7cddfSDavid du Colombier return search;
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier
3927dd7cddfSDavid du Colombier Match*
mkstrmatch(Match * m,char * pat)3937dd7cddfSDavid du Colombier mkstrmatch(Match *m, char *pat)
3947dd7cddfSDavid du Colombier {
3957dd7cddfSDavid du Colombier char *s;
3967dd7cddfSDavid du Colombier
3977dd7cddfSDavid du Colombier for(s = pat; *s; s++){
3987dd7cddfSDavid du Colombier if(*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'){
3997dd7cddfSDavid du Colombier *s = 0;
4007dd7cddfSDavid du Colombier m = mkmatch(m, strlook, pat);
4017dd7cddfSDavid du Colombier pat = s + 1;
4027dd7cddfSDavid du Colombier }else
4037dd7cddfSDavid du Colombier *s = tolower(*s);
4047dd7cddfSDavid du Colombier }
4057dd7cddfSDavid du Colombier return mkmatch(m, strlook, pat);
4067dd7cddfSDavid du Colombier }
4077dd7cddfSDavid du Colombier
4087dd7cddfSDavid du Colombier Match*
mkmatch(Match * next,int (* op)(Match *,char *,char *),char * pat)4097dd7cddfSDavid du Colombier mkmatch(Match *next, int (*op)(Match*, char*, char*), char *pat)
4107dd7cddfSDavid du Colombier {
4117dd7cddfSDavid du Colombier Match *m;
4127dd7cddfSDavid du Colombier char *p;
4137dd7cddfSDavid du Colombier int n;
4147dd7cddfSDavid du Colombier
4157dd7cddfSDavid du Colombier n = strlen(pat);
4167dd7cddfSDavid du Colombier if(n == 0)
4177dd7cddfSDavid du Colombier return next;
4187dd7cddfSDavid du Colombier m = emalloc(sizeof *m);
4197dd7cddfSDavid du Colombier m->op = op;
4207dd7cddfSDavid du Colombier m->len = n;
4217dd7cddfSDavid du Colombier m->pat = strdup(pat);
4227dd7cddfSDavid du Colombier m->up = strdup(pat);
4237dd7cddfSDavid du Colombier for(p = m->up; *p; p++)
4247dd7cddfSDavid du Colombier *p = toupper(*p);
4257dd7cddfSDavid du Colombier for(p = m->pat; *p; p++)
4267dd7cddfSDavid du Colombier *p = tolower(*p);
4277dd7cddfSDavid du Colombier m->next = next;
4287dd7cddfSDavid du Colombier return m;
4297dd7cddfSDavid du Colombier }
4307dd7cddfSDavid du Colombier
4317dd7cddfSDavid du Colombier int
strlook(Match * m,char * str,char * e)4327dd7cddfSDavid du Colombier strlook(Match *m, char *str, char *e)
4337dd7cddfSDavid du Colombier {
4347dd7cddfSDavid du Colombier char *pat, *up, *s;
4357dd7cddfSDavid du Colombier int c, pc, fc, fuc, n;
4367dd7cddfSDavid du Colombier
4377dd7cddfSDavid du Colombier n = m->len;
4387dd7cddfSDavid du Colombier fc = m->pat[0];
4397dd7cddfSDavid du Colombier fuc = m->up[0];
4407dd7cddfSDavid du Colombier for(; str + n <= e; str++){
4417dd7cddfSDavid du Colombier c = *str;
4427dd7cddfSDavid du Colombier if(c != fc && c != fuc)
4437dd7cddfSDavid du Colombier continue;
4447dd7cddfSDavid du Colombier s = str + 1;
4457dd7cddfSDavid du Colombier up = m->up + 1;
4467dd7cddfSDavid du Colombier for(pat = m->pat + 1; pc = *pat; pat++){
4477dd7cddfSDavid du Colombier c = *s;
4487dd7cddfSDavid du Colombier if(c != pc && c != *up)
4497dd7cddfSDavid du Colombier break;
4507dd7cddfSDavid du Colombier up++;
4517dd7cddfSDavid du Colombier s++;
4527dd7cddfSDavid du Colombier }
4537dd7cddfSDavid du Colombier if(pc == 0)
4547dd7cddfSDavid du Colombier return 1;
4557dd7cddfSDavid du Colombier }
4567dd7cddfSDavid du Colombier return 0;
4577dd7cddfSDavid du Colombier }
4587dd7cddfSDavid du Colombier
4597dd7cddfSDavid du Colombier /*
4607dd7cddfSDavid du Colombier * boyer-moore style pattern matching
4617dd7cddfSDavid du Colombier * implements an exact match for ascii
4627dd7cddfSDavid du Colombier * however, if mulitbyte upper-case and lower-case
4637dd7cddfSDavid du Colombier * characters differ in length or in more than one byte,
4647dd7cddfSDavid du Colombier * it only implements an approximate match
4657dd7cddfSDavid du Colombier */
4667dd7cddfSDavid du Colombier void
quickmk(Quick * q,char * spat,int ignorecase)4677dd7cddfSDavid du Colombier quickmk(Quick *q, char *spat, int ignorecase)
4687dd7cddfSDavid du Colombier {
4697dd7cddfSDavid du Colombier char *pat, *up;
4707dd7cddfSDavid du Colombier uchar *j;
4717dd7cddfSDavid du Colombier int ep, ea, cp, ca, i, c, n;
4727dd7cddfSDavid du Colombier
4737dd7cddfSDavid du Colombier /*
4747dd7cddfSDavid du Colombier * allocate the machine
4757dd7cddfSDavid du Colombier */
4767dd7cddfSDavid du Colombier n = strlen(spat);
4777dd7cddfSDavid du Colombier if(n == 0){
4787dd7cddfSDavid du Colombier q->pat = nil;
4797dd7cddfSDavid du Colombier q->up = nil;
4807dd7cddfSDavid du Colombier q->len = -1;
4817dd7cddfSDavid du Colombier return;
4827dd7cddfSDavid du Colombier }
4837dd7cddfSDavid du Colombier pat = emalloc(2* n + 2);
4847dd7cddfSDavid du Colombier q->pat = pat;
4857dd7cddfSDavid du Colombier up = pat;
4867dd7cddfSDavid du Colombier if(ignorecase)
4877dd7cddfSDavid du Colombier up = pat + n + 1;
4887dd7cddfSDavid du Colombier q->up = up;
4897dd7cddfSDavid du Colombier while(c = *spat++){
4907dd7cddfSDavid du Colombier if(ignorecase){
4917dd7cddfSDavid du Colombier *up++ = toupper(c);
4927dd7cddfSDavid du Colombier c = tolower(c);
4937dd7cddfSDavid du Colombier }
4947dd7cddfSDavid du Colombier *pat++ = c;
4957dd7cddfSDavid du Colombier }
4967dd7cddfSDavid du Colombier pat = q->pat;
4977dd7cddfSDavid du Colombier up = q->up;
4987dd7cddfSDavid du Colombier pat[n] = up[n] = '\0';
4997dd7cddfSDavid du Colombier
5007dd7cddfSDavid du Colombier /*
5017dd7cddfSDavid du Colombier * make the skipping table
5027dd7cddfSDavid du Colombier */
5037dd7cddfSDavid du Colombier if(n > 255)
5047dd7cddfSDavid du Colombier n = 255;
5057dd7cddfSDavid du Colombier j = q->jump;
5067dd7cddfSDavid du Colombier memset(j, n, 256);
5077dd7cddfSDavid du Colombier n--;
5087dd7cddfSDavid du Colombier q->len = n;
5097dd7cddfSDavid du Colombier for(i = 0; i <= n; i++){
5107dd7cddfSDavid du Colombier j[(uchar)pat[i]] = n - i;
5117dd7cddfSDavid du Colombier j[(uchar)up[i]] = n - i;
5127dd7cddfSDavid du Colombier }
5137dd7cddfSDavid du Colombier
5147dd7cddfSDavid du Colombier /*
5157dd7cddfSDavid du Colombier * find the minimum safe amount to skip
5167dd7cddfSDavid du Colombier * if we match the last char but not the whole pat
5177dd7cddfSDavid du Colombier */
5187dd7cddfSDavid du Colombier ep = pat[n];
5197dd7cddfSDavid du Colombier ea = up[n];
5207dd7cddfSDavid du Colombier for(i = n - 1; i >= 0; i--){
5217dd7cddfSDavid du Colombier cp = pat[i];
5227dd7cddfSDavid du Colombier ca = up[i];
5237dd7cddfSDavid du Colombier if(cp == ep || cp == ea || ca == ep || ca == ea)
5247dd7cddfSDavid du Colombier break;
5257dd7cddfSDavid du Colombier }
5267dd7cddfSDavid du Colombier q->miss = n - i;
5277dd7cddfSDavid du Colombier }
5287dd7cddfSDavid du Colombier
5297dd7cddfSDavid du Colombier void
quickfree(Quick * q)5307dd7cddfSDavid du Colombier quickfree(Quick *q)
5317dd7cddfSDavid du Colombier {
5327dd7cddfSDavid du Colombier if(q->pat != nil)
5337dd7cddfSDavid du Colombier free(q->pat);
5347dd7cddfSDavid du Colombier q->pat = nil;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier
5377dd7cddfSDavid du Colombier char *
quicksearch(Quick * q,char * s,char * e)5387dd7cddfSDavid du Colombier quicksearch(Quick *q, char *s, char *e)
5397dd7cddfSDavid du Colombier {
5407dd7cddfSDavid du Colombier char *pat, *up, *m, *ee;
5417dd7cddfSDavid du Colombier uchar *j;
5427dd7cddfSDavid du Colombier int len, n, c, mc;
5437dd7cddfSDavid du Colombier
5447dd7cddfSDavid du Colombier len = q->len;
5457dd7cddfSDavid du Colombier if(len < 0)
5467dd7cddfSDavid du Colombier return s;
5477dd7cddfSDavid du Colombier j = q->jump;
5487dd7cddfSDavid du Colombier pat = q->pat;
5497dd7cddfSDavid du Colombier up = q->up;
5507dd7cddfSDavid du Colombier s += len;
5517dd7cddfSDavid du Colombier ee = e - (len * 4 + 4);
5527dd7cddfSDavid du Colombier while(s < e){
5537dd7cddfSDavid du Colombier /*
5547dd7cddfSDavid du Colombier * look for a match on the last char
5557dd7cddfSDavid du Colombier */
5567dd7cddfSDavid du Colombier while(s < ee && (n = j[(uchar)*s])){
5577dd7cddfSDavid du Colombier s += n;
5587dd7cddfSDavid du Colombier s += j[(uchar)*s];
5597dd7cddfSDavid du Colombier s += j[(uchar)*s];
5607dd7cddfSDavid du Colombier s += j[(uchar)*s];
5617dd7cddfSDavid du Colombier }
5627dd7cddfSDavid du Colombier if(s >= e)
5637dd7cddfSDavid du Colombier return nil;
5647dd7cddfSDavid du Colombier while(n = j[(uchar)*s]){
5657dd7cddfSDavid du Colombier s += n;
5667dd7cddfSDavid du Colombier if(s >= e)
5677dd7cddfSDavid du Colombier return nil;
5687dd7cddfSDavid du Colombier }
5697dd7cddfSDavid du Colombier
5707dd7cddfSDavid du Colombier /*
5717dd7cddfSDavid du Colombier * does the string match?
5727dd7cddfSDavid du Colombier */
5737dd7cddfSDavid du Colombier m = s - len;
5747dd7cddfSDavid du Colombier for(n = 0; c = pat[n]; n++){
5757dd7cddfSDavid du Colombier mc = *m++;
5767dd7cddfSDavid du Colombier if(c != mc && mc != up[n])
5777dd7cddfSDavid du Colombier break;
5787dd7cddfSDavid du Colombier }
5797dd7cddfSDavid du Colombier if(!c)
5807dd7cddfSDavid du Colombier return s - len;
5817dd7cddfSDavid du Colombier s += q->miss;
5827dd7cddfSDavid du Colombier }
5837dd7cddfSDavid du Colombier return nil;
5847dd7cddfSDavid du Colombier }
5857dd7cddfSDavid du Colombier
5867dd7cddfSDavid du Colombier void
fsrun(Fs * fs,int fd)5877dd7cddfSDavid du Colombier fsrun(Fs *fs, int fd)
5887dd7cddfSDavid du Colombier {
5897dd7cddfSDavid du Colombier Fcall rpc;
590*9a747e4fSDavid du Colombier char *err;
591*9a747e4fSDavid du Colombier uchar *buf;
5927dd7cddfSDavid du Colombier int n;
5937dd7cddfSDavid du Colombier
594*9a747e4fSDavid du Colombier buf = emalloc(messagesize);
5957dd7cddfSDavid du Colombier for(;;){
5967dd7cddfSDavid du Colombier /*
5977dd7cddfSDavid du Colombier * reading from a pipe or a network device
5987dd7cddfSDavid du Colombier * will give an error after a few eof reads
5997dd7cddfSDavid du Colombier * however, we cannot tell the difference
6007dd7cddfSDavid du Colombier * between a zero-length read and an interrupt
6017dd7cddfSDavid du Colombier * on the processes writing to us,
6027dd7cddfSDavid du Colombier * so we wait for the error
6037dd7cddfSDavid du Colombier */
604*9a747e4fSDavid du Colombier n = read9pmsg(fd, buf, messagesize);
6057dd7cddfSDavid du Colombier if(n == 0)
6067dd7cddfSDavid du Colombier continue;
6077dd7cddfSDavid du Colombier if(n < 0)
6087dd7cddfSDavid du Colombier fatal("mount read");
6097dd7cddfSDavid du Colombier
610*9a747e4fSDavid du Colombier rpc.data = (char*)buf + IOHDRSZ;
611*9a747e4fSDavid du Colombier if(convM2S(buf, n, &rpc) == 0)
6127dd7cddfSDavid du Colombier continue;
613*9a747e4fSDavid du Colombier // fprint(2, "recv: %F\n", &rpc);
614*9a747e4fSDavid du Colombier
6157dd7cddfSDavid du Colombier
6167dd7cddfSDavid du Colombier /*
6177dd7cddfSDavid du Colombier * flushes are way too hard.
6187dd7cddfSDavid du Colombier * a reply to the original message seems to work
6197dd7cddfSDavid du Colombier */
6207dd7cddfSDavid du Colombier if(rpc.type == Tflush)
6217dd7cddfSDavid du Colombier continue;
6227dd7cddfSDavid du Colombier else if(rpc.type >= Tmax || !fcalls[rpc.type])
6237dd7cddfSDavid du Colombier err = "bad fcall type";
6247dd7cddfSDavid du Colombier else
6257dd7cddfSDavid du Colombier err = (*fcalls[rpc.type])(fs, &rpc);
6267dd7cddfSDavid du Colombier if(err){
6277dd7cddfSDavid du Colombier rpc.type = Rerror;
628*9a747e4fSDavid du Colombier rpc.ename = err;
629*9a747e4fSDavid du Colombier }else
6307dd7cddfSDavid du Colombier rpc.type++;
631*9a747e4fSDavid du Colombier n = convS2M(&rpc, buf, messagesize);
632*9a747e4fSDavid du Colombier // fprint(2, "send: %F\n", &rpc);
6337dd7cddfSDavid du Colombier if(write(fd, buf, n) != n)
6347dd7cddfSDavid du Colombier fatal("mount write");
6357dd7cddfSDavid du Colombier }
6367dd7cddfSDavid du Colombier }
6377dd7cddfSDavid du Colombier
6387dd7cddfSDavid du Colombier Fid*
mkfid(Fs * fs,uint fid)6397dd7cddfSDavid du Colombier mkfid(Fs *fs, uint fid)
6407dd7cddfSDavid du Colombier {
6417dd7cddfSDavid du Colombier Fid *f;
6427dd7cddfSDavid du Colombier int h;
6437dd7cddfSDavid du Colombier
6447dd7cddfSDavid du Colombier h = fid % Nfidhash;
6457dd7cddfSDavid du Colombier for(f = fs->hash[h]; f; f = f->next){
646*9a747e4fSDavid du Colombier if(f->fid == fid)
6477dd7cddfSDavid du Colombier return nil;
6487dd7cddfSDavid du Colombier }
6497dd7cddfSDavid du Colombier
6507dd7cddfSDavid du Colombier f = emalloc(sizeof *f);
6517dd7cddfSDavid du Colombier f->next = fs->hash[h];
6527dd7cddfSDavid du Colombier if(f->next != nil)
6537dd7cddfSDavid du Colombier f->next->last = &f->next;
6547dd7cddfSDavid du Colombier f->last = &fs->hash[h];
6557dd7cddfSDavid du Colombier fs->hash[h] = f;
6567dd7cddfSDavid du Colombier
6577dd7cddfSDavid du Colombier f->fid = fid;
6587dd7cddfSDavid du Colombier f->ref = 1;
6597dd7cddfSDavid du Colombier f->attached = 1;
6607dd7cddfSDavid du Colombier f->open = 0;
6617dd7cddfSDavid du Colombier return f;
6627dd7cddfSDavid du Colombier }
6637dd7cddfSDavid du Colombier
6647dd7cddfSDavid du Colombier Fid*
getfid(Fs * fs,uint fid)6657dd7cddfSDavid du Colombier getfid(Fs *fs, uint fid)
6667dd7cddfSDavid du Colombier {
6677dd7cddfSDavid du Colombier Fid *f;
6687dd7cddfSDavid du Colombier int h;
6697dd7cddfSDavid du Colombier
6707dd7cddfSDavid du Colombier h = fid % Nfidhash;
6717dd7cddfSDavid du Colombier for(f = fs->hash[h]; f; f = f->next){
6727dd7cddfSDavid du Colombier if(f->fid == fid){
6737dd7cddfSDavid du Colombier if(f->attached == 0)
6747dd7cddfSDavid du Colombier break;
6757dd7cddfSDavid du Colombier f->ref++;
6767dd7cddfSDavid du Colombier return f;
6777dd7cddfSDavid du Colombier }
6787dd7cddfSDavid du Colombier }
6797dd7cddfSDavid du Colombier return nil;
6807dd7cddfSDavid du Colombier }
6817dd7cddfSDavid du Colombier
6827dd7cddfSDavid du Colombier void
putfid(Fs *,Fid * f)683*9a747e4fSDavid du Colombier putfid(Fs *, Fid *f)
6847dd7cddfSDavid du Colombier {
6857dd7cddfSDavid du Colombier f->ref--;
6867dd7cddfSDavid du Colombier if(f->ref == 0 && f->attached == 0){
6877dd7cddfSDavid du Colombier *f->last = f->next;
6887dd7cddfSDavid du Colombier if(f->next != nil)
6897dd7cddfSDavid du Colombier f->next->last = f->last;
6907dd7cddfSDavid du Colombier if(f->search != nil)
6917dd7cddfSDavid du Colombier searchfree(f->search);
6927dd7cddfSDavid du Colombier free(f);
6937dd7cddfSDavid du Colombier }
6947dd7cddfSDavid du Colombier }
6957dd7cddfSDavid du Colombier
6967dd7cddfSDavid du Colombier char*
fsversion(Fs *,Fcall * rpc)697*9a747e4fSDavid du Colombier fsversion(Fs *, Fcall *rpc)
6987dd7cddfSDavid du Colombier {
699*9a747e4fSDavid du Colombier if(rpc->msize < 256)
700*9a747e4fSDavid du Colombier return "version: message size too small";
701*9a747e4fSDavid du Colombier if(rpc->msize > messagesize)
702*9a747e4fSDavid du Colombier rpc->msize = messagesize;
703*9a747e4fSDavid du Colombier messagesize = rpc->msize;
704*9a747e4fSDavid du Colombier if(strncmp(rpc->version, "9P2000", 6) != 0)
705*9a747e4fSDavid du Colombier return "unrecognized 9P version";
706*9a747e4fSDavid du Colombier rpc->version = "9P2000";
7077dd7cddfSDavid du Colombier return nil;
7087dd7cddfSDavid du Colombier }
7097dd7cddfSDavid du Colombier
7107dd7cddfSDavid du Colombier char*
fsauth(Fs *,Fcall *)711*9a747e4fSDavid du Colombier fsauth(Fs *, Fcall *)
7127dd7cddfSDavid du Colombier {
713*9a747e4fSDavid du Colombier return "searchfs: authentication not required";
7147dd7cddfSDavid du Colombier }
7157dd7cddfSDavid du Colombier
7167dd7cddfSDavid du Colombier char*
fsattach(Fs * fs,Fcall * rpc)7177dd7cddfSDavid du Colombier fsattach(Fs *fs, Fcall *rpc)
7187dd7cddfSDavid du Colombier {
7197dd7cddfSDavid du Colombier Fid *f;
7207dd7cddfSDavid du Colombier
7217dd7cddfSDavid du Colombier f = mkfid(fs, rpc->fid);
7227dd7cddfSDavid du Colombier if(f == nil)
7237dd7cddfSDavid du Colombier return Einuse;
7247dd7cddfSDavid du Colombier f->open = 0;
725*9a747e4fSDavid du Colombier f->qid.type = QTDIR;
7267dd7cddfSDavid du Colombier f->qid.path = Qroot;
7277dd7cddfSDavid du Colombier f->qid.vers = 0;
7287dd7cddfSDavid du Colombier rpc->qid = f->qid;
7297dd7cddfSDavid du Colombier putfid(fs, f);
7307dd7cddfSDavid du Colombier return nil;
7317dd7cddfSDavid du Colombier }
7327dd7cddfSDavid du Colombier
7337dd7cddfSDavid du Colombier char*
fswalk(Fs * fs,Fcall * rpc)7347dd7cddfSDavid du Colombier fswalk(Fs *fs, Fcall *rpc)
7357dd7cddfSDavid du Colombier {
736*9a747e4fSDavid du Colombier Fid *f, *nf;
737*9a747e4fSDavid du Colombier int nqid, nwname, type;
738*9a747e4fSDavid du Colombier char *err, *name;
739*9a747e4fSDavid du Colombier ulong path;
7407dd7cddfSDavid du Colombier
7417dd7cddfSDavid du Colombier f = getfid(fs, rpc->fid);
7427dd7cddfSDavid du Colombier if(f == nil)
7437dd7cddfSDavid du Colombier return Enofid;
744*9a747e4fSDavid du Colombier nf = nil;
745*9a747e4fSDavid du Colombier if(rpc->fid != rpc->newfid){
746*9a747e4fSDavid du Colombier nf = mkfid(fs, rpc->newfid);
747*9a747e4fSDavid du Colombier if(nf == nil){
7487dd7cddfSDavid du Colombier putfid(fs, f);
749*9a747e4fSDavid du Colombier return Einuse;
7507dd7cddfSDavid du Colombier }
751*9a747e4fSDavid du Colombier nf->qid = f->qid;
7527dd7cddfSDavid du Colombier putfid(fs, f);
753*9a747e4fSDavid du Colombier f = nf; /* walk f */
7547dd7cddfSDavid du Colombier }
755*9a747e4fSDavid du Colombier
756*9a747e4fSDavid du Colombier err = nil;
757*9a747e4fSDavid du Colombier path = f->qid.path;
758*9a747e4fSDavid du Colombier nwname = rpc->nwname;
759*9a747e4fSDavid du Colombier for(nqid=0; nqid<nwname; nqid++){
760*9a747e4fSDavid du Colombier if(path != Qroot){
761*9a747e4fSDavid du Colombier err = Enotdir;
762*9a747e4fSDavid du Colombier break;
763*9a747e4fSDavid du Colombier }
764*9a747e4fSDavid du Colombier name = rpc->wname[nqid];
765*9a747e4fSDavid du Colombier if(strcmp(name, "search") == 0){
766*9a747e4fSDavid du Colombier type = QTFILE;
767*9a747e4fSDavid du Colombier path = Qsearch;
768*9a747e4fSDavid du Colombier }else if(strcmp(name, "stats") == 0){
769*9a747e4fSDavid du Colombier type = QTFILE;
770*9a747e4fSDavid du Colombier path = Qstats;
771*9a747e4fSDavid du Colombier }else if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0){
772*9a747e4fSDavid du Colombier type = QTDIR;
773*9a747e4fSDavid du Colombier path = path;
774*9a747e4fSDavid du Colombier }else{
775*9a747e4fSDavid du Colombier err = Enotexist;
776*9a747e4fSDavid du Colombier break;
777*9a747e4fSDavid du Colombier }
778*9a747e4fSDavid du Colombier rpc->wqid[nqid] = (Qid){path, 0, type};
779*9a747e4fSDavid du Colombier }
780*9a747e4fSDavid du Colombier
781*9a747e4fSDavid du Colombier if(nwname > 0){
782*9a747e4fSDavid du Colombier if(nf != nil && nqid < nwname)
783*9a747e4fSDavid du Colombier nf->attached = 0;
784*9a747e4fSDavid du Colombier if(nqid == nwname)
785*9a747e4fSDavid du Colombier f->qid = rpc->wqid[nqid-1];
786*9a747e4fSDavid du Colombier }
787*9a747e4fSDavid du Colombier
788*9a747e4fSDavid du Colombier putfid(fs, f);
789*9a747e4fSDavid du Colombier rpc->nwqid = nqid;
7907dd7cddfSDavid du Colombier f->open = 0;
791*9a747e4fSDavid du Colombier return err;
7927dd7cddfSDavid du Colombier }
7937dd7cddfSDavid du Colombier
7947dd7cddfSDavid du Colombier char *
fsopen(Fs * fs,Fcall * rpc)7957dd7cddfSDavid du Colombier fsopen(Fs *fs, Fcall *rpc)
7967dd7cddfSDavid du Colombier {
7977dd7cddfSDavid du Colombier Fid *f;
7987dd7cddfSDavid du Colombier int mode;
7997dd7cddfSDavid du Colombier
8007dd7cddfSDavid du Colombier f = getfid(fs, rpc->fid);
8017dd7cddfSDavid du Colombier if(f == nil)
8027dd7cddfSDavid du Colombier return Enofid;
8037dd7cddfSDavid du Colombier if(f->open){
8047dd7cddfSDavid du Colombier putfid(fs, f);
8057dd7cddfSDavid du Colombier return Eisopen;
8067dd7cddfSDavid du Colombier }
8077dd7cddfSDavid du Colombier mode = rpc->mode & OPERM;
8087dd7cddfSDavid du Colombier if(mode == OEXEC
8097dd7cddfSDavid du Colombier || f->qid.path == Qroot && (mode == OWRITE || mode == ORDWR)){
8107dd7cddfSDavid du Colombier putfid(fs, f);
8117dd7cddfSDavid du Colombier return Eperm;
8127dd7cddfSDavid du Colombier }
8137dd7cddfSDavid du Colombier f->open = 1;
8147dd7cddfSDavid du Colombier f->where = nil;
8157dd7cddfSDavid du Colombier f->n = 0;
8167dd7cddfSDavid du Colombier f->search = nil;
8177dd7cddfSDavid du Colombier rpc->qid = f->qid;
818*9a747e4fSDavid du Colombier rpc->iounit = messagesize-IOHDRSZ;
8197dd7cddfSDavid du Colombier putfid(fs, f);
8207dd7cddfSDavid du Colombier return nil;
8217dd7cddfSDavid du Colombier }
8227dd7cddfSDavid du Colombier
8237dd7cddfSDavid du Colombier char *
fscreate(Fs *,Fcall *)8247dd7cddfSDavid du Colombier fscreate(Fs *, Fcall *)
8257dd7cddfSDavid du Colombier {
8267dd7cddfSDavid du Colombier return Eperm;
8277dd7cddfSDavid du Colombier }
8287dd7cddfSDavid du Colombier
8297dd7cddfSDavid du Colombier char*
fsread(Fs * fs,Fcall * rpc)8307dd7cddfSDavid du Colombier fsread(Fs *fs, Fcall *rpc)
8317dd7cddfSDavid du Colombier {
8327dd7cddfSDavid du Colombier Fid *f;
8337dd7cddfSDavid du Colombier int n, off, count, len;
8347dd7cddfSDavid du Colombier
8357dd7cddfSDavid du Colombier f = getfid(fs, rpc->fid);
8367dd7cddfSDavid du Colombier if(f == nil)
8377dd7cddfSDavid du Colombier return Enofid;
8387dd7cddfSDavid du Colombier if(!f->open){
8397dd7cddfSDavid du Colombier putfid(fs, f);
8407dd7cddfSDavid du Colombier return Enotopen;
8417dd7cddfSDavid du Colombier }
8427dd7cddfSDavid du Colombier count = rpc->count;
8437dd7cddfSDavid du Colombier off = rpc->offset;
8447dd7cddfSDavid du Colombier rpc->count = 0;
8457dd7cddfSDavid du Colombier if(f->qid.path == Qroot){
8467dd7cddfSDavid du Colombier if(off > 0)
8477dd7cddfSDavid du Colombier rpc->count = 0;
848*9a747e4fSDavid du Colombier else
849*9a747e4fSDavid du Colombier rpc->count = dostat(Qsearch, (uchar*)rpc->data, count);
8507dd7cddfSDavid du Colombier putfid(fs, f);
851*9a747e4fSDavid du Colombier if(off == 0 && rpc->count <= BIT16SZ)
852*9a747e4fSDavid du Colombier return "directory read count too small";
8537dd7cddfSDavid du Colombier return nil;
8547dd7cddfSDavid du Colombier }
8557dd7cddfSDavid du Colombier if(f->qid.path == Qstats){
8567dd7cddfSDavid du Colombier len = 0;
8577dd7cddfSDavid du Colombier }else{
8587dd7cddfSDavid du Colombier for(len = 0; len < count; len += n){
8597dd7cddfSDavid du Colombier if(f->where == nil || f->search == nil)
8607dd7cddfSDavid du Colombier break;
8617dd7cddfSDavid du Colombier if(f->n == 0)
8627dd7cddfSDavid du Colombier f->where = searchsearch(f->search, f->where, edatabase, &f->n);
8637dd7cddfSDavid du Colombier n = f->n;
8647dd7cddfSDavid du Colombier if(n != 0){
8657dd7cddfSDavid du Colombier if(n > count-len)
8667dd7cddfSDavid du Colombier n = count-len;
8677dd7cddfSDavid du Colombier memmove(rpc->data+len, f->where, n);
8687dd7cddfSDavid du Colombier f->where += n;
8697dd7cddfSDavid du Colombier f->n -= n;
8707dd7cddfSDavid du Colombier }
8717dd7cddfSDavid du Colombier }
8727dd7cddfSDavid du Colombier }
8737dd7cddfSDavid du Colombier putfid(fs, f);
8747dd7cddfSDavid du Colombier rpc->count = len;
8757dd7cddfSDavid du Colombier return nil;
8767dd7cddfSDavid du Colombier }
8777dd7cddfSDavid du Colombier
8787dd7cddfSDavid du Colombier char*
fswrite(Fs * fs,Fcall * rpc)8797dd7cddfSDavid du Colombier fswrite(Fs *fs, Fcall *rpc)
8807dd7cddfSDavid du Colombier {
8817dd7cddfSDavid du Colombier Fid *f;
8827dd7cddfSDavid du Colombier
8837dd7cddfSDavid du Colombier f = getfid(fs, rpc->fid);
8847dd7cddfSDavid du Colombier if(f == nil)
8857dd7cddfSDavid du Colombier return Enofid;
8867dd7cddfSDavid du Colombier if(!f->open || f->qid.path != Qsearch){
8877dd7cddfSDavid du Colombier putfid(fs, f);
8887dd7cddfSDavid du Colombier return Enotopen;
8897dd7cddfSDavid du Colombier }
8907dd7cddfSDavid du Colombier
8917dd7cddfSDavid du Colombier if(f->search != nil)
8927dd7cddfSDavid du Colombier searchfree(f->search);
8937dd7cddfSDavid du Colombier f->search = searchparse(rpc->data, rpc->data + rpc->count);
8947dd7cddfSDavid du Colombier if(f->search == nil){
8957dd7cddfSDavid du Colombier putfid(fs, f);
8967dd7cddfSDavid du Colombier return Ebadsearch;
8977dd7cddfSDavid du Colombier }
8987dd7cddfSDavid du Colombier f->where = database;
8997dd7cddfSDavid du Colombier f->n = 0;
9007dd7cddfSDavid du Colombier putfid(fs, f);
9017dd7cddfSDavid du Colombier return nil;
9027dd7cddfSDavid du Colombier }
9037dd7cddfSDavid du Colombier
9047dd7cddfSDavid du Colombier char *
fsclunk(Fs * fs,Fcall * rpc)9057dd7cddfSDavid du Colombier fsclunk(Fs *fs, Fcall *rpc)
9067dd7cddfSDavid du Colombier {
9077dd7cddfSDavid du Colombier Fid *f;
9087dd7cddfSDavid du Colombier
9097dd7cddfSDavid du Colombier f = getfid(fs, rpc->fid);
9107dd7cddfSDavid du Colombier if(f != nil){
9117dd7cddfSDavid du Colombier f->attached = 0;
9127dd7cddfSDavid du Colombier putfid(fs, f);
9137dd7cddfSDavid du Colombier }
9147dd7cddfSDavid du Colombier return nil;
9157dd7cddfSDavid du Colombier }
9167dd7cddfSDavid du Colombier
9177dd7cddfSDavid du Colombier char *
fsremove(Fs *,Fcall *)9187dd7cddfSDavid du Colombier fsremove(Fs *, Fcall *)
9197dd7cddfSDavid du Colombier {
9207dd7cddfSDavid du Colombier return Eperm;
9217dd7cddfSDavid du Colombier }
9227dd7cddfSDavid du Colombier
9237dd7cddfSDavid du Colombier char *
fsstat(Fs * fs,Fcall * rpc)9247dd7cddfSDavid du Colombier fsstat(Fs *fs, Fcall *rpc)
9257dd7cddfSDavid du Colombier {
9267dd7cddfSDavid du Colombier Fid *f;
9277dd7cddfSDavid du Colombier
9287dd7cddfSDavid du Colombier f = getfid(fs, rpc->fid);
9297dd7cddfSDavid du Colombier if(f == nil)
9307dd7cddfSDavid du Colombier return Enofid;
931*9a747e4fSDavid du Colombier rpc->stat = fs->statbuf;
932*9a747e4fSDavid du Colombier rpc->nstat = dostat(f->qid.path, rpc->stat, sizeof fs->statbuf);
9337dd7cddfSDavid du Colombier putfid(fs, f);
934*9a747e4fSDavid du Colombier if(rpc->nstat <= BIT16SZ)
935*9a747e4fSDavid du Colombier return "stat count too small";
9367dd7cddfSDavid du Colombier return nil;
9377dd7cddfSDavid du Colombier }
9387dd7cddfSDavid du Colombier
9397dd7cddfSDavid du Colombier char *
fswstat(Fs *,Fcall *)9407dd7cddfSDavid du Colombier fswstat(Fs *, Fcall *)
9417dd7cddfSDavid du Colombier {
9427dd7cddfSDavid du Colombier return Eperm;
9437dd7cddfSDavid du Colombier }
9447dd7cddfSDavid du Colombier
945*9a747e4fSDavid du Colombier int
dostat(int path,uchar * buf,int nbuf)946*9a747e4fSDavid du Colombier dostat(int path, uchar *buf, int nbuf)
9477dd7cddfSDavid du Colombier {
9487dd7cddfSDavid du Colombier Dir d;
9497dd7cddfSDavid du Colombier
9507dd7cddfSDavid du Colombier switch(path){
9517dd7cddfSDavid du Colombier case Qroot:
952*9a747e4fSDavid du Colombier d.name = ".";
953*9a747e4fSDavid du Colombier d.mode = DMDIR|0555;
954*9a747e4fSDavid du Colombier d.qid.type = QTDIR;
9557dd7cddfSDavid du Colombier break;
9567dd7cddfSDavid du Colombier case Qsearch:
957*9a747e4fSDavid du Colombier d.name = "search";
9587dd7cddfSDavid du Colombier d.mode = 0666;
959*9a747e4fSDavid du Colombier d.qid.type = QTFILE;
9607dd7cddfSDavid du Colombier break;
9617dd7cddfSDavid du Colombier case Qstats:
962*9a747e4fSDavid du Colombier d.name = "stats";
9637dd7cddfSDavid du Colombier d.mode = 0666;
964*9a747e4fSDavid du Colombier d.qid.type = QTFILE;
9657dd7cddfSDavid du Colombier break;
9667dd7cddfSDavid du Colombier }
9677dd7cddfSDavid du Colombier d.qid.path = path;
9687dd7cddfSDavid du Colombier d.qid.vers = 0;
9697dd7cddfSDavid du Colombier d.length = 0;
970*9a747e4fSDavid du Colombier d.uid = d.gid = d.muid = "none";
9717dd7cddfSDavid du Colombier d.atime = d.mtime = time(nil);
972*9a747e4fSDavid du Colombier return convD2M(&d, buf, nbuf);
9737dd7cddfSDavid du Colombier }
9747dd7cddfSDavid du Colombier
9757dd7cddfSDavid du Colombier char *
urlunesc(char * s,char * e)9767dd7cddfSDavid du Colombier urlunesc(char *s, char *e)
9777dd7cddfSDavid du Colombier {
9787dd7cddfSDavid du Colombier char *t, *v;
9797dd7cddfSDavid du Colombier int c, n;
9807dd7cddfSDavid du Colombier
9817dd7cddfSDavid du Colombier v = emalloc((e - s) + 1);
9827dd7cddfSDavid du Colombier for(t = v; s < e; s++){
9837dd7cddfSDavid du Colombier c = *s;
9847dd7cddfSDavid du Colombier if(c == '%'){
9857dd7cddfSDavid du Colombier if(s + 2 >= e)
9867dd7cddfSDavid du Colombier break;
9877dd7cddfSDavid du Colombier n = s[1];
9887dd7cddfSDavid du Colombier if(n >= '0' && n <= '9')
9897dd7cddfSDavid du Colombier n = n - '0';
9907dd7cddfSDavid du Colombier else if(n >= 'A' && n <= 'F')
9917dd7cddfSDavid du Colombier n = n - 'A' + 10;
9927dd7cddfSDavid du Colombier else if(n >= 'a' && n <= 'f')
9937dd7cddfSDavid du Colombier n = n - 'a' + 10;
9947dd7cddfSDavid du Colombier else
9957dd7cddfSDavid du Colombier break;
9967dd7cddfSDavid du Colombier c = n;
9977dd7cddfSDavid du Colombier n = s[2];
9987dd7cddfSDavid du Colombier if(n >= '0' && n <= '9')
9997dd7cddfSDavid du Colombier n = n - '0';
10007dd7cddfSDavid du Colombier else if(n >= 'A' && n <= 'F')
10017dd7cddfSDavid du Colombier n = n - 'A' + 10;
10027dd7cddfSDavid du Colombier else if(n >= 'a' && n <= 'f')
10037dd7cddfSDavid du Colombier n = n - 'a' + 10;
10047dd7cddfSDavid du Colombier else
10057dd7cddfSDavid du Colombier break;
10067dd7cddfSDavid du Colombier s += 2;
10077dd7cddfSDavid du Colombier c = c * 16 + n;
10087dd7cddfSDavid du Colombier }
10097dd7cddfSDavid du Colombier *t++ = c;
10107dd7cddfSDavid du Colombier }
10117dd7cddfSDavid du Colombier *t = 0;
10127dd7cddfSDavid du Colombier return v;
10137dd7cddfSDavid du Colombier }
10147dd7cddfSDavid du Colombier
10157dd7cddfSDavid du Colombier int
toupper(int c)10167dd7cddfSDavid du Colombier toupper(int c)
10177dd7cddfSDavid du Colombier {
10187dd7cddfSDavid du Colombier if(c >= 'a' && c <= 'z')
10197dd7cddfSDavid du Colombier c += 'A' - 'a';
10207dd7cddfSDavid du Colombier return c;
10217dd7cddfSDavid du Colombier }
10227dd7cddfSDavid du Colombier
10237dd7cddfSDavid du Colombier int
tolower(int c)10247dd7cddfSDavid du Colombier tolower(int c)
10257dd7cddfSDavid du Colombier {
10267dd7cddfSDavid du Colombier if(c >= 'A' && c <= 'Z')
10277dd7cddfSDavid du Colombier c += 'a' - 'A';
10287dd7cddfSDavid du Colombier return c;
10297dd7cddfSDavid du Colombier }
10307dd7cddfSDavid du Colombier
10317dd7cddfSDavid du Colombier void
fatal(char * fmt,...)10327dd7cddfSDavid du Colombier fatal(char *fmt, ...)
10337dd7cddfSDavid du Colombier {
10347dd7cddfSDavid du Colombier va_list arg;
10357dd7cddfSDavid du Colombier char buf[1024];
10367dd7cddfSDavid du Colombier
10377dd7cddfSDavid du Colombier write(2, "searchfs: ", 8);
10387dd7cddfSDavid du Colombier va_start(arg, fmt);
1039*9a747e4fSDavid du Colombier vseprint(buf, buf+1024, fmt, arg);
10407dd7cddfSDavid du Colombier va_end(arg);
10417dd7cddfSDavid du Colombier write(2, buf, strlen(buf));
10427dd7cddfSDavid du Colombier write(2, "\n", 1);
10437dd7cddfSDavid du Colombier exits(fmt);
10447dd7cddfSDavid du Colombier }
10457dd7cddfSDavid du Colombier
10467dd7cddfSDavid du Colombier void *
emalloc(uint n)10477dd7cddfSDavid du Colombier emalloc(uint n)
10487dd7cddfSDavid du Colombier {
10497dd7cddfSDavid du Colombier void *p;
10507dd7cddfSDavid du Colombier
10517dd7cddfSDavid du Colombier p = malloc(n);
10527dd7cddfSDavid du Colombier if(p == nil)
10537dd7cddfSDavid du Colombier fatal("out of memory");
10547dd7cddfSDavid du Colombier memset(p, 0, n);
10557dd7cddfSDavid du Colombier return p;
10567dd7cddfSDavid du Colombier }
10577dd7cddfSDavid du Colombier
10587dd7cddfSDavid du Colombier void
usage(void)10597dd7cddfSDavid du Colombier usage(void)
10607dd7cddfSDavid du Colombier {
10617dd7cddfSDavid du Colombier fprint(2, "usage: searchfs [-m mountpoint] [-s srvfile] database\n");
10627dd7cddfSDavid du Colombier exits("usage");
10637dd7cddfSDavid du Colombier }
1064