]> Zhao Yanbai Git Server - minix.git/commitdiff
libvtreefs: API changes/extensions, part 1 85/2885/2
authorDavid van Moolenbroek <david@minix3.org>
Thu, 6 Nov 2014 15:04:45 +0000 (15:04 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Wed, 12 Nov 2014 12:13:38 +0000 (12:13 +0000)
- move primary I/O buffer into vtreefs; change read hook API;
- add hooks for write, truncate, symlink, mknod, unlink, chmod/chown;
- modernize message_hook;
- change procfs, devman, gpio accordingly;

Change-Id: I9f0669e41195efa3253032e95d93f0a78e9d68d6

21 files changed:
minix/drivers/system/gpio/gpio.c
minix/fs/procfs/buf.c
minix/fs/procfs/const.h
minix/fs/procfs/main.c
minix/fs/procfs/proto.h
minix/fs/procfs/tree.c
minix/include/minix/vtreefs.h
minix/lib/libvtreefs/Makefile
minix/lib/libvtreefs/file.c [new file with mode: 0644]
minix/lib/libvtreefs/inode.c
minix/lib/libvtreefs/link.c
minix/lib/libvtreefs/proto.h
minix/lib/libvtreefs/read.c [deleted file]
minix/lib/libvtreefs/stadir.c
minix/lib/libvtreefs/table.c
minix/lib/libvtreefs/vtreefs.c
minix/servers/devman/buf.c
minix/servers/devman/device.c
minix/servers/devman/devman.h
minix/servers/devman/main.c
minix/servers/devman/proto.h

index b9da4e522a0c34648cd65f84e88c58ec3685567b..9ddc19292eb1b642bc16355ed6a328c799c8c536 100644 (file)
@@ -71,6 +71,9 @@ static struct inode_stat default_file_stat = {
        .dev = NO_DEV,
 };
 
+/* Buffer size for read requests */
+#define DATA_SIZE      26
+
 int
 add_gpio_inode(char *name, int nr, int mode)
 {
@@ -206,14 +209,12 @@ init_hook(void)
        }
 }
 
-static int
+static ssize_t
     read_hook
-    (struct inode *inode, off_t offset, char **ptr, size_t * len,
-    cbdata_t cbdata)
+    (struct inode *inode, char *ptr, size_t len, off_t offset, cbdata_t cbdata)
 {
        /* This hook will be called every time a regular file is read. We use
         * it to dyanmically generate the contents of our file. */
-       static char data[26];
        int value;
        struct gpio_cbdata *gpio_cbdata = (struct gpio_cbdata *) cbdata;
        assert(gpio_cbdata->gpio != NULL);
@@ -222,53 +223,42 @@ static int
            || gpio_cbdata->type == GPIO_CB_OFF) {
                /* turn on or off */
                if (gpio_set(gpio_cbdata->gpio,
-                       (gpio_cbdata->type == GPIO_CB_ON) ? 1 : 0)) {
-                       *len = 0;
+                       (gpio_cbdata->type == GPIO_CB_ON) ? 1 : 0))
                        return EIO;
-               }
-               *len = 0;
-               return OK;
+               return 0;
        }
 
        if (gpio_cbdata->type == GPIO_CB_INTR_READ) {
                /* reading interrupt */
-               if (gpio_intr_read(gpio_cbdata->gpio, &value)) {
-                       *len = 0;
+               if (gpio_intr_read(gpio_cbdata->gpio, &value))
                        return EIO;
-               }
        } else {
                /* reading */
-               if (gpio_read(gpio_cbdata->gpio, &value)) {
-                       *len = 0;
+               if (gpio_read(gpio_cbdata->gpio, &value))
                        return EIO;
-               }
        }
-       snprintf(data, 26, "%d\n", value);
-
-       /* If the offset is beyond the end of the string, return EOF. */
-       if (offset > strlen(data)) {
-               *len = 0;
+       snprintf(ptr, DATA_SIZE, "%d\n", value);
+       len = strlen(ptr);
 
-               return OK;
-       }
+       /* If the offset is at or beyond the end of the string, return EOF. */
+       if (offset >= len)
+               return 0;
 
-       /* Otherwise, return a pointer into 'data'. If necessary, bound the
-        * returned length to the length of the rest of the string. Note that
-        * 'data' has to be static, because it will be used after this
-        * function returns. */
-       *ptr = data + offset;
+       /* Otherwise, we may have to move the data to the start of ptr. */
+       if (offset > 0) {
+               len -= offset;
 
-       if (*len > strlen(data) - offset)
-               *len = strlen(data) - offset;
+               memmove(ptr, &ptr[offset], len);
+       }
 
-       return OK;
+       /* Return the resulting length. */
+       return len;
 }
 
-static int
-message_hook(message * m)
+static void
+message_hook(message * m, int __unused ipc_status)
 {
        gpio_intr_message(m);
-       return OK;
 }
 
 int
@@ -294,7 +284,7 @@ main(int argc, char **argv)
        root_stat.dev = NO_DEV;
 
        /* limit the number of indexed entries */
-       start_vtreefs(&hooks, 30, &root_stat, 0);
+       start_vtreefs(&hooks, 30, &root_stat, 0, DATA_SIZE);
 
        return EXIT_SUCCESS;
 }
index ee2ef7990b91bbb37905e251fd33c341df5fdadf..463c1b822b847af78e6d56a92f64b007c8899bd9 100644 (file)
@@ -3,25 +3,25 @@
 #include "inc.h"
 #include <stdarg.h>
 
-#define BUF_SIZE 4096
-
-static char buf[BUF_SIZE + 1];
-static size_t off, left, used;
+static char *buf;
+static size_t left, used;
 static off_t skip;
 
 /*===========================================================================*
  *                             buf_init                                     *
  *===========================================================================*/
-void buf_init(off_t start, size_t len)
+void buf_init(char *ptr, size_t len, off_t start)
 {
-       /* Initialize the buffer for fresh use. The first 'start' bytes of the
-        * produced output are to be skipped. After that, up to a total of
-        * 'len' bytes are requested.
+       /* Initialize the buffer for fresh use. The output is to be stored into
+        * 'ptr' which is BUF_SIZE bytes in size, since that is the size we
+        * requested. Due to the way vsnprintf works, we cannot use the last
+        * byte of this buffer. The first 'start' bytes of the produced output
+        * are to be skipped. After that, a total of 'len' bytes are requested.
         */
 
+       buf = ptr;
        skip = start;
-       left = MIN(len, BUF_SIZE);
-       off = 0;
+       left = MIN(len, BUF_SIZE - 1);
        used = 0;
 }
 
