[PATCH 9/9] Amiga SmartFileSystem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



diff -ruN linux-source-2.6.24.orig/fs/asfs/symlink.c
linux-source-2.6.24/fs/asfs/symlink.c
--- linux-source-2.6.24.orig/fs/asfs/symlink.c  1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/symlink.c       2008-12-14
23:05:05.000000000 +0300
@@ -0,0 +1,247 @@
+/*
+ *
+ * Amiga Smart File System, Linux implementation
+ * version: 1.0beta12
+ *
+ * Copyright (C) 2003,2004,2005,2006  Marek 'March' Szyprowski <marek@xxxxxxxx>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/pagemap.h>
+#include <linux/nls.h>
+#include "asfs_fs.h"
+
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+int asfs_symlink_readpage(struct file *file, struct page *page)
+{
+       struct buffer_head *bh;
+       struct fsSoftLink *slinkcont;
+       struct inode *inode = page->mapping->host;
+       struct super_block *sb = inode->i_sb;
+       struct nls_table *nls_io = ASFS_SB(sb)->nls_io;
+       struct nls_table *nls_disk = ASFS_SB(sb)->nls_disk;
+       char *link = kmap(page);
+       int i = 0, j = 0;
+       char c, lc = 0, *prefix, *lf, *p;
+       wchar_t uni;
+       int clen;
+
+       asfs_debug("asfs_read_symlink from node %d\n", (int)inode->i_ino);
+
+       if (!(bh = asfs_breadcheck(sb, ASFS_I(inode)->firstblock,
ASFS_SOFTLINK_ID))) {
+               SetPageError(page);
+               kunmap(page);
+               unlock_page(page);
+               return -EIO;
+       }
+       slinkcont = (struct fsSoftLink *) bh->b_data;
+
+       lf = slinkcont->string;
+       prefix = ASFS_SB(sb)->prefix ? ASFS_SB(sb)->prefix : "/";
+
+       asfs_debug("asfs_read_symlink: link target %s\n", lf);
+
+       if ((p = strchr(lf,':'))) {     /* Handle assign or volume name */
+               if (ASFS_SB(sb)->root_volume &&
+                   strncmp(lf, ASFS_SB(sb)->root_volume,
strlen(ASFS_SB(sb)->root_volume)) == 0) {
+                       /* global root volume name found */
+                       link[i++] = '/';
+                       lf = p+1;
+               } else {
+                       /* adding volume prefix */
+                       while (i < 1023 && (c = prefix[i]))
+                               link[i++] = c;
+                       while (i < 1023 && lf[j] != ':')
+                       {
+                               c = lf[j++];
+                               if (ASFS_SB(sb)->flags & ASFS_VOL_LOWERCASE)
+                                       c = asfs_lowerchar(c);
+                               if (nls_io)
+                               {
+                                       clen = nls_disk->char2uni(&c, 1, &uni);
+                                       if (clen>0) {
+                                               clen =
nls_io->uni2char(uni, &link[i], NLS_MAX_CHARSET_SIZE);
+                                               if (clen>0)
+                                                       i += clen;
+                                       }
+                                       if (clen<0)
+                                               link[i++] = '?';
+                               } else
+                                       link[i++] = c;
+                       }
+                       if (i < 1023)
+                               link[i++] = '/';
+                       j++;
+               }
+               lc = '/';
+       }
+
+       while (i < 1023 && (c = lf[j])) {
+               if (c == '/' && lc == '/' && i < 1020) {        /* parent dir */
+                       link[i++] = '.';
+                       link[i++] = '.';
+               }
+               lc = c;
+               if (nls_io)
+               {
+                       clen = nls_disk->char2uni(&c, 1, &uni);
+                       if (clen>0) {
+                               clen = nls_io->uni2char(uni, &link[i],
NLS_MAX_CHARSET_SIZE);
+                               if (clen>0)
+                                       i += clen;
+                       }
+                       if (clen<0)
+                               link[i++] = '?';
+               } else
+                       link[i++] = c;
+               j++;
+       }
+       link[i] = '\0';
+
+       SetPageUptodate(page);
+       kunmap(page);
+       unlock_page(page);
+       asfs_brelse(bh);
+       return 0;
+}
+
+#ifdef CONFIG_ASFS_RW
+
+int asfs_write_symlink(struct inode *symfile, const char *symname)
+{
+       struct super_block *sb = symfile->i_sb;
+       struct buffer_head *bh;
+       struct fsSoftLink *slinkcont;
+       struct nls_table *nls_io = ASFS_SB(sb)->nls_io;
+       struct nls_table *nls_disk = ASFS_SB(sb)->nls_disk;
+       char *p, c, lc;
+       int i, maxlen, pflen;
+       wchar_t uni;
+       int clen, blen;
+
+       asfs_debug("asfs_write_symlink %s to node %d\n", symname,
(int)symfile->i_ino);
+
+       if (!(bh = asfs_breadcheck(sb, ASFS_I(symfile)->firstblock,
ASFS_SOFTLINK_ID))) {
+               return -EIO;
+       }
+       slinkcont = (struct fsSoftLink *) bh->b_data;
+
+       /* translating symlink target path */
+
+       maxlen = sb->s_blocksize - sizeof(struct fsSoftLink) - 2;
+       i  = 0;
+       p  = slinkcont->string;
+       lc = '/';
+
+       if (*symname == '/') {
+               while (*symname == '/')
+                       symname++;
+               if (ASFS_SB(sb)->prefix &&
+                   strncmp(symname-1, ASFS_SB(sb)->prefix, (pflen =
strlen(ASFS_SB(sb)->prefix))) == 0) {
+                       /* found volume prefix, ommiting it */
+                       symname += pflen;
+                       blen = strlen(symname);
+                       while (*symname != '/' && *symname != '\0') {
+                               if (nls_io) {
+                                       clen =
nls_io->char2uni(symname, blen, &uni);
+                                       if (clen>0) {
+                                               symname += clen;
+                                               blen -= clen;
+                                               clen =
nls_disk->uni2char(uni, p, NLS_MAX_CHARSET_SIZE);
+                                               if (clen>0)
+                                                       p += clen;
+                                       }
+                                       else
+                                       {
+                                               symname++;
+                                               blen--;
+                                       }
+                                       if (clen<0)
+                                               *p++ = '?';
+                               } else {
+                                       *p++ = *symname++;
+                               }
+                               i++;
+                       }
+                       symname++;
+                       *p++ = ':';
+               } else if (ASFS_SB(sb)->root_volume) {  /* adding root
volume name */
+                       while (ASFS_SB(sb)->root_volume[i])
+                               *p++ = ASFS_SB(sb)->root_volume[i++];
+                       *p++ = ':';
+               } else {        /* do nothing */
+                       *p++ = '/';
+               }
+               i++;
+       }
+
+       blen = strlen(symname);
+       while (i < maxlen && (c = *symname)) {
+               if (c == '.' && lc == '/' && symname[1] == '.' &&
symname[2] == '/') {
+                       *p++ = '/';
+                       i++;
+                       symname += 3;
+                       blen -= 3;
+                       lc = '/';
+               } else if (c == '.' && lc == '/' && symname[1] == '/') {
+                       symname += 2;
+                       blen -= 2;
+                       lc = '/';
+               } else {
+                       if (nls_io) {
+                               clen = nls_io->char2uni(symname, blen, &uni);
+                               if (clen>0) {
+                                       symname += clen;
+                                       blen -= clen;
+                                       clen = nls_disk->uni2char(uni,
p, NLS_MAX_CHARSET_SIZE);
+                                       if (clen>0)
+                                               lc = *p;
+                                       p += clen;
+                               } else {
+                                       symname++;
+                                       blen--;
+                               }
+                               if (clen<0) {
+                                       *p++ = '?';
+                                       lc = '?';
+                               }
+                       } else {
+                               *p++ = c;
+                               lc = *p;
+                               symname++;
+                               blen--;
+                       }
+                       i++;
+               }
+               if (lc == '/')
+                       while (*symname == '/')
+                       {
+                               symname++;
+                               blen--;
+                       }
+       }
+       *p = 0;
+
+       asfs_debug("asfs_write_symlink: saved %s\n", slinkcont->string);
+
+       asfs_bstore(sb, bh);
+       asfs_brelse(bh);
+
+       return 0;
+}
+
+#endif
diff -ruN linux-source-2.6.24.orig/fs/Kconfig linux-source-2.6.24/fs/Kconfig
--- linux-source-2.6.24.orig/fs/Kconfig 2008-01-25 01:58:37.000000000 +0300
+++ linux-source-2.6.24/fs/Kconfig      2008-12-14 23:05:05.000000000 +0300
@@ -1105,6 +1105,53 @@
          To compile this file system support as a module, choose M here: the
          module will be called ecryptfs.

