Return to mandocdb.c CVS log | Up to [cvsweb.bsd.lv] / mandoc |
version 1.138, 2014/04/18 21:55:38 | version 1.140, 2014/04/19 02:56:54 | ||
---|---|---|---|
|
|
||
ohash_init(&mlinks, 6, &mlinks_info); | ohash_init(&mlinks, 6, &mlinks_info); | ||
if (OP_UPDATE == op || OP_DELETE == op || OP_TEST == op) { | if (OP_UPDATE == op || OP_DELETE == op || OP_TEST == op) { | ||
/* | |||
* Force processing all files. | |||
*/ | |||
use_all = 1; | |||
/* | /* | ||
* All of these deal with a specific directory. | * All of these deal with a specific directory. | ||
* Jump into that directory then collect files specified | * Jump into that directory first. | ||
* on the command-line. | |||
*/ | */ | ||
if (0 == set_basedir(path_arg)) | if (0 == set_basedir(path_arg)) | ||
goto out; | goto out; | ||
if (dbopen(1)) { | if (dbopen(1)) { | ||
/* | |||
* The existing database is usable. Process | |||
* all files specified on the command-line. | |||
*/ | |||
use_all = 1; | |||
for (i = 0; i < argc; i++) | for (i = 0; i < argc; i++) | ||
filescan(argv[i]); | filescan(argv[i]); | ||
if (OP_TEST != op) | if (OP_TEST != op) | ||
|
|
||
* Database missing or corrupt. | * Database missing or corrupt. | ||
* Recreate from scratch. | * Recreate from scratch. | ||
*/ | */ | ||
exitcode = (int)MANDOCLEVEL_OK; | |||
op = OP_DEFAULT; | op = OP_DEFAULT; | ||
if (0 == treescan()) | if (0 == treescan()) | ||
goto out; | goto out; | ||
|
|
||
static int | static int | ||
treescan(void) | treescan(void) | ||
{ | { | ||
char buf[PATH_MAX]; | |||
FTS *f; | FTS *f; | ||
FTSENT *ff; | FTSENT *ff; | ||
struct mlink *mlink; | struct mlink *mlink; | ||
|
|
||
argv[0] = "."; | argv[0] = "."; | ||
argv[1] = (char *)NULL; | argv[1] = (char *)NULL; | ||
/* | f = fts_open((char * const *)argv, | ||
* Walk through all components under the directory, using the | FTS_PHYSICAL | FTS_NOCHDIR, NULL); | ||
* logical descent of files. | |||
*/ | |||
f = fts_open((char * const *)argv, FTS_LOGICAL, NULL); | |||
if (NULL == f) { | if (NULL == f) { | ||
exitcode = (int)MANDOCLEVEL_SYSERR; | exitcode = (int)MANDOCLEVEL_SYSERR; | ||
say("", "&fts_open"); | say("", "&fts_open"); | ||
|
|
||
while (NULL != (ff = fts_read(f))) { | while (NULL != (ff = fts_read(f))) { | ||
path = ff->fts_path + 2; | path = ff->fts_path + 2; | ||
switch (ff->fts_info) { | |||
/* | /* | ||
* Symbolic links require various sanity checks, | |||
* then get handled just like regular files. | |||
*/ | |||
case (FTS_SL): | |||
if (NULL == realpath(path, buf)) { | |||
if (warnings) | |||
say(path, "&realpath"); | |||
continue; | |||
} | |||
if (strstr(buf, basedir) != buf) { | |||
if (warnings) say("", | |||
"%s: outside base directory", buf); | |||
continue; | |||
} | |||
/* Use logical inode to avoid mpages dupe. */ | |||
if (-1 == stat(path, ff->fts_statp)) { | |||
if (warnings) | |||
say(path, "&stat"); | |||
continue; | |||
} | |||
/* FALLTHROUGH */ | |||
/* | |||
* If we're a regular file, add an mlink by using the | * If we're a regular file, add an mlink by using the | ||
* stored directory data and handling the filename. | * stored directory data and handling the filename. | ||
*/ | */ | ||
if (FTS_F == ff->fts_info) { | case (FTS_F): | ||
if (0 == strcmp(path, MANDOC_DB)) | if (0 == strcmp(path, MANDOC_DB)) | ||
continue; | continue; | ||
if ( ! use_all && ff->fts_level < 2) { | if ( ! use_all && ff->fts_level < 2) { | ||
|
|
||
mlink->gzip = gzip; | mlink->gzip = gzip; | ||
mlink_add(mlink, ff->fts_statp); | mlink_add(mlink, ff->fts_statp); | ||
continue; | continue; | ||
} else if (FTS_D != ff->fts_info && | |||
FTS_DP != ff->fts_info) { | case (FTS_D): | ||
/* FALLTHROUGH */ | |||
case (FTS_DP): | |||
break; | |||
default: | |||
if (warnings) | if (warnings) | ||
say(path, "Not a regular file"); | say(path, "Not a regular file"); | ||
continue; | continue; | ||
|
|
||
if (0 == strncmp(file, "./", 2)) | if (0 == strncmp(file, "./", 2)) | ||
file += 2; | file += 2; | ||
/* | |||
* We have to do lstat(2) before realpath(3) loses | |||
* the information whether this is a symbolic link. | |||
* We need to know that because for symbolic links, | |||
* we want to use the orginal file name, while for | |||
* regular files, we want to use the real path. | |||
*/ | |||
if (-1 == lstat(file, &st)) { | |||
exitcode = (int)MANDOCLEVEL_BADARG; | |||
say(file, "&lstat"); | |||
return; | |||
} else if (0 == ((S_IFREG | S_IFLNK) & st.st_mode)) { | |||
exitcode = (int)MANDOCLEVEL_BADARG; | |||
say(file, "Not a regular file"); | |||
return; | |||
} | |||
/* | |||
* We have to resolve the file name to the real path | |||
* in any case for the base directory check. | |||
*/ | |||
if (NULL == realpath(file, buf)) { | if (NULL == realpath(file, buf)) { | ||
exitcode = (int)MANDOCLEVEL_BADARG; | exitcode = (int)MANDOCLEVEL_BADARG; | ||
say(file, "&realpath"); | say(file, "&realpath"); | ||
|
|
||
return; | return; | ||
} | } | ||
if (-1 == stat(buf, &st)) { | /* | ||
exitcode = (int)MANDOCLEVEL_BADARG; | * Now we are sure the file is inside our tree. | ||
say(file, "&stat"); | * If it is a symbolic link, ignore the real path | ||
return; | * and use the original name. | ||
} else if ( ! (S_IFREG & st.st_mode)) { | * This implies passing stuff like "cat1/../man1/foo.1" | ||
exitcode = (int)MANDOCLEVEL_BADARG; | * on the command line won't work. So don't do that. | ||
say(file, "Not a regular file"); | * Note the stat(2) can still fail if the link target | ||
return; | * doesn't exist. | ||
*/ | |||
if (S_IFLNK & st.st_mode) { | |||
if (-1 == stat(buf, &st)) { | |||
exitcode = (int)MANDOCLEVEL_BADARG; | |||
say(file, "&stat"); | |||
return; | |||
} | |||
strlcpy(buf, file, sizeof(buf)); | |||
start = strstr(buf, basedir) == buf ? | |||
buf + strlen(basedir) + 1 : buf; | |||
} | } | ||
mlink = mandoc_calloc(1, sizeof(struct mlink)); | mlink = mandoc_calloc(1, sizeof(struct mlink)); |