| 268 | } |
| 269 | |
| 270 | struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags) |
| 271 | { |
| 272 | struct dir_iterator_int *iter = xcalloc(1, sizeof(*iter)); |
| 273 | struct dir_iterator *dir_iterator = &iter->base; |
| 274 | int saved_errno, err; |
| 275 | |
| 276 | strbuf_init(&iter->base.path, PATH_MAX); |
| 277 | strbuf_addstr(&iter->base.path, path); |
| 278 | |
| 279 | ALLOC_GROW(iter->levels, 10, iter->levels_alloc); |
| 280 | iter->levels_nr = 0; |
| 281 | iter->flags = flags; |
| 282 | |
| 283 | /* |
| 284 | * Note: lstat already checks for NULL or empty strings and |
| 285 | * nonexistent paths. |
| 286 | */ |
| 287 | err = lstat(iter->base.path.buf, &iter->base.st); |
| 288 | |
| 289 | if (err < 0) { |
| 290 | saved_errno = errno; |
| 291 | goto error_out; |
| 292 | } |
| 293 | |
| 294 | if (!S_ISDIR(iter->base.st.st_mode)) { |
| 295 | saved_errno = ENOTDIR; |
| 296 | goto error_out; |
| 297 | } |
| 298 | |
| 299 | return dir_iterator; |
| 300 | |
| 301 | error_out: |
| 302 | dir_iterator_free(dir_iterator); |
| 303 | errno = saved_errno; |
| 304 | return NULL; |
| 305 | } |