@@ -40,21 +40,23 @@ void buf_printf(char *fmt, ...)
 
        /* There is no way to estimate how much space the result will take, so
         * we need to produce the string even when skipping part of the start.
-        * If part of the result is to be skipped, do not memcpy; instead, save
-        * the offset of where the result starts within the buffer.
-        *
         * The null terminating character is not part of the result, so room
         * must be given for it to be stored after completely filling up the
         * requested part of the buffer.
         */
-       max = MIN(skip + left, BUF_SIZE);
+       max = MIN(skip + left + 1, BUF_SIZE);
 
        va_start(args, fmt);
-       len = vsnprintf(&buf[off + used], max + 1, fmt, args);
+       len = vsnprintf(&buf[used], max, fmt, args);
        va_end(args);
 
+       /* The snprintf family returns the number of bytes that would be stored
+        * if the buffer were large enough, excluding the null terminator.
+        */
+       if (len >= BUF_SIZE)
+               len = BUF_SIZE - 1;
+
        if (skip > 0) {
-               assert(off == 0);
                assert(used == 0);
 
                if (skip >= len) {
@@ -63,16 +65,15 @@ void buf_printf(char *fmt, ...)
                        return;
                }
 
-               off = skip;
-               if (left > BUF_SIZE - off)
-                       left = BUF_SIZE - off;
-               len -= off;
+               memmove(buf, &buf[skip], len - skip);
+
+               len -= skip;
                skip = 0;
        }
 
        assert(skip == 0);
        assert(len >= 0);
-       assert((long) left >= 0);
+       assert((ssize_t) left >= 0);
 
        if (len > (ssize_t) left)
                len = left;
@@ -107,22 +108,20 @@ void buf_append(char *data, size_t len)
        if (len > left)
                len = left;
 
-       memcpy(&buf[off + used], data, len);
+       memcpy(&buf[used], data, len);
 
        used += len;
        left -= len;
 }
 
 /*===========================================================================*
- *                             buf_get                                      *
+ *                             buf_result                                   *
  *===========================================================================*/
-size_t buf_get(char **ptr)
+ssize_t buf_result(void)
 {
-       /* Return the buffer's starting address and the length of the used
-        * part, not counting the trailing null character for the latter.
+       /* Return the resulting number of bytes produced, not counting the
+        * trailing null character in the buffer.
         */
 
-       *ptr = &buf[off];
-
        return used;
 }
index 18ad75dc3613431877112c8730eeef996ac11388..ed52f99c72c7b02c320d65602e4270b05bede567 100644 (file)
@@ -30,4 +30,7 @@
 #define DIR_ALL_MODE   (S_IFDIR | 0555)        /* world-accessible directory */
 #define LNK_ALL_MODE   (S_IFLNK | 0777)        /* symbolic link */
 
+/* Size of the I/O buffer. */
+#define BUF_SIZE       4097                    /* 4KB+1 (see buf.c) */
+
 #endif /* _PROCFS_CONST_H */
index 180543aa2debc41c452ffa26e0adcd7cfe6fac23..9e31fb5881036deb1c0889ecc094a451713479b4 100644 (file)
@@ -7,13 +7,11 @@ static void init_hook(void);
 
 /* The hook functions that will be called by VTreeFS. */
 static struct fs_hooks hooks = {
-       init_hook,
-       NULL,           /* cleanup_hook */
-       lookup_hook,
-       getdents_hook,
-       read_hook,
-       rdlink_hook,
-       NULL            /* message_hook */
+       .init_hook      = init_hook,
+       .lookup_hook    = lookup_hook,
+       .getdents_hook  = getdents_hook,
+       .read_hook      = read_hook,
+       .rdlink_hook    = rdlink_hook,
 };
 
 /*===========================================================================*
@@ -90,7 +88,7 @@ int main(void)
        stat.dev        = NO_DEV;
 
        /* Start VTreeFS. */
-       start_vtreefs(&hooks, NR_INODES, &stat, NR_PROCS + NR_TASKS);
+       start_vtreefs(&hooks, NR_INODES, &stat, NR_PROCS + NR_TASKS, BUF_SIZE);
 
        return 0;
 }
index 64f257a6793623229e906364537e8cc4126294be..4fa224e408d31a332082fe9e6926082c194cfb86 100644 (file)
@@ -2,19 +2,18 @@
 #define _PROCFS_PROTO_H
 
 /* buf.c */
-void buf_init(off_t start, size_t len);
+void buf_init(char *ptr, size_t len, off_t start);
 void buf_printf(char *fmt, ...);
 void buf_append(char *data, size_t len);
-size_t buf_get(char **ptr);
+ssize_t buf_result(void);
 
 /* tree.c */
 int init_tree(void);
 int lookup_hook(struct inode *parent, char *name, cbdata_t cbdata);
 int getdents_hook(struct inode *inode, cbdata_t cbdata);
-int read_hook(struct inode *inode, off_t offset, char **ptr, size_t
-       *len, cbdata_t cbdata);
-int rdlink_hook(struct inode *inode, char *ptr, size_t max, cbdata_t
-       cbdata);
+ssize_t read_hook(struct inode *inode, char *ptr, size_t len, off_t off,
+       cbdata_t cbdata);
+int rdlink_hook(struct inode *inode, char *ptr, size_t max, cbdata_t cbdata);
 
 /* util.c */
 int procfs_getloadavg(struct load *loadavg, int nelem);
index 239bd888d5db534dbe7ba68d72eeb5b72791d112..4e5fabde8b5d4f17440d18be98daa450d9659208 100644 (file)
@@ -494,14 +494,14 @@ int getdents_hook(struct inode *node, cbdata_t UNUSED(cbdata))
 /*===========================================================================*
  *                             read_hook                                    *
  *===========================================================================*/
