Репозитории ALT
Группа :: Работа с файлами
Пакет: stmpclean
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: stmpclean-0.3-owl-fixes.patch
Скачать
Скачать
diff -urpN stmpclean-0.3.orig/Makefile stmpclean-0.3/Makefile
--- stmpclean-0.3.orig/Makefile Fri Mar 21 21:58:00 2003
+++ stmpclean-0.3/Makefile Wed Jun 11 20:32:26 2003
@@ -2,24 +2,29 @@
# Written by Stanislav Shalunov.
# $Id: Makefile,v 1.6 2003/03/21 21:58:00 shalunov Exp $
-PREFIX=/usr/local
-BINDIR=$(PREFIX)/sbin
-MANDIR=$(PREFIX)/man/man8
+CC = gcc
+LD = gcc
+CFLAGS = -O2 -fomit-frame-pointer -Wall -W -pedantic
+LDFLAGS = -s
-CFLAGS += -O6 -Wall -W -pedantic
+DESTDIR =
+PREFIX = /usr/local
+SBINDIR = $(PREFIX)/sbin
+MANDIR = $(PREFIX)/man
all: stmpclean stmpclean.0
-install: all
- if [ ! -d $(BINDIR) ] ; then mkdir -p -m 0755 $(BINDIR); fi
- if [ ! -d $(MANDIR) ] ; then mkdir -p -m 0755 $(MANDIR); fi
- install -c -o 0 -g 0 -m 0555 stmpclean $(BINDIR)/
- install -c -o 0 -g 0 -m 0444 stmpclean.8 $(MANDIR)/
+install: stmpclean
+ mkdir -p -m 755 $(DESTDIR)$(SBINDIR) $(DESTDIR)$(MANDIR)/man8
+ install -m 700 stmpclean $(DESTDIR)$(SBINDIR)/
+ ln -s stmpclean $(DESTDIR)$(SBINDIR)/tmpwatch
+ install -m 644 stmpclean.8 tmpwatch.8 $(DESTDIR)$(MANDIR)/man8/
stmpclean.o: stmpclean.c
+ $(CC) $(CFLAGS) -c stmpclean.c
stmpclean: stmpclean.o
- $(CC) -o stmpclean stmpclean.o && strip stmpclean
+ $(LD) $(LDFLAGS) -o stmpclean stmpclean.o
stmpclean.0: stmpclean.8
nroff -mandoc stmpclean.8 > stmpclean.0
diff -urpN stmpclean-0.3.orig/stmpclean.8 stmpclean-0.3/stmpclean.8
--- stmpclean-0.3.orig/stmpclean.8 Fri Mar 21 21:44:09 2003
+++ stmpclean-0.3/stmpclean.8 Wed Jun 11 21:40:54 2003
@@ -4,7 +4,9 @@
.\"
.\" $Id: stmpclean.8,v 1.6 2003/03/21 21:44:09 shalunov Exp $
.\"
-.Dd August 1999
+.\" Last updated on 2003/06/11 by Solar Designer <solar@owl.openwall.com>
+.\"
+.Dd June 2003
.Dt STMPCLEAN 8
.Os
.Sh NAME
@@ -85,21 +87,21 @@ as
.Pp
In FreeBSD
.Nm
-invokation should be placed into the file
+invocation should be placed into the file
.Pa /etc/periodic/daily/110.clean-tmps .
In other versions of BSD it should go into the
.Pa /etc/daily
script.
-In Linux, check if you have
-.Pa /etc/periodic ,
-and if not, you can just run it from cron; usually you'd have to edit
-.Pa /etc/crontab .
+On LSB-compliant Linux distributions, the invocation of
+.Nm
+may be placed in a script under
+.Pa /etc/cron.daily .
.Sh SEE ALSO
.Xr cron 8
.Sh BUGS
When
.Nm
-removes a file from a directory, modification time of the directory
+scans a directory, access time of the directory
changes and it looks new to
.Nm
when it examines it later (if the directory became empty). Thus,
diff -urpN stmpclean-0.3.orig/stmpclean.c stmpclean-0.3/stmpclean.c
--- stmpclean-0.3.orig/stmpclean.c Tue Jun 10 19:07:45 2003
+++ stmpclean-0.3/stmpclean.c Mon Jun 28 17:37:32 2004
@@ -1,9 +1,9 @@
/*
* stmpclean.c -- remove old files from a world-writable directory.
* Written by Stanislav Shalunov, http://www.internet2.edu/~shalunov/
- *
+ *
* Copyright (C) 1999, Stanislav Shalunov.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -42,6 +42,7 @@ static const char rcsid[] =
"$Id: stmpclean.c,v 1.13 2003/06/10 19:07:45 shalunov Exp $";
#endif
+#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
@@ -56,7 +57,16 @@ static const char rcsid[] =
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
+#include <grp.h>
#include <errno.h>
+#include <libgen.h>
+
+#ifndef O_DIRECTORY
+#define O_DIRECTORY 0
+#endif
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
+#endif
/*
* How deep to descend into directories? Won't go any deeper than MAX_DEPTH
@@ -69,13 +79,15 @@ static const char rcsid[] =
#define SECONDS_IN_A_DAY (SECONDS_IN_AN_HOUR * 24)
#define SECONDS_IN_A_WEEK (SECONDS_IN_A_DAY * 7)
-#define GETCWD {if (getcwd(cwd, MAXPATHLEN) == NULL)\
+#define GETCWD {if (getcwd(cwd, sizeof(cwd)) == NULL) \
strcpy(cwd, "/FULL/PATH/TOO/LONG");}
+/* Are we emulating tmpwatch? */
+static int am_tmpwatch;
/* Time at the start of the program, in seconds since beginning of epoch. */
static time_t now;
-/* Minimum age (mtime) of a file or empty directory to be deleted. */
-int minage;
+/* Minimum age (atime) of a file or empty directory to be deleted. */
+static int minage;
/* Current working directory is used for logging purposes only. */
static char cwd[MAXPATHLEN];
/* Flag: be verbose? */
@@ -83,8 +95,13 @@ static int verbose = 0;
/* Print usage message, exit with a failure. */
void
-usage()
+usage(void)
{
+ if (am_tmpwatch) {
+ fprintf(stderr, "stmpclean: "
+ "Don't know how to emulate these tmpwatch options.\n");
+ exit(1);
+ }
fprintf(stderr,
"Usage: stmpclean [-t <timespec>] dir1 [dir2 [dir3]...]]\n\n"
"Where time specification <timespec> is a string like 1w\n"
@@ -96,9 +113,10 @@ usage()
}
/*
- * Parse time specification (a la sendmail queue time), return its value in
- * seconds, or -1 if the spec is invalid.
- *
+ * Parse time specification (a la sendmail queue time or number of hours
+ * when doing tmpwatch emulation), return its value in seconds, or -1 if
+ * the spec is invalid.
+ *
* Side effects: Modifies contents of timespec.
*/
int
@@ -107,14 +125,16 @@ parse_time(timespec)
{
char *p, *q;
char symbol;
- int result, num, multiple;
+ int result, num, multiple, seconds;
result = 0;
p = timespec;
while (*p) {
- if (!isdigit(*p))
+ if (!isdigit((int)(unsigned char)*p))
+ return -1;
+ for (q = p; isdigit((int)(unsigned char)*q); q++);
+ if (q == p || q - p > 9)
return -1;
- for (q = p; isdigit(*q); q++);
symbol = *q;
*q = 0;
num = atoi(p);
@@ -124,6 +144,8 @@ parse_time(timespec)
* didn't want to have strdup()s here all around, did you?
*/
*q = symbol;
+ if (am_tmpwatch && symbol)
+ return -1;
switch (symbol) {
case 'w':
multiple = SECONDS_IN_A_WEEK;
@@ -131,6 +153,11 @@ parse_time(timespec)
case 'd':
multiple = SECONDS_IN_A_DAY;
break;
+ case '\0':
+ if (!am_tmpwatch)
+ return -1;
+ q--;
+ /* FALLTHROUGH */
case 'h':
multiple = SECONDS_IN_AN_HOUR;
break;
@@ -143,8 +170,11 @@ parse_time(timespec)
default:
return -1;
}
- result += num * multiple;
- if (result < 0)
+ seconds = num * multiple;
+ if (seconds < 0 || seconds / multiple != num)
+ return -1;
+ result += seconds;
+ if (result < seconds)
return -1;
p = q + 1;
}
@@ -157,14 +187,18 @@ setecreds(uid, gid)
uid_t uid;
gid_t gid;
{
+ gid_t groups[2];
+
+ groups[0] = groups[1] = gid;
if (geteuid()) {
- if ((seteuid(uid) == -1) || (setegid(gid) == -1)) {
+ if (seteuid(uid) || setegid(gid) ||
+ (uid == 0 && setgroups(1, groups))) {
syslog(LOG_ERR, "cannot set EUID/EGID to %d/%d, exiting",
uid, gid);
exit(1);
}
} else {
- if ((setegid(gid) == -1) || (seteuid(uid) == -1)) {
+ if (setgroups(1, groups) || setegid(gid) || seteuid(uid)) {
syslog(LOG_ERR, "cannot set EUID/EGID to %d/%d, exiting",
uid, gid);
exit(1);
@@ -201,13 +235,13 @@ isemptydir(dir)
}
/*
- * Recursively clean directory DIR, descending no deeper than MAX_DEPTH.
+ * Recursively clean directory DIR, descending no deeper than DEPTH.
* Exit with a failure if a race condition is detected.
*/
void
-clean_dir(dir, depth)
+clean_dir(dir, depth, specified)
char *dir;
- int depth;
+ int depth, specified;
{
struct stat st, st_after;
int dir_fd, dot_dot_fd;
@@ -224,7 +258,9 @@ clean_dir(dir, depth)
"reached maximum depth (%d)", dir, cwd, MAX_DEPTH);
return;
}
- if (lstat(dir, &st) == -1) {
+ if ((specified ? stat(dir, &st) : lstat(dir, &st)) == -1) {
+ if (errno == ENOENT && !specified)
+ return;
GETCWD;
syslog(LOG_ERR, "RACE?: lstat(\"%s\") in %s failed: %m, "
"exiting", dir, cwd);
@@ -236,8 +272,11 @@ clean_dir(dir, depth)
dir, cwd);
exit(1);
}
- dir_fd = open(dir, O_RDONLY);
+ dir_fd = open(dir, O_RDONLY | O_NONBLOCK | O_DIRECTORY |
+ (specified ? 0 : O_NOFOLLOW));
if (dir_fd == -1) {
+ if (errno == ENOENT)
+ return;
GETCWD;
syslog(LOG_ERR,
"RACE?: cannot open(\"%s\"): %m (lstat was OK), "
@@ -264,7 +303,8 @@ clean_dir(dir, depth)
* We'll chdir up later once done with recursive descend. Hence the
* name.
*/
- dot_dot_fd = open(".", O_RDONLY);
+ dot_dot_fd = open(".",
+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_NOFOLLOW);
if (dot_dot_fd == -1) {
GETCWD;
syslog(LOG_ERR, "open(\".\") in %s: %m, exiting", cwd);
@@ -294,6 +334,8 @@ clean_dir(dir, depth)
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
continue;
if (lstat(dp->d_name, &st) == -1) {
+ if (errno == ENOENT)
+ continue;
GETCWD;
syslog(LOG_ERR, "RACE?: lstat(\"%s\") in %s: %m, "
"exiting", dp->d_name, cwd);
@@ -303,11 +345,18 @@ clean_dir(dir, depth)
/* Looking at a directory. */
if (isemptydir(dp->d_name)) {
/* Looking at an empty directory. */
- if (now - st.st_mtime > minage && st.st_uid) {
+ if (now - st.st_atime > minage && st.st_uid) {
/* An old non-root owned directory. */
setecreds(st.st_uid, st.st_gid);
if (rmdir(dp->d_name) == -1
- && errno != EACCES) {
+ && errno != ENOENT
+ && errno != EACCES
+ && errno != EPERM) {
+ if (errno == ENOTEMPTY) {
+ setecreds(0, 0);
+ goto notempty;
+ }
+ setecreds(0, 0);
GETCWD;
syslog(LOG_ERR, "RACE?: rmdir"
"(\"%s\") in %s: %m, "
@@ -323,16 +372,16 @@ clean_dir(dir, depth)
setecreds(0, 0);
}
} else {
+notempty:
/*
* Looking at a non-empty directory. Clean it
* recursively (call ourselves).
*/
- clean_dir(dp->d_name, depth - 1);
+ clean_dir(dp->d_name, depth - 1, 0);
}
} else {
/* Looking at a non-directory. */
- if ((now - st.st_mtime > minage)
- && (now - st.st_ctime > minage)
+ if ((now - st.st_atime > minage)
&& st.st_uid
&& (st.st_nlink == 1)
&& (((st.st_mode & S_IFMT) == S_IFREG)
@@ -342,7 +391,11 @@ clean_dir(dir, depth)
* symlink.
*/
setecreds(st.st_uid, st.st_gid);
- if (unlink(dp->d_name) == -1) {
+ if (unlink(dp->d_name) == -1
+ && errno != ENOENT
+ && errno != EACCES
+ && errno != EPERM) {
+ setecreds(0, 0);
GETCWD;
syslog(LOG_ERR, "RACE?: unlink(\"%s\")"
"in %s: %m, exiting",
@@ -377,15 +430,27 @@ main(argc, argv)
/* By default, delete files older than three days. */
extern char *optarg;
extern int optind;
+ char *me;
int c, i;
struct rlimit rlp;
if (argc <= 0)
usage();
+ me = strdup(argv[0]);
+ if (!me) {
+ errno = ENOMEM;
+ perror("strdup");
+ exit(1);
+ }
+ am_tmpwatch = !strcmp(basename(me), "tmpwatch");
openlog("stmpclean", LOG_PID | LOG_CONS | LOG_PERROR, LOG_DAEMON);
minage = SECONDS_IN_A_DAY * 3;
- while ((c = getopt(argc, argv, "vt:")) != -1)
+ while ((c = getopt(argc, argv, am_tmpwatch ? "uafv" : "vt:")) != -1)
switch (c) {
+ case 'u':
+ case 'a':
+ case 'f':
+ break;
case 't':
minage = parse_time(optarg);
if (minage == -1)
@@ -399,8 +464,14 @@ main(argc, argv)
}
argc -= optind;
argv += optind;
- if (argc <= 0)
+ if (argc <= (am_tmpwatch ? 1 : 0))
usage();
+ if (am_tmpwatch) {
+ argc--;
+ minage = parse_time(*argv++);
+ if (minage == -1)
+ usage();
+ }
/*
* For logging niceties in case one of the directories on the command
* line is bad.
@@ -422,7 +493,7 @@ main(argc, argv)
exit(1);
}
for (i = 0; i < argc; i++)
- clean_dir(argv[i], MAX_DEPTH);
+ clean_dir(argv[i], MAX_DEPTH, 1);
exit(0);
/* NOTREACHED */
}
diff -urpN stmpclean-0.3.orig/tmpwatch.8 stmpclean-0.3/tmpwatch.8
--- stmpclean-0.3.orig/tmpwatch.8 Thu Jan 1 00:00:00 1970
+++ stmpclean-0.3/tmpwatch.8 Sat Mar 30 00:24:51 2002
@@ -0,0 +1 @@
+.so man8/stmpclean.8