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