-int read_hook(struct inode *node, off_t off, char **ptr,
-       size_t *len, cbdata_t cbdata)
+ssize_t read_hook(struct inode *node, char *ptr, size_t len, off_t off,
+       cbdata_t cbdata)
 {
        /* Regular file read hook. Call the appropriate callback function to
         * generate and return the data.
         */
 
-       buf_init(off, *len);
+       buf_init(ptr, len, off);
 
        /* Populate the buffer with the proper content. */
        if (get_inode_index(node) != NO_INDEX) {
@@ -510,9 +510,7 @@ int read_hook(struct inode *node, off_t off, char **ptr,
                ((void (*) (void)) cbdata)();
        }
 
-       *len = buf_get(ptr);
-
-       return OK;
+       return buf_result();
 }
 
 /*===========================================================================*
index 5ab27b863375d3290c1f429defa49a0f3acd1d9c..91c340f849cbd75efed3a46367609f56f26804ca 100644 (file)
@@ -25,11 +25,21 @@ struct fs_hooks {
        void (*cleanup_hook)(void);
        int (*lookup_hook)(struct inode *inode, char *name, cbdata_t cbdata);
        int (*getdents_hook)(struct inode *inode, cbdata_t cbdata);
-       int (*read_hook)(struct inode *inode, off_t offset, char **ptr,
-               size_t *len, cbdata_t cbdata);
+       ssize_t (*read_hook)(struct inode *inode, char *ptr, size_t len,
+           off_t off, cbdata_t cbdata);
+       ssize_t (*write_hook)(struct inode *inode, char *ptr, size_t max,
+           off_t off, cbdata_t cbdata);
+       int (*trunc_hook)(struct inode *inode, off_t offset, cbdata_t cbdata);
+       int (*mknod_hook)(struct inode *inode, char *name,
+           struct inode_stat *stat, cbdata_t cbdata);
+       int (*unlink_hook)(struct inode *inode, cbdata_t cbdata);
+       int (*slink_hook)(struct inode *inode, char *name,
+           struct inode_stat *stat, char *path, cbdata_t cbdata);
        int (*rdlink_hook)(struct inode *inode, char *ptr, size_t max,
-               cbdata_t cbdata);
-       int (*message_hook)(message *m);
+           cbdata_t cbdata);
+       int (*chstat_hook)(struct inode *inode, struct inode_stat *stat,
+           cbdata_t cbdata);
+       void (*message_hook)(message *m, int ipc_status);
 };
 
 extern struct inode *add_inode(struct inode *parent, const char *name,
@@ -55,6 +65,6 @@ extern void get_inode_stat(const struct inode *inode, struct inode_stat *stat);
 extern void set_inode_stat(struct inode *inode, struct inode_stat *stat);
 
 extern void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes,
-       struct inode_stat *stat, index_t nr_indexed_entries);
+       struct inode_stat *stat, index_t nr_indexed_entries, size_t buf_size);
 
 #endif /* _MINIX_VTREEFS_H */
index f885652fbc47533fd50598085e248e0c75386aa4..181b053c0efef61331b4063e87327f0e97921b83 100644 (file)
@@ -7,11 +7,11 @@ CPPFLAGS+= -D_MINIX_SYSTEM
 LIB=   vtreefs
 
 SRCS=  \
+       file.c \
        inode.c \
        link.c \
        mount.c \
        path.c \
-       read.c \
        sdbm.c \
        stadir.c \
        table.c \
diff --git a/minix/lib/libvtreefs/file.c b/minix/lib/libvtreefs/file.c
new file mode 100644 (file)
index 0000000..3d3b2c9
--- /dev/null
@@ -0,0 +1,293 @@
+/* VTreeFS - file.c - file and directory I/O */
+
+#include "inc.h"
+#include <dirent.h>
+
+#define GETDENTS_BUFSIZ 4096
+
+static char *buf = NULL;
+static size_t bufsize = 0;
+
+/*
+ * Initialize the main buffer used for I/O.  Return OK or an error code.
+ */
+int
+init_buf(size_t size)
+{
+
+       /* A default buffer size, for at least getdents. */
+       if (size < GETDENTS_BUFSIZ)
+               size = GETDENTS_BUFSIZ;
+
+       if ((buf = malloc(size)) == NULL)
+               return ENOMEM;
+
+       bufsize = size;
+       return OK;
+}
+
+/*
+ * Free up the I/O buffer.
+ */
+void
+cleanup_buf(void)
+{
+
+       free(buf);
+
+       buf = NULL;
+       bufsize = 0;
+}
+
+/*
+ * Read from a file.
+ */
+ssize_t
+fs_read(ino_t ino_nr, struct fsdriver_data * data, size_t bytes,
+       off_t pos, int __unused call)
+{
+       struct inode *node;
+       size_t off, chunk;
+       ssize_t r, len;
+
+       /* Try to get inode by its inode number. */
+       if ((node = find_inode(ino_nr)) == NULL)
+               return EINVAL;
+
+       /* Check whether the node is a regular file. */
+       if (!S_ISREG(node->i_stat.mode))
+               return EINVAL;
+
+       /* For deleted files or with no read hook, feign an empty file. */
+       if (is_inode_deleted(node) || vtreefs_hooks->read_hook == NULL)
+               return 0; /* EOF */
+
+       assert(buf != NULL);
+       assert(bufsize > 0);
+
+       /*
+        * Call the read hook to fill the result buffer, repeatedly for as long
+        * as 1) the request is not yet fully completed, and 2) the read hook
+        * fills the entire buffer.
+        */
+       for (off = 0; off < bytes; ) {
+               /* Get the next result chunk by calling the read hook. */
+               chunk = bytes - off;
+               if (chunk > bufsize)
+                       chunk = bufsize;
+
+               len = vtreefs_hooks->read_hook(node, buf, chunk, pos,
+                   get_inode_cbdata(node));
+
+               /* Copy any resulting data to user space. */
+               if (len > 0)
+                       r = fsdriver_copyout(data, off, buf, len);
+               else
+                       r = len; /* EOF or error */
+
+               /*
+                * If an error occurred, but we already produced some output,
+                * return a partial result.  Otherwise return the error.
+                */
+               if (r < 0)
+                       return (off > 0) ? off : r;
+
+               off += len;
+               pos += len;
+
+               if ((size_t)len < bufsize)
+                       break;
+       }
+
+       return off;
+}
+
+/*
+ * Write to a file.
+ */
+ssize_t
+fs_write(ino_t ino_nr, struct fsdriver_data * data, size_t bytes, off_t pos,
+       int __unused call)
+{
+       struct inode *node;
+       size_t off, chunk;
+       ssize_t r;
+
+       if ((node = find_inode(ino_nr)) == NULL)
+               return EINVAL;
+
+       if (!S_ISREG(node->i_stat.mode))
+               return EINVAL;
+
+       if (is_inode_deleted(node) || vtreefs_hooks->write_hook == NULL)
+               return EACCES;
+
+       if (bytes == 0)
+               return 0;
+
+       assert(buf != NULL);
+       assert(bufsize > 0);
+
+       /*
+        * Call the write hook to process the incoming data, repeatedly for as
+        * long as 1) the request is not yet fully completed, and 2) the write
+        * hook processes at least some of the given data.
+        */
+       for (off = 0; off < bytes; ) {
+               chunk = bytes - off;
+               if (chunk > bufsize)
+                       chunk = bufsize;
+
+               /* Copy the data from user space. */
+               r = fsdriver_copyin(data, off, buf, chunk);
+
+               /* Call the write hook for the chunk. */
+               if (r == OK)
+                       r = vtreefs_hooks->write_hook(node, buf, chunk, pos,
+                           get_inode_cbdata(node));
+
+               /*
+                * If an error occurred, but we already processed some input,
+                * return a partial result.  Otherwise return the error.
+                */
+               if (r < 0)
+                       return (off > 0) ? off : r;
+
+               off += r;
+               pos += r;
+
+               if ((size_t)r == 0)
+                       break;
+       }
+
+       return off;
+}
+
+/*
+ * Truncate a file.
+ */
+int
+fs_trunc(ino_t ino_nr, off_t start_pos, off_t end_pos)
+{
+       struct inode *node;
+
+       if ((node = find_inode(ino_nr)) == NULL)
+               return EINVAL;
+
+       if (!S_ISREG(node->i_stat.mode))
+               return EINVAL;
+
+       if (is_inode_deleted(node) || vtreefs_hooks->trunc_hook == NULL)
+               return EACCES;
+
+       /* TODO: translate this case into all-zeroes write callbacks. */
+       if (end_pos != 0)
+               return EINVAL;
+
+       return vtreefs_hooks->trunc_hook(node, start_pos,
+           get_inode_cbdata(node));
+}
+
+/*
+ * Retrieve directory entries.
+ */
+ssize_t
+fs_getdents(ino_t ino_nr, struct fsdriver_data * data, size_t bytes,
+       off_t * posp)
+{
+       struct fsdriver_dentry fsdentry;
+       struct inode *node, *child;
+       const char *name;
+       off_t pos;
+       int r, skip, get_next, indexed;
+
+       if (*posp >= ULONG_MAX)
+               return EIO;
+
+       if ((node = find_inode(ino_nr)) == NULL)
+               return EINVAL;
+
+       indexed = node->i_indexed;
+       get_next = FALSE;
+       child = NULL;
+
+       /* Call the getdents hook, if any, to "refresh" the directory. */
+       if (!is_inode_deleted(node) && vtreefs_hooks->getdents_hook != NULL) {
+               r = vtreefs_hooks->getdents_hook(node, get_inode_cbdata(node));
+               if (r != OK)
+                       return r;
+       }
+
+       assert(buf != NULL);
+       assert(bufsize > 0);
+
+       fsdriver_dentry_init(&fsdentry, data, bytes, buf, bufsize);
+
+       do {
+               /* Determine which inode and name to use for this entry. */
+               pos = (*posp)++;
+
+               if (pos == 0) {
+                       /* The "." entry. */
+                       child = node;
+                       name = ".";
+               } else if (pos == 1) {
+                       /* The ".." entry. */
+                       child = get_parent_inode(node);
+                       if (child == NULL)
+                               child = node;
+                       name = "..";
+               } else if (pos - 2 < indexed) {
+                       /* All indexed entries. */
+                       child = get_inode_by_index(node, pos - 2);
+
+                       /*
+                        * If there is no inode with this particular index,
+                        * continue with the next index number.
+                        */
+                       if (child == NULL) continue;
+
+                       name = child->i_name;
+               } else {
+                       /* All non-indexed entries. */
+                       /*
+                        * If this is the first loop iteration, first get to
+                        * the non-indexed child identified by the current
+                        * position.
+                        */
+                       if (get_next == FALSE) {
+                               skip = pos - indexed - 2;
+                               child = get_first_inode(node);
+
+                               /* Skip indexed children. */
+                               while (child != NULL &&
+                                   child->i_index != NO_INDEX)
+                                       child = get_next_inode(child);
+
+                               /* Skip to the right position. */
+                               while (child != NULL && skip-- > 0)
+                                       child = get_next_inode(child);
+
+                               get_next = TRUE;
+                       } else
+                               child = get_next_inode(child);
+
+                       /* No more children? Then stop. */
+                       if (child == NULL)
+                               break;
+
+                       assert(!is_inode_deleted(child));
+
+                       name = child->i_name;
+               }
+
+               /* Add the directory entry to the output. */
+               r = fsdriver_dentry_add(&fsdentry,
+                   (ino_t)get_inode_number(child), name, strlen(name),
+                   IFTODT(child->i_stat.mode));
+               if (r < 0)
+                       return r;
+       } while (r > 0);
+
+       return fsdriver_dentry_finish(&fsdentry);
+}
index 98eac18e414318f4120a46f6ba19e2c30e1e695f..0363dc595704e07533e82f7b8fc7f10005633ef5 100644 (file)
@@ -26,7 +26,7 @@ static LIST_HEAD(index_head, inode) *parent_index_head;
 /*
  * Initialize the inode-related state.
  */
-void
+int
 init_inodes(unsigned int inodes, struct inode_stat * stat,
        index_t nr_indexed_entries)
 {
@@ -39,13 +39,21 @@ init_inodes(unsigned int inodes, struct inode_stat * stat,
        nr_inodes = inodes;
 
        /* Allocate the inode and hash tables. */
-       inode = malloc(nr_inodes * sizeof(inode[0]));
+       if ((inode = malloc(nr_inodes * sizeof(inode[0]))) == NULL)
+               return ENOMEM;
+
        parent_name_head = malloc(nr_inodes * sizeof(parent_name_head[0]));
-       parent_index_head = malloc(nr_inodes * sizeof(parent_index_head[0]));
+       if (parent_name_head == NULL) {
+               free(inode);
+               return ENOMEM;
+       }
 
-       assert(inode != NULL);
-       assert(parent_name_head != NULL);
-       assert(parent_index_head != NULL);
+       parent_index_head = malloc(nr_inodes * sizeof(parent_index_head[0]));
+       if (parent_index_head == NULL) {
+               free(parent_name_head);
+               free(inode);
+               return ENOMEM;
+       }
 
 #if DEBUG
        printf("VTREEFS: allocated %d+%d+%d bytes\n",
@@ -83,6 +91,8 @@ init_inodes(unsigned int inodes, struct inode_stat * stat,
        set_inode_stat(node, stat);
        node->i_indexed = nr_indexed_entries;
        node->i_cbdata = NULL;
+
+       return OK;
 }
 
 /*
index 5637ba6582acb926a0712777919ea5173780dc22..5296dbab8cf6186ca7abfe343dc5e5f588a05410 100644 (file)
@@ -1,9 +1,9 @@
-/* VTreeFS - link.c - support for symbolic links */
+/* VTreeFS - link.c - support for symbolic links and device nodes */
 
 #include "inc.h"
 
 /*
- * Retrieve symbolic link target.
+ * Retrieve symbolic link target.
  */
 ssize_t
 fs_rdlink(ino_t ino_nr, struct fsdriver_data * data, size_t bytes)
@@ -16,11 +16,10 @@ fs_rdlink(ino_t ino_nr, struct fsdriver_data * data, size_t bytes)
        if ((node = find_inode(ino_nr)) == NULL)
                return EINVAL;
 
-       /*
-        * Call the rdlink hook.  The hook must be non-NULL if the file system
-        * adds symlink nodes.  If it doesn't, we will never get here.
-        */
-       assert(vtreefs_hooks->rdlink_hook != NULL);
+       /* The hook should be provided for any FS that adds symlink inodes.. */
+       if (vtreefs_hooks->rdlink_hook == NULL)
+               return ENOSYS;
+
        assert(!is_inode_deleted(node));        /* symlinks cannot be opened */
 
        r = vtreefs_hooks->rdlink_hook(node, path, sizeof(path),
@@ -39,3 +38,92 @@ fs_rdlink(ino_t ino_nr, struct fsdriver_data * data, size_t bytes)
 
        return len;
 }
+
+/*
+ * Create a symbolic link.
+ */
+int
+fs_slink(ino_t dir_nr, char * name, uid_t uid, gid_t gid,
+       struct fsdriver_data * data, size_t bytes)
+{
+       char path[PATH_MAX];
+       struct inode *node;
+       struct inode_stat stat;
+       int r;
+
+       if ((node = find_inode(dir_nr)) == NULL)
+               return EINVAL;
+
+       if (vtreefs_hooks->slink_hook == NULL)
+               return ENOSYS;
+
+       if (get_inode_by_name(node, name) != NULL)
+               return EEXIST;
+
+       if (bytes >= sizeof(path))
+               return ENAMETOOLONG;
+
+       if ((r = fsdriver_copyin(data, 0, path, bytes)) != OK)
+               return r;
+       path[bytes] = 0;
+
+       memset(&stat, 0, sizeof(stat));
+       stat.mode = S_IFLNK | RWX_MODES;
+       stat.uid = uid;
+       stat.gid = gid;
+       stat.size = strlen(path);
+       stat.dev = 0;
+
+       return vtreefs_hooks->slink_hook(node, name, &stat, path,
+           get_inode_cbdata(node));
+}
+
+/*
+ * Create a device node.
+ */
+int
+fs_mknod(ino_t dir_nr, char * name, mode_t mode, uid_t uid, gid_t gid,
+       dev_t rdev)
+{
+       struct inode *node;
+       struct inode_stat stat;
+
+       if ((node = find_inode(dir_nr)) == NULL)
+               return EINVAL;
+
+       if (get_inode_by_name(node, name) != NULL)
+               return EEXIST;
+
+       if (vtreefs_hooks->mknod_hook == NULL)
+               return ENOSYS;
+
+       memset(&stat, 0, sizeof(stat));
+       stat.mode = mode;
+       stat.uid = uid;
+       stat.gid = gid;
+       stat.size = 0;
+       stat.dev = rdev;
+
+       return vtreefs_hooks->mknod_hook(node, name, &stat,
+           get_inode_cbdata(node));
+}
+
+/*
+ * Unlink a node.
+ */
+int
+fs_unlink(ino_t dir_nr, char * name, int __unused call)
+{
+       struct inode *dir_node, *node;
+
+       if ((dir_node = find_inode(dir_nr)) == NULL)
+               return EINVAL;
+
+       if ((node = get_inode_by_name(dir_node, name)) == NULL)
+               return ENOENT;
+
+       if (vtreefs_hooks->unlink_hook == NULL)
+               return ENOSYS;
+
+       return vtreefs_hooks->unlink_hook(node, get_inode_cbdata(node));
+}
index 683daea7aa6fa8576a24d960316c68716951d9ec..acead73cb3ef901860ec3fc4266c44dd8abec40b 100644 (file)
@@ -1,9 +1,20 @@
 #ifndef _VTREEFS_PROTO_H
 #define _VTREEFS_PROTO_H
 
+/* file.c */
+int init_buf(size_t size);
+void cleanup_buf(void);
+ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
+       off_t pos, int call);
+ssize_t fs_write(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
+       off_t pos, int call);
+int fs_trunc(ino_t ino_nr, off_t start_pos, off_t end_pos);
+ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
+       off_t *pos);
+
 /* inode.c */
-void init_inodes(unsigned int inodes, struct inode_stat *stat, index_t
-       nr_indexed_entries);
+int init_inodes(unsigned int inodes, struct inode_stat *stat,
+       index_t nr_indexed_entries);
 void cleanup_inodes(void);
 struct inode *find_inode(ino_t num);
 struct inode *get_inode(ino_t num);
@@ -15,6 +26,11 @@ int fs_putnode(ino_t ino_nr, unsigned int count);
 
 /* link.c */
 ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes);
+int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid,
+       struct fsdriver_data *data, size_t bytes);
+int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
+       dev_t rdev);
+int fs_unlink(ino_t dir_nr, char *name, int call);
 
 /* mount.c */
 int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
