2 * Copyright (C) 2008 Andre Noll <maan@systemlinux.org>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file create.c \brief The create mode of adu. */
9 #include <dirent.h> /* readdir() */
12 #include "gcc-compat.h"
19 /* Id of the device containing the base dir. */
20 static dev_t device_id
;
22 static int add_directory(char *dirname
, uint64_t *dir_num
, uint64_t *parent_dir_num
,
23 uint64_t *dir_size
, uint64_t *dir_files
)
25 struct osl_object dir_objects
[NUM_DT_COLUMNS
];
27 INFO_LOG("adding #%llu: %s\n", (long long unsigned)*dir_num
, dirname
);
28 dir_objects
[DT_NAME
].data
= dirname
;
29 dir_objects
[DT_NAME
].size
= strlen(dirname
) + 1;
30 dir_objects
[DT_NUM
].data
= dir_num
;
31 dir_objects
[DT_NUM
].size
= sizeof(*dir_num
);
32 dir_objects
[DT_PARENT_NUM
].data
= parent_dir_num
;
33 dir_objects
[DT_PARENT_NUM
].size
= sizeof(*parent_dir_num
);
34 dir_objects
[DT_BYTES
].data
= dir_size
;
35 dir_objects
[DT_BYTES
].size
= sizeof(*dir_size
);
36 dir_objects
[DT_FILES
].data
= dir_files
;
37 dir_objects
[DT_FILES
].size
= sizeof(*dir_files
);
38 return osl(osl_add_row(dir_table
, dir_objects
));
41 static int update_user_row(struct osl_table
*t
, uint64_t dir_num
,
45 struct osl_object obj
= {.data
= &dir_num
, .size
= sizeof(dir_num
)};
47 int ret
= osl(osl_get_row(t
, UT_DIR_NUM
, &obj
, &row
));
49 if (ret
== -E_OSL
&& osl_errno
!= E_OSL_RB_KEY_NOT_FOUND
)
51 if (ret
< 0) { /* this is the first file we add */
52 struct osl_object objects
[NUM_UT_COLUMNS
];
53 uint64_t num_files
= 1;
55 objects
[UT_DIR_NUM
].data
= &dir_num
;
56 objects
[UT_DIR_NUM
].size
= sizeof(dir_num
);
57 objects
[UT_BYTES
].data
= add
;
58 objects
[UT_BYTES
].size
= sizeof(*add
);
59 objects
[UT_FILES
].data
= &num_files
;
60 objects
[UT_FILES
].size
= sizeof(num_files
);
61 ret
= osl(osl_add_row(t
, objects
));
63 } else { /* add size and increment file count */
65 struct osl_object obj1
, obj2
= {.data
= &num
, .size
= sizeof(num
)};
67 ret
= osl(osl_get_object(t
, row
, UT_BYTES
, &obj1
));
70 num
= *(uint64_t *)obj1
.data
+ *add
;
71 ret
= osl(osl_update_object(t
, row
, UT_BYTES
, &obj2
));
74 ret
= osl(osl_get_object(t
, row
, UT_FILES
, &obj1
));
77 num
= *(uint64_t *)obj1
.data
+ 1;
78 return osl(osl_update_object(t
, row
, UT_FILES
, &obj2
));
82 static int scan_dir(char *dirname
, uint64_t *parent_dir_num
)
86 int ret
, cwd_fd
, ret2
;
87 uint64_t dir_size
= 0, dir_files
= 0;
89 static uint64_t current_dir_num
;
91 uint64_t this_dir_num
= ++current_dir_num
;
94 DEBUG_LOG("----------------- %llu: %s\n", (long long unsigned)current_dir_num
, dirname
);
95 ret
= adu_opendir(dirname
, &dir
, &cwd_fd
);
97 if (ret
!= -ERRNO_TO_ERROR(EACCES
))
99 WARNING_LOG("permission denied for %s\n", dirname
);
102 while ((entry
= readdir(dir
))) {
107 struct user_info
*ui
;
109 if (!strcmp(entry
->d_name
, "."))
111 if (!strcmp(entry
->d_name
, ".."))
113 if (lstat64(entry
->d_name
, &s
) == -1) {
114 WARNING_LOG("lstat64 error for %s/%s (%s)\n",
115 dirname
, entry
->d_name
, strerror(errno
));
119 if (!S_ISREG(m
) && !S_ISDIR(m
))
122 if (conf
.one_file_system_given
&& s
.st_dev
!= device_id
)
124 ret
= scan_dir(entry
->d_name
, &this_dir_num
);
134 ret
= create_user_table(conf
.database_dir_arg
, uid
, &ui
);
137 ret
= update_user_row(ui
->table
, this_dir_num
, &size
);
141 ret
= add_directory(dirname
, &this_dir_num
, parent_dir_num
,
142 &dir_size
, &dir_files
);
145 ret2
= adu_fchdir(cwd_fd
);
146 if (ret2
< 0 && ret
>= 0)
153 * The main function of the create mode.
159 uint64_t zero
= 0ULL;
163 if (lstat(conf
.base_dir_arg
, &statbuf
) == -1)
164 return -ERRNO_TO_ERROR(errno
);
165 if (!S_ISDIR(statbuf
.st_mode
))
166 return -ERRNO_TO_ERROR(ENOTDIR
);
167 device_id
= statbuf
.st_dev
;
168 create_hash_table(conf
.hash_table_bits_arg
);
169 ret
= open_dir_table(1);
173 ret
= scan_dir(conf
.base_dir_arg
, &zero
);
176 ret
= write_uid_file(conf
.database_dir_arg
);