Line data Source code
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 0 : int tftw(TALLOC_CTX *mem_ctx, const char *fpath, tftw_walker_fn fn, size_t depth, void *userdata) 29 : { 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 : } 41 : 42 0 : if ((dh = opendir(fpath)) == NULL) { 43 : /* permission denied */ 44 0 : if (errno == EACCES) { 45 0 : return 0; 46 : } else { 47 0 : DBG_ERR("opendir failed for: [%s]\n", strerror(errno)); 48 0 : goto error; 49 : } 50 : } 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 : } 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 : } 66 : 67 0 : filename = talloc_asprintf(mem_ctx, "%s/%s", fpath, d_name); 68 0 : if (filename == NULL) { 69 0 : goto error; 70 : } 71 : 72 0 : rc = lstat(filename, &sb); 73 0 : if (rc < 0) { 74 0 : dirent = NULL; 75 0 : goto error; 76 : } 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 : case S_IFCHR: 87 : case S_IFSOCK: 88 : 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 : } 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 : strerror(errno)); 104 0 : closedir(dh); 105 0 : goto done; 106 : } 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 : } 114 : } 115 0 : TALLOC_FREE(filename); 116 0 : dirent = NULL; 117 : } 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 : } 127 0 : TALLOC_FREE(filename); 128 0 : return -1; 129 : }