/* userspace library to interface with dazukofs Copyright (C) 2008-2009 John Ogness Author: John Ogness This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include "dazukofs.h" struct dazukofs_handle { int dev_fd; unsigned long event_id; char *group_name; }; #define DAZUKOFS_ALLOWED_GROUPCHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" static int check_group_name(const char *gname) { size_t len = strlen(gname); const char *p; if (len > 20) return -1; for (p = gname; *p; p++) { if (strchr(DAZUKOFS_ALLOWED_GROUPCHARS, *p) == NULL) return -1; } return 0; } dazukofs_handle_t dazukofs_open(const char *gname, int flags) { struct dazukofs_handle *hndl = NULL; char key[25]; char buf[256]; char *p; int gid; int fd; if (check_group_name(gname) != 0) goto error_out; fd = open("/dev/dazukofs.ctrl", O_RDWR); if (fd == -1) { /* try to read at least * (maybe the group already exists) */ fd = open("/dev/dazukofs.ctrl", O_RDONLY); if (fd == -1) goto error_out; } else { memset(buf, 0, sizeof(buf)); if (flags & DAZUKOFS_TRACK_GROUP) snprintf(buf, sizeof(buf) - 1, "addtrack=%s", gname); else snprintf(buf, sizeof(buf) - 1, "add=%s", gname); if (write(fd, buf, strlen(buf)) == -1) goto error_out_close; lseek(fd, 0, SEEK_SET); } memset(buf, 0, sizeof(buf)); if (read(fd, buf, sizeof(buf)-1) == -1) goto error_out_close; memset(key, 0, sizeof(key)); snprintf(key, sizeof(key) - 1, ":%s\n", gname); p = strstr(buf, key); if (!p || p == buf) goto error_out_close; p--; gid = *p - '0'; if (gid < 0 || gid > 9) goto error_out_close; hndl = malloc(sizeof(struct dazukofs_handle)); if (!hndl) goto error_out_close; memset(hndl, 0, sizeof(struct dazukofs_handle)); hndl->group_name = strdup(gname); if (!hndl->group_name) goto error_out_free; memset(key, 0, sizeof(key)); snprintf(key, sizeof(key) - 1, "/dev/dazukofs.%d", gid); hndl->dev_fd = open(key, O_RDWR); if (hndl->dev_fd == -1) goto error_out_free; close(fd); return hndl; error_out_free: if (hndl->group_name) free(hndl->group_name); free(hndl); hndl = NULL; error_out_close: close(fd); error_out: return hndl; } int dazukofs_close(dazukofs_handle_t hndl, int flags) { char buf[48]; int fd; int ret = -1; if (flags & DAZUKOFS_REMOVE_GROUP) { fd = open("/dev/dazukofs.ctrl", O_WRONLY); if (fd == -1) goto error_out; memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf) - 1, "del=%s", hndl->group_name); if (write(fd, buf, strlen(buf)) == -1) { close(fd); goto error_out; } close(fd); } ret = close(hndl->dev_fd); if (ret != 0) goto error_out; free(hndl->group_name); free(hndl); return 0; error_out: return ret; } int dazukofs_get_access(dazukofs_handle_t hndl, struct dazukofs_access *acc) { char buf[48]; char *p; int err = -1; memset(buf, 0, sizeof(buf)); if (read(hndl->dev_fd, buf, sizeof(buf)-1) == -1) goto out; p = strstr(buf, "id="); if (!p) goto out; p += 3; hndl->event_id = strtoul(p, &p, 10); p = strstr(p, "fd="); if (!p) goto out; p += 3; acc->fd = (int)strtol(p, &p, 10); p = strstr(p, "pid="); if (!p) goto out; p += 4; acc->pid = strtoul(p, NULL, 10); acc->deny = 0; err = 0; out: return err; } int dazukofs_return_access(dazukofs_handle_t hndl, struct dazukofs_access *acc) { char buf[48]; int err = -1; if (close(acc->fd) != 0) goto out; snprintf(buf, sizeof(buf)-1, "id=%lu r=%d", hndl->event_id, acc->deny ? 1 : 0); buf[sizeof(buf)-1] = 0; if (write(hndl->dev_fd, buf, strlen(buf)) == -1) goto out; lseek(hndl->dev_fd, 0, SEEK_SET); err = 0; out: return err; } int dazukofs_get_filename(struct dazukofs_access *acc, char *buf, size_t bufsiz) { char proc[48]; int ret; memset(proc, 0, sizeof(proc)); snprintf(proc, sizeof(proc) - 1, "/proc/self/fd/%d", acc->fd); ret = readlink(proc, buf, bufsiz - 1); buf[bufsiz - 1] = 0; if (ret > 0) buf[ret] = 0; return ret; }