@@ -28,17 +44,13 @@ void fs_other(const message *m_ptr, int ipc_status);
 int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
        int *is_mountpt);
 
-/* read.c */
-ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
-       off_t pos, int call);
-ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
-       off_t *pos);
-
 /* sdbm.c */
 long sdbm_hash(const char *str, int len);
 
 /* stadir.c */
 int fs_stat(ino_t ino_nr, struct stat *buf);
+int fs_chmod(ino_t ino_nr, mode_t *mode);
+int fs_chown(ino_t ino_nr, uid_t uid, gid_t gid, mode_t *mode);
 int fs_statvfs(struct statvfs *buf);
 
 #endif /* _VTREEFS_PROTO_H */
diff --git a/minix/lib/libvtreefs/read.c b/minix/lib/libvtreefs/read.c
deleted file mode 100644 (file)
index 7d510c3..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/* VTreeFS - read.c - reading from files and directories */
-
-#include "inc.h"
-#include <dirent.h>
-
-#define GETDENTS_BUFSIZ 4096
-
-/*
- * Read from a file.
- */
-ssize_t
-fs_read(ino_t ino_nr, struct fsdriver_data * data, size_t bytes,
-       off_t pos, int __unused call)
-{
-       struct inode *node;
-       size_t len;
-       char *ptr;
-       int r;
-
-       /* Try to get inode by its inode number. */
-       if ((node = find_inode(ino_nr)) == NULL)
-               return EINVAL;
-
-       /* Check whether the node is a regular file. */
-       if (!S_ISREG(node->i_stat.mode))
-               return EINVAL;
-
-       /* Call the read hook, if any. */
-       if (!is_inode_deleted(node) && vtreefs_hooks->read_hook != NULL) {
-               len = bytes;
-
-               /*
-                * On success, the read hook provides us with a pointer to the
-                * resulting data.  This avoids copying overhead.
-                */
-               r = vtreefs_hooks->read_hook(node, pos, &ptr, &len,
-                       get_inode_cbdata(node));
-
-               assert(len <= bytes);
-
-               /* Copy the resulting data to user space. */
-               if (r == OK && len > 0)
-                       r = fsdriver_copyout(data, 0, ptr, len);
-       } else {
-               /* Feign an empty file. */
-               r = OK;
-               len = 0;
-       }
-
-       return (r != OK) ? r : len;
-}
-
-/*
- * Retrieve directory entries.
- */
-ssize_t
-fs_getdents(ino_t ino_nr, struct fsdriver_data * data, size_t bytes,
-       off_t * posp)
-{
-       struct fsdriver_dentry fsdentry;
-       struct inode *node, *child;
-       const char *name;
-       off_t pos;
-       int r, skip, get_next, indexed;
-       static char buf[GETDENTS_BUFSIZ];
-
-       if (*posp >= ULONG_MAX)
-               return EIO;
-
-       if ((node = find_inode(ino_nr)) == NULL)
-               return EINVAL;
-
-       indexed = node->i_indexed;
-       get_next = FALSE;
-       child = NULL;
-
-       /* Call the getdents hook, if any, to "refresh" the directory. */
-       if (!is_inode_deleted(node) && vtreefs_hooks->getdents_hook != NULL) {
-               r = vtreefs_hooks->getdents_hook(node, get_inode_cbdata(node));
-               if (r != OK)
-                       return r;
-       }
-
-       fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf));
-
-       do {
-               /* Determine which inode and name to use for this entry. */
-               pos = (*posp)++;
-
-               if (pos == 0) {
-                       /* The "." entry. */
-                       child = node;
-                       name = ".";
-               } else if (pos == 1) {
-                       /* The ".." entry. */
-                       child = get_parent_inode(node);
-                       if (child == NULL)
-                               child = node;
-                       name = "..";
-               } else if (pos - 2 < indexed) {
-                       /* All indexed entries. */
-                       child = get_inode_by_index(node, pos - 2);
-
-                       /*
-                        * If there is no inode with this particular index,
-                        * continue with the next index number.
-                        */
-                       if (child == NULL) continue;
-
-                       name = child->i_name;
-               } else {
-                       /* All non-indexed entries. */
-                       /*
-                        * If this is the first loop iteration, first get to
-                        * the non-indexed child identified by the current
-                        * position.
-                        */
-                       if (get_next == FALSE) {
-                               skip = pos - indexed - 2;
-                               child = get_first_inode(node);
-
-                               /* Skip indexed children. */
-                               while (child != NULL &&
-                                   child->i_index != NO_INDEX)
-                                       child = get_next_inode(child);
-
-                               /* Skip to the right position. */
-                               while (child != NULL && skip-- > 0)
-                                       child = get_next_inode(child);
-
-                               get_next = TRUE;
-                       } else
-                               child = get_next_inode(child);
-
-                       /* No more children? Then stop. */
-                       if (child == NULL)
-                               break;
-
-                       assert(!is_inode_deleted(child));
-
-                       name = child->i_name;
-               }
-
-               /* Add the directory entry to the output. */
-               r = fsdriver_dentry_add(&fsdentry,
-                   (ino_t)get_inode_number(child), name, strlen(name),
-                   IFTODT(child->i_stat.mode));
-               if (r < 0)
-                       return r;
-       } while (r > 0);
-
-       return fsdriver_dentry_finish(&fsdentry);
-}
index 6eba24eadb797de5ba185aff73b965eec8173b57..329c6e065d5ecec0ea12bf13992947348a8c30e4 100644 (file)
@@ -1,4 +1,4 @@
-/* VTreeFS - stadir.c - file and file system status retrieval */
+/* VTreeFS - stadir.c - file and file system status management */
 
 #include "inc.h"
 
