Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/lib/util/tftw.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2008-2018 by Andreas Schneider <asn@samba.org>
3
 *
4
 * Adopted from the csync source code
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
#include "replace.h"
21
#include "system/filesys.h"
22
#include "system/dir.h"
23
#include "lib/util/debug.h"
24
25
#include "tftw.h"
26
27
28
int tftw(TALLOC_CTX *mem_ctx, const char *fpath, tftw_walker_fn fn, size_t depth, void *userdata)
29
0
{
30
0
  char *filename = NULL;
31
0
  char *d_name = NULL;
32
0
  DIR *dh = NULL;
33
0
  struct dirent *dirent = NULL;
34
0
  struct stat sb = {0};
35
0
  int rc = 0;
36
37
0
  if (fpath[0] == '\0') {
38
0
    errno = ENOENT;
39
0
    goto error;
40
0
  }
41
42
0
  if ((dh = opendir(fpath)) == NULL) {
43
    /* permission denied */
44
0
    if (errno == EACCES) {
45
0
      return 0;
46
0
    } else {
47
0
      DBG_ERR("opendir failed for: [%s]\n", strerror(errno));
48
0
      goto error;
49
0
    }
50
0
  }
51
52
0
  while ((dirent = readdir(dh))) {
53
0
    int flag;
54
55
0
    d_name = dirent->d_name;
56
0
    if (d_name == NULL) {
57
0
      goto error;
58
0
    }
59
60
    /* skip "." and ".." */
61
0
    if (d_name[0] == '.' && (d_name[1] == '\0'
62
0
          || (d_name[1] == '.' && d_name[2] == '\0'))) {
63
0
      dirent = NULL;
64
0
      continue;
65
0
    }
66
67
0
    filename = talloc_asprintf(mem_ctx, "%s/%s", fpath, d_name);
68
0
    if (filename == NULL) {
69
0
      goto error;
70
0
    }
71
72
0
    rc = lstat(filename, &sb);
73
0
    if (rc < 0) {
74
0
      dirent = NULL;
75
0
      goto error;
76
0
    }
77
78
0
    switch (sb.st_mode & S_IFMT) {
79
0
      case S_IFLNK:
80
0
        flag = TFTW_FLAG_SLINK;
81
0
        break;
82
0
      case S_IFDIR:
83
0
        flag = TFTW_FLAG_DIR;
84
0
        break;
85
0
      case S_IFBLK:
86
0
      case S_IFCHR:
87
0
      case S_IFSOCK:
88
0
      case S_IFIFO:
89
0
        flag = TFTW_FLAG_SPEC;
90
0
        break;
91
0
      default:
92
0
        flag = TFTW_FLAG_FILE;
93
0
        break;
94
0
    }
95
96
0
    DBG_INFO("walk: [%s]\n", filename);
97
98
    /* Call walker function for each file */
99
0
    rc = fn(mem_ctx, filename, &sb, flag, userdata);
100
101
0
    if (rc < 0) {
102
0
      DBG_ERR("provided callback fn() failed: [%s]\n",
103
0
        strerror(errno));
104
0
      closedir(dh);
105
0
      goto done;
106
0
    }
107
108
0
    if (flag == TFTW_FLAG_DIR && depth) {
109
0
      rc = tftw(mem_ctx, filename, fn, depth - 1, userdata);
110
0
      if (rc < 0) {
111
0
        closedir(dh);
112
0
        goto done;
113
0
      }
114
0
    }
115
0
    TALLOC_FREE(filename);
116
0
    dirent = NULL;
117
0
  }
118
0
  closedir(dh);
119
120
0
done:
121
0
  TALLOC_FREE(filename);
122
0
  return rc;
123
0
error:
124
0
  if (dh != NULL) {
125
0
    closedir(dh);
126
0
  }
127
  TALLOC_FREE(filename);
128
0
  return -1;
129
0
}