📄 filepath.c
字号:
#endif /* ndef(NETWARE) */}APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath, const char *basepath, const char *addpath, apr_int32_t flags, apr_pool_t *p){ char path[APR_PATH_MAX]; /* isn't null term */ const char *baseroot = NULL; const char *addroot; apr_size_t rootlen; /* the length of the root portion of path, d:/ is 3 */ apr_size_t baselen; /* the length of basepath (excluding baseroot) */ apr_size_t keptlen; /* the length of the retained basepath (incl root) */ apr_size_t pathlen; /* the length of the result path */ apr_size_t segend; /* the end of the current segment */ apr_size_t seglen; /* the length of the segment (excl trailing chars) */ apr_status_t basetype = 0; /* from parsing the basepath's baseroot */ apr_status_t addtype; /* from parsing the addpath's addroot */ apr_status_t rv;#ifndef NETWARE int fixunc = 0; /* flag to complete an incomplete UNC basepath */#endif /* Treat null as an empty path, otherwise split addroot from the addpath */ if (!addpath) { addpath = addroot = ""; addtype = APR_ERELATIVE; } else { /* This call _should_ test the path */ addtype = apr_filepath_root(&addroot, &addpath, APR_FILEPATH_TRUENAME | (flags & APR_FILEPATH_NATIVE), p); if (addtype == APR_SUCCESS) { addtype = APR_EABSOLUTE; } else if (addtype == APR_ERELATIVE) { addroot = ""; } else if (addtype != APR_EINCOMPLETE) { /* apr_filepath_root was incomprehensible so fail already */ return addtype; } } /* If addpath is (even partially) rooted, then basepath is * unused. Ths violates any APR_FILEPATH_SECUREROOTTEST * and APR_FILEPATH_NOTABSOLUTE flags specified. */ if (addtype == APR_EABSOLUTE || addtype == APR_EINCOMPLETE) { if (flags & APR_FILEPATH_SECUREROOTTEST) return APR_EABOVEROOT; if (flags & APR_FILEPATH_NOTABSOLUTE) return addtype; } /* Optimized tests before we query the current working path */ if (!basepath) { /* If APR_FILEPATH_NOTABOVEROOT wasn't specified, * we won't test the root again, it's ignored. * Waste no CPU retrieving the working path. */ if (addtype == APR_EABSOLUTE && !(flags & APR_FILEPATH_NOTABOVEROOT)) { basepath = baseroot = ""; basetype = APR_ERELATIVE; } /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller * requires an absolutely relative result, So do not retrieve * the working path. */ if (addtype == APR_ERELATIVE && (flags & APR_FILEPATH_NOTABSOLUTE)) { basepath = baseroot = ""; basetype = APR_ERELATIVE; } } if (!basepath) { /* Start with the current working path. This is bass akwards, * but required since the compiler (at least vc) doesn't like * passing the address of a char const* for a char** arg. * We must grab the current path of the designated drive * if addroot is given in drive-relative form (e.g. d:foo) */ char *getpath;#ifndef NETWARE if (addtype == APR_EINCOMPLETE && addroot[1] == ':') rv = filepath_drive_get(&getpath, addroot[0], flags, p); else#endif rv = apr_filepath_get(&getpath, flags, p); if (rv != APR_SUCCESS) return rv; basepath = getpath; } if (!baseroot) { /* This call should _not_ test the path */ basetype = apr_filepath_root(&baseroot, &basepath, (flags & APR_FILEPATH_NATIVE), p); if (basetype == APR_SUCCESS) { basetype = APR_EABSOLUTE; } else if (basetype == APR_ERELATIVE) { baseroot = ""; } else if (basetype != APR_EINCOMPLETE) { /* apr_filepath_root was incomprehensible so fail already */ return basetype; } } baselen = strlen(basepath); /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller * requires an absolutely relative result. If the given * basepath is not relative then fail. */ if ((flags & APR_FILEPATH_NOTABSOLUTE) && basetype != APR_ERELATIVE) return basetype; /* The Win32 nightmare on unc street... start combining for * many possible root combinations. */ if (addtype == APR_EABSOLUTE) { /* Ignore the given root path, and start with the addroot */ if ((flags & APR_FILEPATH_NOTABOVEROOT) && strncmp(baseroot, addroot, strlen(baseroot))) return APR_EABOVEROOT; keptlen = 0; rootlen = pathlen = strlen(addroot); memcpy(path, addroot, pathlen); } else if (addtype == APR_EINCOMPLETE) { /* There are several types of incomplete paths, * incomplete UNC paths (//foo/ or //), * drives without rooted paths (d: as in d:foo), * and simple roots (/ as in /foo). * Deal with these in significantly different manners... */#ifndef NETWARE if ((addroot[0] == '/' || addroot[0] == '\\') && (addroot[1] == '/' || addroot[1] == '\\')) { /* Ignore the given root path if the incomplete addpath is UNC, * (note that the final result will be incomplete). */ if (flags & APR_FILEPATH_NOTRELATIVE) return addtype; if ((flags & APR_FILEPATH_NOTABOVEROOT) && strncmp(baseroot, addroot, strlen(baseroot))) return APR_EABOVEROOT; fixunc = 1; keptlen = 0; rootlen = pathlen = strlen(addroot); memcpy(path, addroot, pathlen); } else#endif if ((addroot[0] == '/' || addroot[0] == '\\') && !addroot[1]) { /* Bring together the drive or UNC root from the baseroot * if the addpath is a simple root and basepath is rooted, * otherwise disregard the basepath entirely. */ if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE)) return basetype; if (basetype != APR_ERELATIVE) {#ifndef NETWARE if (basetype == APR_INCOMPLETE && (baseroot[0] == '/' || baseroot[0] == '\\') && (baseroot[1] == '/' || baseroot[1] == '\\')) fixunc = 1;#endif keptlen = rootlen = pathlen = strlen(baseroot); memcpy(path, baseroot, pathlen); } else { if (flags & APR_FILEPATH_NOTABOVEROOT) return APR_EABOVEROOT; keptlen = 0; rootlen = pathlen = strlen(addroot); memcpy(path, addroot, pathlen); } }#ifdef NETWARE else if (filepath_has_drive(addroot, DRIVE_ONLY, p)) { /* If the addroot is a drive (without a volume root) * use the basepath _if_ it matches this drive letter! * Otherwise we must discard the basepath. */ if (!filepath_compare_drive(addroot, baseroot, p) && filepath_has_drive(baseroot, 0, p)) {#else else if (addroot[0] && addroot[1] == ':' && !addroot[2]) { /* If the addroot is a drive (without a volume root) * use the basepath _if_ it matches this drive letter! * Otherwise we must discard the basepath. */ if (addroot[0] == baseroot[0] && baseroot[1] == ':') {#endif /* Base the result path on the basepath */ if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE)) return basetype; rootlen = strlen(baseroot); keptlen = pathlen = rootlen + baselen; if (keptlen >= sizeof(path)) return APR_ENAMETOOLONG; memcpy(path, baseroot, rootlen); memcpy(path + rootlen, basepath, baselen); } else { if (flags & APR_FILEPATH_NOTRELATIVE) return addtype; if (flags & APR_FILEPATH_NOTABOVEROOT) return APR_EABOVEROOT; keptlen = 0; rootlen = pathlen = strlen(addroot); memcpy(path, addroot, pathlen); } } else { /* Now this is unexpected, we aren't aware of any other * incomplete path forms! Fail now. */ return APR_EBADPATH; } } else { /* addtype == APR_ERELATIVE */ /* If both paths are relative, fail early */ if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE)) return basetype;#ifndef NETWARE /* An incomplete UNC path must be completed */ if (basetype == APR_INCOMPLETE && (baseroot[0] == '/' || baseroot[0] == '\\') && (baseroot[1] == '/' || baseroot[1] == '\\')) fixunc = 1;#endif /* Base the result path on the basepath */ rootlen = strlen(baseroot); keptlen = pathlen = rootlen + baselen; if (keptlen >= sizeof(path)) return APR_ENAMETOOLONG; memcpy(path, baseroot, rootlen); memcpy(path + rootlen, basepath, baselen); } /* '/' terminate the given root path unless it's already terminated * or is an incomplete drive root. Correct the trailing slash unless * we have an incomplete UNC path still to fix. */ if (pathlen && path[pathlen - 1] != ':') { if (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\') { if (pathlen + 1 >= sizeof(path)) return APR_ENAMETOOLONG; path[pathlen++] = ((flags & APR_FILEPATH_NATIVE) ? '\\' : '/'); } /* XXX: wrong, but gotta figure out what I intended; * else if (!fixunc) * path[pathlen++] = ((flags & APR_FILEPATH_NATIVE) ? '\\' : '/'); */ } while (*addpath) { /* Parse each segment, find the closing '/' */ seglen = 0; while (addpath[seglen] && addpath[seglen] != '/' && addpath[seglen] != '\\') ++seglen; /* Truncate all trailing spaces and all but the first two dots */ segend = seglen; while (seglen && (addpath[seglen - 1] == ' ' || addpath[seglen - 1] == '.')) { if (seglen > 2 || addpath[seglen - 1] != '.' || addpath[0] != '.') --seglen; else break; } if (seglen == 0 || (seglen == 1 && addpath[0] == '.')) { /* NOTE: win32 _hates_ '/ /' and '/. /' (yes, with spaces in there) * so eliminate all preconceptions that it is valid. */ if (seglen < segend) return APR_EBADPATH;#ifndef NETWARE /* This isn't legal unless the unc path is completed */ if (fixunc) return APR_EBADPATH;#endif /* Otherwise, this is a noop segment (/ or ./) so ignore it */ } else if (seglen == 2 && addpath[0] == '.' && addpath[1] == '.')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -