From: Pavel Fedin <sonic.amiga@gmail.com>
To: linux-fsdevel@vger.kernel.org
Subject: [PATCH 9/9] Amiga SmartFileSystem
Date: Fri, 26 Dec 2008 15:07:21 +0300 [thread overview]
Message-ID: <607683472.20081226150721@gmail.com> (raw)
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 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
next reply other threads:[~2009-02-12 8:05 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-26 12:07 Pavel Fedin [this message]
-- strict thread matches above, loose matches on Subject: below --
2009-02-09 6:57 [PATCH 9/9] Amiga SmartFileSystem Pavel Fedin
2009-02-09 9:22 ` Matthew Wilcox
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=607683472.20081226150721@gmail.com \
--to=sonic.amiga@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).