1 /* @(#)walk.c 1.11 10/12/19 Copyright 2005-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)walk.c 1.11 10/12/19 Copyright 2005-2010 J. Schilling";
6 #endif
7 /*
8 * This file contains the callback code for treewalk() as used
9 * with mkisofs -find.
10 *
11 * Copyright (c) 2005-2010 J. Schilling
12 */
13 /*
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2
16 * as published by the Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License along with
24 * this program; see the file COPYING. If not, write to the Free Software
25 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 */
27
28 #include <schily/stat.h>
29 #include <schily/walk.h>
30 #include <schily/find.h>
31 #include "mkisofs.h"
32 #include <schily/schily.h>
33
34 #ifdef USE_FIND
35 /*
36 * The callback function for treewalk()
37 */
38 EXPORT int
walkfunc(nm,fs,type,state)39 walkfunc(nm, fs, type, state)
40 char *nm;
41 struct stat *fs;
42 int type;
43 struct WALK *state;
44 {
45 if (type == WALK_NS) {
46 errmsg(_("Cannot stat '%s'.\n"), nm);
47 state->err = 1;
48 return (0);
49 } else if (type == WALK_SLN && (state->walkflags & WALK_PHYS) == 0) {
50 errmsg(_("Cannot follow symlink '%s'.\n"), nm);
51 state->err = 1;
52 return (0);
53 } else if (type == WALK_DNR) {
54 if (state->flags & WALK_WF_NOCHDIR)
55 errmsg(_("Cannot chdir to '%s'.\n"), nm);
56 else
57 errmsg(_("Cannot read '%s'.\n"), nm);
58 state->err = 1;
59 return (0);
60 }
61 if (state->maxdepth >= 0 && state->level >= state->maxdepth)
62 state->flags |= WALK_WF_PRUNE;
63 if (state->mindepth >= 0 && state->level < state->mindepth)
64 return (0);
65
66 if (state->tree == NULL ||
67 find_expr(nm, nm + state->base, fs, state, state->tree)) {
68 struct directory *de;
69 char *p;
70 char *xp;
71 struct wargs *wa = state->auxp;
72
73 de = wa->dir;
74 /*
75 * Loop down deeper and deeper until we find the
76 * correct insertion spot.
77 * Canonicalize the filename while parsing it.
78 */
79 for (xp = &nm[state->auxi]; xp < nm + state->base; ) {
80 do {
81 while (xp[0] == '.' && xp[1] == '/')
82 xp += 2;
83 while (xp[0] == '/')
84 xp += 1;
85 if (xp[0] == '.' && xp[1] == '.' && xp[2] == '/') {
86 /*
87 * de == NULL cannot really happen
88 */
89 if (de && de != root) {
90 de = de->parent;
91 xp += 2;
92 }
93 }
94 } while ((xp[0] == '/') || (xp[0] == '.' && xp[1] == '/'));
95 p = strchr(xp, PATH_SEPARATOR);
96 if (p == NULL)
97 break;
98 *p = '\0';
99 if (debug) {
100 error(_("BASE Point:'%s' in '%s : %s' (%s)\n"),
101 xp,
102 de?de->whole_name:"[null]",
103 de?de->de_name:"[null]",
104 nm);
105 }
106 de = find_or_create_directory(de,
107 nm,
108 NULL, TRUE);
109 *p = PATH_SEPARATOR;
110 xp = p + 1;
111 }
112
113 if (state->base == 0) {
114 char *short_name;
115 /*
116 * This is one of the path type arguments to -find
117 */
118 short_name = wa->name;
119 if (short_name == NULL) {
120 short_name = strrchr(nm, PATH_SEPARATOR);
121 if (short_name == NULL || short_name < nm) {
122 short_name = nm;
123 } else {
124 short_name++;
125 if (*short_name == '\0')
126 short_name = nm;
127 }
128 }
129 if (S_ISDIR(fs->st_mode))
130 attach_dot_entries(de, fs, fs);
131 else
132 insert_file_entry(de, nm, short_name, NULL, 0);
133 } else {
134 int ret = insert_file_entry(de,
135 nm, nm + state->base, fs, 0);
136
137 if (S_ISDIR(fs->st_mode)) {
138 int sret;
139 struct stat parent;
140
141 if (ret == 0) {
142 /*
143 * Direcory nesting too deep.
144 */
145 state->flags |= WALK_WF_PRUNE;
146 return (0);
147 }
148 sret = stat(".", &parent);
149 de = find_or_create_directory(de,
150 nm,
151 NULL, TRUE);
152 attach_dot_entries(de,
153 fs,
154 sret < 0 ? NULL:&parent);
155 }
156 }
157 }
158 return (0);
159 }
160 #endif
161