Example #1
0
/*
 * Print a list of available virtual hosts
 */
void vhostlist(state *st)
{
	sdirent dir[MAX_SDIRENT];
	struct tm *ltime;
	char timestr[20];
	char buf[BUFSIZE];
	int width;
	int num;
	int i;

	/* Scan the root dir for vhost dirs */
	num = sortdir(st->server_root, dir, MAX_SDIRENT);
	if (num < 0) die(st, ERR_NOTFOUND, "WTF?");

	/* Width of filenames for fancy listing */
	width = st->out_width - DATE_WIDTH - 15;

	/* Loop through the directory entries */
	for (i = 0; i < num; i++) {

		/* Skip dotfiles */
		if (dir[i].name[0] == '.') continue;

		/* Require FQDN */
		if (!strchr(dir[i].name, '.')) continue;

		/* We only want world-readable directories */
		if ((dir[i].mode & S_IROTH) == 0) continue;
		if ((dir[i].mode & S_IFMT) != S_IFDIR) continue;

		/* Generate display string for vhost */
		snprintf(buf, sizeof(buf), VHOST_FORMAT, dir[i].name);

		/* Fancy listing */
		if (st->opt_date) {
			ltime = localtime(&dir[i].mtime);
			strftime(timestr, sizeof(timestr), DATE_FORMAT, ltime);

			printf("1%-*.*s   %s        -  \t/;%s\t%s\t%i" CRLF,
				width, width, buf, timestr, dir[i].name, 
				dir[i].name, st->server_port);
		}

		/* Teh boring version */
		else {
			printf("1%.*s\t/;%s\t%s\t%i" CRLF, st->out_width, buf,
				dir[i].name, dir[i].name, st->server_port);
		}
	}
}
Example #2
0
static
int
check_dir(uint32_t ino, uint32_t parentino, const char *pathsofar)
{
	struct sfs_inode sfi;
	struct sfs_dir *direntries;
	int *sortvector;
	uint32_t dirsize, ndirentries, maxdirentries, subdircount, i;
	int ichanged=0, dchanged=0, dotseen=0, dotdotseen=0;

	diskread(&sfi, ino);
	swapinode(&sfi);

	if (remember_dir(ino, pathsofar)) {
		/* crosslinked dir */
		return 1;
	}

	bitmap_mark(ino, B_INODE, ino);
	count_dirs++;

	if (sfi.sfi_size % sizeof(struct sfs_dir) != 0) {
		setbadness(EXIT_RECOV);
		warnx("Directory /%s has illegal size %lu (fixed)",
		      pathsofar, (unsigned long) sfi.sfi_size);
		sfi.sfi_size = SFS_ROUNDUP(sfi.sfi_size,
					   sizeof(struct sfs_dir));
		ichanged = 1;
	}

	if (check_inode_blocks(ino, &sfi, 1)) {
		ichanged = 1;
	}

	ndirentries = sfi.sfi_size/sizeof(struct sfs_dir);
	maxdirentries = SFS_ROUNDUP(ndirentries,
				    SFS_BLOCKSIZE/sizeof(struct sfs_dir));
	dirsize = maxdirentries * sizeof(struct sfs_dir);
	direntries = domalloc(dirsize);
	sortvector = domalloc(ndirentries * sizeof(int));

	dirread(&sfi, direntries, ndirentries);
	for (i=ndirentries; i<maxdirentries; i++) {
		direntries[i].sfd_ino = SFS_NOINO;
		bzero(direntries[i].sfd_name, sizeof(direntries[i].sfd_name));
	}

	for (i=0; i<ndirentries; i++) {
		if (check_dir_entry(pathsofar, i, &direntries[i])) {
			dchanged = 1;
		}
		sortvector[i] = i;
	}

	sortdir(sortvector, direntries, ndirentries);

	/* don't use ndirentries-1 here in case ndirentries == 0 */
	for (i=0; i+1<ndirentries; i++) {
		struct sfs_dir *d1 = &direntries[sortvector[i]];
		struct sfs_dir *d2 = &direntries[sortvector[i+1]];
		assert(d1 != d2);

		if (d1->sfd_ino == SFS_NOINO) {
			continue;
		}

		if (!strcmp(d1->sfd_name, d2->sfd_name)) {
			if (d1->sfd_ino == d2->sfd_ino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Duplicate entries for "
				      "%s (merged)",
				      pathsofar, d1->sfd_name);
				d1->sfd_ino = SFS_NOINO;
				d1->sfd_name[0] = 0;
			}
			else {
				snprintf(d1->sfd_name, sizeof(d1->sfd_name),
					 "FSCK.%lu.%lu",
					 (unsigned long) d1->sfd_ino,
					 (unsigned long) uniquecounter++);
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Duplicate names %s "
				      "(one renamed: %s)",
				      pathsofar, d2->sfd_name, d1->sfd_name);
			}
			dchanged = 1;
		}
	}

	for (i=0; i<ndirentries; i++) {
		if (!strcmp(direntries[i].sfd_name, ".")) {
			if (direntries[i].sfd_ino != ino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Incorrect `.' entry "
				      "(fixed)", pathsofar);
				direntries[i].sfd_ino = ino;
				dchanged = 1;
			}
			assert(dotseen==0); /* due to duplicate checking */
			dotseen = 1;
		}
		else if (!strcmp(direntries[i].sfd_name, "..")) {
			if (direntries[i].sfd_ino != parentino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Incorrect `..' entry "
				      "(fixed)", pathsofar);
				direntries[i].sfd_ino = parentino;
				dchanged = 1;
			}
			assert(dotdotseen==0); /* due to duplicate checking */
			dotdotseen = 1;
		}
	}

	if (!dotseen) {
		if (dir_tryadd(direntries, ndirentries, ".", ino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `.' entry (added)",
			      pathsofar);
			dchanged = 1;
		}
		else if (dir_tryadd(direntries, maxdirentries, ".", ino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `.' entry (added)",
			      pathsofar);
			ndirentries++;
			dchanged = 1;
			sfi.sfi_size += sizeof(struct sfs_dir);
			ichanged = 1;
		}
		else {
			setbadness(EXIT_UNRECOV);
			warnx("Directory /%s: No `.' entry (NOT FIXED)",
			      pathsofar);
		}
	}

	if (!dotdotseen) {
		if (dir_tryadd(direntries, ndirentries, "..", parentino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `..' entry (added)",
			      pathsofar);
			dchanged = 1;
		}
		else if (dir_tryadd(direntries, maxdirentries, "..",
				    parentino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `..' entry (added)",
			      pathsofar);
			ndirentries++;
			dchanged = 1;
			sfi.sfi_size += sizeof(struct sfs_dir);
			ichanged = 1;
		}
		else {
			setbadness(EXIT_UNRECOV);
			warnx("Directory /%s: No `..' entry (NOT FIXED)",
			      pathsofar);
		}
	}

	subdircount=0;
	for (i=0; i<ndirentries; i++) {
		if (!strcmp(direntries[i].sfd_name, ".")) {
			/* nothing */
		}
		else if (!strcmp(direntries[i].sfd_name, "..")) {
			/* nothing */
		}
		else if (direntries[i].sfd_ino == SFS_NOINO) {
			/* nothing */
		}
		else {
			char path[strlen(pathsofar)+SFS_NAMELEN+1];
			struct sfs_inode subsfi;

			diskread(&subsfi, direntries[i].sfd_ino);
			swapinode(&subsfi);
			snprintf(path, sizeof(path), "%s/%s",
				 pathsofar, direntries[i].sfd_name);

			switch (subsfi.sfi_type) {
			    case SFS_TYPE_FILE:
				if (check_inode_blocks(direntries[i].sfd_ino,
						       &subsfi, 0)) {
					swapinode(&subsfi);
					diskwrite(&subsfi,
						  direntries[i].sfd_ino);
				}
				observe_filelink(direntries[i].sfd_ino);
				break;
			    case SFS_TYPE_DIR:
				if (check_dir(direntries[i].sfd_ino,
					      ino,
					      path)) {
					setbadness(EXIT_RECOV);
					warnx("Directory /%s: Crosslink to "
					      "other directory (removed)",
					      path);
					direntries[i].sfd_ino = SFS_NOINO;
					direntries[i].sfd_name[0] = 0;
					dchanged = 1;
				}
				else {
					subdircount++;
				}
				break;
			    default:
				setbadness(EXIT_RECOV);
				warnx("Object /%s: Invalid inode type "
				      "(removed)", path);
				direntries[i].sfd_ino = SFS_NOINO;
				direntries[i].sfd_name[0] = 0;
				dchanged = 1;
				break;
			}
		}
	}

	if (sfi.sfi_linkcount != subdircount+2) {
		setbadness(EXIT_RECOV);
		warnx("Directory /%s: Link count %lu should be %lu (fixed)",
		      pathsofar, (unsigned long) sfi.sfi_linkcount,
		      (unsigned long) subdircount+2);
		sfi.sfi_linkcount = subdircount+2;
		ichanged = 1;
	}

	if (dchanged) {
		dirwrite(&sfi, direntries, ndirentries);
	}

	if (ichanged) {
		swapinode(&sfi);
		diskwrite(&sfi, ino);
	}

	free(direntries);
	free(sortvector);

	return 0;
}
Example #3
0
/*
 * Handle gopher menus
 */
