int ismatch(char* s, char* p) { if(*s == '\0' && *p == '\0') return 1; if(*p == '*' && *(p+1) != '\0' && *s == '\0') return 0; if(*p == '?' || *p == *s) return ismatch(s+1, p+1); if(*p == '*') return ismatch(s, p+1) || ismatch(s+1, p); return 0; }
void main() { char s[] = "match"; char p[] = "m?tc*??"; printf("\nismatch(%s, %s) = %s\n", s, p, ismatch(s, p) ? "Matching" : "Not a match"); }
/* * Given a process id, iterate through all open files of that process * looking for a match to the target file, and then determine how it * is being used by that process. This is quite different in QNX to * UNIX, as chroot and chdir do not hold open a reference to the file. * The iteration process attempts to dup each file descriptor into * this process, so it can then be queried; attempt to skip things which * aren't files (heuristic guess) and use a timeout as self-defence. */ int howused(pid_t pid, match_t *match) { struct _server_info sinfo; struct _fdinfo finfo; struct stat st; io_dup_t msg; uint64_t to; int fd, coid, usage; usage = 0; for (fd = 0; (fd = ConnectServerInfo(pid, fd, &sinfo)) != -1; ++fd) { if ((pid != sinfo.pid || !(fd & _NTO_SIDE_CHANNEL)) && (coid = ConnectAttach(sinfo.nd, sinfo.pid, sinfo.chid, 0, _NTO_COF_CLOEXEC)) != -1) { msg.i.type = _IO_DUP; msg.i.combine_len = sizeof(msg.i); msg.i.info.nd = netmgr_remote_nd(sinfo.nd, ND_LOCAL_NODE); msg.i.info.pid = pid; msg.i.info.chid = sinfo.chid; msg.i.info.scoid = sinfo.scoid; msg.i.info.coid = fd; TimerTimeout(CLOCK_MONOTONIC, _NTO_TIMEOUT_SEND | _NTO_TIMEOUT_REPLY, NULL, (to = 1000000000LL, &to), NULL); if (MsgSend(coid, &msg.i, sizeof(msg.i), NULL, 0) == -1) { ConnectDetach(coid); } else { if (fstat(coid, &st) != -1 && ismatch(match, st.st_dev, st.st_ino)) { if (iofdinfo(coid, 0, &finfo, NULL, 0) == -1 || sinfo.pid != PATHMGR_PID || finfo.mode != 0) usage |= USED_OPEN; } close(coid); } } } return(usage); }
/* * Concatenate a directory path and a filename. Note that this function * currently does NOT handle the case where file itself contains * directory components (except on Unix platforms, because it is trivial.) */ char *nasm_catfile(const char *dir, const char *file) { #ifndef catsep return nasm_strcat(dir, file); #else size_t dl = strlen(dir); size_t fl = strlen(file); char *p; bool dosep = true; if (!dl || ismatch(separators, dir[dl-1])) { /* No separator necessary */ dosep = false; } p = nasm_malloc(dl + fl + dosep + 1); memcpy(p, dir, dl); p += dl; if (dosep) *p++ = catsep; memcpy(p, file, fl+1); return p; #endif }
/* Return the directory name portion of a PATH as a new string */ char *nasm_dirname(const char *path) { const char *p = first_filename_char(path); const char *p0 = p; (void)p0; /* Don't warn if unused */ if (p == path) return nasm_strdup(curdir); #ifdef cleandirend while (p > path+leaveonclean) { if (ismatch(cleandirend, p[-1])) break; p--; } #endif #ifdef leave_leading /* If the directory contained ONLY separators, leave as-is */ if (p == path+leaveonclean) p = p0; #endif return nasm_strndup(path, p-path); }
static int ismatch(Node *a, Node *b) { if (!a && !b) return 1; if (!a || !b) return 0; if (a->ntyp != b->ntyp) return 0; if (a->sym && b->sym && strcmp(a->sym->name, b->sym->name) != 0) return 0; if (ismatch(a->lft, b->lft) && ismatch(a->rgt, b->rgt)) return 1; return 0; }
Node * in_cache(Node *n) { Cache *d; int nr=0; for (d = stored; d; d = d->nxt, nr++) if (isequal(d->before, n)) { CacheHits++; if (d->same && ismatch(n, d->before)) return n; return dupnode(d->after); } return ZN; }
int match(State *start, char *s) { List *clist, *nlist, *t; clist = startlist(start, &l1); nlist = &l2; for (; *s; s++) { char c = *s & 0xFF; step(clist, c, nlist); t = clist; clist = nlist; nlist = t; } return ismatch(clist); }
/* Run DFA to determine whether it matches s. */ int match(DState *start, char *s) { DState *d, *next; int c, i; d = start; for(; *s; s++){ c = *s & 0xFF; if((next = d->next[c]) == NULL) next = nextstate(d, c); d = next; } return ismatch(&d->l); }
static const char *first_filename_char(const char *path) { #ifdef separators const char *p = path + strlen(path); while (p > path) { if (ismatch(separators, p[-1])) return p; p--; } return p; #else return path; #endif }
int grammarAnalyze(const char* line) { int ret = 0; if (line == NULL) return -1; int i = 0; LinkStack *stack = NULL; stack = LinkStack_Create(); if (stack == NULL) return -2; while (*(line + i) != '\0') { if (isalpha(line[i])) { i++; continue; } else if (isleft(line[i])) { LinkStack_Push(stack, (void *)&line[i]); } else if (isright(line[i])) { char *tmp; tmp = (char *)LinkStack_Pop(stack); if (tmp == NULL || !ismatch(*tmp, line[i])) { break; } } i++; } if (LinkStack_Size(stack) == 0 && line[i] == '\0') { ret = 1; } LinkList_Destroy(stack); return ret; }
Node * cached(Node *n) { Cache *d; Node *m; if (!n) return n; if ((m = in_cache(n)) != ZN) return m; Caches++; d = (Cache *) tl_emalloc(sizeof(Cache)); d->before = dupnode(n); d->after = Canonical(n); /* n is released */ if (ismatch(d->before, d->after)) { d->same = 1; releasenode(1, d->after); d->after = d->before; } d->nxt = stored; stored = d; return dupnode(d->after); }
void main(int argc, char **argv) { char *f[10], *local, *name, *remote, *s, *t, verb; int fd, havedb, havelocal, i, k, n, nf, resolve1, skip; int checkedmatch1, checkedmatch2, checkedmatch3, checkedmatch4; ulong now; Biobuf bin; Dir dbd, ld, nd, rd; Avlwalk *w; Entry *e; membogus(argv); quotefmtinstall(); ARGBEGIN{ case 's': case 'c': i = ARGC(); addresolve(i, EARGF(usage())); break; case 'n': donothing = 1; verbose = 1; break; case 'S': safeinstall = 0; break; case 'T': timefile = EARGF(usage()); break; case 't': tempspool = 0; break; case 'u': douid = 1; break; case 'v': verbose++; break; default: usage(); }ARGEND if(argc < 3) usage(); if(timefile) readtimefile(); lroot = argv[1]; if(!isdir(lroot)) sysfatal("bad local root directory"); rroot = argv[2]; if(!isdir(rroot)) sysfatal("bad remote root directory"); match = argv+3; nmatch = argc-3; for(i=0; i<nmatch; i++) if(match[i][0] == '/') match[i]++; if((clientdb = opendb(argv[0])) == nil) sysfatal("opendb %q: %r", argv[2]); copyerr = opendb(nil); skip = 0; Binit(&bin, 0, OREAD); for(; s=Brdstr(&bin, '\n', 1); free(s)){ t = estrdup(s); nf = tokenize(s, f, nelem(f)); if(nf != 10 || strlen(f[2]) != 1){ skip = 1; fprint(2, "warning: skipping bad log entry <%s>\n", t); free(t); continue; } free(t); now = strtoul(f[0], 0, 0); n = atoi(f[1]); verb = f[2][0]; name = f[3]; if(now < maxnow || (now==maxnow && n <= maxn)) continue; local = mkname(localbuf, sizeof localbuf, lroot, name); if(strcmp(f[4], "-") == 0) f[4] = f[3]; remote = mkname(remotebuf, sizeof remotebuf, rroot, f[4]); rd.name = f[4]; rd.mode = strtoul(f[5], 0, 8); rd.uid = f[6]; rd.gid = f[7]; rd.mtime = strtoul(f[8], 0, 10); rd.length = strtoll(f[9], 0, 10); havedb = finddb(clientdb, name, &dbd)>=0; havelocal = localdirstat(local, &ld)>=0; resolve1 = resolve(name); /* * if(!ismatch(name)){ * skip = 1; * continue; * } * * This check used to be right here, but we want * the time to be able to move forward past entries * that don't match and have already been applied. * So now every path below must checked !ismatch(name) * before making any changes to the local file * system. The fake variable checkedmatch * tracks whether !ismatch(name) has been checked. * If the compiler doesn't produce any used/set * warnings, then all the paths should be okay. * Even so, we have the asserts to fall back on. */ switch(verb){ case 'd': /* delete file */ delce(local); if(!havelocal) /* doesn't exist; who cares? */ break; if(access(remote, AEXIST) >= 0) /* got recreated! */ break; if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch1); if(!havedb){ if(resolve1 == 's') goto DoRemove; else if(resolve1 == 'c') goto DoRemoveDb; conflict(name, "locally created; will not remove"); skip = 1; continue; } assert(havelocal && havedb); if(dbd.mtime > rd.mtime) /* we have a newer file than what was deleted */ break; if(samecontents(local, remote) > 0){ /* going to get recreated */ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); break; } if(!(dbd.mode&DMDIR) && (dbd.mtime != ld.mtime || dbd.length != ld.length)){ /* locally modified since we downloaded it */ if(resolve1 == 's') goto DoRemove; else if(resolve1 == 'c') break; conflict(name, "locally modified; will not remove"); skip = 1; continue; } DoRemove: USED(checkedmatch1); assert(ismatch(name)); chat("d %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); if(donothing) break; if(remove(local) < 0){ error("removing %q: %r", name); skip = 1; continue; } DoRemoveDb: USED(checkedmatch1); assert(ismatch(name)); removedb(clientdb, name); break; case 'a': /* add file */ if(!havedb){ if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch2); if(!havelocal) goto DoCreate; if((ld.mode&DMDIR) && (rd.mode&DMDIR)) break; if(samecontents(local, remote) > 0){ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); goto DoCreateDb; } if(resolve1 == 's') goto DoCreate; else if(resolve1 == 'c') goto DoCreateDb; conflict(name, "locally created; will not overwrite"); skip = 1; continue; } assert(havedb); if(dbd.mtime >= rd.mtime) /* already created this file; ignore */ break; if(havelocal){ if((ld.mode&DMDIR) && (rd.mode&DMDIR)) break; if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch2); if(samecontents(local, remote) > 0){ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); goto DoCreateDb; } if(dbd.mtime==ld.mtime && dbd.length==ld.length) goto DoCreate; if(resolve1=='s') goto DoCreate; else if(resolve1 == 'c') goto DoCreateDb; conflict(name, "locally modified; will not overwrite"); skip = 1; continue; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch2); DoCreate: USED(checkedmatch2); assert(ismatch(name)); if(notexists(remote)){ addce(local); /* no skip=1 */ break;; } chat("a %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); if(donothing) break; if(rd.mode&DMDIR){ fd = create(local, OREAD, DMDIR); if(fd < 0 && isdir(local)) fd = open(local, OREAD); if(fd < 0){ error("mkdir %q: %r", name); skip = 1; continue; } nulldir(&nd); nd.mode = rd.mode; if(dirfwstat(fd, &nd) < 0) fprint(2, "warning: cannot set mode on %q\n", local); nulldir(&nd); nd.gid = rd.gid; if(dirfwstat(fd, &nd) < 0) fprint(2, "warning: cannot set gid on %q\n", local); if(douid){ nulldir(&nd); nd.uid = rd.uid; if(dirfwstat(fd, &nd) < 0) fprint(2, "warning: cannot set uid on %q\n", local); } close(fd); rd.mtime = now; }else{ if(copyfile(local, remote, name, &rd, 1, &k) < 0){ if(k) addce(local); skip = 1; continue; } } DoCreateDb: USED(checkedmatch2); assert(ismatch(name)); insertdb(clientdb, name, &rd); break; case 'c': /* change contents */ if(!havedb){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch3); if(resolve1 == 's') goto DoCopy; else if(resolve1=='c') goto DoCopyDb; if(samecontents(local, remote) > 0){ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); goto DoCopyDb; } if(havelocal) conflict(name, "locally created; will not update"); else conflict(name, "not replicated; will not update"); skip = 1; continue; } if(dbd.mtime >= rd.mtime) /* already have/had this version; ignore */ break; if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch3); if(!havelocal){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(resolve1 == 's') goto DoCopy; else if(resolve1 == 'c') break; conflict(name, "locally removed; will not update"); skip = 1; continue; } assert(havedb && havelocal); if(dbd.mtime != ld.mtime || dbd.length != ld.length){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(samecontents(local, remote) > 0){ chat("= %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); goto DoCopyDb; } if(resolve1 == 's') goto DoCopy; else if(resolve1 == 'c') goto DoCopyDb; conflict(name, "locally modified; will not update [%llud %lud -> %llud %lud]", dbd.length, dbd.mtime, ld.length, ld.mtime); skip = 1; continue; } DoCopy: USED(checkedmatch3); assert(ismatch(name)); if(notexists(remote)){ addce(local); /* no skip=1 */ break; } chat("c %q\n", name); if(donothing) break; if(copyfile(local, remote, name, &rd, 0, &k) < 0){ if(k) addce(local); skip = 1; continue; } DoCopyDb: USED(checkedmatch3); assert(ismatch(name)); if(!havedb){ if(havelocal) dbd = ld; else dbd = rd; } dbd.mtime = rd.mtime; dbd.length = rd.length; insertdb(clientdb, name, &dbd); break; case 'm': /* change metadata */ if(!havedb){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); if(resolve1 == 's'){ USED(checkedmatch4); SET(checkedmatch2); goto DoCreate; } else if(resolve1 == 'c') goto DoMetaDb; if(havelocal) conflict(name, "locally created; will not update metadata"); else conflict(name, "not replicated; will not update metadata"); skip = 1; continue; } if(!(dbd.mode&DMDIR) && dbd.mtime > rd.mtime) /* have newer version; ignore */ break; if((dbd.mode&DMDIR) && dbd.mtime > now) break; if(havelocal && (!douid || strcmp(ld.uid, rd.uid)==0) && strcmp(ld.gid, rd.gid)==0 && ld.mode==rd.mode) break; if(!havelocal){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); if(resolve1 == 's'){ USED(checkedmatch4); SET(checkedmatch2); goto DoCreate; } else if(resolve1 == 'c') break; conflict(name, "locally removed; will not update metadata"); skip = 1; continue; } if(!(dbd.mode&DMDIR) && (dbd.mtime != ld.mtime || dbd.length != ld.length)){ /* this check might be overkill */ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); if(resolve1 == 's' || samecontents(local, remote) > 0) goto DoMeta; else if(resolve1 == 'c') break; conflict(name, "contents locally modified (%s); will not update metadata to %s %s %luo", dbd.mtime != ld.mtime ? "mtime" : dbd.length != ld.length ? "length" : "unknown", rd.uid, rd.gid, rd.mode); skip = 1; continue; } if((douid && strcmp(ld.uid, dbd.uid)!=0) || strcmp(ld.gid, dbd.gid)!=0 || ld.mode!=dbd.mode){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); if(resolve1 == 's') goto DoMeta; else if(resolve1 == 'c') break; conflict(name, "metadata locally changed; will not update metadata to %s %s %luo", rd.uid, rd.gid, rd.mode); skip = 1; continue; } if(!ismatch(name)){ skip = prstopped(skip, name); continue; } SET(checkedmatch4); DoMeta: USED(checkedmatch4); assert(ismatch(name)); if(notexists(remote)){ addce(local); /* no skip=1 */ break; } chat("m %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); if(donothing) break; nulldir(&nd); nd.gid = rd.gid; nd.mode = rd.mode; if(douid) nd.uid = rd.uid; if(dirwstat(local, &nd) < 0){ error("dirwstat %q: %r", name); skip = 1; continue; } DoMetaDb: USED(checkedmatch4); assert(ismatch(name)); if(!havedb){ if(havelocal) dbd = ld; else dbd = rd; } if(dbd.mode&DMDIR) dbd.mtime = now; dbd.gid = rd.gid; dbd.mode = rd.mode; if(douid) dbd.uid = rd.uid; insertdb(clientdb, name, &dbd); break; } if(!skip && !donothing){ maxnow = now; maxn = n; } } w = avlwalk(copyerr->avl); while(e = (Entry*)avlnext(w)) error("copying %q: %s\n", e->name, e->d.name); if(timefile) writetimefile(); if(nconf) exits("conflicts"); if(errors) exits("errors"); exits(nil); }