struct pathnode * relpath(struct pathnode *f, struct pathnode *t) { struct pathnode *p = f; struct pathnode *q = t; struct pathnode *r; struct pathnode root; /* We deal only with proper path-roots */ if (f == NULL || t == NULL) return NULL; while (p->next != NULL && q->next != NULL && strcmp((p->next)->name, (q->next)->name) == 0) { p = p->next; q = q->next; } root.next = NULL; r = &root; while (p->next != NULL) { r->next = palloc(); (r->next)->prev = r; r = r->next; r->name = strdup(".."); r->next = NULL; p = p->next; } pathcopy(q->next,r); if (! root.next) { /* * The two paths are the same, the relative path in between * is NULL. * We rather add a simple dot component and refrain from using * NULL paths. */ r = palloc(); root.next = r; r->name = strdup("."); r->next = NULL; } root.next->prev = NULL; return root.next; }
void pathcopy(struct pathnode *f, struct pathnode *t) { struct pathnode *p = palloc(); if (f == NULL) { t->next = NULL; return; } p->prev = t; p->next = NULL; p->name = strdup(f->name); t->next = p; if ((f->next) != NULL) pathcopy(f->next,p); }
struct path * strtopath(struct path *p, const char *str) { struct path *path, *n; int i, j; if (str[0] == '/' || p == nil) { path = p = nil; } else { path = pathcopy(p); if (path == nil) { return nil; } for (p = path; p != nil && p->next != nil; p = p->next) ; } while (*str != 0) { for (i = 0; str[i] != 0 && str[i] != '/'; i++) ; if (i == 0) { str += 1; continue; } else if (i >= NAMEMAX) { pathfree(path); return nil; } if (str[0] == '.') { if (str[1] == '.' && i == 2) { /* Remove current and prev */ if (p == nil) { str += 2; continue; } n = p; if (p == path) { path = p->prev; } p = p->prev; if (p != nil) { p->next = nil; } lock(&pathalloc.lock); n->next = pathalloc.free; pathalloc.free = n; unlock(&pathalloc.lock); str += 2; continue; } else if (i == 1) { /* Remove current */ str += 1; continue; } } lock(&pathalloc.lock); n = pathalloc.free; if (n == nil) { n = malloc(sizeof(struct path)); if (n == nil) { pathfree(path); return nil; } } else { pathalloc.free = n->next; } unlock(&pathalloc.lock); for (j = 0; j < i; j++) n->s[j] = str[j]; n->s[j] = 0; n->next = nil; n->prev = p; if (p != nil) { p->next = n; } else { path = n; } p = n; str += i; } return path; }