@@ -44,6 +44,72 @@ fs_stat(ino_t ino_nr, struct stat * buf)
        return OK;
 }
 
+/*
+ * Change file mode.
+ */
+int
+fs_chmod(ino_t ino_nr, mode_t * mode)
+{
+       struct inode *node;
+       struct inode_stat stat;
+       int r;
+
+       if ((node = find_inode(ino_nr)) == NULL)
+               return EINVAL;
+
+       if (vtreefs_hooks->chstat_hook == NULL)
+               return ENOSYS;
+
+       get_inode_stat(node, &stat);
+
+       stat.mode = (stat.mode & ~ALL_MODES) | (*mode & ALL_MODES);
+
+       r = vtreefs_hooks->chstat_hook(node, &stat, get_inode_cbdata(node));
+
+       if (r != OK)
+               return r;
+
+       get_inode_stat(node, &stat);
+
+       *mode = stat.mode;
+
+       return OK;
+}
+
+/*
+ * Change file ownership.
+ */
+int
+fs_chown(ino_t ino_nr, uid_t uid, gid_t gid, mode_t * mode)
+{
+       struct inode *node;
+       struct inode_stat stat;
+       int r;
+
+       if ((node = find_inode(ino_nr)) == NULL)
+               return EINVAL;
+
+       if (vtreefs_hooks->chstat_hook == NULL)
+               return ENOSYS;
+
+       get_inode_stat(node, &stat);
+
+       stat.uid = uid;
+       stat.gid = gid;
+       stat.mode &= ~(S_ISUID | S_ISGID);
+
+       r = vtreefs_hooks->chstat_hook(node, &stat, get_inode_cbdata(node));
+
+       if (r != OK)
+               return r;
+
+       get_inode_stat(node, &stat);
+
+       *mode = stat.mode;
+
+       return OK;
+}
+
 /*
  * Retrieve file system statistics.
  */