void gopher_menu(state *st)
{
	FILE *fp;
	sdirent dir[MAX_SDIRENT];
	struct tm *ltime;
	struct stat file;
	char buf[BUFSIZE];
	char pathname[BUFSIZE];
	char displayname[BUFSIZE];
	char encodedname[BUFSIZE];
	char timestr[20];
	char sizestr[20];
	char *parent;
	char *c;
	char type;
	int width;
	int num;
	int i;
	int n;

	/* Check for a gophermap */
	snprintf(pathname, sizeof(pathname), "%s/%s",
		st->req_realpath, st->map_file);

	if (stat(pathname, &file) == OK &&
	    (file.st_mode & S_IFMT) == S_IFREG) {

		/* Parse gophermap */
		if (gophermap(st, pathname, 0) == QUIT) {
			footer(st);
			return;
		}
	}

	else {
		/* Check for a gophertag */
		snprintf(pathname, sizeof(pathname), "%s/%s",
			st->req_realpath, st->tag_file);

		if (stat(pathname, &file) == OK &&
		    (file.st_mode & S_IFMT) == S_IFREG) {

			/* Read & output gophertag */
			if ((fp = fopen(pathname , "r"))) {

				fgets(buf, sizeof(buf), fp);
				chomp(buf);

				info(st, buf, TYPE_TITLE);
				info(st, EMPTY, TYPE_INFO);
				fclose(fp);
			}
		}

		/* No gophermap or tag found - print default header */
		else if (st->opt_header) {

			/* Use the selector as menu title */
			sstrlcpy(displayname, st->req_selector);

			/* Shorten too long titles */
			while (strlen(displayname) > (st->out_width - sizeof(HEADER_FORMAT))) {
				if ((c = strchr(displayname, '/')) == NULL) break;

				if (!*++c) break;
				sstrlcpy(displayname, c);
			}

			/* Output menu title */
			snprintf(buf, sizeof(buf), HEADER_FORMAT, displayname);
			info(st, buf, TYPE_TITLE);
			info(st, EMPTY, TYPE_INFO);
		}
	}

	/* Scan the directory */
	num = sortdir(st->req_realpath, dir, MAX_SDIRENT);
	if (num < 0) die(st, ERR_NOTFOUND, "WTF?");

	/* Create link to parent directory */
	if (st->opt_parent) {
		sstrlcpy(buf, st->req_selector);
		parent = dirname(buf);

		/* Root has no parent */
		if (strcmp(st->req_selector, ROOT) != MATCH) {

			/* Prevent double-slash */
			if (strcmp(parent, ROOT) == MATCH) parent++;

			/* Print link */
			printf("1%-*s\t%s/\t%s\t%i" CRLF,
				st->opt_date ? (st->out_width - 1) : (int) strlen(PARENT),
				PARENT, parent, st->server_host, st->server_port);
		}
	}

	/* Width of filenames for fancy listing */
	width = st->out_width - DATE_WIDTH - 15;

	/* Loop through the directory entries */
	for (i = 0; i < num; i++) {

		/* Get full path+name */
		snprintf(pathname, sizeof(pathname), "%s/%s",
			st->req_realpath, dir[i].name);

		/* Skip dotfiles and non world-readables */
		if (dir[i].name[0] == '.') continue;
		if ((dir[i].mode & S_IROTH) == 0) continue;

		/* Skip gophermaps and tags (but not dirs) */
		if ((dir[i].mode & S_IFMT) != S_IFDIR) {
			if (strcmp(dir[i].name, st->map_file) == MATCH) continue;
			if (strcmp(dir[i].name, st->tag_file) == MATCH) continue;
		}

		/* Skip files marked for hiding */
		for (n = 0; n < st->hidden_count; n++)
			if (strcmp(dir[i].name, st->hidden[n]) == MATCH) break;
		if (n < st->hidden_count) continue;	/* Cruel hack... */

		/* Generate display name with correct output charset */
		if (st->opt_iconv)
			sstrniconv(st->out_charset, displayname, dir[i].name);
		else
			sstrlcpy(displayname, dir[i].name);

		/* #OCT-encode filename */
		strnencode(encodedname, dir[i].name, sizeof(encodedname));

		/* Handle inline .gophermap */
		if (strstr(displayname, st->map_file) > displayname) {
			gophermap(st, pathname, 0);
			continue;
		}

		/* Handle directories */
		if ((dir[i].mode & S_IFMT) == S_IFDIR) {

			/* Check for a gophertag */
			snprintf(buf, sizeof(buf), "%s/%s",
				pathname, st->tag_file);

			if (stat(buf, &file) == OK &&
			    (file.st_mode & S_IFMT) == S_IFREG) {

				/* Use the gophertag as displayname */
				if ((fp = fopen(buf , "r"))) {

					fgets(buf, sizeof(buf), fp);
					chomp(buf);
					fclose(fp);

					/* Skip empty gophertags */
					if (*buf) {

						/* Convert to output charset */
						if (st->opt_iconv) sstrniconv(st->out_charset, displayname, buf);
						else sstrlcpy(displayname, buf);
					}

				}
			}

			/* Dir listing with dates */
			if (st->opt_date) {
				ltime = localtime(&dir[i].mtime);
				strftime(timestr, sizeof(timestr), DATE_FORMAT, ltime);

				/* Hack to get around UTF-8 byte != char */
				n = width - strcut(displayname, width);
				strrepeat(buf, ' ', n);

				printf("1%s%s   %s        -  \t%s%s/\t%s\t%i" CRLF,
					displayname,
					buf,
					timestr,
					st->req_selector,
					encodedname,
					st->server_host,
					st->server_port);
			}

			/* Regular dir listing */
			else {
				strcut(displayname, st->out_width);
				printf("1%s\t%s%s/\t%s\t%i" CRLF,
					displayname,
					st->req_selector,
					encodedname,
					st->server_host,
					st->server_port);
			}

			continue;
		}

		/* Skip special files (sockets, fifos etc) */
		if ((dir[i].mode & S_IFMT) != S_IFREG) continue;

		/* Get file type */
		type = gopher_filetype(st, pathname, st->opt_magic);

		/* File listing with dates & sizes */
		if (st->opt_date) {
			ltime = localtime(&dir[i].mtime);
			strftime(timestr, sizeof(timestr), DATE_FORMAT, ltime);
			strfsize(sizestr, dir[i].size, sizeof(sizestr));

			/* Hack to get around UTF-8 byte != char */
			n = width - strcut(displayname, width);
			strrepeat(buf, ' ', n);

			printf("%c%s%s   %s %s\t%s%s\t%s\t%i" CRLF, type,
				displayname,
				buf,
				timestr,
				sizestr,
				st->req_selector,
				encodedname,
				st->server_host,
				st->server_port);
		}

		/* Regular file listing */
		else {
			strcut(displayname, st->out_width);
			printf("%c%s\t%s%s\t%s\t%i" CRLF, type,
				displayname,
				st->req_selector,
				encodedname,
				st->server_host,
				st->server_port);
		}
	}

	/* Print footer */
	footer(st);
}
Example #4
0
/*
 * Get suffices of all sub-mandir directories in a mandir.
 */
