Bug Summary

File:bld/../path_utils/path_utils.c
Location:line 616, column 5
Description:Value stored to 'result' is never read

Annotated Source Code

1/*
2 Authors:
3 John Dennis <jdennis.redhat.com>
4
5 Copyright (C) 2009 Red Hat
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21/*****************************************************************************/
22/******************************** Documentation ******************************/
23/*****************************************************************************/
24
25/*****************************************************************************/
26/******************************* Include Files *******************************/
27/*****************************************************************************/
28
29#include <stdio.h>
30#include <string.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <dirent.h>
34#include <sys/errno(*__errno_location ()).h>
35#include <sys/stat.h>
36
37#include <libgen.h>
38
39#include "path_utils.h"
40
41/*****************************************************************************/
42/****************************** Internal Defines *****************************/
43/*****************************************************************************/
44
45/*****************************************************************************/
46/************************** Internal Type Definitions ************************/
47/*****************************************************************************/
48
49/*****************************************************************************/
50/********************** External Function Declarations *********************/
51/*****************************************************************************/
52
53/*****************************************************************************/
54/********************** Internal Function Declarations *********************/
55/*****************************************************************************/
56
57/*****************************************************************************/
58/************************* External Global Variables ***********************/
59/*****************************************************************************/
60
61/*****************************************************************************/
62/************************* Internal Global Variables ***********************/
63/*****************************************************************************/
64
65/*****************************************************************************/
66/**************************** Inline Functions *****************************/
67/*****************************************************************************/
68
69/*****************************************************************************/
70/*************************** Internal Functions ****************************/
71/*****************************************************************************/
72
73/*****************************************************************************/
74/**************************** Exported Functions ***************************/
75/*****************************************************************************/
76
77const char *path_utils_error_string(int error)
78{
79 switch(error) {
80 case SUCCESS0: return _("Success")gettext("Success");
81 case PATH_UTILS_ERROR_NOT_FULLY_NORMALIZED(-3000 + 1): return _("Path could not be fully normalized")gettext("Path could not be fully normalized");
82 }
83 return NULL((void*)0);
84}
85
86static int dot_to_absolute(char *rel_path, int rel_path_size)
87{
88 char tmp_path[PATH_MAX4096];
89
90 if (strcmp(rel_path, ".") == 0) {
91 if (getcwd(rel_path, rel_path_size) == NULL((void*)0)) {
92 if (errno(*__errno_location ()) == ERANGE34)
93 return ENOBUFS105;
94 else
95 return errno(*__errno_location ());
96 }
97 } else if (strcmp(rel_path, "..") == 0) {
98 if (getcwd(tmp_path, sizeof(tmp_path)) == NULL((void*)0)) {
99 if (errno(*__errno_location ()) == ERANGE34)
100 return ENOBUFS105;
101 else
102 return errno(*__errno_location ());
103 }
104 strncpy(rel_path, dirname(tmp_path), rel_path_size);
105 if (rel_path[rel_path_size-1] != 0) return ENOBUFS105;
106 }
107
108 return SUCCESS0;
109}
110
111int get_basename(char *base_name, size_t base_name_size, const char *path)
112{
113 char tmp_path[PATH_MAX4096];
114 int ret;
115
116 if (!path) return EINVAL22;
117 if (!base_name || base_name_size < 1) return ENOBUFS105;
118
119 strncpy(tmp_path, path, sizeof(tmp_path));
120 if (tmp_path[sizeof(tmp_path)-1] != 0) return ENOBUFS105;
121 strncpy(base_name, basename__xpg_basename(tmp_path), base_name_size);
122 if (base_name[base_name_size-1] != 0) return ENOBUFS105;
123
124 ret = dot_to_absolute(base_name, base_name_size);
125 if (ret != SUCCESS0) {
126 return ret;
127 }
128
129 return SUCCESS0;
130}
131
132int get_dirname(char *dir_path, size_t dir_path_size, const char *path)
133{
134 char tmp_path[PATH_MAX4096];
135 int ret;
136
137 if (!path) return EINVAL22;
138 if (!dir_path || dir_path_size < 1) return ENOBUFS105;
139
140 strncpy(tmp_path, path, sizeof(tmp_path));
141 if (tmp_path[sizeof(tmp_path)-1] != 0) return ENOBUFS105;
142 strncpy(dir_path, dirname(tmp_path), dir_path_size);
143 if (dir_path[dir_path_size-1] != 0) return ENOBUFS105;
144
145 ret = dot_to_absolute(dir_path, dir_path_size);
146 if (ret != SUCCESS0) {
147 return ret;
148 }
149
150 return SUCCESS0;
151}
152
153int get_directory_and_base_name(char *dir_path, size_t dir_path_size,
154 char *base_name, size_t base_name_size,
155 const char *path)
156{
157 char tmp_path[PATH_MAX4096];
158 int ret;
159
160 if (!path) return EINVAL22;
161 if (!dir_path || dir_path_size < 1) return ENOBUFS105;
162 if (!base_name || base_name_size < 1) return ENOBUFS105;
163
164 strncpy(tmp_path, path, sizeof(tmp_path));
165 if (tmp_path[sizeof(tmp_path)-1] != 0) return ENOBUFS105;
166 strncpy(base_name, basename__xpg_basename(tmp_path), base_name_size);
167 if (base_name[base_name_size-1] != 0) return ENOBUFS105;
168
169 strncpy(tmp_path, path, sizeof(tmp_path));
170 if (tmp_path[sizeof(tmp_path)-1] != 0) return ENOBUFS105;
171 strncpy(dir_path, dirname(tmp_path), dir_path_size);
172 if (dir_path[dir_path_size-1] != 0) return ENOBUFS105;
173
174 ret = dot_to_absolute(dir_path, dir_path_size);
175 if (ret != SUCCESS0) {
176 return ret;
177 }
178
179 if (strcmp(base_name, ".") == 0) {
180 strncpy(base_name, "", base_name_size);
181 if (base_name[base_name_size-1] != 0) return ENOBUFS105;
182 }
183
184 return SUCCESS0;
185}
186
187bool_Bool is_absolute_path(const char *path)
188{
189 if (!path) return false0;
190 return path[0] == '/';
191}
192
193int path_concat(char *path, size_t path_size, const char *head, const char *tail)
194{
195 int ret;
196 const char *p, *src;
197 char *dst, *dst_end;
198
199 if (!path || path_size < 1) return ENOBUFS105;
200
201 dst = path;
202 dst_end = path + path_size - 1; /* -1 allows for NULL terminator */
203
204 if (head && *head) {
205 /* walk to end of head */
206 for (p = head; *p; p++);
207
208 /* skip any trailing slashes in head */
209 for (p--; p > head && *p == '/'; p--);
210
211 /* If the length of head exceeds the buffer size, fail */
212 if ((p - head) > path_size-1) {
213 ret = ENOBUFS105;
214 goto fail;
215 }
216
217 /* Copy head into path */
218 for (src = head; src <= p && dst < dst_end;) {
219 *dst++ = *src++;
220 }
221 }
222 if (tail && *tail) {
223 /* skip any leading slashes in tail */
224 for (p = tail; *p && *p == '/'; p++);
225
226 if (dst > path)
227 /* insert single slash between head & tail
228 * Making sure not to add an extra if the
229 * preceding character is also a slash
230 * (such as the case where head was the
231 * special-case "/".
232 */
233 if (dst < dst_end && *(dst-1) != '/') {
234 *dst++ = '/';
235 }
236
237 /* Copy the tail into the path */
238 for (src = p; *src && dst < dst_end;) {
239 *dst++ = *src++;
240 }
241
242 /* If we got past dst_end and there is more data
243 * in the src buffer, we should return ENOBUFS
244 */
245 if (*src) {
246 ret = ENOBUFS105; /* failed to copy everything */
247 goto fail;
248 }
249 }
250 *dst = 0;
251
252 return SUCCESS0;
253
254fail:
255 /* On failure, set the buffer to the empty string for safety */
256 *path = '\0';
257 return ret;
258}
259
260int make_path_absolute(char *absolute_path, size_t absolute_path_size, const char *path)
261{
262 int result = SUCCESS0;
263 const char *src;
264 char *dst, *dst_end;
265
266 if (!absolute_path || absolute_path_size < 1) return ENOBUFS105;
267
268 dst = absolute_path;
269 dst_end = absolute_path + absolute_path_size - 1; /* -1 allows for NULL terminator */
270
271 if (is_absolute_path(path)) {
272 for (src = path; *src && dst < dst_end;) *dst++ = *src++;
273 *dst = 0;
274 if (dst > dst_end || *src) result = ENOBUFS105;
275 return result;
276 }
277
278 if ((getcwd(absolute_path, absolute_path_size) == NULL((void*)0))) {
279 if (errno(*__errno_location ()) == ERANGE34)
280 return ENOBUFS105;
281 else
282 return errno(*__errno_location ());
283 }
284
285 for (dst = absolute_path; *dst && dst < dst_end; dst++);
286 if (!(path && *path)) return result;
287 if (dst > dst_end) {
288 *absolute_path = 0;
289 return ENOBUFS105;
290 }
291
292 *dst++ = '/';
293 if (dst > dst_end) {
294 *absolute_path = 0;
295 return ENOBUFS105;
296 }
297
298 for (src = path; *src && dst < dst_end;) *dst++ = *src++;
299 if (*src) return ENOBUFS105; /* failed to copy everything */
300 *dst = 0;
301
302 return result;
303}
304
305char **split_path(const char *path, int *count)
306{
307 int n_components, component_len, total_component_len, alloc_len;
308 const char *start, *end;
309 char *mem_block, **array_ptr, *component_ptr;
310
311 if (count) *count = 0;
312 if (!path) return NULL((void*)0);
313
314 /* If path is absolute add in special "/" root component */
315 if (*path == '/') {
316 n_components = 1;
317 total_component_len = 2;
318 } else {
319 n_components = 0;
320 total_component_len = 0;
321 }
322
323 /* Scan for components, keep several counts */
324 for (start = end = path; *start; start = end) {
325 for (start = end; *start && *start == '/'; start++);
326 for (end = start; *end && *end != '/'; end++);
327 if ((component_len = end - start) == 0) break;
328 n_components++;
329 total_component_len += component_len + 1;
330 }
331
332 /*
333 * Allocate a block big enough for component array (with trailing NULL
334 * entry, hence n_components+1) and enough room for a copy of each NULL
335 * terminated component. We'll copy the components into the same allocation
336 * block after the end of the pointer array.
337 */
338 alloc_len = ((n_components+1) * sizeof(char *)) + total_component_len;
339
340 if ((mem_block = malloc(alloc_len)) == NULL((void*)0)) {
341 if (count) *count = -1;
342 return NULL((void*)0);
343 }
344
345 /* component array */
346 array_ptr = (char **)mem_block;
347 /* components copied after end of array */
348 component_ptr = mem_block + ((n_components+1)*sizeof(char *));
349
350 /* If path is absolute add in special "/" root component */
351 if (*path == '/') {
352 *array_ptr++ = component_ptr;
353 *component_ptr++ = '/';
354 *component_ptr++ = 0;
355 }
356
357 for (start = end = path; *start; start = end) {
358 for (start = end; *start && *start == '/'; start++);
359 for (end = start; *end && *end != '/'; end++);
360 if ((component_len = end - start) == 0) break;
361
362 *array_ptr++ = component_ptr;
363 while (start < end) *component_ptr++ = *start++;
364 *component_ptr++ = 0;
365 }
366 *array_ptr++ = NULL((void*)0);
367 if (count) *count = n_components;
368 return (char **)mem_block;
369}
370
371int normalize_path(char *normalized_path, size_t normalized_path_size, const char *path)
372{
373 int result = SUCCESS0;
374 int component_len;
375 bool_Bool is_absolute, can_backup;
376 const char *start, *end;
377 char *dst, *dst_end, *p, *limit;
378
379 if (!normalized_path || normalized_path_size < 1) return ENOBUFS105;
380
381 dst = normalized_path;
382 dst_end = normalized_path + normalized_path_size - 1; /* -1 allows for NULL terminator */
383 can_backup = true1;
384
385 if (!path || !*path) {
386 if (dst > dst_end) {
387 *dst = 0;
388 return ENOBUFS105;
389 }
390 *dst++ = '.';
391 *dst = 0;
392 return result;
393 }
394
395 if ((is_absolute = *path == '/')) {
396 if (dst < dst_end) {
397 *dst++ = '/';
398 } else {
399 *dst = 0;
400 return ENOBUFS105;
401 }
402 }
403
404 for (start = end = path; *start; start = end) {
405 for (start = end; *start && *start == '/'; start++);
406 for (end = start; *end && *end != '/'; end++);
407 if ((component_len = end - start) == 0) break;
408 if (component_len == 1 && start[0] == '.') continue;
409 if (component_len == 2 && start[0] == '.' && start[1] == '.' && can_backup) {
410 /* back up one level */
411 if ((is_absolute && dst == normalized_path+1) || (!is_absolute && dst == normalized_path)) {
412 if (is_absolute) continue;
413 can_backup = false0;
414 result = PATH_UTILS_ERROR_NOT_FULLY_NORMALIZED(-3000 + 1);
415 } else {
416 if (is_absolute)
417 limit = normalized_path+1;
418 else
419 limit = normalized_path;
420 for (p = dst-1; p >= limit && *p != '/'; p--);
421 if (p < limit)
422 dst = limit;
423 else
424 dst = p;
425 continue;
426 }
427 }
428
429 if ((end-start) > (dst_end-dst)) {
430 return ENOBUFS105;
431 }
432
433 if ((dst > normalized_path) && (dst < dst_end) && (dst[-1] != '/')) *dst++ = '/';
434 while ((start < end) && (dst < dst_end)) *dst++ = *start++;
435 }
436
437 if (dst == normalized_path) {
438 if (is_absolute)
439 *dst++ = '/';
440 else
441 *dst++ = '.';
442 }
443 *dst = 0;
444 return result;
445}
446
447int common_path_prefix(char *common_path,
448 size_t common_path_size,
449 int *common_count,
450 const char *path1, const char *path2)
451{
452 int count1, count2, min_count, i, n_common, result;
453 char **split1, **split2;
454 char *dst, *dst_end, *src;
455
456 if (!common_path || common_path_size < 1) return ENOBUFS105;
457
458 result = SUCCESS0;
459 n_common = 0;
460 split1 = split_path(path1, &count1);
461 split2 = split_path(path2, &count2);
462
463 if (count1 <= count2)
464 min_count = count1;
465 else
466 min_count = count2;
467
468 if (min_count <= 0 || !split1 || !split2 ) {
469 result = SUCCESS0;
470 *common_path = 0;
471 goto done;
472 }
473
474 for (n_common = 0; n_common < min_count; n_common++) {
475 if (strcmp(split1[n_common], split2[n_common]) != 0) break;
476 }
477
478 if (n_common == 0) {
479 result = SUCCESS0;
480 *common_path = 0;
481 goto done;
482 }
483
484 dst = common_path;
485 dst_end = common_path + common_path_size - 1; /* -1 allows for NULL terminator */
486 for (i = 0; i < n_common; i++) {
487 for (src = split1[i]; *src && dst < dst_end;) *dst++ = *src++;
488 if (dst == dst_end && *src) {
489 *dst = 0;
490 result = ENOBUFS105;
491 goto done;
492 }
493 if (dst[-1] != '/' && i < n_common-1) { /* insert path separator */
494 if (dst == dst_end) {
495 *dst = 0;
496 result = ENOBUFS105;
497 goto done;
498 }
499 *dst++ = '/';
500 }
501 }
502 *dst = 0;
503
504 done:
505 free(split1);
506 free(split2);
507 if (common_count) *common_count = n_common;
508 return result;
509}
510
511int make_normalized_absolute_path(char *result_path, size_t result_path_size, const char *path)
512{
513 int error;
514 char absolute_path[PATH_MAX4096];
515
516 if (!result_path || result_path_size < 1) return ENOBUFS105;
517 *result_path = 0;
518 if ((error = make_path_absolute(absolute_path, sizeof(absolute_path), path)) != SUCCESS0) return error;
519 if ((error = normalize_path(result_path, result_path_size, absolute_path)) != SUCCESS0) return error;
520 return SUCCESS0;
521}
522
523int find_existing_directory_ancestor(char *ancestor, size_t ancestor_size, const char *path)
524{
525 int error;
526 char dir_path[PATH_MAX4096];
527 struct stat info;
528
529 if (!ancestor || ancestor_size < 1) return ENOBUFS105;
530 *ancestor = 0;
531 strncpy(dir_path, path, sizeof(dir_path));
532 if (dir_path[sizeof(dir_path)-1] != 0) return ENOBUFS105;
533
534 while (strcmp(dir_path, "/") != 0) {
535 if (lstat(dir_path, &info) < 0) {
536 error = errno(*__errno_location ());
537 if (error != ENOENT2) return error;
538 } else {
539 if (S_ISDIR(info.st_mode)((((info.st_mode)) & 0170000) == (0040000))) break;
540 }
541 error = get_dirname(dir_path, sizeof(dir_path), dir_path);
542 if (error != SUCCESS0) {
543 return error;
544 }
545 }
546
547 strncpy(ancestor, dir_path, ancestor_size);
548 if (ancestor[ancestor_size-1] != 0) return ENOBUFS105;
549 return SUCCESS0;
550}
551
552int directory_list(const char *path, bool_Bool recursive,
553 directory_list_callback_t callback, void *user_data)
554{
555 DIR *dir;
556 struct dirent *entry;
557 struct stat info;
558 int error = 0;
559 char entry_path[PATH_MAX4096];
560 bool_Bool prune = false0;
561
562 if (!(dir = opendir(path))) {
563 error = errno(*__errno_location ());
564 return error;
565 }
566
567 for (entry = readdir(dir); entry; entry = readdir(dir)) {
568 prune = false0;
569 if (strcmp(entry->d_name, ".") == 0 ||
570 strcmp(entry->d_name, "..") == 0) {
571 continue;
572 }
573
574 error = path_concat(entry_path, sizeof(entry_path),
575 path, entry->d_name);
576 if (error != SUCCESS0) {
577 closedir(dir);
578 /* Don't bother checking the return here.
579 * The path_concat error is more important
580 */
581 return error;
582 }
583
584 if (lstat(entry_path, &info) < 0) {
585 continue;
586 }
587
588 prune = !callback(path, entry->d_name, entry_path, &info, user_data);
589 if (S_ISDIR(info.st_mode)((((info.st_mode)) & 0170000) == (0040000))) {
590 if (recursive && !prune) {
591 error = directory_list(entry_path, recursive,
592 callback, user_data);
593 if (error != SUCCESS0) {
594 closedir(dir);
595 /* Don't bother checking the return here.
596 * The directory_list error is more important
597 */
598 return error;
599 }
600 }
601 }
602 }
603 error = closedir(dir);
604 if (error) {
605 return error;
606 }
607 return SUCCESS0;
608}
609
610bool_Bool is_ancestor_path(const char *ancestor, const char *path)
611{
612 char **path_components, **ancestor_components;
613 int i, path_count, ancestor_count;
614 bool_Bool result;
615
616 result = false0;
Value stored to 'result' is never read
617 path_components = split_path(path, &path_count);
618 ancestor_components = split_path(ancestor, &ancestor_count);
619
620 if (!path_components || !ancestor_components) {
621 result = false0;
622 goto exit;
623 }
624
625 if (ancestor_count >= path_count) {
626 result = false0;
627 goto exit;
628 }
629
630 for (i = 0; i < ancestor_count; i++) {
631 if (strcmp(path_components[i], ancestor_components[i]) != 0) {
632 result = false0;
633 goto exit;
634 }
635 }
636
637 result = true1;
638
639 exit:
640 free(path_components);
641 free(ancestor_components);
642 return result;
643}
644