Merge lp:~xnox/ubuntu/raring/libnih/fix-xfs into lp:ubuntu/raring/libnih

Proposed by Dimitri John Ledkov
Status: Merged
Merged at revision: 1068
Proposed branch: lp:~xnox/ubuntu/raring/libnih/fix-xfs
Merge into: lp:ubuntu/raring/libnih
Diff against target: 122 lines (+80/-1)
3 files modified
debian/changelog (+8/-0)
nih/file.c (+11/-1)
nih/tests/test_file.c (+61/-0)
To merge this branch: bzr merge lp:~xnox/ubuntu/raring/libnih/fix-xfs
Reviewer Review Type Date Requested Status
Upstart Developers Pending
Upstart Developers Pending
Review via email: mp+139065@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

I have tested this on ubuntu & debian and it fixes the referenced bugs.
But I still would like a second review before pushing to lp:ubuntu/libnih.

Revision history for this message
Steve Langasek (vorlon) wrote :

The main concern I have here is that we're not checking the return value of lstat, which means statbuf may be uninitialized and yield random behavior. If lstat() fails, we should assume it's not a directory.

The other consideration is that having to do an lstat for each entry just to check if it's a directory makes this walk a bit more expensive. According to readdir(3), if d_type isn't supported, its value should be set to DT_UNKNOWN. What about calling lstat *iff* d_type == DT_UNKNOWN? This would keep this speedy in the common case, but address the problem of portability to other filesystems.

1069. By Dimitri John Ledkov

use lstat, if d_type is not present

1070. By Dimitri John Ledkov

Check lstat return code

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

I like your suggestion. d_type indeed is set to DT_UNKNOWN on xfs. Implemented your suggestions and tested on ext4 & xfs. All tests pass.

1071. By Dimitri John Ledkov

Update changelog entry

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2012-10-25 10:57:30 +0000
+++ debian/changelog 2012-12-11 11:12:26 +0000
@@ -1,3 +1,11 @@
1libnih (1.0.3-4ubuntu13) UNRELEASED; urgency=low
2
3 [ Petr Lautrbach <plautrba@redhat.com>, Dmitrijs Ledkovs ]
4 * Fallback to lstat, if dirent.d_type is not available (not portable)
5 (LP: #672643) (Closes: #695604)
6
7 -- Dmitrijs Ledkovs <dmitrij.ledkov@ubuntu.com> Mon, 10 Dec 2012 18:13:28 +0000
8
1libnih (1.0.3-4ubuntu12) raring; urgency=low9libnih (1.0.3-4ubuntu12) raring; urgency=low
210
3 * nih/logging.c: Use our own __nih_abort_msg rather than the (e)glibc11 * nih/logging.c: Use our own __nih_abort_msg rather than the (e)glibc
412
=== modified file 'nih/file.c'
--- nih/file.c 2010-02-04 22:30:23 +0000
+++ nih/file.c 2012-12-11 11:12:26 +0000
@@ -619,6 +619,8 @@
619 struct dirent *ent;619 struct dirent *ent;
620 char **paths;620 char **paths;
621 size_t npaths;621 size_t npaths;
622 int isdir;
623 struct stat statbuf;
622624
623 nih_assert (path != NULL);625 nih_assert (path != NULL);
624626
@@ -640,7 +642,15 @@
640 subpath = NIH_MUST (nih_sprintf (NULL, "%s/%s",642 subpath = NIH_MUST (nih_sprintf (NULL, "%s/%s",
641 path, ent->d_name));643 path, ent->d_name));
642644
643 if (filter && filter (data, subpath, ent->d_type == DT_DIR))645 if (ent->d_type == DT_UNKNOWN) {
646 if ( lstat (subpath, &statbuf))
647 isdir = 0;
648 else
649 isdir = S_ISDIR(statbuf.st_mode);
650 } else
651 isdir = ent->d_type == DT_DIR;
652
653 if (filter && filter (data, subpath, isdir))
644 continue;654 continue;
645655
646 NIH_MUST (nih_str_array_addp (&paths, NULL, &npaths, subpath));656 NIH_MUST (nih_str_array_addp (&paths, NULL, &npaths, subpath));
647657
=== modified file 'nih/tests/test_file.c'
--- nih/tests/test_file.c 2010-02-04 22:30:23 +0000
+++ nih/tests/test_file.c 2012-12-11 11:12:26 +0000
@@ -724,6 +724,25 @@
724 return FALSE;724 return FALSE;
725}725}
726726
727/* find only frodo files */
728static int
729my_filter_frodo_file (void *data,
730 const char *path,
731 int is_dir)
732{
733 char *slash;
734
735 if (is_dir)
736 return FALSE;
737
738 slash = strrchr (path, '/');
739 if (strcmp (slash, "/frodo"))
740 return TRUE;
741
742 return FALSE;
743}
744
745
727static int logger_called = 0;746static int logger_called = 0;
728747
729static int748static int
@@ -905,6 +924,48 @@
905 TEST_EQ_STR (v->path, filename);924 TEST_EQ_STR (v->path, filename);
906925
907 nih_free (visited);926 nih_free (visited);
927
928 /* Try also inverse filter */
929 TEST_ALLOC_SAFE {
930 visitor_called = 0;
931 visited = nih_list_new (NULL);
932 }
933
934 ret = nih_dir_walk (dirname, my_filter_frodo_file,
935 my_visitor, NULL, &ret);
936
937 TEST_EQ (ret, 0);
938 TEST_EQ (visitor_called, 4);
939
940 v = (Visited *)visited->next;
941 TEST_EQ (v->data, &ret);
942 TEST_EQ_STR (v->dirname, dirname);
943 strcpy (filename, dirname);
944 strcat (filename, "/bar");
945 TEST_EQ_STR (v->path, filename);
946
947 v = (Visited *)v->entry.next;
948 TEST_EQ (v->data, &ret);
949 TEST_EQ_STR (v->dirname, dirname);
950 strcpy (filename, dirname);
951 strcat (filename, "/bar/frodo");
952 TEST_EQ_STR (v->path, filename);
953
954 v = (Visited *)v->entry.next;
955 TEST_EQ (v->data, &ret);
956 TEST_EQ_STR (v->dirname, dirname);
957 strcpy (filename, dirname);
958 strcat (filename, "/baz");
959 TEST_EQ_STR (v->path, filename);
960
961 v = (Visited *)v->entry.next;
962 TEST_EQ (v->data, &ret);
963 TEST_EQ_STR (v->dirname, dirname);
964 strcpy (filename, dirname);
965 strcat (filename, "/frodo");
966 TEST_EQ_STR (v->path, filename);
967
968 nih_free (visited);
908 }969 }
909970
910971

Subscribers

People subscribed via source and target branches