static void
get_all_sect(struct man_node *manp)
{
	DIR	*dp;
	char	**dirv;
	char	**dv;
	char	**p;
	char	*prev = NULL;
	char 	*tmp = NULL;
	int	maxentries = MAXTOKENS;
	int	entries = 0;

	if ((dp = opendir(manp->path)) == 0)
		return;

	sortdir(dp, &dirv);

	(void) closedir(dp);

	if (manp->secv == NULL) {
		if ((manp->secv = malloc(maxentries * sizeof (char *))) == NULL)
			err(1, "malloc");
	}

	for (dv = dirv, p = manp->secv; *dv; dv++) {
		if (strcmp(*dv, CONFIG) == 0) {
			free(*dv);
			continue;
		}

		free(tmp);
		if ((tmp = strdup(*dv + 3)) == NULL)
			err(1, "strdup");

		if (prev != NULL && strcmp(prev, tmp) == 0) {
			free(*dv);
			continue;
		}

		free(prev);
		if ((prev = strdup(*dv + 3)) == NULL)
			err(1, "strdup");

		if ((*p = strdup(*dv + 3)) == NULL)
			err(1, "strdup");

		p++; entries++;

		if (entries == maxentries) {
			maxentries += MAXTOKENS;
			if ((manp->secv = realloc(manp->secv,
			    sizeof (char *) * maxentries)) == NULL)
				err(1, "realloc");
			p = manp->secv + entries;
		}
		free(*dv);
	}
	free(tmp);
	free(prev);
	*p = NULL;
	free(dirv);
}
Example #5
0
/*
 * For a specified manual directory, read, store and sort section subdirs.
 * For each section specified, find and search matching subdirs.
 */
