aboutsummaryrefslogtreecommitdiffstats
path: root/src/bindfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bindfs.c')
-rw-r--r--src/bindfs.c75
1 files changed, 65 insertions, 10 deletions
diff --git a/src/bindfs.c b/src/bindfs.c
index e94402d..1ca24ed 100644
--- a/src/bindfs.c
+++ b/src/bindfs.c
@@ -68,10 +68,11 @@
#include <fuse_opt.h>
#include "debug.h"
+#include "misc.h"
#include "permchain.h"
+#include "rate_limiter.h"
#include "userinfo.h"
#include "usermap.h"
-#include "misc.h"
/* SETTINGS */
static struct Settings {
@@ -91,6 +92,9 @@ static struct Settings {
UserMap* usermap; /* From the --map option. */
UserMap* usermap_reverse;
+ RateLimiter* read_limiter;
+ RateLimiter* write_limiter;
+
enum CreatePolicy {
CREATE_AS_USER,
CREATE_AS_MOUNTER
@@ -766,6 +770,10 @@ static int bindfs_read(const char *path, char *buf, size_t size, off_t offset,
int res;
(void) path;
+ if (settings.read_limiter) {
+ rate_limiter_wait(settings.read_limiter, size);
+ }
+
res = pread(fi->fh, buf, size, offset);
if (res == -1)
res = -errno;
@@ -779,6 +787,10 @@ static int bindfs_write(const char *path, const char *buf, size_t size,
int res;
(void) path;
+ if (settings.write_limiter) {
+ rate_limiter_wait(settings.write_limiter, size);
+ }
+
res = pwrite(fi->fh, buf, size, offset);
if (res == -1)
res = -errno;
@@ -956,24 +968,24 @@ static void print_usage(const char *progname)
" -V --version Print version number and exit.\n"
"\n"
"File ownership:\n"
- " -u --force-user Set file owner.\n"
- " -g --force-group Set file group.\n"
- " -m --mirror Comma-separated list of users who will see\n"
+ " -u --force-user=... Set file owner.\n"
+ " -g --force-group=... Set file group.\n"
+ " -m --mirror=... Comma-separated list of users who will see\n"
" themselves as the owners of all files.\n"
- " -M --mirror-only Like --mirror but disallow access for\n"
+ " -M --mirror-only=... Like --mirror but disallow access for\n"
" all other users.\n"
" --map=user1/user2:... Let user2 see files of user1 as his own.\n"
"\n"
"Permission bits:\n"
- " -p --perms Specify permissions, similar to chmod\n"
+ " -p --perms=... Specify permissions, similar to chmod\n"
" e.g. og-x,og+rD,u=rwX,g+rw or 0644,a+X\n"
"\n"
"File creation policy:\n"
" --create-as-user New files owned by creator (default for root). *\n"
" --create-as-mounter New files owned by fs mounter (default for users).\n"
- " --create-for-user New files owned by specified user. *\n"
- " --create-for-group New files owned by specified group. *\n"
- " --create-with-perms Alter permissions of new files.\n"
+ " --create-for-user=... New files owned by specified user. *\n"
+ " --create-for-group=... New files owned by specified group. *\n"
+ " --create-with-perms=... Alter permissions of new files.\n"
"\n"
"Chown policy:\n"
" --chown-normal Try to chown the original files (the default).\n"
@@ -989,7 +1001,7 @@ static void print_usage(const char *progname)
" --chmod-normal Try to chmod the original files (the default).\n"
" --chmod-ignore Have all chmods fail silently.\n"
" --chmod-deny Have all chmods fail with 'permission denied'.\n"
- " --chmod-filter Change permissions of chmod requests.\n"
+ " --chmod-filter=... Change permissions of chmod requests.\n"
" --chmod-allow-x Allow changing file execute bits in any case.\n"
"\n"
"Extended attribute policy:\n"
@@ -997,6 +1009,10 @@ static void print_usage(const char *progname)
" --xattr-ro Read-only xattr operations.\n"
" --xattr-rw Read-write xattr operations (the default).\n"
"\n"
+ "Rate limits:\n"
+ " --read-rate=... Limit to bytes/sec that can be read.\n"
+ " --write-rate=... Limit to bytes/sec that can be written.\n"
+ "\n"
"Miscellaneous:\n"
" -n --no-allow-other Do not add -o allow_other to fuse options.\n"
" --realistic-permissions Hide permission bits for actions mounter can't do.\n"
@@ -1331,6 +1347,16 @@ static void atexit_func()
{
free(settings.original_working_dir);
settings.original_working_dir = NULL;
+ if (settings.read_limiter) {
+ rate_limiter_destroy(settings.read_limiter);
+ free(settings.read_limiter);
+ settings.read_limiter = NULL;
+ }
+ if (settings.write_limiter) {
+ rate_limiter_destroy(settings.write_limiter);
+ free(settings.write_limiter);
+ settings.write_limiter = NULL;
+ }
usermap_destroy(settings.usermap);
settings.usermap = NULL;
usermap_destroy(settings.usermap_reverse);
@@ -1361,6 +1387,8 @@ int main(int argc, char *argv[])
char *mirror;
char *mirror_only;
char *map;
+ char *read_rate;
+ char *write_rate;
char *create_for_user;
char *create_for_group;
char *create_with_perms;
@@ -1395,6 +1423,9 @@ int main(int argc, char *argv[])
OPT_OFFSET2("--map=%s", "map=%s", map, -1),
OPT_OFFSET3("-n", "--no-allow-other", "no-allow-other", no_allow_other, -1),
+ OPT_OFFSET2("--read-rate=%s", "read-rate=%s", read_rate, -1),
+ OPT_OFFSET2("--write-rate=%s", "write-rate=%s", write_rate, -1),
+
OPT2("--create-as-user", "create-as-user", OPTKEY_CREATE_AS_USER),
OPT2("--create-as-mounter", "create-as-mounter", OPTKEY_CREATE_AS_MOUNTER),
OPT_OFFSET2("--create-for-user=%s", "create-for-user=%s", create_for_user, -1),
@@ -1435,6 +1466,8 @@ int main(int argc, char *argv[])
settings.permchain = permchain_create();
settings.usermap = usermap_create();
settings.usermap_reverse = usermap_create();
+ settings.read_limiter = NULL;
+ settings.write_limiter = NULL;
settings.new_uid = -1;
settings.new_gid = -1;
settings.create_for_uid = -1;
@@ -1500,6 +1533,28 @@ int main(int argc, char *argv[])
}
}
+ /* Parse rate limits */
+ if (od.read_rate) {
+ double rate;
+ if (parse_byte_count(od.read_rate, &rate) && rate > 0) {
+ settings.read_limiter = malloc(sizeof(RateLimiter));
+ rate_limiter_init(settings.read_limiter, rate, &gettimeofday_clock);
+ } else {
+ fprintf(stderr, "Error: Invalid --read-rate.\n");
+ return 1;
+ }
+ }
+ if (od.write_rate) {
+ double rate;
+ if (parse_byte_count(od.write_rate, &rate) && rate > 0) {
+ settings.write_limiter = malloc(sizeof(RateLimiter));
+ rate_limiter_init(settings.write_limiter, rate, &gettimeofday_clock);
+ } else {
+ fprintf(stderr, "Error: Invalid --write-rate.\n");
+ return 1;
+ }
+ }
+
/* Parse usermap */
if (od.map) {
if (getuid() != 0) {