GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: ftree.c,v 1.41 2017/09/16 07:42:34 otto Exp $ */ |
||
2 |
/* $NetBSD: ftree.c,v 1.4 1995/03/21 09:07:21 cgd Exp $ */ |
||
3 |
|||
4 |
/*- |
||
5 |
* Copyright (c) 1992 Keith Muller. |
||
6 |
* Copyright (c) 1992, 1993 |
||
7 |
* The Regents of the University of California. All rights reserved. |
||
8 |
* |
||
9 |
* This code is derived from software contributed to Berkeley by |
||
10 |
* Keith Muller of the University of California, San Diego. |
||
11 |
* |
||
12 |
* Redistribution and use in source and binary forms, with or without |
||
13 |
* modification, are permitted provided that the following conditions |
||
14 |
* are met: |
||
15 |
* 1. Redistributions of source code must retain the above copyright |
||
16 |
* notice, this list of conditions and the following disclaimer. |
||
17 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
18 |
* notice, this list of conditions and the following disclaimer in the |
||
19 |
* documentation and/or other materials provided with the distribution. |
||
20 |
* 3. Neither the name of the University nor the names of its contributors |
||
21 |
* may be used to endorse or promote products derived from this software |
||
22 |
* without specific prior written permission. |
||
23 |
* |
||
24 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
25 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
26 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
27 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
28 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
29 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
30 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
31 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
32 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
33 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
34 |
* SUCH DAMAGE. |
||
35 |
*/ |
||
36 |
|||
37 |
#include <sys/types.h> |
||
38 |
#include <sys/stat.h> |
||
39 |
#include <errno.h> |
||
40 |
#include <fts.h> |
||
41 |
#include <stdio.h> |
||
42 |
#include <stdlib.h> |
||
43 |
#include <string.h> |
||
44 |
#include <unistd.h> |
||
45 |
|||
46 |
#include "pax.h" |
||
47 |
#include "extern.h" |
||
48 |
|||
49 |
/* |
||
50 |
* Data structure used to store the file args to be handed to fts(). |
||
51 |
* It keeps track of which args generated a "selected" member. |
||
52 |
*/ |
||
53 |
typedef struct ftree { |
||
54 |
char *fname; /* file tree name */ |
||
55 |
int refcnt; /* has tree had a selected file? */ |
||
56 |
int newercnt; /* skipped due to -u/-D */ |
||
57 |
int chflg; /* change directory flag */ |
||
58 |
struct ftree *fow; /* pointer to next entry on list */ |
||
59 |
} FTREE; |
||
60 |
|||
61 |
|||
62 |
/* |
||
63 |
* routines to interface with the fts library function. |
||
64 |
* |
||
65 |
* file args supplied to pax are stored on a single linked list (of type FTREE) |
||
66 |
* and given to fts to be processed one at a time. pax "selects" files from |
||
67 |
* the expansion of each arg into the corresponding file tree (if the arg is a |
||
68 |
* directory, otherwise the node itself is just passed to pax). The selection |
||
69 |
* is modified by the -n and -u flags. The user is informed when a specific |
||
70 |
* file arg does not generate any selected files. -n keeps expanding the file |
||
71 |
* tree arg until one of its files is selected, then skips to the next file |
||
72 |
* arg. when the user does not supply the file trees as command line args to |
||
73 |
* pax, they are read from stdin |
||
74 |
*/ |
||
75 |
|||
76 |
static FTS *ftsp = NULL; /* current FTS handle */ |
||
77 |
static int ftsopts; /* options to be used on fts_open */ |
||
78 |
static char *farray[2]; /* array for passing each arg to fts */ |
||
79 |
static FTREE *fthead = NULL; /* head of linked list of file args */ |
||
80 |
static FTREE *fttail = NULL; /* tail of linked list of file args */ |
||
81 |
static FTREE *ftcur = NULL; /* current file arg being processed */ |
||
82 |
static FTSENT *ftent = NULL; /* current file tree entry */ |
||
83 |
static int ftree_skip; /* when set skip to next file arg */ |
||
84 |
|||
85 |
static int ftree_arg(void); |
||
86 |
static char *getpathname(char *, int); |
||
87 |
|||
88 |
/* |
||
89 |
* ftree_start() |
||
90 |
* initialize the options passed to fts_open() during this run of pax |
||
91 |
* options are based on the selection of pax options by the user |
||
92 |
* fts_start() also calls fts_arg() to open the first valid file arg. We |
||
93 |
* also attempt to reset directory access times when -t (tflag) is set. |
||
94 |
* Return: |
||
95 |
* 0 if there is at least one valid file arg to process, -1 otherwise |
||
96 |
*/ |
||
97 |
|||
98 |
int |
||
99 |
ftree_start(void) |
||
100 |
{ |
||
101 |
/* |
||
102 |
* set up the operation mode of fts, open the first file arg. We must |
||
103 |
* use FTS_NOCHDIR, as the user may have to open multiple archives and |
||
104 |
* if fts did a chdir off into the boondocks, we may create an archive |
||
105 |
* volume in an place where the user did not expect to. |
||
106 |
*/ |
||
107 |
220 |
ftsopts = FTS_NOCHDIR; |
|
108 |
|||
109 |
/* |
||
110 |
* optional user flags that effect file traversal |
||
111 |
* -H command line symlink follow only (half follow) |
||
112 |
* -L follow sylinks (logical) |
||
113 |
* -P do not follow sylinks (physical). This is the default. |
||
114 |
* -X do not cross over mount points |
||
115 |
* -t preserve access times on files read. |
||
116 |
* -n select only the first member of a file tree when a match is found |
||
117 |
* -d do not extract subtrees rooted at a directory arg. |
||
118 |
*/ |
||
119 |
110 |
if (Lflag) |
|
120 |
ftsopts |= FTS_LOGICAL; |
||
121 |
else |
||
122 |
ftsopts |= FTS_PHYSICAL; |
||
123 |
✗✓ | 110 |
if (Hflag) |
124 |
ftsopts |= FTS_COMFOLLOW; |
||
125 |
✗✓ | 110 |
if (Xflag) |
126 |
ftsopts |= FTS_XDEV; |
||
127 |
|||
128 |
✓✓✗✓ |
195 |
if ((fthead == NULL) && ((farray[0] = malloc(PAXPATHLEN+2)) == NULL)) { |
129 |
paxwarn(1, "Unable to allocate memory for file name buffer"); |
||
130 |
return(-1); |
||
131 |
} |
||
132 |
|||
133 |
✓✓ | 110 |
if (ftree_arg() < 0) |
134 |
34 |
return(-1); |
|
135 |
✗✓✗✗ |
76 |
if (tflag && (atdir_start() < 0)) |
136 |
return(-1); |
||
137 |
76 |
return(0); |
|
138 |
110 |
} |
|
139 |
|||
140 |
/* |
||
141 |
* ftree_add() |
||
142 |
* add the arg to the linked list of files to process. Each will be |
||
143 |
* processed by fts one at a time |
||
144 |
* Return: |
||
145 |
* 0 if added to the linked list, -1 if failed |
||
146 |
*/ |
||
147 |
|||
148 |
int |
||
149 |
ftree_add(char *str, int chflg) |
||
150 |
{ |
||
151 |
FTREE *ft; |
||
152 |
int len; |
||
153 |
|||
154 |
/* |
||
155 |
* simple check for bad args |
||
156 |
*/ |
||
157 |
✓✗✗✓ |
7254 |
if ((str == NULL) || (*str == '\0')) { |
158 |
paxwarn(0, "Invalid file name argument"); |
||
159 |
return(-1); |
||
160 |
} |
||
161 |
|||
162 |
/* |
||
163 |
* allocate FTREE node and add to the end of the linked list (args are |
||
164 |
* processed in the same order they were passed to pax). Get rid of any |
||
165 |
* trailing / the user may pass us. (watch out for / by itself). |
||
166 |
*/ |
||
167 |
✗✓ | 2418 |
if ((ft = malloc(sizeof(FTREE))) == NULL) { |
168 |
paxwarn(0, "Unable to allocate memory for filename"); |
||
169 |
return(-1); |
||
170 |
} |
||
171 |
|||
172 |
✓✓✗✓ |
4819 |
if (((len = strlen(str) - 1) > 0) && (str[len] == '/')) |
173 |
str[len] = '\0'; |
||
174 |
2418 |
ft->fname = str; |
|
175 |
2418 |
ft->refcnt = 0; |
|
176 |
2418 |
ft->newercnt = 0; |
|
177 |
2418 |
ft->chflg = chflg; |
|
178 |
2418 |
ft->fow = NULL; |
|
179 |
✓✓ | 2418 |
if (fthead == NULL) { |
180 |
25 |
fttail = fthead = ft; |
|
181 |
25 |
return(0); |
|
182 |
} |
||
183 |
2393 |
fttail->fow = ft; |
|
184 |
2393 |
fttail = ft; |
|
185 |
2393 |
return(0); |
|
186 |
2418 |
} |
|
187 |
|||
188 |
/* |
||
189 |
* ftree_sel() |
||
190 |
* this entry has been selected by pax. bump up reference count and handle |
||
191 |
* -n and -d processing. |
||
192 |
*/ |
||
193 |
|||
194 |
void |
||
195 |
ftree_sel(ARCHD *arcn) |
||
196 |
{ |
||
197 |
/* |
||
198 |
* set reference bit for this pattern. This linked list is only used |
||
199 |
* when file trees are supplied pax as args. The list is not used when |
||
200 |
* the trees are read from stdin. |
||
201 |
*/ |
||
202 |
✓✓ | 5088 |
if (ftcur != NULL) |
203 |
2510 |
ftcur->refcnt = 1; |
|
204 |
|||
205 |
/* |
||
206 |
* if -n we are done with this arg, force a skip to the next arg when |
||
207 |
* pax asks for the next file in next_file(). |
||
208 |
* if -d we tell fts only to match the directory (if the arg is a dir) |
||
209 |
* and not the entire file tree rooted at that point. |
||
210 |
*/ |
||
211 |
✗✓ | 2544 |
if (nflag) |
212 |
ftree_skip = 1; |
||
213 |
|||
214 |
✗✓✗✗ |
2544 |
if (!dflag || (arcn->type != PAX_DIR)) |
215 |
return; |
||
216 |
|||
217 |
if (ftent != NULL) |
||
218 |
(void)fts_set(ftsp, ftent, FTS_SKIP); |
||
219 |
2544 |
} |
|
220 |
|||
221 |
/* |
||
222 |
* ftree_skipped_newer() |
||
223 |
* file has been skipped because a newer file exists and -u/-D given |
||
224 |
*/ |
||
225 |
|||
226 |
void |
||
227 |
ftree_skipped_newer(ARCHD *arcn) |
||
228 |
{ |
||
229 |
/* skipped due to -u/-D, mark accordingly */ |
||
230 |
if (ftcur != NULL) |
||
231 |
ftcur->newercnt = 1; |
||
232 |
} |
||
233 |
|||
234 |
/* |
||
235 |
* ftree_chk() |
||
236 |
* called at end on pax execution. Prints all those file args that did not |
||
237 |
* have a selected member (reference count still 0) |
||
238 |
*/ |
||
239 |
|||
240 |
void |
||
241 |
ftree_chk(void) |
||
242 |
{ |
||
243 |
FTREE *ft; |
||
244 |
int wban = 0; |
||
245 |
|||
246 |
/* |
||
247 |
* make sure all dir access times were reset. |
||
248 |
*/ |
||
249 |
✗✓ | 186 |
if (tflag) |
250 |
atdir_end(); |
||
251 |
|||
252 |
/* |
||
253 |
* walk down list and check reference count. Print out those members |
||
254 |
* that never had a match |
||
255 |
*/ |
||
256 |
✓✓ | 5022 |
for (ft = fthead; ft != NULL; ft = ft->fow) { |
257 |
✗✓✗✗ ✗✗ |
2418 |
if ((ft->refcnt > 0) || ft->newercnt > 0 || ft->chflg) |
258 |
continue; |
||
259 |
if (wban == 0) { |
||
260 |
paxwarn(1,"WARNING! These file names were not selected:"); |
||
261 |
++wban; |
||
262 |
} |
||
263 |
(void)fprintf(stderr, "%s\n", ft->fname); |
||
264 |
} |
||
265 |
93 |
} |
|
266 |
|||
267 |
/* |
||
268 |
* ftree_arg() |
||
269 |
* Get the next file arg for fts to process. Can be from either the linked |
||
270 |
* list or read from stdin when the user did not them as args to pax. Each |
||
271 |
* arg is processed until the first successful fts_open(). |
||
272 |
* Return: |
||
273 |
* 0 when the next arg is ready to go, -1 if out of file args (or EOF on |
||
274 |
* stdin). |
||
275 |
*/ |
||
276 |
|||
277 |
static int |
||
278 |
ftree_arg(void) |
||
279 |
{ |
||
280 |
|||
281 |
/* |
||
282 |
* close off the current file tree |
||
283 |
*/ |
||
284 |
✓✓ | 5158 |
if (ftsp != NULL) { |
285 |
2469 |
(void)fts_close(ftsp); |
|
286 |
2469 |
ftsp = NULL; |
|
287 |
2469 |
} |
|
288 |
|||
289 |
/* |
||
290 |
* keep looping until we get a valid file tree to process. Stop when we |
||
291 |
* reach the end of the list (or get an eof on stdin) |
||
292 |
*/ |
||
293 |
for (;;) { |
||
294 |
✓✓ | 2579 |
if (fthead == NULL) { |
295 |
/* |
||
296 |
* the user didn't supply any args, get the file trees |
||
297 |
* to process from stdin; |
||
298 |
*/ |
||
299 |
✓✓ | 136 |
if (getpathname(farray[0], PAXPATHLEN+1) == NULL) |
300 |
85 |
return(-1); |
|
301 |
} else { |
||
302 |
/* |
||
303 |
* the user supplied the file args as arguments to pax |
||
304 |
*/ |
||
305 |
✓✓ | 2443 |
if (ftcur == NULL) |
306 |
25 |
ftcur = fthead; |
|
307 |
✓✓ | 2418 |
else if ((ftcur = ftcur->fow) == NULL) |
308 |
25 |
return(-1); |
|
309 |
✗✓ | 2418 |
if (ftcur->chflg) { |
310 |
/* First fchdir() back... */ |
||
311 |
if (fchdir(cwdfd) < 0) { |
||
312 |
syswarn(1, errno, |
||
313 |
"Can't fchdir to starting directory"); |
||
314 |
return(-1); |
||
315 |
} |
||
316 |
if (chdir(ftcur->fname) < 0) { |
||
317 |
syswarn(1, errno, "Can't chdir to %s", |
||
318 |
ftcur->fname); |
||
319 |
return(-1); |
||
320 |
} |
||
321 |
continue; |
||
322 |
} else |
||
323 |
2418 |
farray[0] = ftcur->fname; |
|
324 |
} |
||
325 |
|||
326 |
/* |
||
327 |
* watch it, fts wants the file arg stored in a array of char |
||
328 |
* ptrs, with the last one a null. we use a two element array |
||
329 |
* and set farray[0] to point at the buffer with the file name |
||
330 |
* in it. We cannot pass all the file args to fts at one shot |
||
331 |
* as we need to keep a handle on which file arg generates what |
||
332 |
* files (the -n and -d flags need this). If the open is |
||
333 |
* successful, return a 0. |
||
334 |
*/ |
||
335 |
✗✓ | 2469 |
if ((ftsp = fts_open(farray, ftsopts, NULL)) != NULL) |
336 |
break; |
||
337 |
} |
||
338 |
2469 |
return(0); |
|
339 |
2579 |
} |
|
340 |
|||
341 |
/* |
||
342 |
* next_file() |
||
343 |
* supplies the next file to process in the supplied archd structure. |
||
344 |
* Return: |
||
345 |
* 0 when contents of arcn have been set with the next file, -1 when done. |
||
346 |
*/ |
||
347 |
|||
348 |
int |
||
349 |
next_file(ARCHD *arcn) |
||
350 |
{ |
||
351 |
int cnt; |
||
352 |
|||
353 |
/* |
||
354 |
* ftree_sel() might have set the ftree_skip flag if the user has the |
||
355 |
* -n option and a file was selected from this file arg tree. (-n says |
||
356 |
* only one member is matched for each pattern) ftree_skip being 1 |
||
357 |
* forces us to go to the next arg now. |
||
358 |
*/ |
||
359 |
✗✓ | 5240 |
if (ftree_skip) { |
360 |
/* |
||
361 |
* clear and go to next arg |
||
362 |
*/ |
||
363 |
ftree_skip = 0; |
||
364 |
if (ftree_arg() < 0) |
||
365 |
return(-1); |
||
366 |
} |
||
367 |
|||
368 |
/* |
||
369 |
* loop until we get a valid file to process |
||
370 |
*/ |
||
371 |
for (;;) { |
||
372 |
✓✓ | 5072 |
if ((ftent = fts_read(ftsp)) == NULL) { |
373 |
✗✓ | 2469 |
if (errno) |
374 |
syswarn(1, errno, "next_file"); |
||
375 |
/* |
||
376 |
* out of files in this tree, go to next arg, if none |
||
377 |
* we are done |
||
378 |
*/ |
||
379 |
✓✓ | 2469 |
if (ftree_arg() < 0) |
380 |
76 |
return(-1); |
|
381 |
continue; |
||
382 |
} |
||
383 |
|||
384 |
/* |
||
385 |
* handle each type of fts_read() flag |
||
386 |
*/ |
||
387 |
✓✗✗✗ ✗✓✓ |
2603 |
switch (ftent->fts_info) { |
388 |
case FTS_D: |
||
389 |
case FTS_DEFAULT: |
||
390 |
case FTS_F: |
||
391 |
case FTS_SL: |
||
392 |
case FTS_SLNONE: |
||
393 |
/* |
||
394 |
* these are all ok |
||
395 |
*/ |
||
396 |
break; |
||
397 |
case FTS_DP: |
||
398 |
/* |
||
399 |
* already saw this directory. If the user wants file |
||
400 |
* access times reset, we use this to restore the |
||
401 |
* access time for this directory since this is the |
||
402 |
* last time we will see it in this file subtree |
||
403 |
* remember to force the time (this is -t on a read |
||
404 |
* directory, not a created directory). |
||
405 |
*/ |
||
406 |
✓✗ | 42 |
if (!tflag) |
407 |
continue; |
||
408 |
do_atdir(ftent->fts_path, ftent->fts_statp->st_dev, |
||
409 |
ftent->fts_statp->st_ino); |
||
410 |
continue; |
||
411 |
case FTS_DC: |
||
412 |
/* |
||
413 |
* fts claims a file system cycle |
||
414 |
*/ |
||
415 |
paxwarn(1,"File system cycle found at %s",ftent->fts_path); |
||
416 |
continue; |
||
417 |
case FTS_DNR: |
||
418 |
syswarn(1, ftent->fts_errno, |
||
419 |
"Unable to read directory %s", ftent->fts_path); |
||
420 |
continue; |
||
421 |
case FTS_ERR: |
||
422 |
syswarn(1, ftent->fts_errno, |
||
423 |
"File system traversal error"); |
||
424 |
continue; |
||
425 |
case FTS_NS: |
||
426 |
case FTS_NSOK: |
||
427 |
34 |
syswarn(1, ftent->fts_errno, |
|
428 |
17 |
"Unable to access %s", ftent->fts_path); |
|
429 |
17 |
continue; |
|
430 |
} |
||
431 |
|||
432 |
/* |
||
433 |
* ok got a file tree node to process. copy info into arcn |
||
434 |
* structure (initialize as required) |
||
435 |
*/ |
||
436 |
5088 |
arcn->skip = 0; |
|
437 |
5088 |
arcn->pad = 0; |
|
438 |
5088 |
arcn->ln_nlen = 0; |
|
439 |
5088 |
arcn->ln_name[0] = '\0'; |
|
440 |
5088 |
memcpy(&arcn->sb, ftent->fts_statp, sizeof(arcn->sb)); |
|
441 |
|||
442 |
/* |
||
443 |
* file type based set up and copy into the arcn struct |
||
444 |
* SIDE NOTE: |
||
445 |
* we try to reset the access time on all files and directories |
||
446 |
* we may read when the -t flag is specified. files are reset |
||
447 |
* when we close them after copying. we reset the directories |
||
448 |
* when we are done with their file tree (we also clean up at |
||
449 |
* end in case we cut short a file tree traversal). However |
||
450 |
* there is no way to reset access times on symlinks. |
||
451 |
*/ |
||
452 |
✓✗✗✓ ✗✗✗✓ |
5088 |
switch (S_IFMT & arcn->sb.st_mode) { |
453 |
case S_IFDIR: |
||
454 |
42 |
arcn->type = PAX_DIR; |
|
455 |
✗✓ | 42 |
if (!tflag) |
456 |
break; |
||
457 |
add_atdir(ftent->fts_path, arcn->sb.st_dev, |
||
458 |
arcn->sb.st_ino, &arcn->sb.st_mtim, |
||
459 |
&arcn->sb.st_atim); |
||
460 |
break; |
||
461 |
case S_IFCHR: |
||
462 |
arcn->type = PAX_CHR; |
||
463 |
break; |
||
464 |
case S_IFBLK: |
||
465 |
arcn->type = PAX_BLK; |
||
466 |
break; |
||
467 |
case S_IFREG: |
||
468 |
/* |
||
469 |
* only regular files with have data to store on the |
||
470 |
* archive. all others will store a zero length skip. |
||
471 |
* the skip field is used by pax for actual data it has |
||
472 |
* to read (or skip over). |
||
473 |
*/ |
||
474 |
2502 |
arcn->type = PAX_REG; |
|
475 |
2502 |
arcn->skip = arcn->sb.st_size; |
|
476 |
2502 |
break; |
|
477 |
case S_IFLNK: |
||
478 |
arcn->type = PAX_SLK; |
||
479 |
/* |
||
480 |
* have to read the symlink path from the file |
||
481 |
*/ |
||
482 |
if ((cnt = readlink(ftent->fts_path, arcn->ln_name, |
||
483 |
PAXPATHLEN)) < 0) { |
||
484 |
syswarn(1, errno, "Unable to read symlink %s", |
||
485 |
ftent->fts_path); |
||
486 |
continue; |
||
487 |
} |
||
488 |
/* |
||
489 |
* set link name length, watch out readlink does not |
||
490 |
* NUL terminate the link path |
||
491 |
*/ |
||
492 |
arcn->ln_name[cnt] = '\0'; |
||
493 |
arcn->ln_nlen = cnt; |
||
494 |
break; |
||
495 |
case S_IFSOCK: |
||
496 |
/* |
||
497 |
* under BSD storing a socket is senseless but we will |
||
498 |
* let the format specific write function make the |
||
499 |
* decision of what to do with it. |
||
500 |
*/ |
||
501 |
arcn->type = PAX_SCK; |
||
502 |
break; |
||
503 |
case S_IFIFO: |
||
504 |
arcn->type = PAX_FIF; |
||
505 |
break; |
||
506 |
} |
||
507 |
break; |
||
508 |
} |
||
509 |
|||
510 |
/* |
||
511 |
* copy file name, set file name length |
||
512 |
*/ |
||
513 |
2544 |
arcn->nlen = strlcpy(arcn->name, ftent->fts_path, sizeof(arcn->name)); |
|
514 |
✗✓ | 2544 |
if ((size_t)arcn->nlen >= sizeof(arcn->name)) |
515 |
arcn->nlen = sizeof(arcn->name) - 1; /* XXX truncate? */ |
||
516 |
2544 |
arcn->org_name = ftent->fts_path; |
|
517 |
2544 |
return(0); |
|
518 |
2620 |
} |
|
519 |
|||
520 |
/* |
||
521 |
* getpathname() |
||
522 |
* Reads a pathname from stdin, handling NUL- or newline-termination. |
||
523 |
* Return: |
||
524 |
* NULL at end of file, otherwise the NUL-terminated buffer. |
||
525 |
*/ |
||
526 |
|||
527 |
static char * |
||
528 |
getpathname(char *buf, int buflen) |
||
529 |
{ |
||
530 |
char *bp, *ep; |
||
531 |
int ch, term; |
||
532 |
|||
533 |
✗✓ | 272 |
if (zeroflag) { |
534 |
/* |
||
535 |
* Read a NUL-terminated pathname, being especially |
||
536 |
* paranoid about proper termination and pathname length. |
||
537 |
*/ |
||
538 |
for (bp = buf, ep = buf + buflen; bp < ep; bp++) { |
||
539 |
if ((ch = getchar()) == EOF) { |
||
540 |
if (bp != buf) |
||
541 |
paxwarn(1, "Ignoring unterminated " |
||
542 |
"pathname at EOF"); |
||
543 |
return(NULL); |
||
544 |
} |
||
545 |
if ((*bp = ch) == '\0') |
||
546 |
return(buf); |
||
547 |
} |
||
548 |
/* Too long - skip this path */ |
||
549 |
*--bp = '\0'; |
||
550 |
term = '\0'; |
||
551 |
} else { |
||
552 |
✓✓ | 136 |
if (fgets(buf, buflen, stdin) == NULL) |
553 |
85 |
return(NULL); |
|
554 |
✗✓✗✗ ✗✗✗✗ |
51 |
if ((bp = strchr(buf, '\n')) != NULL || feof(stdin)) { |
555 |
✓✗ | 51 |
if (bp != NULL) |
556 |
51 |
*bp = '\0'; |
|
557 |
51 |
return(buf); |
|
558 |
} |
||
559 |
/* Too long - skip this path */ |
||
560 |
term = '\n'; |
||
561 |
} |
||
562 |
while ((ch = getchar()) != term && ch != EOF) |
||
563 |
continue; |
||
564 |
paxwarn(1, "Ignoring too-long pathname: %s", buf); |
||
565 |
return(NULL); |
||
566 |
136 |
} |
Generated by: GCOVR (Version 3.3) |