index 17370bcfd6ebb17b8af1a47e4c1c099653895d97..df2085cbed190856a97cdb2b88b825a5e73a3840 100644 (file)
@@ -9,9 +9,16 @@ struct fsdriver vtreefs_table = {
        .fdr_lookup     = fs_lookup,
        .fdr_putnode    = fs_putnode,
        .fdr_read       = fs_read,
+       .fdr_write      = fs_write,
        .fdr_getdents   = fs_getdents,
+       .fdr_trunc      = fs_trunc,
+       .fdr_mknod      = fs_mknod,
+       .fdr_unlink     = fs_unlink,
+       .fdr_slink      = fs_slink,
        .fdr_rdlink     = fs_rdlink,
        .fdr_stat       = fs_stat,
+       .fdr_chmod      = fs_chmod,
+       .fdr_chown      = fs_chown,
        .fdr_statvfs    = fs_statvfs,
        .fdr_other      = fs_other
 };
index e433a736a85ced5ab87a171c7079b7ce3a34cc37..f63d1064a525ec70c8f02fd6ec932c764b9b8958 100644 (file)
@@ -5,16 +5,24 @@
 static unsigned int inodes;
 static struct inode_stat *root_stat;
 static index_t root_entries;
+static size_t buf_size;
 
 /*
- * Initialize internal state, and register with VFS.
+ * Initialize internal state.  This is the only place where dynamic memory
+ * allocation takes place.
  */
 static int
 init_server(int __unused type, sef_init_info_t * __unused info)
 {
+       int r;
 
        /* Initialize the virtual tree. */
-       init_inodes(inodes, root_stat, root_entries);
+       if ((r = init_inodes(inodes, root_stat, root_entries)) != OK)
+               panic("init_inodes failed: %d", r);
+
+       /* Initialize the I/O buffer. */
+       if ((r = init_buf(buf_size)) != OK)
+               panic("init_buf failed: %d", r);
 
        return OK;
 }