+config ASFS_FS
+       tristate "Amiga SFS file system support (EXPERIMENTAL)"
+       select NLS
+       depends on EXPERIMENTAL
+       help
+
+         The Amiga Smart FileSystem (SFS) is the file system used on hard
+         disks by Amiga(tm) and MorphOS(tm) systems.  Say Y if you want
+         to be able to read files from an Amiga SFS partition on your hard
+         drive.
+
+         For more information read <file:Documentation/filesystems/asfs.txt>
+
+         To compile this file system support as a module, choose M here: the
+         module will be called asfs.
+
+         If unsure, say N.
+
+config ASFS_DEFAULT_CODEPAGE
+       string "Default codepage for SFS"
+       depends on ASFS_FS
+       default ""
+       help
+         This option should be set to the codepage of your SFS filesystems.
+         It can be overridden with the 'codepage' mount option. Leave it blank
+         or enter 'none' to disable filename converting.
+
+         Use full codepage name (for example 'cp1251' instead of '1251') here,
+         this allows to specify any character set, not only numbered one (like
+         'iso8859-2').
+
+         If unsure, leave it blank.
+
+config ASFS_RW
+       bool "Amiga SFS write support (DANGEROUS)"
+       depends on ASFS_FS
+       help
+
+         If you say Y here, you will be able to write to ASFS file
+         systems as well as read from them. The read-write support in ASFS
+         is in beta stage. This means that useing it to write files to SFS
+         partitions is DANGEROUS and COULD corrupt the filesystem.
+
+         For more information read <file:Documentation/filesystems/asfs.txt>
+
+         If unsure, say N.
+
 config HFS_FS
        tristate "Apple Macintosh file system support (EXPERIMENTAL)"
        depends on BLOCK && EXPERIMENTAL
