* Resolve a symlink. Called by filesystem-specific routines. * * Code flow is: * ... -> cache_fplookup_symlink -> VOP_FPLOOKUP_SYMLINK -> cache_symlink_resolve */
| 4856 | * ... -> cache_fplookup_symlink -> VOP_FPLOOKUP_SYMLINK -> cache_symlink_resolve |
| 4857 | */ |
| 4858 | int |
| 4859 | cache_symlink_resolve(struct cache_fpl *fpl, const char *string, size_t len) |
| 4860 | { |
| 4861 | struct nameidata *ndp; |
| 4862 | struct componentname *cnp; |
| 4863 | size_t adjust; |
| 4864 | |
| 4865 | ndp = fpl->ndp; |
| 4866 | cnp = fpl->cnp; |
| 4867 | |
| 4868 | if (__predict_false(len == 0)) { |
| 4869 | return (ENOENT); |
| 4870 | } |
| 4871 | |
| 4872 | if (__predict_false(len > MAXPATHLEN - 2)) { |
| 4873 | if (cache_fpl_istrailingslash(fpl)) { |
| 4874 | return (EAGAIN); |
| 4875 | } |
| 4876 | } |
| 4877 | |
| 4878 | ndp->ni_pathlen = fpl->nulchar - cnp->cn_nameptr - cnp->cn_namelen + 1; |
| 4879 | #ifdef INVARIANTS |
| 4880 | if (ndp->ni_pathlen != fpl->debug.ni_pathlen) { |
| 4881 | panic("%s: mismatch (%zu != %zu) nulchar %p nameptr %p [%s] ; full string [%s]\n", |
| 4882 | __func__, ndp->ni_pathlen, fpl->debug.ni_pathlen, fpl->nulchar, |
| 4883 | cnp->cn_nameptr, cnp->cn_nameptr, cnp->cn_pnbuf); |
| 4884 | } |
| 4885 | #endif |
| 4886 | |
| 4887 | if (__predict_false(len + ndp->ni_pathlen > MAXPATHLEN)) { |
| 4888 | return (ENAMETOOLONG); |
| 4889 | } |
| 4890 | |
| 4891 | if (__predict_false(ndp->ni_loopcnt++ >= MAXSYMLINKS)) { |
| 4892 | return (ELOOP); |
| 4893 | } |
| 4894 | |
| 4895 | adjust = len; |
| 4896 | if (ndp->ni_pathlen > 1) { |
| 4897 | bcopy(ndp->ni_next, cnp->cn_pnbuf + len, ndp->ni_pathlen); |
| 4898 | } else { |
| 4899 | if (cache_fpl_istrailingslash(fpl)) { |
| 4900 | adjust = len + 1; |
| 4901 | cnp->cn_pnbuf[len] = '/'; |
| 4902 | cnp->cn_pnbuf[len + 1] = '\0'; |
| 4903 | } else { |
| 4904 | cnp->cn_pnbuf[len] = '\0'; |
| 4905 | } |
| 4906 | } |
| 4907 | bcopy(string, cnp->cn_pnbuf, len); |
| 4908 | |
| 4909 | ndp->ni_pathlen += adjust; |
| 4910 | cache_fpl_pathlen_add(fpl, adjust); |
| 4911 | cnp->cn_nameptr = cnp->cn_pnbuf; |
| 4912 | fpl->nulchar = &cnp->cn_nameptr[ndp->ni_pathlen - 1]; |
| 4913 | fpl->tvp = NULL; |
| 4914 | return (0); |
| 4915 | } |
no test coverage detected