return (http_req_chk_dir(con, req)); else if (req->conf_friendly_file && ((errno == ENOENT) || (errno == ENOTDIR) ||  (errno == ENAMETOOLONG) ||  FALSE))
int http_req_op_get(struct Con *con, Httpd_req_data *req){ /* GET or HEAD ops */  Vstr_base *data = con->evnt->io_r;  Vstr_base *out  = con->evnt->io_w;  Vstr_base *fname = req->fname;  const char *fname_cstr = NULL;  unsigned int http_ret_code = 200;  const char * http_ret_line = "OK";    if (fname->conf->malloc_bad)    goto malloc_err;  assert(VPREFIX(fname, 1, fname->len, "/"));  /* final act of vengance, before policy */  if (vstr_srch_cstr_buf_fwd(data, req->path_pos, req->path_len, "//"))  { /* in theory we can skip this if there is no policy */    vstr_sub_vstr(fname, 1, fname->len, data, req->path_pos, req->path_len, 0);    if (!httpd_canon_path(fname))      goto malloc_err;    httpd_req_absolute_uri(con, req, fname, 1, fname->len);    HTTPD_ERR_301(req);      return (http_fin_err_req(con, req));  }    if (!http__policy_req(con, req))    return (FALSE);  if (req->error_code)    return (http_fin_err_req(con, req));  httpd_sc_add_default_filename(req, fname);    if (!http__conf_req(con, req))    return (FALSE);  if (req->error_code)    return (http_fin_err_req(con, req));      if (!http_req_content_type(req))    return (http_fin_err_req(con, req));  /* don't change vary_a/vary_al just because of 406 */  if (req->parse_accept)  {    if (!http_parse_accept(req, HTTP__XTRA_HDR_PARAMS(req, content_type)))      HTTPD_ERR_RET(req, 406, http_fin_err_req(con, req));  }  if (!req->content_language_vs1 || !req->content_language_len)    req->parse_accept_language = FALSE;  if (req->parse_accept_language)  {    if (!http_parse_accept_language(req,                                    HTTP__XTRA_HDR_PARAMS(req,                                                          content_language)))      HTTPD_ERR_RET(req, 406, http_fin_err_req(con, req));  }    /* Add the document root now, this must be at least . so   * "///foo" becomes ".///foo" ... this is done now   * so nothing has to deal with document_root values */  if (!req->skip_document_root)    http_prepend_doc_root(fname, req);    fname_cstr = vstr_export_cstr_ptr(fname, 1, fname->len);    if (fname->conf->malloc_bad)    goto malloc_err;  ASSERT(con->fs && !con->fs_num && !con->fs_off && (con->fs->fd == -1));  if ((con->fs->fd = io_open_nonblock(fname_cstr)) == -1)  {    if (0) { }    else if (req->direct_filename && (errno == EISDIR)) /* don't allow */      HTTPD_ERR(req, 404);    else if (errno == EISDIR)      return (http_req_chk_dir(con, req));    else if (((errno == ENOENT) && req->conf_friendly_dirs) ||             (errno == ENOTDIR) || /* part of path was not a dir */             (errno == ENAMETOOLONG) || /* 414 ? */             FALSE)      return (http_req_chk_file(con, req));    else if (errno == EACCES)      HTTPD_ERR(req, 403);    else if ((errno == ENOENT) ||             (errno == ENODEV) || /* device file, with no driver */             (errno == ENXIO) || /* device file, with no driver */             (errno == ELOOP) || /* symlinks */             FALSE)      HTTPD_ERR(req, 404);    else      HTTPD_ERR(req, 500);        return (http_fin_err_req(con, req));  }  if (fstat64(con->fs->fd, req->f_stat) == -1)    HTTPD_ERR_RET(req, 500, http_fin_err_close_req(con, req));  if (req->policy->use_public_only && !(req->f_stat->st_mode & S_IROTH))    HTTPD_ERR_RET(req, 403, http_fin_err_close_req(con, req));    if (S_ISDIR(req->f_stat->st_mode))  {    if (req->direct_filename) /* don't allow */      HTTPD_ERR_RET(req, 404, http_fin_err_close_req(con, req));    httpd_fin_fd_close(con);    return (http_req_chk_dir(con, req));  }  if (!S_ISREG(req->f_stat->st_mode))    HTTPD_ERR_RET(req, 403, http_fin_err_close_req(con, req));    con->fs->len = req->f_stat->st_size;    if (req->ver_0_9)  {    httpd_serv_file_sects_none(con, req);    httpd_serv_call_file_init(con, req, &http_ret_code, &http_ret_line);    http_ret_line = "OK - HTTP/0.9";  }  else if (!http_req_1_x(con, req, &http_ret_code, &http_ret_line))    return (http_fin_err_close_req(con, req));    if (out->conf->malloc_bad)    goto malloc_close_err;    vlg_dbg3(vlg, "REPLY:\n$<vstr.all:%p>\n", out);    if (con->use_mmap && !vstr_mov(con->evnt->io_w, con->evnt->io_w->len,                                 req->f_mmap, 1, req->f_mmap->len))    goto malloc_close_err;  /* req->head_op is set for 304 returns */  vlg_info(vlg, "REQ $<vstr.sect:%p%p%u> from[$<sa:%p>] ret[%03u %s]"           " sz[${BKMG.ju:%ju}:%ju]", data, req->sects, 1U, CON_CEVNT_SA(con),           http_ret_code, http_ret_line, con->fs->len, con->fs->len);  http_vlg_def(con, req);    return (http_fin_fd_req(con, req));   malloc_close_err:  httpd_fin_fd_close(con); malloc_err:  VLG_WARNNOMEM_RET(http_fin_errmem_req(con, req), (vlg, "op_get(): %m\n"));}