dgaudet 97/06/30 15:50:45
Modified: src CHANGES http_core.c http_request.c httpd.h mod_negotiation.c util.c Log: directory_walk() is an expensive function, keep a little more state to avoid needless string counting. Add two new functions make_dirstr_parent and make_dirstr_prefix which replace all existing uses of make_dirstr. The new functions are a little less general than make_dirstr, but work more efficiently (less memory, less string counting). Revision Changes Path 1.316 +7 -0 apache/src/CHANGES Index: CHANGES =================================================================== RCS file: /export/home/cvs/apache/src/CHANGES,v retrieving revision 1.315 retrieving revision 1.316 diff -C3 -r1.315 -r1.316 *** CHANGES 1997/06/30 21:42:29 1.315 --- CHANGES 1997/06/30 22:50:38 1.316 *************** *** 1,4 **** --- 1,11 ---- Changes with Apache 1.3 + + *) directory_walk() is an expensive function, keep a little more state to + avoid needless string counting. Add two new functions make_dirstr_parent + and make_dirstr_prefix which replace all existing uses of make_dirstr. + The new functions are a little less general than make_dirstr, but + work more efficiently (less memory, less string counting). + [Dean Gaudet] *) EXTRA_LFLAGS was changed to EXTRA_LDFLAGS (and LFLAGS was changed to LDFLAGS) to avoid complications with lex rules in make files. 1.90 +1 -1 apache/src/http_core.c Index: http_core.c =================================================================== RCS file: /export/home/cvs/apache/src/http_core.c,v retrieving revision 1.89 retrieving revision 1.90 diff -C3 -r1.89 -r1.90 *** http_core.c 1997/06/29 17:53:03 1.89 --- http_core.c 1997/06/30 22:50:39 1.90 *************** *** 117,123 **** core_dir_config *base = (core_dir_config *)basev; core_dir_config *new = (core_dir_config *)newv; core_dir_config *conf = ! (core_dir_config *)pcalloc (a, sizeof(core_dir_config)); int i; memcpy ((char *)conf, (const char *)base, sizeof(core_dir_config)); --- 117,123 ---- core_dir_config *base = (core_dir_config *)basev; core_dir_config *new = (core_dir_config *)newv; core_dir_config *conf = ! (core_dir_config *)palloc (a, sizeof(core_dir_config)); int i; memcpy ((char *)conf, (const char *)base, sizeof(core_dir_config)); 1.54 +33 -18 apache/src/http_request.c Index: http_request.c =================================================================== RCS file: /export/home/cvs/apache/src/http_request.c,v retrieving revision 1.53 retrieving revision 1.54 diff -C3 -r1.53 -r1.54 *** http_request.c 1997/06/28 21:46:57 1.53 --- http_request.c 1997/06/30 22:50:39 1.54 *************** *** 251,259 **** core_dir_config **sec = (core_dir_config **)sec_array->elts; int num_sec = sec_array->nelts; char *test_filename = pstrdup (r->pool, r->filename); int num_dirs, res; ! int i; /* Are we dealing with a file? If not, we can (hopefuly) safely assume * we have a handler that doesn't require one, but for safety's sake, --- 251,260 ---- core_dir_config **sec = (core_dir_config **)sec_array->elts; int num_sec = sec_array->nelts; char *test_filename = pstrdup (r->pool, r->filename); + char *test_dirname, *test_htaccess; int num_dirs, res; ! int i, test_filename_len; /* Are we dealing with a file? If not, we can (hopefuly) safely assume * we have a handler that doesn't require one, but for safety's sake, *************** *** 333,360 **** return res; } ! if (test_filename[strlen(test_filename)-1] == '/') --num_dirs; ! if (S_ISDIR (r->finfo.st_mode)) { ! ++num_dirs; ! } for (i = 1; i <= num_dirs; ++i) { core_dir_config *core_dir = (core_dir_config *)get_module_config(per_dir_defaults, &core_module); int overrides_here; void *this_conf = NULL, *htaccess_conf = NULL; ! char *this_dir = make_dirstr (r->pool, test_filename, i); int j; ! /* Do symlink checks first, because they are done with the * permissions appropriate to the *parent* directory... */ ! if ((res = check_symlinks (this_dir, core_dir->opts))) { ! log_reason("Symbolic link not allowed", this_dir, r); return res; } --- 334,367 ---- return res; } ! test_filename_len = strlen (test_filename); ! if (test_filename[test_filename_len-1] == '/') --num_dirs; ! if (S_ISDIR (r->finfo.st_mode)) ++num_dirs; + /* we need somewhere to scratch while building directory names and + * htaccess names + */ + test_dirname = palloc (r->pool, test_filename_len+1); + test_htaccess = NULL; for (i = 1; i <= num_dirs; ++i) { core_dir_config *core_dir = (core_dir_config *)get_module_config(per_dir_defaults, &core_module); int overrides_here; void *this_conf = NULL, *htaccess_conf = NULL; ! char *test_dirname_tail; int j; ! ! test_dirname_tail = make_dirstr_prefix (test_dirname, test_filename, i); ! /* Do symlink checks first, because they are done with the * permissions appropriate to the *parent* directory... */ ! if ((res = check_symlinks (test_dirname, core_dir->opts))) { ! log_reason("Symbolic link not allowed", test_dirname, r); return res; } *************** *** 374,380 **** entry_dir = entry_core->d; if (entry_core->r) { ! if (!regexec(entry_core->r, this_dir, 0, NULL, (j == num_sec) ? 0 : REG_NOTEOL)) { /* Don't try this wildcard again --- if it ends in '*' * it'll match again, and subdirectories won't be able to --- 381,387 ---- entry_dir = entry_core->d; if (entry_core->r) { ! if (!regexec(entry_core->r, test_dirname, 0, NULL, (j == num_sec) ? 0 : REG_NOTEOL)) { /* Don't try this wildcard again --- if it ends in '*' * it'll match again, and subdirectories won't be able to *************** *** 385,395 **** } } else if (entry_core->d_is_matchexp && ! !strcmp_match(this_dir, entry_dir)) { sec[j] = NULL; this_conf = entry_config; } ! else if (!strcmp (this_dir, entry_dir)) this_conf = entry_config; if (this_conf) { --- 392,402 ---- } } else if (entry_core->d_is_matchexp && ! !strcmp_match(test_dirname, entry_dir)) { sec[j] = NULL; this_conf = entry_config; } ! else if (!strcmp (test_dirname, entry_dir)) this_conf = entry_config; if (this_conf) { *************** *** 407,416 **** */ if (overrides_here) { ! char *config_name = make_full_path(r->pool, this_dir, ! sconf->access_name); res = parse_htaccess (&htaccess_conf, r, overrides_here, ! this_dir, config_name); if (res) return res; } --- 414,431 ---- */ if (overrides_here) { ! int len; ! ! if (test_htaccess == NULL) { ! /* we delayed allocating this in case there wasn't a need */ ! test_htaccess = palloc (r->pool, ! test_filename_len + 1 + strlen (sconf->access_name)); ! } ! len = test_dirname_tail - test_dirname; ! memcpy (test_htaccess, test_dirname, len); ! strcpy (test_htaccess + len, sconf->access_name); res = parse_htaccess (&htaccess_conf, r, overrides_here, ! test_dirname, test_htaccess); if (res) return res; } *************** *** 615,621 **** parse_uri(rnew, new_file); else { ! udir = make_dirstr (rnew->pool, r->uri, count_dirs (r->uri)); udir = escape_uri(rnew->pool, udir); /* re-escape it */ parse_uri (rnew, make_full_path (rnew->pool, udir, new_file)); } --- 630,636 ---- parse_uri(rnew, new_file); else { ! udir = make_dirstr_parent (rnew->pool, r->uri); udir = escape_uri(rnew->pool, udir); /* re-escape it */ parse_uri (rnew, make_full_path (rnew->pool, udir, new_file)); } *************** *** 684,690 **** rnew->request_config = create_request_config (rnew->pool); rnew->htaccess = r->htaccess; /* copy htaccess cache */ set_sub_req_protocol (rnew, r); ! fdir = make_dirstr (rnew->pool, r->filename, count_dirs (r->filename)); /* Check for a special case... if there are no '/' characters in new_file * at all, then we are looking at a relative lookup in the same directory. --- 699,705 ---- rnew->request_config = create_request_config (rnew->pool); rnew->htaccess = r->htaccess; /* copy htaccess cache */ set_sub_req_protocol (rnew, r); ! fdir = make_dirstr_parent (rnew->pool, r->filename); /* Check for a special case... if there are no '/' characters in new_file * at all, then we are looking at a relative lookup in the same directory. *************** *** 693,699 **** */ if (strchr (new_file, '/') == NULL) { ! char *udir = make_dirstr(rnew->pool, r->uri, count_dirs(r->uri)); rnew->uri = make_full_path (rnew->pool, udir, new_file); rnew->filename = make_full_path (rnew->pool, fdir, new_file); --- 708,714 ---- */ if (strchr (new_file, '/') == NULL) { ! char *udir = make_dirstr_parent (rnew->pool, r->uri); rnew->uri = make_full_path (rnew->pool, udir, new_file); rnew->filename = make_full_path (rnew->pool, fdir, new_file); 1.121 +3 -0 apache/src/httpd.h Index: httpd.h =================================================================== RCS file: /export/home/cvs/apache/src/httpd.h,v retrieving revision 1.120 retrieving revision 1.121 diff -C3 -r1.120 -r1.121 *** httpd.h 1997/06/30 21:10:02 1.120 --- httpd.h 1997/06/30 22:50:40 1.121 *************** *** 712,717 **** --- 712,720 ---- char *escape_shell_cmd (pool *p, const char *s); int count_dirs(const char *path); + char *make_dirstr_prefix (char *d, const char *s, int n); + char *make_dirstr_parent (pool *p, const char *s); + /* deprecated. The previous two routines are preferred. */ char *make_dirstr(pool *a, const char *s, int n); char *make_full_path(pool *a, const char *dir, const char *f); 1.44 +2 -2 apache/src/mod_negotiation.c Index: mod_negotiation.c =================================================================== RCS file: /export/home/cvs/apache/src/mod_negotiation.c,v retrieving revision 1.43 retrieving revision 1.44 diff -C3 -r1.43 -r1.44 *** mod_negotiation.c 1997/06/24 03:03:49 1.43 --- mod_negotiation.c 1997/06/30 22:50:40 1.44 *************** *** 444,450 **** new->pool = r->pool; new->r = r; ! new->dir_name = make_dirstr(r->pool, r->filename, count_dirs(r->filename)); new->accepts = do_header_line (r->pool, table_get (hdrs, "Accept")); --- 444,450 ---- new->pool = r->pool; new->r = r; ! new->dir_name = make_dirstr_parent (r->pool, r->filename); new->accepts = do_header_line (r->pool, table_get (hdrs, "Accept")); *************** *** 1899,1905 **** if (r->path_info && *r->path_info) { r->uri[find_path_info(r->uri, r->path_info)] = '\0'; } ! udir = make_dirstr (r->pool, r->uri, count_dirs (r->uri)); udir = escape_uri(r->pool, udir); internal_redirect(pstrcat(r->pool, udir, best->file_name, r->path_info, NULL), r); --- 1899,1905 ---- if (r->path_info && *r->path_info) { r->uri[find_path_info(r->uri, r->path_info)] = '\0'; } ! udir = make_dirstr_parent (r->pool, r->uri); udir = escape_uri(r->pool, udir); internal_redirect(pstrcat(r->pool, udir, best->file_name, r->path_info, NULL), r); 1.59 +55 -0 apache/src/util.c Index: util.c =================================================================== RCS file: /export/home/cvs/apache/src/util.c,v retrieving revision 1.58 retrieving revision 1.59 diff -C3 -r1.58 -r1.59 *** util.c 1997/06/29 17:26:59 1.58 --- util.c 1997/06/30 22:50:41 1.59 *************** *** 339,344 **** --- 339,399 ---- else x++; } + + /* + * copy at most n leading directories of s into d + * d should be at least as large as s plus 1 extra byte + * assumes n > 0 + * the return value is the ever useful pointer to the trailing \0 of d + * + * examples: + * /a/b, 1 ==> / + * /a/b, 2 ==> /a/ + * /a/b, 3 ==> /a/b/ + * /a/b, 4 ==> /a/b/ + */ + char *make_dirstr_prefix (char *d, const char *s, int n) + { + for(;;) { + *d = *s; + if (*d == '\0') { + *d = '/'; + break; + } + if (*d == '/' && (--n) == 0 ) break; + ++d; + ++s; + } + *++d = 0; + return (d); + } + + + /* + * return the parent directory name including trailing / of the file s + */ + char *make_dirstr_parent (pool *p, const char *s) + { + char *last_slash = strrchr (s, '/'); + char *d; + int l; + + if (last_slash == NULL) { + /* XXX: well this is really broken if this happens */ + return (pstrdup (p,"/")); + } + l = (last_slash-s)+1; + d = palloc (p, l+1); + memcpy (d, s, l); + d[l] = 0; + return (d); + } + + + /* + * This function is deprecated. Use one of the preceeding two functions + * which are faster. + */ char *make_dirstr(pool *p, const char *s, int n) { register int x,f; char *res;