Mercurial > hg > toybox
annotate lib/dirtree.c @ 601:a6a541b7fc34
Add dirtree_parentfd()
author | Rob Landley <rob@landley.net> |
---|---|
date | Sat, 16 Jun 2012 15:16:08 -0500 |
parents | fb582378a36a |
children | 8bee9c27c219 |
rev | line source |
---|---|
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
1 /* vi: set sw=4 ts=4 :*/ |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
2 /* dirtree.c - Functions for dealing with directory trees. |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
3 * |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
4 * Copyright 2007 Rob Landley <rob@landley.net> |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
5 */ |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
6 |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
7 #include "toys.h" |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
8 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
9 // Create a dirtree node from a path, with stat and symlink info. |
569
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
10 // (This doesn't open directory filehandles yet so as not to exhaust the |
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
11 // filehandle space on large trees. handle_callback() does that instead.) |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
12 |
593
fb582378a36a
Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents:
589
diff
changeset
|
13 struct dirtree *dirtree_add_node(int dirfd, char *name, int symfollow) |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
14 { |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
15 struct dirtree *dt = NULL; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
16 struct stat st; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
17 char buf[4096]; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
18 int len = 0, linklen = 0; |
156
1e8f4b05cb65
Remove trailing whitespace (thanks to Charlie Shepherd), and a couple comment
Rob Landley <rob@landley.net>
parents:
143
diff
changeset
|
19 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
20 if (name) { |
593
fb582378a36a
Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents:
589
diff
changeset
|
21 if (fstatat(dirfd, name, &st, symfollow ? 0 : AT_SYMLINK_NOFOLLOW)) |
fb582378a36a
Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents:
589
diff
changeset
|
22 goto error; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
23 if (S_ISLNK(st.st_mode)) { |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
24 if (0>(linklen = readlinkat(dirfd, name, buf, 4095))) goto error; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
25 buf[linklen++]=0; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
26 } |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
27 len = strlen(name); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
28 } |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
29 dt = xzalloc((len = sizeof(struct dirtree)+len+1)+linklen); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
30 if (name) { |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
31 memcpy(&(dt->st), &st, sizeof(struct stat)); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
32 strcpy(dt->name, name); |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
33 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
34 if (linklen) { |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
35 dt->symlink = memcpy(len+(char *)dt, buf, linklen); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
36 dt->data = --linklen; |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
37 } |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
38 } |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
39 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
40 return dt; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
41 |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
42 error: |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
43 perror_msg("%s",name); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
44 free(dt); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
45 return 0; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
46 } |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
47 |
569
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
48 // Return path to this node, assembled recursively. |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
49 |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
50 char *dirtree_path(struct dirtree *node, int *plen) |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
51 { |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
52 char *path; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
53 int len; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
54 |
569
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
55 if (!node || !node->name) { |
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
56 path = xmalloc(*plen); |
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
57 *plen = 0; |
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
58 return path; |
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
59 } |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
60 |
569
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
61 len = (plen ? *plen : 0)+strlen(node->name)+1; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
62 path = dirtree_path(node->parent, &len); |
576
4058eacd4fbc
Whitespace (tabs vs spaces) cleanup.
Rob Landley <rob@landley.net>
parents:
569
diff
changeset
|
63 if (len) path[len++]='/'; |
569
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
64 len = (stpcpy(path+len, node->name) - path); |
576
4058eacd4fbc
Whitespace (tabs vs spaces) cleanup.
Rob Landley <rob@landley.net>
parents:
569
diff
changeset
|
65 if (plen) *plen = len; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
66 |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
67 return path; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
68 } |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
69 |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
70 // Default callback, filters out "." and "..". |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
71 |
580
4877cff01b25
dirtree logic cleanup: switch DIRTREE_NORECURSE and DIRTREE_NOSAVE to DIRTREE_RECURSE and DIRTREE_SAVE.
Rob Landley <rob@landley.net>
parents:
576
diff
changeset
|
72 int dirtree_notdotdot(struct dirtree *catch) |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
73 { |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
74 // Should we skip "." and ".."? |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
75 if (catch->name[0]=='.' && (!catch->name[1] || |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
76 (catch->name[1]=='.' && !catch->name[2]))) |
580
4877cff01b25
dirtree logic cleanup: switch DIRTREE_NORECURSE and DIRTREE_NOSAVE to DIRTREE_RECURSE and DIRTREE_SAVE.
Rob Landley <rob@landley.net>
parents:
576
diff
changeset
|
77 return 0; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
78 |
580
4877cff01b25
dirtree logic cleanup: switch DIRTREE_NORECURSE and DIRTREE_NOSAVE to DIRTREE_RECURSE and DIRTREE_SAVE.
Rob Landley <rob@landley.net>
parents:
576
diff
changeset
|
79 return DIRTREE_SAVE|DIRTREE_RECURSE; |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
80 } |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
81 |
601 | 82 int dirtree_parentfd(struct dirtree *node) |
83 { | |
84 return node->parent ? node->parent->data : AT_FDCWD; | |
85 } | |
86 | |
589
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
87 // get open filehandle for node in extra, giving caller the option of |
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
88 // using DIRTREE_COMEAGAIN or not. |
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
89 int dirtree_opennode(struct dirtree *try) |
588
9c2277b92b86
Factor out dirtree_comeagain() callback, setting up depth-first search with open filehandle in node->extra.
Rob Landley <rob@landley.net>
parents:
582
diff
changeset
|
90 { |
589
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
91 if (!dirtree_notdotdot(try)) return 0; |
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
92 if (S_ISDIR(try->st.st_mode)) { |
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
93 if (!try->extra) { |
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
94 try->extra = xdup(try->data); |
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
95 return DIRTREE_COMEAGAIN; |
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
96 } |
601 | 97 } else try->extra = openat(dirtree_parentfd(try), try->name, 0); |
588
9c2277b92b86
Factor out dirtree_comeagain() callback, setting up depth-first search with open filehandle in node->extra.
Rob Landley <rob@landley.net>
parents:
582
diff
changeset
|
98 |
589
7013fd450ff4
Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
Rob Landley <rob@landley.net>
parents:
588
diff
changeset
|
99 return DIRTREE_SAVE|DIRTREE_RECURSE; |
588
9c2277b92b86
Factor out dirtree_comeagain() callback, setting up depth-first search with open filehandle in node->extra.
Rob Landley <rob@landley.net>
parents:
582
diff
changeset
|
100 } |
9c2277b92b86
Factor out dirtree_comeagain() callback, setting up depth-first search with open filehandle in node->extra.
Rob Landley <rob@landley.net>
parents:
582
diff
changeset
|
101 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
102 // Handle callback for a node in the tree. Returns saved node(s) or NULL. |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
103 // |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
104 // By default, allocates a tree of struct dirtree, not following symlinks |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
105 // If callback==NULL, or callback always returns 0, allocate tree of struct |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
106 // dirtree and return root of tree. Otherwise call callback(node) on each |
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
107 // hit, free structures after use, and return NULL. |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
108 // |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
109 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
110 struct dirtree *handle_callback(struct dirtree *new, |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
111 int (*callback)(struct dirtree *node)) |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
112 { |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
113 int flags, dir = S_ISDIR(new->st.st_mode); |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
114 |
580
4877cff01b25
dirtree logic cleanup: switch DIRTREE_NORECURSE and DIRTREE_NOSAVE to DIRTREE_RECURSE and DIRTREE_SAVE.
Rob Landley <rob@landley.net>
parents:
576
diff
changeset
|
115 if (!callback) callback = dirtree_notdotdot; |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
116 |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
117 // Directory always has filehandle for examining contents. Whether or |
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
118 // not we'll recurse into it gets decided later. |
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
119 |
601 | 120 if (dir) new->data = openat(dirtree_parentfd(new), new->name, 0); |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
121 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
122 flags = callback(new); |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
123 |
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
124 if (dir) { |
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
125 if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) { |
593
fb582378a36a
Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents:
589
diff
changeset
|
126 dirtree_recurse(new, callback, flags & DIRTREE_SYMFOLLOW); |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
127 if (flags & DIRTREE_COMEAGAIN) flags = callback(new); |
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
128 } else close(new->data); |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
129 } |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
130 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
131 // If this had children, it was callback's job to free them already. |
580
4877cff01b25
dirtree logic cleanup: switch DIRTREE_NORECURSE and DIRTREE_NOSAVE to DIRTREE_RECURSE and DIRTREE_SAVE.
Rob Landley <rob@landley.net>
parents:
576
diff
changeset
|
132 if (!(flags & DIRTREE_SAVE)) { |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
133 free(new); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
134 new = NULL; |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
135 } |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
136 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
137 return (flags & DIRTREE_ABORT)==DIRTREE_ABORT ? DIRTREE_ABORTVAL : new; |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
138 } |
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
139 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
140 // Recursively read/process children of directory node (with dirfd in data), |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
141 // filtering through callback(). |
143
9cbb323f297f
Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
142 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
143 void dirtree_recurse(struct dirtree *node, |
593
fb582378a36a
Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents:
589
diff
changeset
|
144 int (*callback)(struct dirtree *node), int symfollow) |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
145 { |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
146 struct dirtree *new, **ddt = &(node->child); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
147 struct dirent *entry; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
148 DIR *dir; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
149 |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
150 if (!(dir = fdopendir(node->data))) { |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
151 char *path = dirtree_path(node, 0); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
152 perror_msg("No %s", path); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
153 free(path); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
154 close(node->data); |
569
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
155 |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
156 return; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
157 } |
569
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
158 |
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
159 // according to the fddir() man page, the filehandle in the DIR * can still |
2e0367cb9585
More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
160 // be externally used by things that don't lseek() it. |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
161 |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
162 // The extra parentheses are to shut the stupid compiler up. |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
163 while ((entry = readdir(dir))) { |
593
fb582378a36a
Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents:
589
diff
changeset
|
164 if (!(new = dirtree_add_node(node->data, entry->d_name, symfollow))) |
fb582378a36a
Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents:
589
diff
changeset
|
165 continue; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
166 new->parent = node; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
167 new = handle_callback(new, callback); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
168 if (new == DIRTREE_ABORTVAL) break; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
169 if (new) { |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
170 *ddt = new; |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
171 ddt = &((*ddt)->next); |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
172 } |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
173 } |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
174 |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
175 // This closes filehandle as well, so note it |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
176 closedir(dir); |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
177 node->data = -1; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
178 } |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
179 |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
180 // Create dirtree from path, using callback to filter nodes. |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
181 // If callback == NULL allocate a tree of struct dirtree nodes and return |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
182 // pointer to root node. |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
183 |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
184 struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)) |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
185 { |
593
fb582378a36a
Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents:
589
diff
changeset
|
186 struct dirtree *root = dirtree_add_node(AT_FDCWD, path, 0); |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
187 |
582
b88bc7dcdb48
Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents:
580
diff
changeset
|
188 return root ? handle_callback(root, callback) : DIRTREE_ABORTVAL; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
320
diff
changeset
|
189 } |