The previous patch didn't include my changes to tux3.h, here is a correction
Cheers,
Michael Pattrick
On Sat, Dec 6, 2008 at 10:53 PM, Michael Pattrick
<[EMAIL PROTECTED]> wrote:
> Inspired by Pranith, I thought I would try to add to the directory
> functions in namei.c. Attached is a patch for rename and rmdir, I cant
> really vouch for the 'correctness' of it, but I tested it out for a
> while in UML and it seems to work correctly.
>
> This is really my first patch for low level file system operations, so
> I won't be offended if you point out any flaws.
>
> Cheers,
> Michael Pattrick
>
diff -r 47e5409786d4 user/kernel/dir.c
--- a/user/kernel/dir.c Fri Dec 05 19:24:40 2008 -0800
+++ b/user/kernel/dir.c Sat Dec 06 23:29:47 2008 -0500
@@ -157,6 +157,59 @@
return (block << blockbits) + offset; /* only needed for xattr create */
}
+int tux_add_link(struct dentry *dentry, struct inode *inode)
+{
+ struct inode *dir = dentry->d_parent->d_inode;
+ tux_dirent *entry;
+ struct buffer_head *buffer;
+ unsigned reclen = TUX_REC_LEN(dentry->d_name.len), rec_len, name_len, offset;
+ unsigned blockbits = tux_sb(dir->i_sb)->blockbits, blocksize = 1 << blockbits;
+ unsigned blocks = dir->i_size >> blockbits, block;
+ for (block = 0; block < blocks; block++) {
+ buffer = blockread(mapping(dir), block);
+ if (!buffer)
+ return -EIO;
+ entry = bufdata(buffer);
+ tux_dirent *limit = bufdata(buffer) + blocksize - reclen;
+ while (entry <= limit) {
+ if (entry->rec_len == 0) {
+ warn("zero-length directory entry");
+ brelse(buffer);
+ return -EIO;
+ }
+ name_len = TUX_REC_LEN(entry->name_len);
+ rec_len = tux_rec_len_from_disk(entry->rec_len);
+ if (is_deleted(entry) && rec_len >= reclen)
+ goto create;
+ if (rec_len >= name_len + reclen)
+ goto create;
+ entry = (tux_dirent *)((char *)entry + rec_len);
+ }
+ brelse(buffer);
+ }
+ buffer = blockget(mapping(dir), block = blocks);
+ entry = bufdata(buffer);
+ name_len = 0;
+ rec_len = blocksize;
+ *entry = (tux_dirent){ .rec_len = tux_rec_len_to_disk(blocksize) };
+ dir->i_size += blocksize;
+create:
+ if (!is_deleted(entry)) {
+ tux_dirent *newent = (tux_dirent *)((char *)entry + name_len);
+ newent->rec_len = tux_rec_len_to_disk(rec_len - name_len);
+ entry->rec_len = tux_rec_len_to_disk(name_len);
+ entry = newent;
+ }
+ entry->name_len = dentry->d_name.len;
+ memcpy(entry->name, dentry->d_name.name, dentry->d_name.len);
+ entry->inum = to_be_u32(tux_inode(inode)->inum);
+ //FIXME I may have the mode (S_IFDIR & S_IFMT) wrong
+ entry->type = tux_type_by_mode[(S_IFDIR & S_IFMT) >> STAT_SHIFT];
+ dir->i_mtime = dir->i_ctime = gettime();
+ brelse_dirty(buffer);
+ return 0;
+}
+
tux_dirent *tux_find_entry(struct inode *dir, const char *name, int len, struct buffer_head **result)
{
unsigned reclen = TUX_REC_LEN(len);
diff -r 47e5409786d4 user/kernel/namei.c
--- a/user/kernel/namei.c Fri Dec 05 19:24:40 2008 -0800
+++ b/user/kernel/namei.c Sat Dec 06 23:29:47 2008 -0500
@@ -43,6 +43,68 @@
return err;
}
+static int tux3_rename (struct inode * old_dir, struct dentry * old_dentry,
+ struct inode * new_dir, struct dentry * new_dentry )
+{
+ struct inode * old_inode = old_dentry->d_inode;
+ struct inode * new_inode = new_dentry->d_inode;
+ struct buffer_head * old_buffer, * new_buffer;
+ tux_dirent * old_de, *new_de=NULL;
+ int err = -ENOENT;
+
+ old_de =tux_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_buffer);
+ if (!old_dir)
+ goto out;
+
+ if (new_inode) {
+ err = -ENOTEMPTY;
+ if (!tux_dir_is_empty (new_inode))
+ goto out;
+ err = -ENOENT;
+ new_de = tux_find_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_buffer);
+ if (!new_de)
+ goto out;
+ tux_delete_entry (new_buffer, new_de);
+ inode_dec_link_count(new_inode);
+ }
+
+ inode_inc_link_count(old_inode);
+
+
+ err = tux_add_link(new_dentry, old_inode);
+ if (err) {
+ inode_dec_link_count(old_inode);
+ goto out;
+ }
+
+ old_inode->i_ctime = CURRENT_TIME_SEC;
+
+ tux_delete_entry (old_buffer, old_de);
+
+out:
+ return err;
+}
+
+static int tux3_rmdir (struct inode *dir, struct dentry *dentry)
+{
+ struct inode * inode = dentry->d_inode;
+ int err = -ENOTEMPTY;
+ struct buffer_head *buffer;
+ tux_dirent *de;
+ if (tux_dir_is_empty(inode)) {
+ de = tux_find_entry (dir, dentry->d_name.name,
+ dentry->d_name.len, &buffer);
+ err = tux_delete_entry (buffer, de);
+
+ if (!err) {
+ inode->i_size = 0;
+ inode_dec_link_count(inode);
+ inode_dec_link_count(dir);
+ }
+ }
+ return err;
+}
+
const struct file_operations tux_dir_fops = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
@@ -56,9 +118,9 @@
// .unlink = ext3_unlink,
// .symlink = ext3_symlink,
// .mkdir = ext3_mkdir,
-// .rmdir = ext3_rmdir,
+ .rmdir = tux3_rmdir,
// .mknod = ext3_mknod,
-// .rename = ext3_rename,
+ .rename = tux3_rename,
// .setattr = ext3_setattr,
// .setxattr = generic_setxattr,
// .getxattr = generic_getxattr,
diff -r 47e5409786d4 user/kernel/tux3.h
--- a/user/kernel/tux3.h Fri Dec 05 19:24:40 2008 -0800
+++ b/user/kernel/tux3.h Sat Dec 06 23:29:47 2008 -0500
@@ -647,6 +647,8 @@
/* dir.c */
tux_dirent *tux_find_entry(struct inode *dir, const char *name, int len, struct buffer_head **result);
loff_t tux_create_entry(struct inode *dir, const char *name, int len, inum_t inum, unsigned mode);
+int tux_add_link(struct dentry *dentry, struct inode *inode);
+int tux_dir_is_empty(struct inode *dir);
int tux_delete_entry(struct buffer_head *buffer, tux_dirent *entry);
int tux_readdir(struct file *file, void *state, filldir_t filldir);
extern const struct file_operations tux_dir_fops;
_______________________________________________
Tux3 mailing list
[email protected]
http://mailman.tux3.org/cgi-bin/mailman/listinfo/tux3