summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/backup-files.c85
-rw-r--r--lib/ftw.c116
-rw-r--r--lib/ftw.h23
3 files changed, 68 insertions, 156 deletions
diff --git a/lib/backup-files.c b/lib/backup-files.c
index 79f3e55..f28e89c 100644
--- a/lib/backup-files.c
+++ b/lib/backup-files.c
@@ -1,8 +1,8 @@
/*
File: backup-files.c
- Copyright (C) 2003 Andreas Gruenbacher <agruen@suse.de>
- SuSE Labs, SuSE Linux AG
+ Copyright (C) 2003, 2004, 2005, 2006
+ Andreas Gruenbacher <agruen@suse.de>, SuSE Labs
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -40,7 +40,7 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
-#include <ftw.h>
+#include <dirent.h>
#if !defined(HAVE_MKSTEMP) && defined(HAVE_MKTEMP)
# define mkstemp(x) creat(mktemp(x), 0600)
@@ -57,7 +57,7 @@ int opt_nolinks, opt_touch;
#define LINE_LENGTH 1024
-void
+static void
usage(void)
{
printf("Usage: %s [-B prefix] [-z suffix] [-f {file|-}] [-s] [-b|-r|-x] [-L] {file|-} ...\n"
@@ -84,13 +84,13 @@ malloc_nofail(size_t size)
{
void *p = malloc(size);
if (!p) {
- fprintf(stderr, "%s\n", strerror(ENOMEM));
+ perror(NULL);
exit(1);
}
return p;
}
-void
+static void
create_parents(const char *filename)
{
struct stat st;
@@ -120,7 +120,7 @@ out:
free(fn);
}
-void
+static void
remove_parents(const char *filename)
{
char *fn = malloc_nofail(strlen(filename) + 1), *f;
@@ -273,7 +273,7 @@ ensure_nolinks(const char *filename)
return 0;
}
-int
+static int
process_file(const char *file)
{
char *backup = malloc_nofail(
@@ -375,19 +375,72 @@ fail:
return 1;
}
-int
-walk(const char *path, const struct stat *stat, int flag)
+static int
+foreachdir_rec(const char *path, struct stat *st,
+ int (*walk)(const char *, const struct stat *))
+{
+ DIR *dir;
+ struct dirent *dp;
+ char *p = NULL;
+ int failed = 0;
+
+ if (!(dir = opendir(path)))
+ return walk(path, NULL);
+ while ((dp = readdir(dir))) {
+ char *p0 = p;
+
+ if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+ continue;
+ if (!(p = realloc(p, strlen(path) + 1 +
+ strlen(dp->d_name) + 1))) {
+ free(p0);
+ return -1;
+ }
+ sprintf(p, "%s/%s", path, dp->d_name);
+ if (lstat(p, st))
+ continue; /* file has disappeared meanwhile */
+ if (S_ISDIR(st->st_mode)) {
+ failed = foreachdir_rec(p, st, walk);
+ if (failed)
+ goto out;
+ } else {
+ failed = walk(p, st);
+ if (failed)
+ goto out;
+ }
+ }
+ if (closedir(dir) != 0)
+ failed = -1;
+
+out:
+ free(p);
+ return failed;
+}
+
+static int
+foreachdir(const char *path,
+ int (*walk)(const char *, const struct stat *))
+{
+ struct stat st;
+
+ if (lstat(path, &st))
+ return walk(path, NULL);
+ return foreachdir_rec(path, &st, walk);
+}
+
+static int
+walk(const char *path, const struct stat *st)
{
size_t prefix_len=strlen(opt_prefix), suffix_len=strlen(opt_suffix);
size_t len = strlen(path);
char *p;
int ret;
- if (flag == FTW_DNR) {
+ if (!st) {
perror(path);
return 1;
}
- if (!S_ISREG(stat->st_mode))
+ if (!S_ISREG(st->st_mode))
return 0;
if (strncmp(opt_prefix, path, prefix_len))
return 0; /* prefix does not match */
@@ -493,14 +546,12 @@ main(int argc, char *argv[])
if (strcmp(argv[optind], "-") == 0) {
char *dir = strdup(opt_prefix), *d = strrchr(dir, '/');
if (d)
- *(d+1) = '\0';
+ *d = '\0';
else
d = ".";
- status = ftw(dir, walk, 0);
- /* An error here indicates a problem somewhere
- * during the walk */
+ status = foreachdir(dir, walk);
if (status == -1)
- perror("ftw");
+ perror(dir);
free(dir);
} else
diff --git a/lib/ftw.c b/lib/ftw.c
deleted file mode 100644
index 8762194..0000000
--- a/lib/ftw.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Written by Jesper Juhl <jj@dif.dk> - released under the terms of the GPL
- *
- * Credit should be given to :
- * R. Stevens author of "Advanced Programming in the UNIX Environment"
- * since I have made heavy use of some of his example code.
- *
- */
-
-/* To compile the test code: gcc -DTEST_FTW ftw.c */
-
-#include "ftw.h"
-
-static int depth;
-static char *path;
-
-static int trawl(char *path, ftw_func *f, int d) {
- int retval;
- struct stat sb;
- struct dirent *dir;
- DIR *dp;
- char *p;
-
- if (depth == d)
- return(0);
-
- if (lstat(path, &sb) == -1)
- return(f(path, &sb, FTW_NS));
-
- if (!S_ISDIR(sb.st_mode))
- return(f(path, &sb, FTW_F));
-
- if ((retval = f(path, &sb, FTW_D)) != 0)
- return(retval);
-
- p = path + strlen(path);
- *p++ = '/';
- *p = '\0';
-
- if ((dp = opendir(path)) == NULL)
- return(f(path, &sb, FTW_DNR));
-
- while ((dir = readdir(dp)) != NULL) {
- if ((strncmp(dir->d_name, ".", 1) == 0) ||
- (strncmp(dir->d_name, "..", 2) == 0))
- continue;
-
- strcpy(p, dir->d_name);
- depth++;
- if ((retval = trawl(path, f, d)) != 0)
- break;
- depth--;
- }
-
- p[-1] = '\0';
-
- closedir(dp);
- return(retval);
-}
-
-int ftw(const char *directory, ftw_func *f, int d) {
- int retval;
-
- if ((path = (char *)malloc(sysconf(_PC_PATH_MAX)+1)) == NULL)
- return(-1);
-
- strcpy(path, directory);
- depth = 0;
- retval = trawl(path, f, d);
-
- free(path);
- return(retval);
-}
-
-#ifdef TEST_FTW
-int foo(const char *file, struct stat *sb, int flag) {
-
- switch (flag) {
- case FTW_F :
- if (S_ISREG(sb->st_mode)) printf("%s is a regular file\n\n", file);
- else if (S_ISBLK(sb->st_mode)) printf("%s is a block dev\n\n", file);
- else if (S_ISCHR(sb->st_mode)) printf("%s is a char dev\n\n", file);
- else if (S_ISFIFO(sb->st_mode)) printf("%s is a fifo\n\n", file);
- else if (S_ISLNK(sb->st_mode)) printf("%s is a link\n\n", file);
- break;
- case FTW_D :
- printf("%s is a directory\n\n", file);
- break;
- case FTW_NS :
- printf("stat failed on %s\n\n", file);
- break;
- case FTW_DNR :
- printf("%s is a directory which can't be read\n\n", file);
- break;
- default :
- printf("%s is unknown\n\n", file);
- break;
- }
- return(0);
-}
-
-int main(int argc, char *argv[]) {
-
- if (argc == 2) {
- ftw(argv[1], foo, 1);
- exit(0);
- } else if (argc > 2) {
- ftw(argv[1], foo, atoi(argv[2]));
- exit(0);
- } else {
- printf("usage %s <dirname> [depth]\n", argv[0]);
- exit(1);
- }
-}
-#endif
-
diff --git a/lib/ftw.h b/lib/ftw.h
deleted file mode 100644
index 5e8f0cf..0000000
--- a/lib/ftw.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _FTW_H_
-#define _FTW_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <limits.h>
-
-#define FTW_F 1
-#define FTW_D 2
-#define FTW_DNR 3
-#define FTW_NS 4
-
-/* This is a replacement for the FTW file traversal utility */
-
-typedef int ftw_func(const char *file, const struct stat *sb, int flag);
-
-int ftw(const char *directory, ftw_func *f, int d);
-
-#endif /* _FTW_H_ */