static void
mandir(char **secv, char *path, char *name, int lspec)
{
	DIR	*dp;
	char	**dirv;
	char	**dv, **pdv;
	int	len, dslen;

	if ((dp = opendir(path)) == NULL)
		return;

	if (lspec)
		DPRINTF("-- Searching mandir: %s\n", path);

	sortdir(dp, &dirv);

	/* Search in the order specified by MANSECTS */
	for (; *secv; secv++) {
		len = strlen(*secv);
		for (dv = dirv; *dv; dv++) {
			dslen = strlen(*dv + 3);
			if (dslen > len)
				len = dslen;
			if (**secv == '\\') {
				if (strcmp(*secv + 1, *dv + 3) != 0)
					continue;
			} else if (strncasecmp(*secv, *dv + 3, len) != 0) {
				if (!all &&
				    (newsection = map_section(*secv, path))
				    == NULL) {
					continue;
				}
				if (newsection == NULL)
					newsection = "";
				if (strncmp(newsection, *dv + 3, len) != 0) {
					continue;
				}
			}

			if (searchdir(path, *dv, name) == 0)
				continue;

			if (!all) {
				pdv = dirv;
				while (*pdv) {
					free(*pdv);
					pdv++;
				}
				(void) closedir(dp);
				free(dirv);
				return;
			}

			if (all && **dv == 'm' && *(dv + 1) &&
			    strcmp(*(dv + 1) + 3, *dv + 3) == 0)
					dv++;
		}
	}
	pdv = dirv;
	while (*pdv != NULL) {
		free(*pdv);
		pdv++;
	}
	free(dirv);
	(void) closedir(dp);
}