| 187 | } |
| 188 | |
| 189 | int dir_iterator_advance(struct dir_iterator *dir_iterator) |
| 190 | { |
| 191 | struct dir_iterator_int *iter = |
| 192 | (struct dir_iterator_int *)dir_iterator; |
| 193 | |
| 194 | if (S_ISDIR(iter->base.st.st_mode) && push_level(iter)) { |
| 195 | if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) |
| 196 | return ITER_ERROR; |
| 197 | if (iter->levels_nr == 0) |
| 198 | return ITER_ERROR; |
| 199 | } |
| 200 | |
| 201 | /* Loop until we find an entry that we can give back to the caller. */ |
| 202 | while (1) { |
| 203 | struct dirent *de; |
| 204 | struct dir_iterator_level *level = |
| 205 | &iter->levels[iter->levels_nr - 1]; |
| 206 | const char *name; |
| 207 | |
| 208 | strbuf_setlen(&iter->base.path, level->prefix_len); |
| 209 | |
| 210 | if (level->dir) { |
| 211 | int ret = next_directory_entry(level->dir, iter->base.path.buf, &de); |
| 212 | if (ret < 0) { |
| 213 | if (iter->flags & DIR_ITERATOR_PEDANTIC) |
| 214 | return ITER_ERROR; |
| 215 | continue; |
| 216 | } else if (ret > 0) { |
| 217 | if (pop_level(iter) == 0) |
| 218 | return ITER_DONE; |
| 219 | continue; |
| 220 | } |
| 221 | |
| 222 | name = de->d_name; |
| 223 | } else { |
| 224 | if (level->entries_idx >= level->entries.nr) { |
| 225 | if (pop_level(iter) == 0) |
| 226 | return ITER_DONE; |
| 227 | continue; |
| 228 | } |
| 229 | |
| 230 | name = level->entries.items[level->entries_idx++].string; |
| 231 | } |
| 232 | |
| 233 | if (prepare_next_entry_data(iter, name)) { |
| 234 | if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) |
| 235 | return ITER_ERROR; |
| 236 | continue; |
| 237 | } |
| 238 | |
| 239 | return ITER_OK; |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | void dir_iterator_free(struct dir_iterator *dir_iterator) |
| 244 | { |