+int isadir(const char* f)
+{
+ struct stat s;
+
+ if(stat(f, &s) < 0)
+ {
+ syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
+ f);
+ return -1;
+ }
+
+ return S_ISDIR(s.st_mode);
+}
+
+int is_safe_path(const char *file)
+{
+ char *p;
+ struct stat s;
+
+ if(*file != '/')
+ {
+ syslog(LOG_ERR, _("`%s' is not an absolute path"), file);
+ return 0;
+ }
+
+ p = strrchr(file, '/');
+ *p = '\0';
+ if(stat(file, &s) < 0)
+ {
+ syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
+ file);
+ return 0;
+ }
+ if(s.st_uid != geteuid())
+ {
+ syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
+ file, s.st_uid, geteuid());
+ return 0;
+ }
+ if(S_ISLNK(s.st_mode))
+ {
+ syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
+ file);
+ /* fixme: read the symlink and start again */
+ }
+
+ *p = '/';
+ if(stat(file, &s) < 0 && errno != ENOENT)
+ {
+ syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
+ file);
+ return 0;
+ }
+ if(errno == ENOENT)
+ return 1;
+ if(s.st_uid != geteuid())
+ {
+ syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
+ file, s.st_uid, geteuid());
+ return 0;
+ }
+ if(S_ISLNK(s.st_mode))
+ {
+ syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
+ file);
+ /* fixme: read the symlink and start again */
+ }
+ if(s.st_mode & 0007)
+ {
+ /* Accessible by others */
+ syslog(LOG_ERR, _("`%s' has unsecure permissions"),
+ file);
+ return 0;
+ }
+
+ return 1;
+}