annotate lib/dirtree.c @ 593:fb582378a36a

Implement DIRTREE_SYMFOLLOW and ls -cSHL.
author Rob Landley <rob@landley.net>
date Sat, 09 Jun 2012 22:25:49 -0500
parents 7013fd450ff4
children a6a541b7fc34
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
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
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
82 // 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
83 // 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
84 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
85 {
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
86 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
87 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
88 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
89 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
90 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
91 }
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 } 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
93 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
94
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
95 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
96 }
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
97
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
98 // 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
99 //
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
100 // 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
101 // 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
102 // 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
103 // 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
104 //
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
105
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
106 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
107 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
108 {
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
109 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
110
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
111 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
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 // 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
114 // 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
115
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
116 if (dir)
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
117 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
118 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
119
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
120 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
121
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
122 if (dir) {
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
123 if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) {
593
fb582378a36a Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents: 589
diff changeset
124 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
125 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
126 } 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
127 }
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
128
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 // 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
130 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
131 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
132 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
133 }
9cbb323f297f Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff changeset
134
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
135 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
136 }
9cbb323f297f Break out dirtree.c and let it call a function instead of returning the data.
Rob Landley <rob@landley.net>
parents:
diff changeset
137
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
138 // 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
139 // 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
140
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
141 void dirtree_recurse(struct dirtree *node,
593
fb582378a36a Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents: 589
diff changeset
142 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
143 {
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 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
145 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
146 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
147
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 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
149 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
150 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
151 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
152 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
153
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
154 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
155 }
569
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
156
2e0367cb9585 More work on ls. Now ls -lR sort of works-ish.
Rob Landley <rob@landley.net>
parents: 565
diff changeset
157 // 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
158 // 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
159
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 // 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
161 while ((entry = readdir(dir))) {
593
fb582378a36a Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents: 589
diff changeset
162 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
163 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
164 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
165 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
166 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
167 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
168 *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
169 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
170 }
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 }
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
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
173 // 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
174 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
175 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
176 }
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
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 // 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
179 // 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
180 // 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
181
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 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
183 {
593
fb582378a36a Implement DIRTREE_SYMFOLLOW and ls -cSHL.
Rob Landley <rob@landley.net>
parents: 589
diff changeset
184 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
185
582
b88bc7dcdb48 Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
Rob Landley <rob@landley.net>
parents: 580
diff changeset
186 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
187 }