@@ -54,7 +62,7 @@ sef_local_startup(void)
  * Call the message hook, if there is one.
  */
 void
-fs_other(const message * m_ptr, int __unused ipc_status)
+fs_other(const message * m_ptr, int ipc_status)
 {
        message msg;
 
@@ -65,7 +73,7 @@ fs_other(const message * m_ptr, int __unused ipc_status)
                 */
                msg = *m_ptr;
 
-               vtreefs_hooks->message_hook(&msg);
+               vtreefs_hooks->message_hook(&msg, ipc_status);
        }
 }
 
@@ -76,7 +84,7 @@ fs_other(const message * m_ptr, int __unused ipc_status)
  */
 void
 start_vtreefs(struct fs_hooks * hooks, unsigned int nr_inodes,
-       struct inode_stat * stat, index_t nr_indexed_entries)
+       struct inode_stat * stat, index_t nr_indexed_entries, size_t bufsize)
 {
 
        /*
@@ -87,10 +95,12 @@ start_vtreefs(struct fs_hooks * hooks, unsigned int nr_inodes,
        inodes = nr_inodes;
        root_stat = stat;
        root_entries = nr_indexed_entries;
+       buf_size = bufsize;
 
        sef_local_startup();
 
        fsdriver_task(&vtreefs_table);
 
+       cleanup_buf();
        cleanup_inodes();
 }
index 961e7f769b78abf1d9cefdd3c90a20c2714466d7..694af690f7752c139bff1da022092dcd362214c2 100755 (executable)
@@ -1,62 +1,29 @@
 /* buf.c - by Alen Stojanov and David van Moolenbroek, taken from procfs */
-#define _SYSTEM                1       /* tell headers that this is the kernel */
-#define DEVMAN_SERVER  1
-
-#include <minix/config.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <lib.h>
-#include <minix/timers.h>
-
-#include <minix/callnr.h>
-#include <minix/type.h>
-#include <minix/const.h>
-#include <minix/com.h>
-#include <minix/syslib.h>
-#include <minix/sysutil.h>
-#include <minix/vfsif.h>
-#include <minix/endpoint.h>
-#include <minix/sysinfo.h>
-#include <minix/u64.h>
-#include <minix/sysinfo.h>
-#include <minix/type.h>
-#include <minix/ipc.h>
-
-#include <sys/time.h>
-#include <sys/times.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <minix/vtreefs.h>
-
-#include <minix/devman.h>
-
 
+#include "devman.h"
+#include "proto.h"
 #include <stdarg.h>
 #include <assert.h>
-#include <string.h>
-#define BUF_SIZE 4096
 
-static char buf[BUF_SIZE + 1];
-static size_t off, left, used;
+static char *buf;
+static size_t left, used;
 static off_t skip;
 
 /*===========================================================================*
  *                             buf_init                                     *
  *===========================================================================*/
-void buf_init(off_t start, size_t len)
+void buf_init(char *ptr, size_t len, off_t start)
 {
-       /* Initialize the buffer for fresh use. The first 'start' bytes of the
-        * produced output are to be skipped. After that, up to a total of
-        * 'len' bytes are requested.
+       /* Initialize the buffer for fresh use. The output is to be stored into
+        * 'ptr' which is BUF_SIZE bytes in size, since that is the size we
+        * requested. Due to the way vsnprintf works, we cannot use the last
+        * byte of this buffer. The first 'start' bytes of the produced output
+        * are to be skipped. After that, a total of 'len' bytes are requested.
         */
 
+       buf = ptr;
        skip = start;
-       left = MIN(len, BUF_SIZE);
-       off = 0;
+       left = MIN(len, BUF_SIZE - 1);
        used = 0;
 }
 
@@ -75,21 +42,23 @@ void buf_printf(char *fmt, ...)
 
        /* There is no way to estimate how much space the result will take, so
         * we need to produce the string even when skipping part of the start.
-        * If part of the result is to be skipped, do not memcpy; instead, save
-        * the offset of where the result starts within the buffer.
-        *
         * The null terminating character is not part of the result, so room
         * must be given for it to be stored after completely filling up the
         * requested part of the buffer.
         */
-       max = MIN(skip + left, BUF_SIZE);
+       max = MIN(skip + left + 1, BUF_SIZE);
 
        va_start(args, fmt);
-       len = vsnprintf(&buf[off + used], max + 1, fmt, args);
+       len = vsnprintf(&buf[used], max, fmt, args);
        va_end(args);
 
+       /* The snprintf family returns the number of bytes that would be stored
+        * if the buffer were large enough, excluding the null terminator.
+        */
+       if (len >= BUF_SIZE)
+               len = BUF_SIZE - 1;
+
        if (skip > 0) {
-               assert(off == 0);
                assert(used == 0);
 
                if (skip >= len) {
@@ -98,16 +67,15 @@ void buf_printf(char *fmt, ...)
                        return;
                }
 
-               off = skip;
-               if (left > BUF_SIZE - off)
-                       left = BUF_SIZE - off;
-               len -= off;
+               memmove(buf, &buf[skip], len - skip);
+
+               len -= skip;
                skip = 0;
        }
 
        assert(skip == 0);
        assert(len >= 0);
-       assert((long) left >= 0);
+       assert((ssize_t) left >= 0);
 
        if (len > (ssize_t) left)
                len = left;
@@ -142,22 +110,20 @@ void buf_append(char *data, size_t len)
        if (len > left)
                len = left;
 
-       memcpy(&buf[off + used], data, len);
+       memcpy(&buf[used], data, len);
 
        used += len;
        left -= len;
 }
 
 /*===========================================================================*
- *                             buf_get                                      *
+ *                             buf_result                                   *
  *===========================================================================*/
