All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pavel Fedin <sonic.amiga@gmail.com>
To: Phillip Lougher <phillip@lougher.demon.co.uk>
Cc: linux-fsdevel@vger.kernel.org
Subject: [PATCH 9/9] Amiga SmartFileSystem, revision 2
Date: Fri, 13 Feb 2009 09:57:58 +0300	[thread overview]
Message-ID: <437470097.20090213095758@gmail.com> (raw)
In-Reply-To: <4994506C.1000209@lougher.demon.co.uk>

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@amiga.pl>
+ *
+ *
+ * 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 reexecutable */
+#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 {
+       __be32 id;                      /* 4 character id string of this block */
+       __be32 checksum;                /* The checksum */
+       __be32 ownblock;                /* The blocknumber of the block this block is stored at */
+};
+
+/* On-disk "super block", called fsRootBlock */
+
+struct fsRootBlock {
+       struct fsBlockHeader bheader;
+
+       __be16 version;                 /* Version number of the filesystem block structure */
+       __be16 sequencenumber;          /* The Root with the highest sequencenumber is valid */
+
+       __be32 datecreated;             /* Creation date (when first formatted).  Cannot be changed. */
+       u8 bits;                        /* various settings, see defines below. */
+       u8 pad1;
+       u16 pad2;
+
+       u32 reserved1[2];
+
+       __be32 firstbyteh;              /* The first byte of our partition from the start of the */
+       __be32 firstbyte;               /* disk.  firstbyteh = upper 32 bits, firstbyte = lower 32 bits. */
+
+       __be32 lastbyteh;               /* The last byte of our partition, excluding this one. */
+       __be32 lastbyte;
+
+       __be32 totalblocks;             /* size of this partition in blocks */
+       __be32 blocksize;               /* blocksize used */
+
+       u32 reserved2[2];
+       u32 reserved3[8];
+
+       __be32 bitmapbase;              /* location of the bitmap */
+       __be32 adminspacecontainer;     /* location of first adminspace container */
+       __be32 rootobjectcontainer;     /* location of the root objectcontainer */
+       __be32 extentbnoderoot;         /* location of the root of the extentbnode B-tree */
+       __be32 objectnoderoot;          /* location of the root of the objectnode tree */
+
+       u32 reserved4[3];
+};
+
+/* On disk inode, called fsObject */
+
+struct fsObject {
+       __be16 owneruid;
+       __be16 ownergid;
+       __be32 objectnode;
+       __be32 protection;
+
+       union {
+               struct {
+                       __be32 data;
+                       __be32 size;
+               } file;
+
+               struct {
+                       __be32 hashtable;       /* for directories & root, 0 means no hashblock */
+                       __be32 firstdirblock;
+               } dir;
+       } object;
+
+       __be32 datemodified;
+       u8 bits;
+
+       u8 name[0];
+       u8 comment[0];
+};
+
+/* On disk block containging a number of fsObjects */
+
+struct fsObjectContainer {
+       struct fsBlockHeader bheader;
+
+       __be32 parent;
+       __be32 next;
+       __be32 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 {
+       __be32 key;             /* data! */
+       __be32 next;
+       __be32 prev;
+       __be16 blocks;          /* The size in blocks of the region this Extent controls */
+};
+
+struct BNode {
+       __be32 key;
+       __be32 data;
+};
+
+struct BTreeContainer {
+       __be16 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;
+       __be32 parent;
+       __be32 next;
+       __be32 previous;
+       u8 string[0];
+};
+
+/* On disk block with hashtable data */
+
+struct fsHashTable {
+       struct fsBlockHeader bheader;
+       __be32 parent;
+       __be32 hashentry[0];
+};
+
+/* On disk block with node index and some helper structures */
+
+struct fsNodeContainer {
+       struct fsBlockHeader bheader;
+       __be32 nodenumber;
+       __be32 nodes;
+       __be32 node[0];
+};
+
+struct fsNode {
+       __be32 data;
+};
+
+struct fsObjectNode {
+       struct fsNode node;
+       __be32 next;
+       __be16 hash16;
+} __attribute__ ((packed));
+
+/* Some adminspace and bitmap block structures */
+
+struct fsAdminSpace {
+       __be32 space;
+       __be32 bits;            
+/* Set bits are used blocks, bit 31 is the first block in the AdminSpace. */
+};
+
+struct fsAdminSpaceContainer {
+       struct fsBlockHeader bheader;
+
+       __be32 next;
+       __be32 previous;
+
+       u8 bits;
+       u8 pad1;
+       u16 pad2;
+
+       struct fsAdminSpace adminspace[0];
+};
+
+struct fsBitmap {
+       struct fsBlockHeader bheader;
+
+       __be32 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 {
+       __be32 deletedblocks;           /* Amount in blocks which deleted files consume. */
+       __be32 deletedfiles;            /* Number of deleted files in recycled. */
+       __be32 freeblocks;              /* Cached number of free blocks on disk. */
+
+       __be32 datecreated;
+
+       __be32 lastallocatedblock;      /* Block which was most recently allocated */
+       __be32 lastallocatedadminspace; /* AdminSpaceContainer which most recently was used to allocate a block */
+       __be32 lastallocatedextentnode; /* ExtentNode which was most recently created */
+       __be32 lastallocatedobjectnode; /* ObjectNode which was most recently created */
+
+       __be32 rovingpointer;
+};
+
+#endif


      parent reply	other threads:[~2009-02-13  6:58 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-09 13:18 Corrupted ASFS patch Pavel Fedin
2009-02-09 13:31 ` maximilian attems
2009-02-12  8:24   ` Re[2]: " Pavel Fedin
2009-02-12  9:42     ` Phillip Lougher
2009-02-12 10:52       ` Re[2]: " Pavel Fedin
2009-02-12 16:38         ` Phillip Lougher
2009-02-13  6:53           ` [PATCH 1/9] Amiga SmartFileSystem, revision 2 Pavel Fedin
2009-02-13  6:54           ` [PATCH 2/9] " Pavel Fedin
2009-02-13  6:55           ` [PATCH 3/9] " Pavel Fedin
2009-02-13  6:55           ` [PATCH 4/9] " Pavel Fedin
2009-02-13  6:56           ` [PATCH 5/9] " Pavel Fedin
2009-02-13  6:56           ` [PATCH 6/9] " Pavel Fedin
2009-02-13  6:56           ` [PATCH 7/9] " Pavel Fedin
2009-02-13  6:57           ` [PATCH 8/9] " Pavel Fedin
2009-02-13  6:57           ` Pavel Fedin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=437470097.20090213095758@gmail.com \
    --to=sonic.amiga@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=phillip@lougher.demon.co.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.