Hello community,
here is the log from the commit of package attr
checked in at Tue Oct 30 01:29:15 CET 2007.
--------
--- attr/attr.changes 2007-10-26 02:34:32.000000000 +0200
+++ /mounts/work_src_done/STABLE/attr/attr.changes 2007-10-28 18:02:17.164738000 +0100
@@ -1,0 +2,6 @@
+Sat Oct 27 18:16:49 CEST 2007 - agruen@suse.de
+
+- Don't exhaust the number of file descriptors in the path walking
+ code, and make sure each directory is only visited once.
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ attr.spec ++++++
--- /var/tmp/diff_new_pack.IQ5172/_old 2007-10-30 01:28:46.000000000 +0100
+++ /var/tmp/diff_new_pack.IQ5172/_new 2007-10-30 01:28:46.000000000 +0100
@@ -15,7 +15,7 @@
AutoReqProv: on
Summary: Commands for Manipulating Extended Attributes
Version: 2.4.39
-Release: 1
+Release: 3
Source: %{name}-%{version}.src.tar.bz2
Source1: xattr.conf
Patch0: builddefs.in.diff
@@ -165,6 +165,9 @@
/%{_lib}/libattr.so.1*
%config %{_sysconfdir}/xattr.conf
%changelog
+* Sat Oct 27 2007 - agruen@suse.de
+- Don't exhaust the number of file descriptors in the path walking
+ code, and make sure each directory is only visited once.
* Fri Oct 26 2007 - agruen@suse.de
- A large jump to the current upstream version 2.4.39.
- Fix the upstream path walking code.
++++++ walk-attr.diff ++++++
--- /var/tmp/diff_new_pack.IQ5172/_old 2007-10-30 01:28:46.000000000 +0100
+++ /var/tmp/diff_new_pack.IQ5172/_new 2007-10-30 01:28:46.000000000 +0100
@@ -78,7 +78,7 @@
}
const char *strerror_ea(int err)
-@@ -347,22 +346,14 @@ int list_attributes(const char *path, in
+@@ -347,21 +346,19 @@ int list_attributes(const char *path, in
return 0;
}
@@ -95,18 +95,21 @@
- * was specified on the command line. Always skip symbolic
- * links if doing a physical walk.
- */
--
-- if (S_ISLNK(stat->st_mode) &&
-- (opt_walk_physical || (ftw->level > 0 && !opt_walk_logical)))
-- return 0;
+ if (walk_flags & WALK_TREE_FAILED) {
+ fprintf(stderr, "%s: %s: %s\n", progname, xquote(path), strerror(errno));
+ return 1;
+ }
+- if (S_ISLNK(stat->st_mode) &&
+- (opt_walk_physical || (ftw->level > 0 && !opt_walk_logical)))
++ if ((walk_flags & WALK_TREE_SYMLINK) &&
++ (walk_flags & WALK_TREE_DEREFERENCE) &&
++ ((walk_flags & WALK_TREE_PHYSICAL) ||
++ !(walk_flags & (WALK_TREE_TOPLEVEL | WALK_TREE_LOGICAL))))
+ return 0;
+
if (opt_name)
- print_attribute(path, opt_name, &header_printed);
-@@ -371,21 +362,6 @@ int do_print(const char *path, const str
+@@ -371,21 +368,6 @@ int do_print(const char *path, const str
if (header_printed)
puts("");
@@ -128,7 +131,7 @@
return 0;
}
-@@ -410,39 +386,6 @@ void help(void)
+@@ -410,39 +392,6 @@ void help(void)
" --help this help text\n"));
}
@@ -168,7 +171,7 @@
int main(int argc, char *argv[])
{
int opt;
-@@ -478,7 +421,7 @@ int main(int argc, char *argv[])
+@@ -478,7 +427,7 @@ int main(int argc, char *argv[])
return 0;
case 'h': /* do not dereference symlinks */
@@ -177,7 +180,7 @@
break;
case 'n': /* get named attribute */
-@@ -497,17 +440,17 @@ int main(int argc, char *argv[])
+@@ -497,17 +446,17 @@ int main(int argc, char *argv[])
break;
case 'L':
@@ -200,12 +203,13 @@
break;
case 'V':
-@@ -531,7 +474,7 @@ int main(int argc, char *argv[])
+@@ -531,7 +480,8 @@ int main(int argc, char *argv[])
}
while (optind < argc) {
- had_errors += walk_tree(argv[optind]);
-+ had_errors += walk_tree(argv[optind], walk_flags, do_print, NULL);
++ had_errors += walk_tree(argv[optind], walk_flags, 0,
++ do_print, NULL);
optind++;
}
@@ -364,7 +368,7 @@
===================================================================
--- /dev/null
+++ attr-2.4.39/include/walk_tree.h
-@@ -0,0 +1,18 @@
+@@ -0,0 +1,19 @@
+#ifndef __WALK_TREE_H
+#define __WALK_TREE_H
+
@@ -373,21 +377,22 @@
+#define WALK_TREE_LOGICAL 0x4
+#define WALK_TREE_DEREFERENCE 0x8
+
-+#define WALK_TREE_SYMLINK 0x10
-+#define WALK_TREE_FAILED 0x20
++#define WALK_TREE_TOPLEVEL 0x100
++#define WALK_TREE_SYMLINK 0x200
++#define WALK_TREE_FAILED 0x400
+
+struct stat;
+
-+extern int walk_tree(const char *path, int walk_flags,
-+ int (*func)(const char *, const struct stat *, int, void *),
-+ void *arg);
++extern int walk_tree(const char *path, int walk_flags, unsigned int num,
++ int (*func)(const char *, const struct stat *, int,
++ void *), void *arg);
+
+#endif
Index: attr-2.4.39/libmisc/walk_tree.c
===================================================================
--- /dev/null
+++ attr-2.4.39/libmisc/walk_tree.c
-@@ -0,0 +1,100 @@
+@@ -0,0 +1,188 @@
+/*
+ File: walk_tree.c
+
@@ -411,6 +416,8 @@
+#include
+#include
+#include
++#include
++#include
+#include
+#include
+#include
@@ -418,75 +425,161 @@
+
+#include "walk_tree.h"
+
++struct entry_handle {
++ struct entry_handle *prev, *next;
++ struct stat st;
++ DIR *stream;
++ off_t pos;
++};
++
++struct entry_handle head = {
++ .next = &head,
++ .prev = &head,
++ /* The other fields are unused. */
++};
++struct entry_handle *closed = &head;
++unsigned int num_dir_handles;
++
+static int walk_tree_rec(const char *path, int walk_flags,
-+ int (*func)(const char *, const struct stat *, int, void *),
-+ void *arg, int depth)
++ int (*func)(const char *, const struct stat *, int,
++ void *), void *arg, int depth)
+{
+ int (*xstat)(const char *, struct stat *) = lstat;
-+ struct stat st;
-+ int local_walk_flags = walk_flags, err;
++ int flags = walk_flags, err;
++ struct entry_handle dir;
+
-+ /* Default to traversing symlinks on the command line, traverse all symlinks
-+ * with -L, and do not traverse symlinks with -P. (This is similar to chown.)
++ /*
++ * If (walk_flags & WALK_TREE_PHYSICAL), do not traverse symlinks.
++ * If (walk_flags & WALK_TREE_LOGICAL), traverse all symlinks.
++ * Otherwise, traverse only top-level symlinks.
+ */
++ if (depth == 0)
++ flags |= WALK_TREE_TOPLEVEL;
+
+follow_symlink:
-+ if (xstat(path, &st) != 0)
-+ return func(path, NULL, local_walk_flags | WALK_TREE_FAILED, arg);
-+ if (S_ISLNK(st.st_mode)) {
-+ if ((local_walk_flags & WALK_TREE_PHYSICAL) ||
-+ (!(local_walk_flags & WALK_TREE_LOGICAL) && depth > 1))
-+ return 0;
-+ local_walk_flags |= WALK_TREE_SYMLINK;
-+ xstat = stat;
-+ if (local_walk_flags & WALK_TREE_DEREFERENCE)
++ if (xstat(path, &dir.st) != 0)
++ return func(path, NULL, flags | WALK_TREE_FAILED, arg);
++ if (S_ISLNK(dir.st.st_mode)) {
++ flags |= WALK_TREE_SYMLINK;
++ if (flags & WALK_TREE_DEREFERENCE) {
++ xstat = stat;
+ goto follow_symlink;
++ }
+ }
-+ err = func(path, &st, local_walk_flags, arg);
-+ if ((local_walk_flags & WALK_TREE_RECURSIVE) &&
-+ (S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))) {
-+ char path2[FILENAME_MAX];
-+ DIR *dir;
++ err = func(path, &dir.st, flags, arg);
++ if ((flags & WALK_TREE_RECURSIVE) &&
++ (S_ISDIR(dir.st.st_mode) || (S_ISLNK(dir.st.st_mode))) &&
++ (!(flags & WALK_TREE_PHYSICAL) || !(flags & WALK_TREE_SYMLINK)) &&
++ (flags & (WALK_TREE_LOGICAL | WALK_TREE_TOPLEVEL))) {
++ struct entry_handle *i;
+ struct dirent *entry;
-+ int err2;
+
-+ dir = opendir(path);
-+ if (!dir) {
-+ /* PATH may be a symlink to a regular file or a dead symlink
-+ * which we didn't follow above.
++ /* Check if we have already visited this directory. */
++ for (i = head.next; i != &head; i = i->next)
++ if (i->st.st_dev == dir.st.st_dev &&
++ i->st.st_ino == dir.st.st_ino)
++ return err;
++
++ if (num_dir_handles == 0 && closed->prev != &head) {
++close_another_dir:
++ /* Close the topmost directory handle still open. */
++ closed = closed->prev;
++ closed->pos = telldir(closed->stream);
++ closedir(closed->stream);
++ closed->stream = NULL;
++ num_dir_handles++;
++ }
++
++ dir.stream = opendir(path);
++ if (!dir.stream) {
++ if (errno == ENFILE && closed->prev != &head) {
++ /* Ran out of file descriptors. */
++ num_dir_handles = 0;
++ goto close_another_dir;
++ }
++
++ /*
++ * PATH may be a symlink to a regular file, or a dead
++ * symlink which we didn't follow above.
+ */
+ if (errno != ENOTDIR && errno != ENOENT)
-+ err += func(path, &st,
-+ local_walk_flags | WALK_TREE_FAILED, arg);
++ err += func(path, &dir.st,
++ flags | WALK_TREE_FAILED, arg);
+ return err;
+ }
-+ while ((entry = readdir(dir)) != NULL) {
-+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
++
++ /* Insert into the list of handles. */
++ dir.next = head.next;
++ dir.prev = &head;
++ dir.prev->next = &dir;
++ dir.next->prev = &dir;
++ num_dir_handles--;
++
++ while ((entry = readdir(dir.stream)) != NULL) {
++ char *path_end;
++
++ if (!strcmp(entry->d_name, ".") ||
++ !strcmp(entry->d_name, ".."))
+ continue;
-+ err2 = snprintf(path2, sizeof(path2), "%s/%s", path,
-+ entry->d_name);
-+ if (err2 < 0 || err2 > FILENAME_MAX) {
++ path_end = strchr(path, 0);
++ if ((path_end - path) + strlen(entry->d_name) + 1 >=
++ FILENAME_MAX) {
+ errno = ENAMETOOLONG;
+ err += func(path, NULL,
-+ local_walk_flags | WALK_TREE_FAILED, arg);
++ flags | WALK_TREE_FAILED, arg);
+ continue;
+ }
-+ err += walk_tree_rec(path2, walk_flags, func, arg, depth + 1);
++ *path_end++ = '/';
++ strcpy(path_end, entry->d_name);
++ err += walk_tree_rec(path, walk_flags, func, arg,
++ depth + 1);
++ *--path_end = 0;
++ if (!dir.stream) {
++ /* Reopen the directory handle. */
++ dir.stream = opendir(path);
++ if (!dir.stream)
++ return err + func(path, &dir.st, flags |
++ WALK_TREE_FAILED, arg);
++ seekdir(dir.stream, dir.pos);
++
++ closed = closed->next;
++ num_dir_handles--;
++ }
+ }
-+ if (closedir(dir) != 0)
-+ err += func(path, &st, local_walk_flags | WALK_TREE_FAILED, arg);
++
++ if (closedir(dir.stream) != 0)
++ err += func(path, &dir.st, flags | WALK_TREE_FAILED,
++ arg);
++
++ /* Remove from the list of handles. */
++ dir.prev->next = dir.next;
++ dir.next->prev = dir.prev;
++ num_dir_handles++;
+ }
+ return err;
+}
+
-+int walk_tree(const char *path, int walk_flags,
-+ int (*func)(const char *, const struct stat *, int, void *), void *arg)
++int walk_tree(const char *path, int walk_flags, unsigned int num,
++ int (*func)(const char *, const struct stat *, int, void *),
++ void *arg)
+{
++ char path_copy[FILENAME_MAX];
++
++ num_dir_handles = num;
++ if (num_dir_handles < 1) {
++ struct rlimit rlimit;
++
++ num_dir_handles = 1;
++ if (getrlimit(RLIMIT_NOFILE, &rlimit) == 0 &&
++ rlimit.rlim_cur >= 2)
++ num_dir_handles = rlimit.rlim_cur / 2;
++ }
+ if (strlen(path) >= FILENAME_MAX) {
+ errno = ENAMETOOLONG;
+ return func(path, NULL, WALK_TREE_FAILED, arg);
+ }
-+ return walk_tree_rec(path, walk_flags, func, arg, 1);
++ strcpy(path_copy, path);
++ return walk_tree_rec(path_copy, walk_flags, func, arg, 0);
+}
Index: attr-2.4.39/test/getfattr.test
===================================================================
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Remember to have fun...
---------------------------------------------------------------------
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org