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