[Libsysio-commit] HEAD: libsysio/src inode.c
Brought to you by:
lward
From: Lee W. <lw...@us...> - 2008-04-14 23:28:44
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1705 Modified Files: inode.c Log Message: Four changes: 1) The routine _sysio_p_path was moved here from chdir.c 2) A new routine, _sysio_p_show, is implemented when P_DEBUG is defined. 3) _sysio_p_find_alias prints the pnode when P_DEBUG is defined, using _sysio_p_show. 4) _sysio_gone prints the pnode when P_DEBUG is defined, using _sysio_p_show. Index: inode.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/inode.c,v retrieving revision 1.37 retrieving revision 1.38 diff -u -w -b -B -p -r1.37 -r1.38 --- inode.c 31 Mar 2008 16:33:55 -0000 1.37 +++ inode.c 14 Apr 2008 23:28:41 -0000 1.38 @@ -623,6 +623,100 @@ _sysio_i_shutdown() #endif /* + * Return path tracked by the path ancestor chain. + * + * If the buf pointer is NULL, a buffer large enough to hold the path + * is allocated from the heap. + */ + +int +_sysio_p_path(struct pnode *pno, char **bufp, size_t size) +{ + struct pnode *cur; + size_t len; + size_t n; + char *cp; + + cur = pno; + + if (!size && bufp && *bufp) + return -EINVAL; + + /* + * Walk up the tree to the root, summing the component name + * lengths and counting the vertices. + */ + len = 0; + n = 0; + do { + /* + * If this is a covering path-node then the name should be + * the *covered* nodes name, not this one unless we are at + * the root of the name-space. + */ + while (pno == pno->p_mount->mnt_root && + pno != pno->p_parent) + pno = pno->p_mount->mnt_covers; + + /* + * Add length of this component to running sum and + * account for this vertex. + */ + assert((len >= pno->p_base->pb_key.pbk_name.len && + (size_t )~0 - pno->p_base->pb_key.pbk_name.len > len) || + (size_t )~0 - len > pno->p_base->pb_key.pbk_name.len); + len += pno->p_base->pb_key.pbk_name.len; + n++; + assert(n); + pno = pno->p_parent; + } while (pno && pno != pno->p_parent); + if (!pno) + return -ENOENT; + + if (!*bufp) + size = len + n + 1; + if (len >= size || n >= size - len) + return -ERANGE; + if (!*bufp) { + /* + * Allocate path buffer from the heap. + */ + *bufp = malloc(size * sizeof(char)); + if (!*bufp) + return -ENOMEM; + } + + /* + * Fill in the path buffer. + */ + pno = cur; + cp = *bufp + len + n; + *cp = '\0'; /* NUL terminate */ + do { + /* + * If this is a covering path-node then the name should be + * the *covered* nodes name, not this one unless we are at + * the root of the name-space. + */ + while (pno == pno->p_mount->mnt_root && + pno != pno->p_parent ) + pno = pno->p_mount->mnt_covers; + + /* + * Add component and separator. + */ + cp -= pno->p_base->pb_key.pbk_name.len; + (void )memcpy(cp, pno->p_base->pb_key.pbk_name.name, + pno->p_base->pb_key.pbk_name.len); + + *--cp = PATH_SEPARATOR; + pno = pno->p_parent; + } while (pno != pno->p_parent); + + return 0; +} + +/* * Allocate, initialize and establish appropriate links for new path (alias) * node. */ @@ -649,6 +743,88 @@ _sysio_p_new_alias(struct pnode *parent, return pno; } +#ifdef P_DEBUG +/* + * Thread-safe strerror. + * + * Returns string describing the passed error number or NULL on failure. + */ +static char * +x_strerror(int err) +{ + char *s; + size_t buflen; + void *p; + int myerr; + + s = NULL; + buflen = 16; + for (;;) { + buflen <<= 1; + p = realloc(s, buflen); + if (!p) + free(s); + s = p; + if (!s) + break; + myerr = 0; +#if defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600 + if (strerror_r(err, s, buflen) != 0) + myerr = errno; +#elif defined(__GNU__) + { + p = strerror_r(err, s, buflen); + if (!p) + myerr = EINVAL; + else if (p != s) { + (void )strncpy(s, (char *)p, buflen - 1); + s[buflen = 1] = '\0'; + } + if (!myerr && strlen(s) == buflen - 1) + myerr = ERANGE; + } +#else +#error I do not know whtat strerror_r returns +#endif + if (!myerr) + break; + if (myerr == ERANGE) + continue; + free(s); + s = NULL; + errno = myerr; + break; + } + return s; +} + +void +_sysio_p_show(const char *pre, struct pnode *pno) +{ + int err; + char *path; + static char error_message[] = "<ERROR>"; + + path = NULL; + if ((err = _sysio_p_path(pno, &path, 0)) != 0) { + char *s; + + s = x_strerror(-err); + if (!s ||(path = malloc(strlen(s) + 2 + 1)) == NULL) { + if (s) + free(s); + path = error_message; + } else { + (void )sprintf(path, "<%s>", s); + free(s); + } + } + _sysio_diag_printf(pre, "%x:%x %s\n", pno->p_mount, pno, path); + if (path != error_message) + free(path); +} +#endif + /* * For reclamation of idle path (alias) node. */ @@ -658,6 +834,9 @@ _sysio_p_gone(struct pnode *pno) assert(!pno->p_ref); assert(!pno->p_cover); +#ifdef P_DEBUG + _sysio_p_show("P_GONE", pno); +#endif TAILQ_REMOVE(&_sysio_idle_pnodes, pno, p_idle); LIST_REMOVE(pno, p_links); @@ -758,8 +937,12 @@ _sysio_p_find_alias(struct pnode *parent if (!pno) err = -ENOMEM; } - if (!err) + if (!err) { +#ifdef P_DEBUG + _sysio_p_show("P_FIND_ALIAS", pno); +#endif *pnop = pno; + } return err; } |