-size_t buf_get(char **ptr)
+ssize_t buf_result(void)
 {
-       /* Return the buffer's starting address and the length of the used
-        * part, not counting the trailing null character for the latter.
+       /* Return the resulting number of bytes produced, not counting the
+        * trailing null character in the buffer.
         */
 
-       *ptr = &buf[off];
-
        return used;
 }
index 9d5ed54c4f71e1eb6a65c1489fb791af8f02453e..0babbfe1bbc9ec82c4814aaaeb7ab35c770cd972 100644 (file)
@@ -8,7 +8,7 @@ static struct devman_device *_find_dev(struct devman_device *dev, int
        dev_id);
 static int devman_dev_add_info(struct devman_device *dev, struct
        devman_device_info_entry *entry, char *buf);
-static int devman_event_read(char **ptr, size_t *len,off_t offset, void
+static ssize_t devman_event_read(char *ptr, size_t len, off_t offset, void
        *data);
 
 static int devman_del_device(struct devman_device *dev);
@@ -138,11 +138,12 @@ devman_device_remove_event(struct devman_device* dev)
 /*===========================================================================*
  *          devman_event_read                                                *
  *===========================================================================*/
-static int
-devman_event_read(char **ptr, size_t *len,off_t offset, void *data)
+static ssize_t
+devman_event_read(char *ptr, size_t len, off_t offset, void *data)
 {
        struct devman_event *ev = NULL;
        struct devman_event_inode *n;
+       ssize_t r;
        
        n = (struct devman_event_inode *) data;
        
@@ -150,35 +151,34 @@ devman_event_read(char **ptr, size_t *len,off_t offset, void *data)
                ev = TAILQ_LAST(&n->event_queue, event_head);
        }
 
-       buf_init(offset, *len);
+       buf_init(ptr, len, offset);
        if (ev != NULL)
                buf_printf("%s", ev->data);
 
-       *len = buf_get(ptr);
+       r = buf_result();
 
        /* read all (EOF)? */
-       if (ev != NULL && *len == 0) {
+       if (ev != NULL && r == 0) {
                TAILQ_REMOVE(&n->event_queue, ev, events);
                free(ev);
        }
 
-       return 0;
+       return r;
 }
 
 /*===========================================================================*
  *          devman_static_info_read                                          *
  *===========================================================================*/
-static int
-devman_static_info_read(char **ptr, size_t *len, off_t offset, void *data)
+static ssize_t
+devman_static_info_read(char *ptr, size_t len, off_t offset, void *data)
 {
        struct devman_static_info_inode *n;
 
        n = (struct devman_static_info_inode *) data;
 
-       buf_init(offset, *len);
+       buf_init(ptr, len, offset);
        buf_printf("%s\n", n->data);
-       *len = buf_get(ptr);
-       return 0;
+       return buf_result();
 }
 
 /*===========================================================================*
index dff8d7c69392e72040d4e57b32e078bef1192f68..a9d77d5f01e94fb751f7e37311fb88712dc6cc1e 100644 (file)
@@ -36,6 +36,8 @@
 #include <minix/devman.h>
 #include <sys/queue.h>
 
+#define BUF_SIZE 4097
+
 #define DEVMAN_DEFAULT_MODE   (S_IRUSR | S_IRGRP | S_IROTH)
 #define DEVMAN_STRING_LEN 128
 
@@ -48,8 +50,8 @@ enum devman_inode_type {
        DEVMAN_DEVICE
 };
 
-typedef int (*devman_read_fn)
-    (char **ptr, size_t *len, off_t offset, void *data);
+typedef ssize_t (*devman_read_fn)
+    (char *ptr, size_t len, off_t offset, void *data);
 
 struct devman_device_file {
        int minor;
index 91477ff9fd55eb21b7e1f11cca70ff950b8be36a..924d6fb706d6247141a7d2b0e9e7563a1ce1e301 100644 (file)
@@ -43,24 +43,23 @@ static void init_hook(void) {
 }
 
 
-static int message_hook (message *m)
+static void message_hook(message *m, int __unused ipc_status)
 {
        switch (m->m_type) {
                case DEVMAN_ADD_DEV:
-                       return do_add_device(m);
+                       do_add_device(m);
                case DEVMAN_DEL_DEV:
-                       return do_del_device(m);
+                       do_del_device(m);
                case DEVMAN_BIND:
-                       return do_bind_device(m);
+                       do_bind_device(m);
                case DEVMAN_UNBIND:
-                       return do_unbind_device(m);
-               default: return -1;
+                       do_unbind_device(m);
        }
 }
 
-static int 
+static ssize_t
 read_hook
-(struct inode *inode, off_t offset, char **ptr, size_t *len, cbdata_t cbdata)
+(struct inode *inode, char *ptr, size_t len, off_t offset, cbdata_t cbdata)
 {
        struct devman_inode *d_inode = (struct devman_inode *) cbdata;
 
@@ -77,7 +76,7 @@ int main (int argc, char* argv[])
        /* fill in the hooks */
        memset(&hooks, 0, sizeof(hooks));
        hooks.init_hook         = init_hook;
-       hooks.read_hook         = read_hook; /* read will never be called */
+       hooks.read_hook         = read_hook;
        hooks.message_hook      = message_hook; /* handle the ds_update call */
 
        root_stat.mode  = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH;
@@ -87,7 +86,7 @@ int main (int argc, char* argv[])
        root_stat.dev   = NO_DEV;
 
        /* limit the number of indexed entries */
-       start_vtreefs(&hooks, 1024 , &root_stat, 0);
+       start_vtreefs(&hooks, 1024, &root_stat, 0, BUF_SIZE);
        return 0;
 }
 
index 540fb9137ccfeb28a3da79557ac80b2df35df0d5..bcc2ebbdf921d515372048e88caa80440b25da61 100644 (file)
@@ -2,10 +2,10 @@
 #define _DEVMAN_PROTO_H
 
 /* buf.c */
-void buf_init(off_t start, size_t len);
+void buf_init(char *ptr, size_t len, off_t off);
 void buf_printf(char *fmt, ...);
 void buf_append(char *data, size_t len);
-size_t buf_get(char **ptr);
+ssize_t buf_result(void);
 
 /* message handlers */
 int do_add_device(message *m);