Skip to content

Commit a5e8804

Browse files
committed
initial data structure and methods for dir_rc
1 parent f927f77 commit a5e8804

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

include/bf.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ OF SUCH DAMAGE.
6565
#ifndef BF_H
6666
#define BF_H
6767

68+
#include <dirent.h>
6869
#include <inttypes.h>
6970
#include <sys/stat.h>
7071

@@ -324,6 +325,19 @@ typedef enum {
324325
CLOSE_DB = 0x04,
325326
} CleanUpTasks;
326327

328+
/*
329+
* A reference-counted directory handle.
330+
*/
331+
struct dir_rc {
332+
DIR *dir;
333+
uint64_t rc;
334+
};
335+
336+
struct dir_rc *open_dir_rc(int optional_fd, char *path);
337+
int get_dir_fd(struct dir_rc *dir);
338+
void dir_inc(struct dir_rc *dir);
339+
void dir_dec(struct dir_rc *dir);
340+
327341
/*
328342
* Minimum data needs to be passed around between threads.
329343
*
@@ -346,6 +360,9 @@ struct work {
346360
long long int pinode;
347361
size_t recursion_level;
348362

363+
/* an optional reference to the parent dir -- to keep it alive */
364+
struct dir_rc *parent_dir;
365+
349366
/* probably shouldn't be here */
350367
char * fullpath;
351368
size_t fullpath_len;

src/bf.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ OF SUCH DAMAGE.
6262

6363

6464

65+
#include <fcntl.h>
6566
#include <pwd.h>
6667
#include <stdint.h>
6768
#include <stdio.h>
@@ -579,6 +580,62 @@ INSTALL_NUMBER(INT, int, "%d")
579580
INSTALL_NUMBER(SIZE, size_t, "%zu")
580581
INSTALL_NUMBER(UINT64, uint64_t, "%" PRIu64)
581582

583+
/*
584+
* Create a new reference-counted DIR object. If optional_fd is a valid FD, then
585+
* openat() the new DIR relative to that FD. Otherwise, just opendir() the path.
586+
*
587+
* Increments the refcount on the new object.
588+
*/
589+
struct dir_rc *open_dir_rc(int optional_fd, char *path) {
590+
DIR *dir;
591+
592+
if (optional_fd < 0) {
593+
dir = opendir(path);
594+
} else {
595+
// XXX: assuming path is relative to optional_fd here... is this the right way to go????
596+
// or do I need to do something like basename(path) first?
597+
int fd = openat(optional_fd, path, O_RDONLY|O_DIRECTORY);
598+
if (fd < 0) {
599+
return NULL;
600+
}
601+
dir = fdopendir(fd);
602+
}
603+
604+
if (!dir) {
605+
return NULL;
606+
}
607+
608+
struct dir_rc *new = calloc(1, sizeof(*new));
609+
new->dir = dir;
610+
dir_inc(new);
611+
return new;
612+
}
613+
614+
/*
615+
* Get a DIR * out of a dir_rc.
616+
*/
617+
int get_dir_fd(struct dir_rc *dir) {
618+
return gufi_dirfd(dir->dir);
619+
}
620+
621+
/*
622+
* Increment the reference count for a dir_rc.
623+
*/
624+
void dir_inc(struct dir_rc *dir) {
625+
// XXX: is relaxed OK here?
626+
__atomic_fetch_add(&dir->rc, 1, __ATOMIC_ACQ_REL);
627+
}
628+
629+
/*
630+
* Decrement the reference count for a dir_rc, and free it if that was the last reference.
631+
*/
632+
void dir_dec(struct dir_rc *dir) {
633+
if (__atomic_sub_fetch(&dir->rc, 1, __ATOMIC_ACQ_REL) == 0) {
634+
closedir(dir->dir);
635+
free(dir);
636+
}
637+
}
638+
582639
/*
583640
* Returns size of a dynamically sized struct work_packed.
584641
*

0 commit comments

Comments
 (0)