annotate lib/dirtree.c @ 589:7013fd450ff4

Changed my mind about the design again, now callback is dirtree_opennode() and recursion choice is how caller interprets flags.
author Rob Landley <rob@landley.net>
date Fri, 01 Jun 2012 20:27:51 -0500
parents 9c2277b92b86
children fb582378a36a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
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
13 struct dirtree *dirtree_add_node(int dirfd, char *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
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) {
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
21 if (fstatat(dirfd, name, &st, AT_SYMLINK_NOFOLLOW)) 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
22 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
23 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
24 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
25 }
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 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
27 }
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 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
29 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
30 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
31 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
32
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
33 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
34 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
35 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
36 }
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
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
39 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
40
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 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
42 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
43 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
44 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
45 }
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
569
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
47 // 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
48
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 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
50 {
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 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
52 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
53
569
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
54 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
55 path = xmalloc(*plen);
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
56 *plen = 0;
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
57 return path;
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
58 }
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
59
569
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
60 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
61 path = dirtree_path(node->parent, &len);
576
4058eacd4fbc Whitespace (tabs vs spaces) cleanup.
Rob Landley <rob@landley.net>
parents: 569
diff changeset
62 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
63 len = (stpcpy(path+len, node->name) - path);
576
4058eacd4fbc Whitespace (tabs vs spaces) cleanup.
Rob Landley <rob@landley.net>
parents: 569
diff changeset
64 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
65
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 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
67 }
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 // 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
70
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
71 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
72 {
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 // 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
74 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
75 (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
76 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
77
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
78 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
79 }
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
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
81 // 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
82 // 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
83 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
84 {
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
85 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
86 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
87 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
88 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
89 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
90 }
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 } else try->extra = openat(try->parent ? try->parent->data : AT_FDCWD,
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 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
93
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
94 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
95 }
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
96
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
97 // 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
98 //
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
99 // 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
100 // 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
101 // 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
102 // 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
103 //
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
104
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
105 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
106 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
107 {
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
108 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
109
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
110 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
111
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
112 // 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
113 // 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
114
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
115 if (dir)
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
116 new->data = openat(new->parent ? new->parent->data : AT_FDCWD,
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
117 new->name, 0);
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
118
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
119 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
120
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
121 if (dir) {
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
122 if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) {
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
123 dirtree_recurse(new, callback);
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
124 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
125 } 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
126 }
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
127
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
128 // 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
129 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
130 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
131 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
132 }
9cbb323f297f Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff changeset
133
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
134 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
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 // 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
138 // 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
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 void dirtree_recurse(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
141 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
142 {
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 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
144 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
145 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
146
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 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
148 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
149 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
150 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
151 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
152
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
153 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
154 }
569
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
155
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
156 // 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
157 // 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
158
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
159 // 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
160 while ((entry = readdir(dir))) {
569
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
161 if (!(new = dirtree_add_node(node->data, entry->d_name))) 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
162 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
163 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
164 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
165 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
166 *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
167 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
168 }
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 }
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
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
171 // 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
172 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
173 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
174 }
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
175
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 // 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
177 // 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
178 // 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
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 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
181 {
569
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
182 struct dirtree *root = dirtree_add_node(AT_FDCWD, path);
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
183
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
184 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
185 }