/* For caching of stat() calls */ extern fileStatus *eStat (const char *const fileName) { struct stat status; static fileStatus file; if (file.name == NULL || strcmp (fileName, file.name) != 0) { eStatFree (&file); file.name = eStrdup (fileName); if (lstat (file.name, &status) != 0) file.exists = FALSE; else { file.isSymbolicLink = (boolean) S_ISLNK (status.st_mode); if (file.isSymbolicLink && stat (file.name, &status) != 0) file.exists = FALSE; else { file.exists = TRUE; file.isDirectory = (boolean) S_ISDIR (status.st_mode); file.isNormalFile = (boolean) (S_ISREG (status.st_mode)); file.isExecutable = (boolean) ((status.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); file.isSetuid = (boolean) ((status.st_mode & S_ISUID) != 0); file.isSetgid = (boolean) ((status.st_mode & S_ISGID) != 0); file.size = status.st_size; } } } return &file; }
static boolean isSafeExecutable (const char* path) { fileStatus *file; boolean r; Assert (path); file = eStat (path); if (!file->exists) { /* The file doesn't exist. So I cannot say it is unsafe. The caller should handle this case. */ r = TRUE; } else if (file->isSetuid) { error (WARNING, "xcmd doesn't run a setuid executable: %s", path); r = FALSE; } else if (file->isSetgid) { error (WARNING, "xcmd doesn't run a setgid executable: %s", path); r = FALSE; } else r = TRUE; eStatFree (file); return r; }
static boolean createTagsForEntry (const char *const entryName) { boolean resize = FALSE; fileStatus *status = eStat (entryName); Assert (entryName != NULL); if (isExcludedFile (entryName)) verbose ("excluding \"%s\"\n", entryName); else if (status->isSymbolicLink && ! Option.followLinks) verbose ("ignoring \"%s\" (symbolic link)\n", entryName); else if (! status->exists) error (WARNING | PERROR, "cannot open source file \"%s\"", entryName); else if (status->isDirectory) resize = recurseIntoDirectory (entryName); else if (! status->isNormalFile) verbose ("ignoring \"%s\" (special file)\n", entryName); else resize = parseFile (entryName); eStatFree (status); return resize; }