From: Marco Stornelli <marco.storne...@gmail.com>

File operations for directories.

Signed-off-by: Marco Stornelli <marco.storne...@gmail.com>
---
diff --git a/fs/pramfs/dir.c b/fs/pramfs/dir.c
new file mode 100644
index 0000000..cf0bcba
--- /dev/null
+++ b/fs/pramfs/dir.c
@@ -0,0 +1,208 @@
+/*
+ * BRIEF DESCRIPTION
+ *
+ * File operations for directories.
+ *
+ * Copyright 2009-2010 Marco Stornelli <marco.storne...@gmail.com>
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include "pram.h"
+
+/*
+ *     Parent is locked.
+ */
+int pram_add_link(struct dentry *dentry, struct inode *inode)
+{
+       struct inode *dir = dentry->d_parent->d_inode;
+       struct pram_inode *pidir, *pi, *pitail = NULL;
+       u64 tail_ino, prev_ino;
+
+       const char *name = dentry->d_name.name;
+
+       int namelen = min_t(unsigned int, dentry->d_name.len, PRAM_NAME_LEN);
+
+       pidir = pram_get_inode(dir->i_sb, dir->i_ino);
+       pi = pram_get_inode(dir->i_sb, inode->i_ino);
+
+       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+
+       tail_ino = be64_to_cpu(pidir->i_type.dir.tail);
+       if (tail_ino != 0) {
+               pitail = pram_get_inode(dir->i_sb, tail_ino);
+               pram_memunlock_inode(dir->i_sb, pitail);
+               pitail->i_d.d_next = cpu_to_be64(inode->i_ino);
+               pram_memlock_inode(dir->i_sb, pitail);
+
+               prev_ino = tail_ino;
+
+               pram_memunlock_inode(dir->i_sb, pidir);
+               pidir->i_type.dir.tail = cpu_to_be64(inode->i_ino);
+               pidir->i_mtime = cpu_to_be32(dir->i_mtime.tv_sec);
+               pidir->i_ctime = cpu_to_be32(dir->i_ctime.tv_sec);
+               pram_memlock_inode(dir->i_sb, pidir);
+       } else {
+               /* the directory is empty */
+               prev_ino = 0;
+
+               pram_memunlock_inode(dir->i_sb, pidir);
+               pidir->i_type.dir.tail = cpu_to_be64(inode->i_ino);
+               pidir->i_type.dir.head = cpu_to_be64(inode->i_ino);
+               pidir->i_mtime = cpu_to_be32(dir->i_mtime.tv_sec);
+               pidir->i_ctime = cpu_to_be32(dir->i_ctime.tv_sec);
+               pram_memlock_inode(dir->i_sb, pidir);
+       }
+
+
+       pram_memunlock_inode(dir->i_sb, pi);
+       pi->i_d.d_prev = cpu_to_be64(prev_ino);
+       pi->i_d.d_parent = cpu_to_be64(dir->i_ino);
+       memcpy(pi->i_d.d_name, name, namelen);
+       pi->i_d.d_name[namelen] = '\0';
+       pram_memlock_inode(dir->i_sb, pi);
+       return 0;
+}
+
+int pram_remove_link(struct inode *inode)
+{
+       struct super_block *sb = inode->i_sb;
+       struct pram_inode *prev = NULL;
+       struct pram_inode *next = NULL;
+       struct pram_inode *pidir, *pi;
+
+       pi = pram_get_inode(sb, inode->i_ino);
+       pidir = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_parent));
+       if (!pidir)
+               return -EACCES;
+
+       if (inode->i_ino == be64_to_cpu(pidir->i_type.dir.head)) {
+               /* first inode in directory */
+               next = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_next));
+
+               if (next) {
+                       pram_memunlock_inode(sb, next);
+                       next->i_d.d_prev = 0;
+                       pram_memlock_inode(sb, next);
+
+                       pram_memunlock_inode(sb, pidir);
+                       pidir->i_type.dir.head = pi->i_d.d_next;
+               } else {
+                       pram_memunlock_inode(sb, pidir);
+                       pidir->i_type.dir.head = 0;
+                       pidir->i_type.dir.tail = 0;
+               }
+               pram_memlock_inode(sb, pidir);
+       } else if (inode->i_ino == be64_to_cpu(pidir->i_type.dir.tail)) {
+               /* last inode in directory */
+               prev = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_prev));
+
+               pram_memunlock_inode(sb, prev);
+               prev->i_d.d_next = 0;
+               pram_memlock_inode(sb, prev);
+
+               pram_memunlock_inode(sb, pidir);
+               pidir->i_type.dir.tail = pi->i_d.d_prev;
+               pram_memlock_inode(sb, pidir);
+       } else {
+               /* somewhere in the middle */
+               prev = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_prev));
+               next = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_next));
+
+               if (prev && next) {
+                       pram_memunlock_inode(sb, prev);
+                       prev->i_d.d_next = pi->i_d.d_next;
+                       pram_memlock_inode(sb, prev);
+
+                       pram_memunlock_inode(sb, next);
+                       next->i_d.d_prev = pi->i_d.d_prev;
+                       pram_memlock_inode(sb, next);
+               }
+       }
+
+       pram_memunlock_inode(sb, pi);
+       pi->i_d.d_next = 0;
+       pi->i_d.d_prev = 0;
+       pi->i_d.d_parent = 0;
+       pram_memlock_inode(sb, pi);
+
+       return 0;
+}
+
+#define DT2IF(dt) (((dt) << 12) & S_IFMT)
+#define IF2DT(sif) (((sif) & S_IFMT) >> 12)
+
+static int pram_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct super_block *sb = inode->i_sb;
+       struct pram_inode *pi;
+       int namelen, ret = 0;
+       char *name;
+       ino_t ino;
+
+       pi = pram_get_inode(sb, inode->i_ino);
+
+       switch ((unsigned long)filp->f_pos) {
+       case 0:
+               ret = filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR);
+               filp->f_pos++;
+               return ret;
+       case 1:
+               ret = filldir(dirent, "..", 2, 1, 
be64_to_cpu(pi->i_d.d_parent), DT_DIR);
+               ino = be64_to_cpu(pi->i_type.dir.head);
+               filp->f_pos = ino ? ino : 2;
+               return ret;
+       case 2:
+               ino = be64_to_cpu(pi->i_type.dir.head);
+               if (ino) {
+                       filp->f_pos = ino;
+                       pi = pram_get_inode(sb, ino);
+                       break;
+               } else {
+                       /* the directory is empty */
+                       filp->f_pos = 2;
+                       return 0;
+               }
+       case 3:
+               return 0;
+       default:
+               ino = filp->f_pos;
+               pi = pram_get_inode(sb, ino);
+               break;
+       }
+
+       while (pi && !be16_to_cpu(pi->i_links_count)) {
+               ino = filp->f_pos = be64_to_cpu(pi->i_d.d_next);
+               pi = pram_get_inode(sb, ino);
+       }
+
+       if (pi) {
+               name = pi->i_d.d_name;
+               namelen = strlen(name);
+
+               ret = filldir(dirent, name, namelen,
+                             filp->f_pos, ino,
+                             IF2DT(be16_to_cpu(pi->i_mode)));
+               filp->f_pos = pi->i_d.d_next ? be64_to_cpu(pi->i_d.d_next) : 3;
+       } else
+               filp->f_pos = 3;
+
+       return ret;
+}
+
+struct file_operations pram_dir_operations = {
+       .read           = generic_read_dir,
+       .readdir        = pram_readdir,
+       .fsync          = noop_fsync,
+       .unlocked_ioctl = pram_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = pram_compat_ioctl,
+#endif
+};
--
To unsubscribe from this list: send the line "unsubscribe linux-embedded" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to