diff -ruN linux-source-2.6.24.orig/fs/Makefile linux-source-2.6.24/fs/Makefile
--- linux-source-2.6.24.orig/fs/Makefile        2008-01-25
01:58:37.000000000 +0300
+++ linux-source-2.6.24/fs/Makefile     2008-12-14 23:05:05.000000000 +0300
@@ -100,6 +100,7 @@
 obj-$(CONFIG_EFS_FS)           += efs/
 obj-$(CONFIG_JFFS2_FS)         += jffs2/
 obj-$(CONFIG_AFFS_FS)          += affs/
+obj-$(CONFIG_ASFS_FS)          += asfs/
 obj-$(CONFIG_ROMFS_FS)         += romfs/
 obj-$(CONFIG_QNX4FS_FS)                += qnx4/
 obj-$(CONFIG_AUTOFS_FS)                += autofs/
diff -ruN linux-source-2.6.24.orig/include/linux/amigasfs.h
linux-source-2.6.24/include/linux/amigasfs.h
--- linux-source-2.6.24.orig/include/linux/amigasfs.h   1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/include/linux/amigasfs.h        2008-12-14
23:05:05.000000000 +0300
@@ -0,0 +1,276 @@
+#ifndef __LINUX_AMIGASFS_H
+#define __LINUX_AMIGASFS_H
+
+#include <linux/types.h>
+
+/* some helper macros... */
+#define ASFS_MAKE_ID(a,b,c,d)
(((a)&0xff)<<24|((b)&0xff)<<16|((c)&0xff)<<8|((d)&0xff))
+
+/* Amiga SFS block IDs */
+#define ASFS_ROOTID                 ASFS_MAKE_ID('S','F','S','\0')
+#define ASFS_OBJECTCONTAINER_ID     ASFS_MAKE_ID('O','B','J','C')
+#define ASFS_BNODECONTAINER_ID      ASFS_MAKE_ID('B','N','D','C')
+#define ASFS_NODECONTAINER_ID       ASFS_MAKE_ID('N','D','C',' ')
+#define ASFS_HASHTABLE_ID           ASFS_MAKE_ID('H','T','A','B')
+#define ASFS_SOFTLINK_ID            ASFS_MAKE_ID('S','L','N','K')
+#define ASFS_ADMINSPACECONTAINER_ID ASFS_MAKE_ID('A','D','M','C')
+#define ASFS_BITMAP_ID              ASFS_MAKE_ID('B','T','M','P')
+#define ASFS_TRANSACTIONFAILURE_ID  ASFS_MAKE_ID('T','R','F','A')
+
+/* Amiga SFS defines and magic values */
+
+#define ASFS_MAGIC 0xa0ff
+#define ASFS_MAXFN (105u)
+#define ASFS_MAXFILESIZE 0x8FFFFFFE
+
+#define ASFS_STRUCTURE_VERISON (3)
+#define ASFS_BLCKFACCURACY     (5)
+
+#define ASFS_ROOTBITS_CASESENSITIVE (128)
+#define ASFS_READONLY (512)
+#define ASFS_VOL_LOWERCASE (1024)
+
+#define ASFS_ROOTNODE   (1)
+#define ASFS_RECYCLEDNODE (2)
+
+#define OTYPE_HIDDEN      (1)
+#define OTYPE_HARDLINK    (32)
+#define OTYPE_LINK        (64)
+#define OTYPE_DIR         (128)
+
+#define MSB_MASK (1ul << 31)
+
+#define NODE_STRUCT_SIZE (10)  /* (sizeof(struct fsObjectNode)) */
+#define NODECONT_BLOCK_COUNT ((sb->s_blocksize - sizeof(struct
fsNodeContainer)) / sizeof(u32))
+
+#define ASFS_ALWAYSFREE (16)           /* keep this amount of blocks free */
+
+#define ASFS_BLOCKCHUNKS (16)          /* try to allocate this number
of blocks in one request */
+
+#ifndef TRUE
+#define TRUE           1
+#endif
+#ifndef FALSE
+#define FALSE          0
+#endif
+
+/* amigados protection bits */
+
+#define FIBB_SCRIPT    6       /* program is a script (execute) file */
+#define FIBB_PURE      5       /* program is reentrant and rexecutable */
+#define FIBB_ARCHIVE   4       /* cleared whenever file is changed */
+#define FIBB_READ      3       /* ignored by old filesystem */
+#define FIBB_WRITE     2       /* ignored by old filesystem */
+#define FIBB_EXECUTE   1       /* ignored by system, used by Shell */
+#define FIBB_DELETE    0       /* prevent file from being deleted */
+
+#define FIBF_SCRIPT    (1<<FIBB_SCRIPT)
+#define FIBF_PURE      (1<<FIBB_PURE)
+#define FIBF_ARCHIVE   (1<<FIBB_ARCHIVE)
+#define FIBF_READ      (1<<FIBB_READ)
+#define FIBF_WRITE     (1<<FIBB_WRITE)
+#define FIBF_EXECUTE   (1<<FIBB_EXECUTE)
+#define FIBF_DELETE    (1<<FIBB_DELETE)
+
+/* name hashing macro */
+
+#define HASHCHAIN(x) (u16)(x % (u16)(((sb->s_blocksize) -
sizeof(struct fsHashTable))>>2))
+
+/* Each block has its own header with checksum and id, its called
fsBlockHeader */
+
+struct fsBlockHeader {
+       u32 id;                 /* 4 character id string of this block */
+       u32 checksum;           /* The checksum */
+       u32 ownblock;           /* The blocknumber of the block this
block is stored at */
+};
+
+/* On-disk "super block", called fsRootBlock */
+
+struct fsRootBlock {
+       struct fsBlockHeader bheader;
+
+       u16 version;            /* Version number of the filesystem
block structure */
+       u16 sequencenumber;     /* The Root with the highest
sequencenumber is valid */
+
+       u32 datecreated;        /* Creation date (when first
formatted).  Cannot be changed. */
+       u8 bits;                /* various settings, see defines below. */
+       u8 pad1;
+       u16 pad2;
+
+       u32 reserved1[2];
+
+       u32 firstbyteh;         /* The first byte of our partition
from the start of the */
+       u32 firstbyte;          /* disk.  firstbyteh = upper 32 bits,
firstbyte = lower 32 bits. */
+
+       u32 lastbyteh;          /* The last byte of our partition,
excluding this one. */
+       u32 lastbyte;
+
+       u32 totalblocks;        /* size of this partition in blocks */
+       u32 blocksize;          /* blocksize used */
+
+       u32 reserved2[2];
+       u32 reserved3[8];
+
+       u32 bitmapbase;         /* location of the bitmap */
+       u32 adminspacecontainer;        /* location of first
adminspace container */
+       u32 rootobjectcontainer;        /* location of the root
objectcontainer */
+       u32 extentbnoderoot;    /* location of the root of the
extentbnode B-tree */
+       u32 objectnoderoot;     /* location of the root of the
objectnode tree */
+
+       u32 reserved4[3];
+};
+
+/* On disk inode, called fsObject */
+
+struct fsObject {
+       u16 owneruid;
+       u16 ownergid;
+       u32 objectnode;
+       u32 protection;
+
+       union {
+               struct {
+                       u32 data;
+                       u32 size;
+               } file;
+
+               struct {
+                       u32 hashtable;  /* for directories & root, 0
means no hashblock */
+                       u32 firstdirblock;
+               } dir;
+       } object;
+
+       u32 datemodified;
+       u8 bits;
+
+       u8 name[0];
+       u8 comment[0];
+};
+
+/* On disk block containging a number of fsObjects */
+
+struct fsObjectContainer {
+       struct fsBlockHeader bheader;
+
+       u32 parent;
+       u32 next;
+       u32 previous;           /* 0 for the first block in the
directory chain */
+
+       struct fsObject object[0];
+};
+
+/* BTree structures, used to collect file data position on disk */
+
+struct fsExtentBNode {
+       u32 key;                /* data! */
+       u32 next;
+       u32 prev;
+       u16 blocks;             /* The size in blocks of the region
this Extent controls */
+};
+
+struct BNode {
+       u32 key;
+       u32 data;
+};
+
+struct BTreeContainer {
+       u16 nodecount;
+       u8 isleaf;
+       u8 nodesize;            /* Must be a multiple of 2 */
+
+       struct BNode bnode[0];
+};
+
+/* On disk block with BTreeContainer */
+
+struct fsBNodeContainer {
+       struct fsBlockHeader bheader;
+       struct BTreeContainer btc;
+};
+
+/* On disk block  with soft link data */
+
+struct fsSoftLink {
+       struct fsBlockHeader bheader;
+       u32 parent;
+       u32 next;
+       u32 previous;
+       u8 string[0];
+};
+
+/* On disk block with hashtable data */
+
+struct fsHashTable {
+       struct fsBlockHeader bheader;
+       u32 parent;
+       u32 hashentry[0];
+};
+
+/* On disk block with node index and some helper structures */
+
+struct fsNodeContainer {
+       struct fsBlockHeader bheader;
+       u32 nodenumber;
+       u32 nodes;
+       u32 node[0];
+};
+
+struct fsNode {
+       u32 data;
+};
+
+struct fsObjectNode {
+       struct fsNode node;
+       u32 next;
+       u16 hash16;
+} __attribute__ ((packed));
+
+/* Some adminspace and bitmap block structures */
+
+struct fsAdminSpace {
+       u32 space;
+       u32 bits;
+/* Set bits are used blocks, bit 31 is the first block in the AdminSpace. */
+};
+
+struct fsAdminSpaceContainer {
+       struct fsBlockHeader bheader;
+
+       u32 next;
+       u32 previous;
+
+       u8 bits;
+       u8 pad1;
+       u16 pad2;
+
+       struct fsAdminSpace adminspace[0];
+};
+
+struct fsBitmap {
+       struct fsBlockHeader bheader;
+
+       u32 bitmap[0];
+
+/* Bits are 1 if the block is free, and 0 if full.
+   Bitmap must consist of an integral number of longwords. */
+};
+
+/* The fsRootInfo structure has all kinds of information about the format
+   of the disk. */
+
+struct fsRootInfo {
+       u32 deletedblocks;      /* Amount in blocks which deleted
files consume. */
+       u32 deletedfiles;       /* Number of deleted files in recycled. */
+       u32 freeblocks;         /* Cached number of free blocks on disk. */
+
+       u32 datecreated;
+
+       u32 lastallocatedblock; /* Block which was most recently allocated */
+       u32 lastallocatedadminspace;    /* AdminSpaceContainer which
most recently was used to allocate a block */
+       u32 lastallocatedextentnode;    /* ExtentNode which was most
recently created */
+       u32 lastallocatedobjectnode;    /* ObjectNode which was most
recently created */
+
+       u32 rovingpointer;
+};
+
+#endif
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux