static int my_g_metadata_store(const char *name, u_char *md, size_t size) { char path[MAXPATHLEN]; unsigned sectorsize; off_t mediasize; u_char *sector; int error, fd; pathgen(name, path, sizeof(path)); sector = NULL; error = 0; fd = open(path, O_RDWR); if (fd == -1) return (errno); mediasize = g_get_mediasize(name); if (mediasize == 0) { error = errno; goto out; } sectorsize = g_get_sectorsize(name); if (sectorsize == 0) { error = errno; goto out; } assert(sectorsize >= size); sector = malloc(sectorsize); if (sector == NULL) { error = ENOMEM; goto out; } bcopy(md, sector, size); if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) != (ssize_t)sectorsize) { error = errno; goto out; } out: if (sector != NULL) free(sector); close(fd); return (error); }
int main(void) { int i; char buf[PATH_MAX]; DIR *cwd; struct req req; char *p, *path, *subpath; /* Scan our run-time environment. */ if (NULL == (cache = getenv("CACHE_DIR"))) cache = "/cache/man.cgi"; if (NULL == (progname = getenv("SCRIPT_NAME"))) progname = ""; if (NULL == (css = getenv("CSS_DIR"))) css = ""; if (NULL == (host = getenv("HTTP_HOST"))) host = "localhost"; /* * First we change directory into the cache directory so that * subsequent scanning for manpath directories is rooted * relative to the same position. */ if (-1 == chdir(cache)) { perror(cache); resp_bad(); return(EXIT_FAILURE); } else if (NULL == (cwd = opendir(cache))) { perror(cache); resp_bad(); return(EXIT_FAILURE); } memset(&req, 0, sizeof(struct req)); strlcpy(buf, ".", PATH_MAX); pathgen(cwd, buf, &req); closedir(cwd); /* Next parse out the query string. */ if (NULL != (p = getenv("QUERY_STRING"))) http_parse(&req, p); /* * Now juggle paths to extract information. * We want to extract our filetype (the file suffix), the * initial path component, then the trailing component(s). * Start with leading subpath component. */ subpath = path = NULL; req.page = PAGE__MAX; if (NULL == (path = getenv("PATH_INFO")) || '\0' == *path) req.page = PAGE_INDEX; if (NULL != path && '/' == *path && '\0' == *++path) req.page = PAGE_INDEX; /* Strip file suffix. */ if (NULL != path && NULL != (p = strrchr(path, '.'))) if (NULL != p && NULL == strchr(p, '/')) *p++ = '\0'; /* Resolve subpath component. */ if (NULL != path && NULL != (subpath = strchr(path, '/'))) *subpath++ = '\0'; /* Map path into one we recognise. */ if (NULL != path && '\0' != *path) for (i = 0; i < (int)PAGE__MAX; i++) if (0 == strcmp(pages[i], path)) { req.page = (enum page)i; break; } /* Route pages. */ switch (req.page) { case (PAGE_INDEX): pg_index(&req, subpath); break; case (PAGE_SEARCH): pg_search(&req, subpath); break; case (PAGE_SHOW): pg_show(&req, subpath); break; default: resp_error404(path); break; } for (i = 0; i < (int)req.psz; i++) { free(req.p[i].path); free(req.p[i].name); } free(req.p); return(EXIT_SUCCESS); }
int main(void) { struct req req; struct itimerval itimer; const char *path; const char *querystring; int i; /* Poor man's ReDoS mitigation. */ itimer.it_value.tv_sec = 2; itimer.it_value.tv_usec = 0; itimer.it_interval.tv_sec = 2; itimer.it_interval.tv_usec = 0; if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) { fprintf(stderr, "setitimer: %s\n", strerror(errno)); pg_error_internal(); return(EXIT_FAILURE); } /* Scan our run-time environment. */ if (NULL == (scriptname = getenv("SCRIPT_NAME"))) scriptname = ""; if ( ! validate_urifrag(scriptname)) { fprintf(stderr, "unsafe SCRIPT_NAME \"%s\"\n", scriptname); pg_error_internal(); return(EXIT_FAILURE); } /* * First we change directory into the MAN_DIR so that * subsequent scanning for manpath directories is rooted * relative to the same position. */ if (-1 == chdir(MAN_DIR)) { fprintf(stderr, "MAN_DIR: %s: %s\n", MAN_DIR, strerror(errno)); pg_error_internal(); return(EXIT_FAILURE); } memset(&req, 0, sizeof(struct req)); pathgen(&req); /* Next parse out the query string. */ if (NULL != (querystring = getenv("QUERY_STRING"))) http_parse(&req, querystring); if (req.q.manpath == NULL) req.q.manpath = mandoc_strdup(req.p[0]); else if ( ! validate_manpath(&req, req.q.manpath)) { pg_error_badrequest( "You specified an invalid manpath."); return(EXIT_FAILURE); } if ( ! (NULL == req.q.arch || validate_urifrag(req.q.arch))) { pg_error_badrequest( "You specified an invalid architecture."); return(EXIT_FAILURE); } /* Dispatch to the three different pages. */ path = getenv("PATH_INFO"); if (NULL == path) path = ""; else if ('/' == *path) path++; if ('\0' != *path) pg_show(&req, path); else if (NULL != req.q.query) pg_search(&req); else pg_index(&req); free(req.q.manpath); free(req.q.arch); free(req.q.sec); free(req.q.query); for (i = 0; i < (int)req.psz; i++) free(req.p[i]); free(req.p); return(EXIT_SUCCESS); }
/* * Scan for indexable paths. * This adds all paths with "etc/catman.conf" to the buffer. */ static void pathgen(DIR *dir, char *path, struct req *req) { struct dirent *d; char *cp; DIR *cd; int rc; size_t sz, ssz; sz = strlcat(path, "/", PATH_MAX); if (sz >= PATH_MAX) { fprintf(stderr, "%s: Path too long", path); return; } /* * First, scan for the "etc" directory. * If it's found, then see if it should cause us to stop. This * happens when a catman.conf is found in the directory. */ rc = 0; while (0 == rc && NULL != (d = readdir(dir))) { if (DT_DIR != d->d_type || strcmp(d->d_name, "etc")) continue; path[(int)sz] = '\0'; ssz = strlcat(path, d->d_name, PATH_MAX); if (ssz >= PATH_MAX) { fprintf(stderr, "%s: Path too long", path); return; } else if (NULL == (cd = opendir(path))) { perror(path); return; } rc = pathstop(cd); closedir(cd); } if (rc > 0) { /* This also strips the trailing slash. */ path[(int)--sz] = '\0'; req->p = mandoc_realloc (req->p, (req->psz + 1) * sizeof(struct paths)); /* * Strip out the leading "./" unless we're just a ".", * in which case use an empty string as our name. */ req->p[(int)req->psz].path = mandoc_strdup(path); req->p[(int)req->psz].name = cp = mandoc_strdup(path + (1 == sz ? 1 : 2)); req->psz++; /* * The name is just the path with all the slashes taken * out of it. Simple but effective. */ for ( ; '\0' != *cp; cp++) if ('/' == *cp) *cp = ' '; return; } /* * If no etc/catman.conf was found, recursively enter child * directory and continue scanning. */ rewinddir(dir); while (NULL != (d = readdir(dir))) { if (DT_DIR != d->d_type || '.' == d->d_name[0]) continue; path[(int)sz] = '\0'; ssz = strlcat(path, d->d_name, PATH_MAX); if (ssz >= PATH_MAX) { fprintf(stderr, "%s: Path too long", path); return; } else if (NULL == (cd = opendir(path))) { perror(path); return; } pathgen(cd, path, req); closedir(cd); } }