case insensitive, and case in names is preserved. Say Y. You can
disable it at mount time with the -N os2 parameter of ncpmount.
+Lowercase DOS filenames on LONG namespace volume
+CONFIG_NCPFS_SMALLDOS
+ Saying Y here will convert every filename with creator/owner DOS
+ namespace on NetWare servers to lowercase characters as silently
+ kernel does when you mount NetWare file server volumes with DOS
+ namespace without OS2/LONG namespace support. Saying N here will
+ give you these filenames with uppercase characters.
+
+ This is only cosmetic option because of OS2/LONG namespace is
+ case insensitive. The only major reason for this option is
+ backward compatibility when you want to do step from DOS to
+ OS2/LONG namespace support. Long filenames (created by Win95)
+ will not be affected.
+
+ This option does not solve a problem that filenames appear
+ differently in Linux box and in MS environment because of MS
+ does an additional conversions on client side. You can achieve
+ simillar effects enabling ncpfs option "Allow using of Native
+ Language Support" below.
+
Allow mounting of volume subdirectories
CONFIG_NCPFS_MOUNT_SUBDIR
Allows you to mount not only whole servers or whole volumes, but
servers. Do not say Y if security is primary for you because root
can read your session key (from /proc/kcore).
+Allow using of Native Language Support
+CONFIG_NCPFS_NLS
+ Allows you to use codepages and I/O charsets for file name translation
+ between file system on server and input/output. This may be useful,
+ if you want to access to the server with other operating systems,
+ e.g. Windows 95. See also NLS for more Information.
+
+ To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer.
+
+Symbolic links and mode permission bits
+CONFIG_NCPFS_EXTRAS
+ This enables the use of symbolic links and an execute permission
+ bit on NCPFS. The file server need not have long name space or NFS
+ name space loaded for these to work, they are stored using rarely
+ found combinations of Hidden, System and Shared flags.
+
+ To use the new attributes, you are recommended to use the flags
+ '-f 600 -d 755' on the ncpmount commandline.
+
nls codepage 437
CONFIG_NLS_CODEPAGE_437
The Microsoft fat filesystem family can deal with filenames in
[This file is cloned from VesaFB. Thanks go to Gerd Knorr]
-what is matroxfb?
+What is matroxfb?
=================
This is a driver for a graphic framebuffer for Matrox devices on
sync:X - sync. pulse - bit 0 inverts HSYNC polarity, bit 1 VSYNC polarity.
If bit 3 (value 0x08) is set, composite sync instead of HSYNC is
generated. If bit 5 (value 0x20) is set, sync on green is turned on.
+ Do not forget that if you want sync on green, you also probably
+ want composite sync.
Default depends on `vesa'.
depth:X - Bits per pixel: 0=text, 4,8,15,16,24 or 32. Default depends on
`vesa'.
+ current fbset is not able to set 15bpp videomode: you must specify
depth==16 and green.length==5. fbset does not allow you to set
green.length.
- + hardware cursor is available only in accelerated videomodes. Maybe that
- this is misfeature and not feature.
+ text mode uses 6 bit VGA palette instead of 8 bit (one of 262144 colors
instead of one of 16M colors). It is due to hardware limitation of
MilleniumI/II and SVGALib compatibility.
VERSION = 2
PATCHLEVEL = 2
-SUBLEVEL = 6
+SUBLEVEL = 7
EXTRAVERSION =
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
* fixed tick loss calculation in timer_interrupt
* (round system clock to nearest tick instead of truncating)
* fixed algorithm in time_init for getting time from CMOS clock
+ * 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net)
+ * fixed algorithm in do_gettimeofday() for calculating the precise time
+ * from processor cycle counter (now taking lost_ticks into account)
*/
#include <linux/config.h>
#include <linux/errno.h>
void
do_gettimeofday(struct timeval *tv)
{
- unsigned long flags, now, delta_cycles, delta_usec;
+ unsigned long flags, delta_cycles, delta_usec;
unsigned long sec, usec;
+ __u32 now;
+ extern volatile unsigned long lost_ticks; /*kernel/sched.c*/
now = rpcc();
save_and_cli(flags);
* with no clear gain.
*/
- delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625;
+ delta_usec = (delta_cycles * state.scaled_ticks_per_cycle
+ + state.partial_tick
+ + (lost_ticks << FIX_SHIFT) ) * 15625;
delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
+ /* the 'lost_tics' term above implements this:
+ * delta_usec += lost_ticks * (1000000 / HZ);
+ */
+
usec += delta_usec;
if (usec >= 1000000) {
sec += 1;
DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2"),
DEVICE( 3DFX, 3DFX_BANSHEE, "Banshee"),
DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX"),
+ DEVICE( AVM, AVM_A1, "A1 (Fritz)"),
DEVICE( STALLION, STALLION_ECHPCI832,"EasyConnection 8/32"),
DEVICE( STALLION, STALLION_ECHPCI864,"EasyConnection 8/64"),
DEVICE( STALLION, STALLION_EIOPCI,"EasyIO"),
case PCI_VENDOR_ID_O2: return "O2 Micro";
case PCI_VENDOR_ID_3DFX: return "3Dfx";
case PCI_VENDOR_ID_SIGMADES: return "Sigma Designs";
+ case PCI_VENDOR_ID_AVM: return "AVM";
case PCI_VENDOR_ID_CCUBE: return "C-Cube";
case PCI_VENDOR_ID_DIPIX: return "Dipix";
case PCI_VENDOR_ID_STALLION: return "Stallion Technologies";
*
* (c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>
*
- * Version: 1.9 1999/01/04
+ * Version: 1.15 1999/04/19
*
* MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
*
* "Daniel Haun" <haund@usa.net>
* Testing, hardware cursor fixes
*
+ * "Scott Wood" <sawst46+@pitt.edu>
+ * Fixes
+ *
* "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
* Betatesting
*
#define CPMINFO const struct matrox_fb_info* minfo,
#define PMINFO minfo,
-static inline struct matrox_fb_info* mxinfo(struct display* p) {
+static inline struct matrox_fb_info* mxinfo(const struct display* p) {
return (struct matrox_fb_info*)p->fb_info;
}
#define PMINFO
#if 0
-static inline struct matrox_fb_info* mxinfo(struct display* p) {
+static inline struct matrox_fb_info* mxinfo(const struct display* p) {
return &global_mxinfo;
}
#endif
step = ACCESS_FBINFO(devflags.textstep);
offs = yy * p->next_line + xx * step;
- attr = attr_fgcol(p,scr_readw(s)) | (attr_bgcol(p,scr_readw(s)) << 4);
+ attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4);
while (count-- > 0) {
unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8;
if (chr & 0x10000) chr ^= 0x10008;
DBG("initMatrox")
+ if (ACCESS_FBINFO(currcon_display) != p)
+ return;
+ if (p->dispsw && p->conp)
+ fb_con.con_cursor(p->conp, CM_ERASE);
p->dispsw_data = NULL;
if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
if (p->type == FB_TYPE_TEXT) {
for (i = 0; i < 21; i++) {
outTi3026(PMINFO DACseq[i], hw->DACreg[i]);
}
+ if (oldhw) {
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
+ oldhw->DACclk[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+ oldhw->DACclk[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x15);
+ oldhw->DACclk[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+ oldhw->DACclk[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
+ oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+ oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+ }
if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) {
/* agrhh... setting up PLL is very slow on Millenium... */
/* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */
"MGA-G200 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
0, 0,
- DEVF_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
230000,
&vbG200,
"unknown G200 (AGP)"},
}
#ifndef MODULE
+static int __init initialized = 0;
+
__initfunc(void matroxfb_init(void))
{
DBG("matroxfb_init")
-#if defined(CONFIG_FB_OF)
-/* Nothing to do, must be called from offb */
-#else
- matrox_init();
-#endif
+
+ if (!initialized) {
+ initialized = 1;
+ matrox_init();
+ }
}
#if defined(CONFIG_FB_OF)
__initfunc(int matrox_of_init(struct device_node *dp)) {
DBG("matrox_of_init");
- matrox_init();
+
+ if (!initialized) {
+ initialized = 1;
+ matrox_init();
+ }
if (!fb_list) return -ENXIO;
return 0;
}
remove_from_lru_list(bh);
}
-static inline void put_last_lru(struct buffer_head * bh)
-{
- if (bh) {
- struct buffer_head **bhp = &lru_list[bh->b_list];
-
- if (bh == *bhp) {
- *bhp = bh->b_next_free;
- return;
- }
-
- if(bh->b_dev == B_FREE)
- panic("Wrong block for lru list");
-
- /* Add to back of free list. */
- remove_from_lru_list(bh);
- if(!*bhp) {
- *bhp = bh;
- (*bhp)->b_prev_free = bh;
- }
-
- bh->b_next_free = *bhp;
- bh->b_prev_free = (*bhp)->b_prev_free;
- (*bhp)->b_prev_free->b_next_free = bh;
- (*bhp)->b_prev_free = bh;
- }
-}
-
static inline void put_last_free(struct buffer_head * bh)
{
if (bh) {
bh = get_hash_table(dev, block, size);
if (bh) {
if (!buffer_dirty(bh)) {
- if (buffer_uptodate(bh))
- put_last_lru(bh);
bh->b_flushtime = 0;
}
return bh;
return;
}
buf->b_count = 0;
+ buf->b_state = 0;
remove_from_queues(buf);
put_last_free(buf);
}
* Use gfp() for the hash table to decrease TLB misses, use
* SLAB cache for buffer heads.
*/
-void __init buffer_init(void)
+void __init buffer_init(unsigned long memory_size)
{
- int order = 5; /* Currently maximum order.. */
+ int order;
unsigned int nr_hash;
- nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct buffer_head *);
- hash_table = (struct buffer_head **) __get_free_pages(GFP_ATOMIC, order);
+ /* we need to guess at the right sort of size for a buffer cache.
+ the heuristic from working with large databases and getting
+ fsync times (ext2) manageable, is the following */
+
+ memory_size >>= 20;
+ for (order = 5; (1UL << order) < memory_size; order++);
+
+ /* try to allocate something until we get it or we're asking
+ for something that is really too small */
+
+ do {
+ nr_hash = (1UL << order) * PAGE_SIZE /
+ sizeof(struct buffer_head *);
+ hash_table = (struct buffer_head **)
+ __get_free_pages(GFP_ATOMIC, order);
+ } while (hash_table == NULL && --order > 4);
if (!hash_table)
panic("Failed to allocate buffer hash table\n");
EXPORT_SYMBOL(unlock_fat);
EXPORT_SYMBOL(fat_dir_ioctl);
EXPORT_SYMBOL(fat_readpage);
+EXPORT_SYMBOL(fat_is_binary);
int init_fat_fs(void)
{
if(raw_entry->attr & ATTR_SYS)
if (MSDOS_SB(sb)->options.sys_immutable)
inode->i_flags |= S_IMMUTABLE;
- MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(sb)->options.conversion,
- raw_entry->ext);
+ MSDOS_I(inode)->i_binary =
+ fat_is_binary(MSDOS_SB(sb)->options.conversion, raw_entry->ext);
MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
/* this is as close to the truth as we can get ... */
inode->i_blksize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
/*
- * is_binary selects optional text conversion based on the conversion mode and
- * the extension part of the file name.
+ * fat_is_binary selects optional text conversion based on the conversion mode
+ * and the extension part of the file name.
*/
-int is_binary(char conversion,char *extension)
+int fat_is_binary(char conversion,char *extension)
{
char *walk;
fat_cache_inval_inode(old_inode);
old_inode->i_version = ++event;
MSDOS_I(old_inode)->i_binary =
- is_binary(MSDOS_SB(sb)->options.conversion, free_de->ext);
+ fat_is_binary(MSDOS_SB(sb)->options.conversion, free_de->ext);
old_inode->i_ino = free_ino;
fat_mark_buffer_dirty(sb, free_bh, 1);
old_de->name[0] = DELETED_FLAG;
bool ' Clear remove/delete inhibit when needed' CONFIG_NCPFS_STRONG
bool ' Use NFS namespace if available' CONFIG_NCPFS_NFS_NS
bool ' Use LONG (OS/2) namespace if available' CONFIG_NCPFS_OS2_NS
+if [ "$CONFIG_NCPFS_OS2_NS" = "y" ]; then
+ bool ' Lowercase DOS filenames' CONFIG_NCPFS_SMALLDOS
+fi
bool ' Allow mounting of volume subdirectories' CONFIG_NCPFS_MOUNT_SUBDIR
# bool ' NDS interserver authentication support' CONFIG_NCPFS_NDS_DOMAINS
+bool ' Use Native Language Support' CONFIG_NCPFS_NLS
+bool ' Enable symbolic links and execute flags' CONFIG_NCPFS_EXTRAS
O_TARGET := ncpfs.o
O_OBJS := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \
- ncpsign_kernel.o
+ symlink.o ncpsign_kernel.o
M_OBJS := $(O_TARGET)
# If you want debugging output, please uncomment the following line
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified for big endian by J.F. Chadima and David S. Miller
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ * Modified 1998 Wolfram Pienkoss for NLS
*
*/
#include <linux/locks.h>
#include <linux/ncp_fs.h>
+
#include "ncplib_kernel.h"
struct ncp_dirent {
static int ncp_rmdir(struct inode *, struct dentry *);
static int ncp_rename(struct inode *, struct dentry *,
struct inode *, struct dentry *);
-
+#ifdef CONFIG_NCPFS_EXTRAS
+extern int ncp_symlink(struct inode *, struct dentry *, const char *);
+#endif
+
static struct file_operations ncp_dir_operations =
{
NULL, /* lseek - default */
ncp_lookup, /* lookup */
NULL, /* link */
ncp_unlink, /* unlink */
+#ifdef CONFIG_NCPFS_EXTRAS
+ ncp_symlink, /* symlink */
+#else
NULL, /* symlink */
+#endif
ncp_mkdir, /* mkdir */
ncp_rmdir, /* rmdir */
NULL, /* mknod */
}
}
-/* Here we encapsulate the inode number handling that depends upon the
- * mount mode: When we mount a complete server, the memory address of
- * the ncp_inode_info is used as the inode number. When only a single
- * volume is mounted, then the dirEntNum is used as the inode
- * number. As this is unique for the complete volume, this should
- * enable the NFS exportability of a ncpfs-mounted volume.
- */
-
/*
* Generate a unique inode number.
*/
ncp_force_unlink(struct inode *dir, struct dentry* dentry)
{
int res=0x9c,res2;
- struct iattr ia;
+ struct nw_modify_dos_info info;
+ __u32 old_nwattr;
+ struct inode *inode;
+ memset(&info, 0, sizeof(info));
+
/* remove the Read-Only flag on the NW server */
+ inode = dentry->d_inode;
- memset(&ia,0,sizeof(struct iattr));
- ia.ia_mode = dentry->d_inode->i_mode;
- ia.ia_mode |= NCP_SERVER(dir)->m.file_mode & 0222; /* set write bits */
- ia.ia_valid = ATTR_MODE;
-
- res2=ncp_notify_change(dentry, &ia);
- if (res2)
- {
- goto leave_me;
- }
+ old_nwattr = NCP_FINFO(inode)->nwattr;
+ info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
+ res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
+ if (res2)
+ goto leave_me;
/* now try again the delete operation */
-
res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
if (res) /* delete failed, set R bit again */
{
- memset(&ia,0,sizeof(struct iattr));
- ia.ia_mode = dentry->d_inode->i_mode;
- ia.ia_mode &= ~(NCP_SERVER(dir)->m.file_mode & 0222); /* clear write bits */
- ia.ia_valid = ATTR_MODE;
-
- res2=ncp_notify_change(dentry, &ia);
- if (res2)
- {
+ info.attributes = old_nwattr;
+ res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
+ if (res2)
goto leave_me;
- }
}
leave_me:
return(res);
#ifdef CONFIG_NCPFS_STRONG
static int
ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
- struct inode *new_dir, struct dentry* new_dentry, char *_new_name,
- int *done_flag)
+ struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
{
+ struct nw_modify_dos_info info;
int res=0x90,res2;
- struct iattr ia;
+ struct inode *old_inode = old_dentry->d_inode;
+ __u32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
+ __u32 new_nwattr = 0; /* shut compiler warning */
+ int old_nwattr_changed = 0;
+ int new_nwattr_changed = 0;
+ memset(&info, 0, sizeof(info));
+
/* remove the Read-Only flag on the NW server */
- memset(&ia,0,sizeof(struct iattr));
- ia.ia_mode = old_dentry->d_inode->i_mode;
- if (S_ISDIR(ia.ia_mode))
- goto leave_me;
- ia.ia_mode |= NCP_SERVER(old_dir)->m.file_mode & 0222; /* set write bits */
- ia.ia_valid = ATTR_MODE;
-
- res2=ncp_notify_change(old_dentry, &ia);
- if (res2)
- {
- goto leave_me;
- }
-
+ info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+ res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
+ if (!res2)
+ old_nwattr_changed = 1;
+ if (new_dentry && new_dentry->d_inode) {
+ new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
+ info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+ res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
+ if (!res2)
+ new_nwattr_changed = 1;
+ }
/* now try again the rename operation */
- res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
- old_dir, _old_name,
- new_dir, _new_name);
-
- if (!res) {
- ncp_invalid_dir_cache(old_dir);
- ncp_invalid_dir_cache(new_dir);
- d_move(old_dentry,new_dentry);
- *done_flag=1;
-
- if (!old_dentry->d_inode) {
- DPRINTK(KERN_INFO "ncpfs: no inode -- file remains rw\n");
- goto leave_me;
- }
- if ((res2=ncp_lookup_validate(old_dentry))) {
- DPRINTK(KERN_DEBUG "ncpfs: ncp_lookup_validate returned %d\n",res2);
- }
- }
-
- memset(&ia,0,sizeof(struct iattr));
- ia.ia_mode = old_dentry->d_inode->i_mode;
- ia.ia_mode &= ~(NCP_SERVER(old_dentry->d_inode)->m.file_mode & 0222); /* clear write bits */
- ia.ia_valid = ATTR_MODE;
-
- DPRINTK(KERN_INFO "calling ncp_notify_change() with %s/%s\n",
- old_dentry->d_parent->d_name.name,old_dentry->d_name.name);
-
- res2=ncp_notify_change(old_dentry, &ia);
- if (res2)
- {
- printk(KERN_INFO "ncpfs: ncp_notify_change (2) failed: %08x\n",res2);
- /* goto leave_me; */
- }
-
- leave_me:
+ /* but only if something really happened */
+ if (new_nwattr_changed || old_nwattr_changed) {
+ res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
+ old_dir, _old_name,
+ new_dir, _new_name);
+ }
+ if (res)
+ goto leave_me;
+ /* file was successfully renamed, so:
+ do not set attributes on old file - it no longer exists
+ copy attributes from old file to new */
+ new_nwattr_changed = old_nwattr_changed;
+ new_nwattr = old_nwattr;
+ old_nwattr_changed = 0;
+
+leave_me:;
+ if (old_nwattr_changed) {
+ info.attributes = old_nwattr;
+ res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
+ /* ignore errors */
+ }
+ if (new_nwattr_changed) {
+ info.attributes = new_nwattr;
+ res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
+ /* ignore errors */
+ }
return(res);
}
#endif /* CONFIG_NCPFS_STRONG */
printk(KERN_DEBUG "ncp_lookup_validate: %s, len %d\n", __name, len);
#endif
- if (!ncp_preserve_case(dir)) {
- str_lower(__name);
- down_case = 1;
- }
-
/* If the file is in the dir cache, we do not have to ask the
server. */
#endif
if (ncp_is_server_root(dir))
{
- str_upper(__name);
+ io2vol(server, __name, 1);
down_case = 1;
res = ncp_lookup_volume(server, __name,
&(finfo.nw_info.i));
} else
{
- if (!ncp_preserve_case(dir))
- {
- str_upper(__name);
- down_case = 1;
- }
+ down_case = !ncp_preserve_case(dir);
+ io2vol(server, __name, down_case);
res = ncp_obtain_info(server, dir, __name,
&(finfo.nw_info.i));
}
else
printk(KERN_DEBUG "ncp_lookup_validate: found, but dirEntNum changed\n");
#endif
+ vol2io(server, finfo.nw_info.i.entryName,
+ !ncp_preserve_entry_case(dir,
+ finfo.nw_info.i.NSCreator));
ncp_update_inode2(dentry->d_inode, &finfo.nw_info);
}
if (!val) ncp_invalid_dir_cache(dir);
c_last_returned_index = 0;
index = 0;
- if (!ncp_preserve_case(inode)) {
- for (i = 0; i < c_size; i++) {
- str_lower(c_entry[i].i.entryName);
- }
+ for (i = 0; i < c_size; i++)
+ {
+ vol2io(server, c_entry[i].i.entryName,
+ !ncp_preserve_entry_case(inode,
+ c_entry[i].i.NSCreator));
}
}
}
struct dentry* dent;
result = -ENOENT;
- str_upper(server->m.mounted_vol);
+ io2vol(server, server->m.mounted_vol, 1);
if (ncp_lookup_volume(server, server->m.mounted_vol,
&(server->root.finfo.i)) != 0) {
#ifdef NCPFS_PARANOIA
#endif
goto out;
}
- str_lower(server->root.finfo.i.entryName);
+ vol2io(server, server->root.finfo.i.entryName, 1);
dent = server->root_dentry;
if (dent) {
struct inode* ino = dent->d_inode;
printk(KERN_DEBUG "ncp_lookup: %s, len %d\n", __name, len);
#endif
- if (!ncp_preserve_case(dir)) {
- str_lower(__name);
- down_case = 1;
- }
-
/* If the file is in the dir cache, we do not have to ask the
server. */
#endif
if (ncp_is_server_root(dir))
{
- str_upper(__name);
+ io2vol(server, __name, 1);
down_case = 1;
res = ncp_lookup_volume(server, __name,
&(finfo.nw_info.i));
} else
{
- if (!ncp_preserve_case(dir))
- {
- str_upper(__name);
- down_case = 1;
- }
+ down_case = !ncp_preserve_case(dir);
+ io2vol(server, __name, down_case);
res = ncp_obtain_info(server, dir, __name,
&(finfo.nw_info.i));
}
/*
* If we didn't find an entry, make a negative dentry.
*/
- if (res != 0)
+ if (res != 0) {
goto add_entry;
+ } else vol2io(server, finfo.nw_info.i.entryName,
+ ncp_preserve_entry_case(dir,
+ finfo.nw_info.i.NSCreator));
}
/*
goto out;
}
-static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
+int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
+ int attributes)
{
int error, result;
struct ncpfs_inode_info finfo;
__u8 _name[dentry->d_name.len + 1];
-
+
#ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_create: creating %s/%s, mode=%x\n",
+printk(KERN_DEBUG "ncp_create_new: creating %s/%s, mode=%x\n",
dentry->d_parent->d_name.name, dentry->d_name.name, mode);
#endif
if (!dir || !S_ISDIR(dir->i_mode)) {
- printk(KERN_WARNING "ncp_create: inode is NULL or not a directory\n");
+ printk(KERN_WARNING "ncp_create_new: inode is NULL or not a directory\n");
return -ENOENT;
}
error = -EIO;
strncpy(_name, dentry->d_name.name, dentry->d_name.len);
_name[dentry->d_name.len] = '\0';
- if (!ncp_preserve_case(dir)) {
- str_upper(_name);
- }
+ io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir));
error = -EACCES;
result = ncp_open_create_file_or_subdir(NCP_SERVER(dir), dir, _name,
OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
- 0, AR_READ | AR_WRITE, &finfo.nw_info);
+ attributes, AR_READ | AR_WRITE, &finfo.nw_info);
if (!result) {
finfo.nw_info.access = O_RDWR;
error = ncp_instantiate(dir, dentry, &finfo);
return error;
}
+static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+ return ncp_create_new(dir, dentry, mode, 0);
+}
+
static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
int error;
strncpy(_name, dentry->d_name.name, dentry->d_name.len);
_name[dentry->d_name.len] = '\0';
- if (!ncp_preserve_case(dir)) {
- str_upper(_name);
- }
+ io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir));
error = -EACCES;
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), dir, _name,
strncpy(_name, dentry->d_name.name, dentry->d_name.len);
_name[dentry->d_name.len] = '\0';
- if (!ncp_preserve_case(dir))
- {
- str_upper(_name);
- }
- error = -EACCES;
+ io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir));
result = ncp_del_file_or_subdir(NCP_SERVER(dir), dir, _name);
- if (!result)
- {
- ncp_invalid_dir_cache(dir);
- error = 0;
- }
+ switch (result) {
+ case 0x00:
+ ncp_invalid_dir_cache(dir);
+ error = 0;
+ break;
+ case 0x85: /* unauthorized to delete file */
+ case 0x8A: /* unauthorized to delete file */
+ error = -EACCES;
+ break;
+ case 0x8F:
+ case 0x90: /* read only */
+ error = -EPERM;
+ break;
+ case 0x9F: /* in use by another client */
+ error = -EBUSY;
+ break;
+ case 0xA0: /* directory not empty */
+ error = -ENOTEMPTY;
+ break;
+ case 0xFF: /* someone deleted file */
+ error = -ENOENT;
+ break;
+ default:
+ error = -EACCES;
+ break;
+ }
out:
return error;
}
error = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
#ifdef CONFIG_NCPFS_STRONG
+ /* 9C is Invalid path.. It should be 8F, 90 - read only, but
+ it is not :-( */
if (error == 0x9C && NCP_SERVER(dir)->m.flags & NCP_MOUNT_STRONG) { /* R/O */
error = ncp_force_unlink(dir, dentry);
}
#endif
- if (!error) {
- DPRINTK(KERN_DEBUG "ncp: removed %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
- ncp_invalid_dir_cache(dir);
- d_delete(dentry);
- } else if (error == 0xFF) {
- error = -ENOENT;
- } else {
- error = -EACCES;
+ switch (error) {
+ case 0x00:
+ DPRINTK(KERN_DEBUG "ncp: removed %s/%s\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+ ncp_invalid_dir_cache(dir);
+ d_delete(dentry);
+ break;
+ case 0x85:
+ case 0x8A:
+ error = -EACCES;
+ break;
+ case 0x8D: /* some files in use */
+ case 0x8E: /* all files in use */
+ error = -EBUSY;
+ break;
+ case 0x8F: /* some read only */
+ case 0x90: /* all read only */
+ case 0x9C: /* !!! returned when in-use or read-only by NW4 */
+ error = -EPERM;
+ break;
+ case 0xFF:
+ error = -ENOENT;
+ break;
+ default:
+ error = -EACCES;
+ break;
}
out:
{
int old_len = old_dentry->d_name.len;
int new_len = new_dentry->d_name.len;
- int error, done_flag=0;
+ int error;
char _old_name[old_dentry->d_name.len + 1];
char _new_name[new_dentry->d_name.len + 1];
strncpy(_old_name, old_dentry->d_name.name, old_len);
_old_name[old_len] = '\0';
- if (!ncp_preserve_case(old_dir)) {
- str_upper(_old_name);
- }
+ io2vol(NCP_SERVER(old_dir), _old_name, !ncp_preserve_case(old_dir));
strncpy(_new_name, new_dentry->d_name.name, new_len);
_new_name[new_len] = '\0';
- if (!ncp_preserve_case(new_dir)) {
- str_upper(_new_name);
- }
+ io2vol(NCP_SERVER(new_dir), _new_name, !ncp_preserve_case(new_dir));
error = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
old_dir, _old_name,
new_dir, _new_name);
#ifdef CONFIG_NCPFS_STRONG
- if (error == 0x90 && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */
+ if ((error == 0x90 || error == -EACCES) && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */
error = ncp_force_rename(old_dir, old_dentry, _old_name,
- new_dir, new_dentry, _new_name,
- &done_flag);
+ new_dir, new_dentry, _new_name);
}
#endif
- if (error == 0)
- {
- if (done_flag == 0) /* if 1, the following already happened */
- { /* in ncp_force_rename() */
- DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n",
+ switch (error) {
+ case 0x00:
+ DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n",
old_dentry->d_name.name,new_dentry->d_name.name);
- ncp_invalid_dir_cache(old_dir);
- ncp_invalid_dir_cache(new_dir);
- if (!S_ISDIR(old_dentry->d_inode->i_mode))
- d_move(old_dentry,new_dentry);
- }
- } else {
- if (error == 0x9E)
+ ncp_invalid_dir_cache(old_dir);
+ ncp_invalid_dir_cache(new_dir);
+ /* d_move(old_dentry, new_dentry); */
+ break;
+ case 0x9E:
error = -ENAMETOOLONG;
- else if (error == 0xFF)
+ break;
+ case 0xFF:
error = -ENOENT;
- else
+ break;
+ default:
error = -EACCES;
+ break;
}
out:
return error;
static int utc2local(int time)
{
- return time - sys_tz.tz_minuteswest * 60 +
- (sys_tz.tz_dsttime ? 3600 : 0);
+ return time - sys_tz.tz_minuteswest * 60;
}
static int local2utc(int time)
{
- return time + sys_tz.tz_minuteswest * 60 -
- (sys_tz.tz_dsttime ? 3600 : 0);
+ return time + sys_tz.tz_minuteswest * 60;
}
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
{
int month, year, secs;
- month = ((date >> 5) & 15) - 1;
+ /* first subtract and mask after that... Otherwise, if
+ date == 0, bad things happen */
+ month = ((date >> 5) - 1) & 15;
year = date >> 9;
secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified for big endian by J.F. Chadima and David S. Miller
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ * Modified 1998 Wolfram Pienkoss for NLS
*
*/
#include <linux/init.h>
#include <linux/ncp_fs.h>
+
#include "ncplib_kernel.h"
static void ncp_read_inode(struct inode *);
};
extern struct dentry_operations ncp_dentry_operations;
+#ifdef CONFIG_NCPFS_EXTRAS
+extern struct inode_operations ncp_symlink_inode_operations;
+extern int ncp_symlink(struct inode*, struct dentry*, const char*);
+#endif
static struct nw_file_info *read_nwinfo = NULL;
static struct semaphore read_sem = MUTEX;
NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
+#ifdef CONFIG_NCPFS_SMALLDOS
+ NCP_FINFO(inode)->origNS = nwinfo->i.NSCreator;
+#endif
+#ifdef CONFIG_NCPFS_STRONG
+ NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
+#endif
NCP_FINFO(inode)->opened = nwinfo->opened;
NCP_FINFO(inode)->access = nwinfo->access;
NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
struct ncp_server *server = NCP_SERVER(inode);
if (!NCP_FINFO(inode)->opened) {
+#ifdef CONFIG_NCPFS_STRONG
+ NCP_FINFO(inode)->nwattr = nwi->attributes;
+#endif
if (nwi->attributes & aDIR) {
inode->i_mode = server->m.dir_mode;
inode->i_size = 512;
} else {
inode->i_mode = server->m.file_mode;
inode->i_size = le32_to_cpu(nwi->dataStreamSize);
+#ifdef CONFIG_NCPFS_EXTRAS
+ if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) && (nwi->attributes & aSHARED)) {
+ switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
+ case aHIDDEN:
+ if (server->m.flags & NCP_MOUNT_SYMLINKS) {
+ if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
+ && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+ inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
+ break;
+ }
+ }
+ /* FALLTHROUGH */
+ case 0:
+ if (server->m.flags & NCP_MOUNT_EXTRAS)
+ inode->i_mode |= 0444;
+ break;
+ case aSYSTEM:
+ if (server->m.flags & NCP_MOUNT_EXTRAS)
+ inode->i_mode |= (inode->i_mode >> 2) & 0111;
+ break;
+ /* case aSYSTEM|aHIDDEN: */
+ default:
+ /* reserved combination */
+ break;
+ }
+ }
+#endif
}
if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
}
} else {
inode->i_mode = server->m.file_mode;
inode->i_size = le32_to_cpu(nwi->dataStreamSize);
+#ifdef CONFIG_NCPFS_EXTRAS
+ if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
+ && (nwi->attributes & aSHARED)) {
+ switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
+ case aHIDDEN:
+ if (server->m.flags & NCP_MOUNT_SYMLINKS) {
+ if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
+ && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+ inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
+ break;
+ }
+ }
+ /* FALLTHROUGH */
+ case 0:
+ if (server->m.flags & NCP_MOUNT_EXTRAS)
+ inode->i_mode |= 0444;
+ break;
+ case aSYSTEM:
+ if (server->m.flags & NCP_MOUNT_EXTRAS)
+ inode->i_mode |= (inode->i_mode >> 2) & 0111;
+ break;
+ /* case aSYSTEM|aHIDDEN: */
+ default:
+ /* reserved combination */
+ break;
+ }
+ }
+#endif
}
if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
inode->i_op = &ncp_file_inode_operations;
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &ncp_dir_inode_operations;
+#ifdef CONFIG_NCPFS_EXTRAS
+ } else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &ncp_symlink_inode_operations;
+#endif
} else {
inode->i_op = NULL;
}
{
struct ncp_inode_info *root = &(server->root);
struct nw_info_struct *i = &(root->finfo.i);
- unsigned short dummy;
DPRINTK(KERN_DEBUG "ncp_init_root: i = %x\n", (int) i);
i->dataStreamSize= 1024;
i->dirEntNum = 0;
i->DosDirNum = 0;
+#ifdef CONFIG_NCPFS_SMALLDOS
+ i->NSCreator = NW_NS_DOS;
+#endif
i->volNumber = NCP_NUMBER_OF_VOLUMES + 1; /* illegal volnum */
- ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
- ncp_date_unix2dos(0, &(i->modifyTime ), &(i->modifyDate));
- ncp_date_unix2dos(0, &(dummy ), &(i->lastAccessDate));
- i->creationTime = le16_to_cpu(i->creationTime);
- i->creationDate = le16_to_cpu(i->creationDate);
- i->modifyTime = le16_to_cpu(i->modifyTime);
- i->modifyDate = le16_to_cpu(i->modifyDate);
- i->lastAccessDate= le16_to_cpu(i->lastAccessDate);
+ /* set dates of mountpoint to Jan 1, 1986; 00:00 */
+ i->creationTime = i->modifyTime = cpu_to_le16(0x0000);
+ i->creationDate = i->modifyDate = i->lastAccessDate = cpu_to_le16(0x0C21);
i->nameLen = 0;
i->entryName[0] = '\0';
lock_super(sb);
- sb->s_flags |= MS_ODD_RENAME; /* This should go away */
-
sb->s_blocksize = 1024; /* Eh... Is this correct? */
sb->s_blocksize_bits = 10;
sb->s_magic = NCP_SUPER_MAGIC;
server->m.dir_mode = (server->m.dir_mode &
(S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
+#ifdef CONFIG_NCPFS_NLS
+ /* load the default NLS charsets */
+ server->nls_charsets.codepage[0] = 0;
+ server->nls_charsets.iocharset[0] = 0;
+ server->nls_vol = load_nls_default();
+ server->nls_io = load_nls_default();
+#endif /* CONFIG_NCPFS_NLS */
+
server->packet_size = NCP_PACKET_SIZE;
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
if (server->packet == NULL)
out_no_packet:
printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
out_free_server:
+#ifdef CONFIG_NCPFS_NLS
+ unload_nls(server->nls_io);
+ unload_nls(server->nls_vol);
+#endif
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
goto out_unlock;
out_no_server:
ncp_disconnect(server);
ncp_unlock_server(server);
+#ifdef CONFIG_NCPFS_NLS
+ /* unload the NLS charsets */
+ if (server->nls_vol)
+ {
+ unload_nls(server->nls_vol);
+ server->nls_vol = NULL;
+ }
+ if (server->nls_io)
+ {
+ unload_nls(server->nls_io);
+ server->nls_io = NULL;
+ }
+#endif /* CONFIG_NCPFS_NLS */
+
fput(server->ncp_filp);
kill_proc(server->m.wdog_pid, SIGTERM, 1);
int result = 0;
int info_mask;
struct nw_modify_dos_info info;
+ struct ncp_server *server;
result = -EIO;
- if (!ncp_conn_valid(NCP_SERVER(inode)))
+
+ server = NCP_SERVER(inode);
+ if ((!server) || !ncp_conn_valid(server))
goto out;
result = inode_change_ok(inode, attr);
result = -EPERM;
if (((attr->ia_valid & ATTR_UID) &&
- (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
+ (attr->ia_uid != server->m.uid)))
goto out;
if (((attr->ia_valid & ATTR_GID) &&
- (attr->ia_gid != NCP_SERVER(inode)->m.gid)))
+ (attr->ia_gid != server->m.gid)))
goto out;
if (((attr->ia_valid & ATTR_MODE) &&
#if 1
if ((attr->ia_valid & ATTR_MODE) != 0)
{
- if (!S_ISREG(inode->i_mode))
+ if (S_ISDIR(inode->i_mode)) {
+ umode_t newmode;
+
+ info_mask |= DM_ATTRIBUTES;
+ newmode = attr->ia_mode;
+ newmode &= NCP_SERVER(inode)->m.dir_mode;
+
+ if (newmode & 0222)
+ info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+ else
+ info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+ } else if (!S_ISREG(inode->i_mode))
{
return -EPERM;
}
else
{
umode_t newmode;
-
+#ifdef CONFIG_NCPFS_EXTRAS
+ int extras;
+
+ extras = server->m.flags & NCP_MOUNT_EXTRAS;
+#endif
info_mask |= DM_ATTRIBUTES;
newmode=attr->ia_mode;
- newmode &= NCP_SERVER(inode)->m.file_mode;
+#ifdef CONFIG_NCPFS_EXTRAS
+ if (!extras)
+#endif
+ newmode &= server->m.file_mode;
if (newmode & 0222) /* any write bit set */
{
- info.attributes &= ~0x60001;
+ info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
}
else
{
- info.attributes |= 0x60001;
+ info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
}
+#ifdef CONFIG_NCPFS_EXTRAS
+ if (extras) {
+ if (newmode & 0111) /* any execute bit set */
+ info.attributes |= aSHARED | aSYSTEM;
+ /* read for group/world and not in default file_mode */
+ else if (newmode & ~server->m.file_mode & 0444)
+ info.attributes |= aSHARED;
+ }
+#endif
}
}
#endif
result = 0;
}
}
+#ifdef CONFIG_NCPFS_STRONG
+ if ((!result) && (info_mask & DM_ATTRIBUTES))
+ NCP_FINFO(inode)->nwattr = info.attributes;
+#endif
}
if ((attr->ia_valid & ATTR_SIZE) != 0) {
int written;
*
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ * Modified 1998 Wolfram Pienkoss for NLS
*
*/
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
+
#include "ncplib_kernel.h"
/* maximum limit for ncp_objectname_ioctl */
return 0;
}
#endif /* CONFIG_NCPFS_NDS_DOMAINS */
+
+#ifdef CONFIG_NCPFS_NLS
+/* Here we are select the iocharset and the codepage for NLS.
+ * Thanks Petr Vandrovec for idea and many hints.
+ */
+ case NCP_IOC_SETCHARSETS:
+ if ( (permission(inode, MAY_WRITE) != 0)
+ && (current->uid != server->m.mounted_uid))
+ {
+ return -EACCES;
+ }
+ if (server->root_setuped) return -EBUSY;
+ {
+ struct ncp_nls_ioctl user;
+ struct nls_table *codepage;
+ struct nls_table *iocharset;
+ struct nls_table *oldset_io;
+ struct nls_table *oldset_cp;
+
+ if (copy_from_user(&user,
+ (struct ncp_nls_ioctl*)arg,
+ sizeof(user))) return -EFAULT;
+
+ codepage = NULL;
+ if (!user.codepage[0]) {
+ codepage = load_nls_default();
+ }
+ else {
+ codepage = load_nls(user.codepage);
+ if (! codepage) {
+ return -EBADRQC;
+ }
+ }
+
+ iocharset = NULL;
+ if (user.iocharset[0] == 0) {
+ iocharset = load_nls_default();
+ }
+ else {
+ iocharset = load_nls(user.iocharset);
+ if (! iocharset) {
+ unload_nls(codepage);
+ return -EBADRQC;
+ }
+ }
+
+ oldset_cp = server->nls_vol;
+ server->nls_vol = codepage;
+ oldset_io = server->nls_io;
+ server->nls_io = iocharset;
+ server->nls_charsets = user;
+ if (oldset_cp) unload_nls(oldset_cp);
+ if (oldset_io) unload_nls(oldset_io);
+ return 0;
+ }
+
+ case NCP_IOC_GETCHARSETS: /* not tested */
+ if (copy_to_user((struct ncp_nls_ioctl*)arg,
+ &(server->nls_charsets),
+ sizeof(server->nls_charsets))) return -EFAULT;
+ return 0;
+#endif /* CONFIG_NCPFS_NLS */
+
default:
return -EINVAL;
}
}
static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
- __u32 dir_base, int have_dir_base, char *path)
+ __u32 dir_base, int have_dir_base,
+ const char *path)
{
ncp_add_byte(server, vol_num);
ncp_add_dword(server, dir_base);
target->nameLen = strlen(volname);
strcpy(target->entryName, volname);
target->attributes = aDIR;
+ /* set dates to Jan 1, 1986 00:00 */
+ target->creationTime = target->modifyTime = cpu_to_le16(0x0000);
+ target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21);
return 0;
}
-int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
- struct inode *dir, __u32 info_mask,
- struct nw_modify_dos_info *info)
+int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
+ struct inode *dir,
+ const char *path,
+ __u32 info_mask,
+ const struct nw_modify_dos_info *info)
{
__u8 volnum = NCP_FINFO(dir)->volNumber;
__u32 dirent = NCP_FINFO(dir)->dirEntNum;
ncp_add_dword(server, info_mask);
ncp_add_mem(server, info, sizeof(*info));
- ncp_add_handle_path(server, volnum, dirent, 1, NULL);
+ ncp_add_handle_path(server, volnum, dirent, 1, path);
result = ncp_request(server, 87);
ncp_unlock_server(server);
return result;
}
+int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
+ struct inode *dir,
+ __u32 info_mask,
+ const struct nw_modify_dos_info *info)
+{
+ return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL,
+ info_mask, info);
+}
+
static int
ncp_DeleteNSEntry(struct ncp_server *server,
__u8 have_dir_base, __u8 volnum, __u32 dirent,
return result;
}
+#ifdef CONFIG_NCPFS_EXTRAS
+int
+ncp_read_kernel(struct ncp_server *server, const char *file_id,
+ __u32 offset, __u16 to_read, char *target, int *bytes_read) {
+ int error;
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+ error = ncp_read(server, file_id, offset, to_read, target, bytes_read);
+ set_fs(old_fs);
+ return error;
+}
+
+int
+ncp_write_kernel(struct ncp_server *server, const char *file_id,
+ __u32 offset, __u16 to_write,
+ const char *source, int *bytes_written) {
+ int error;
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+ error = ncp_write(server, file_id, offset, to_write, source, bytes_written);
+ set_fs(old_fs);
+ return error;
+}
+#endif
+
#ifdef CONFIG_NCPFS_IOCTL_LOCKING
int
ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id,
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified for big endian by J.F. Chadima and David S. Miller
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ * Modified 1998 Wolfram Pienkoss for NLS
*
*/
#include <asm/unaligned.h>
#include <asm/string.h>
+#ifdef CONFIG_NCPFS_NLS
+#include <linux/nls.h>
+#endif
+
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
#include <linux/ncp_fs_sb.h>
int ncp_read(struct ncp_server *, const char *, __u32, __u16, char *, int *);
int ncp_write(struct ncp_server *, const char *, __u32, __u16,
const char *, int *);
+#ifdef CONFIG_NCPFS_EXTRAS
+int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, char *, int *);
+int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16,
+ const char *, int *);
+#endif
int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
struct nw_info_struct *target);
int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *);
int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
- __u32, struct nw_modify_dos_info *info);
+ __u32, const struct nw_modify_dos_info *info);
+int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *,
+ const char* path, __u32, const struct nw_modify_dos_info *info);
int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *);
ncp_mount_subdir(struct ncp_server* server, __u8 volNumber,
__u8 srcNS, __u32 srcDirEntNum);
#endif /* CONFIG_NCPFS_MOUNT_SUBDIR */
+
+#ifdef CONFIG_NCPFS_NLS
+/* This are the NLS conversion routines with inspirations and code parts
+ * from the vfat file system and hints from Petr Vandrovec.
+ */
+
+/*
+ * It should be replaced by charset specifc conversion. Gordon Chaffee
+ * has prepared some things, but I don't know, what he thinks about it.
+ * The conversion tables for the io charsets should be generatable by
+ * Unicode table, shouldn't it? I have written so generation code for it.
+ * The tables for the vendor specific codepages...? Hmm. The Samba sources
+ * contains also any hints.
+ */
+
+#define toupperif(c, u) ((((u) != 0) && ((c) >= 'a') && ((c) <= 'z')) \
+ ? (c)-('a'-'A') : (c))
+#define tolowerif(c, u) ((((u) != 0) && ((c) >= 'A') && ((c) <= 'Z')) \
+ ? (c)-('A'-'a') : (c))
+
+static inline void
+io2vol(struct ncp_server *server, char *name, int case_trans)
+{
+ unsigned char nc;
+ unsigned char *np;
+ unsigned char *up;
+ struct nls_unicode uc;
+ struct nls_table *nls_in;
+ struct nls_table *nls_out;
+
+ nls_in = server->nls_io;
+ nls_out = server->nls_vol;
+ np = name;
+
+ while (*np)
+ {
+ nc = 0;
+ uc = nls_in->charset2uni[toupperif(*np, case_trans)];
+ up = nls_out->page_uni2charset[uc.uni2];
+ if (up != NULL) nc = up[uc.uni1];
+ if (nc != 0) *np = nc;
+ np++;
+ }
+}
+
+static inline void
+vol2io(struct ncp_server *server, char *name, int case_trans)
+{
+ unsigned char nc;
+ unsigned char *np;
+ unsigned char *up;
+ struct nls_unicode uc;
+ struct nls_table *nls_in;
+ struct nls_table *nls_out;
+
+ nls_in = server->nls_vol;
+ nls_out = server->nls_io;
+ np = name;
+
+ while (*np)
+ {
+ nc = 0;
+ uc = nls_in->charset2uni[*np];
+ up = nls_out->page_uni2charset[uc.uni2];
+ if (up != NULL) nc = up[uc.uni1];
+ if (nc == 0) nc = *np;
+ *np = tolowerif(nc, case_trans);
+ np++;
+ }
+}
+
+#else
+
+#define io2vol(S,N,U) if (U) str_upper(N)
+#define vol2io(S,N,U) if (U) str_lower(N)
+
+#endif /* CONFIG_NCPFS_NLS */
+
#endif /* _NCPLIB_H */
+
--- /dev/null
+/*
+ * linux/fs/ncpfs/symlink.c
+ *
+ * Code for allowing symbolic links on NCPFS (i.e. NetWare)
+ * Symbolic links are not supported on native NetWare, so we use an
+ * infrequently-used flag (Sh) and store a two-word magic header in
+ * the file to make sure we don't accidentally use a non-link file
+ * as a link.
+ *
+ * from linux/fs/ext2/symlink.c
+ *
+ * Copyright (C) 1998-99, Frank A. Vorstenbosch
+ *
+ * ncpfs symlink handling code
+ * NLS support (c) 1999 Petr Vandrovec
+ *
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_NCPFS_EXTRAS
+
+#include <asm/uaccess.h>
+#include <asm/segment.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ncp_fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/stat.h>
+#include "ncplib_kernel.h"
+
+
+/* these magic numbers must appear in the symlink file -- this makes it a bit
+ more resilient against the magic attributes being set on random files. */
+
+#define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */
+#define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e)
+
+static int ncp_readlink(struct dentry *, char *, int);
+static struct dentry *ncp_follow_link(struct dentry *, struct dentry *, unsigned int);
+int ncp_create_new(struct inode *dir, struct dentry *dentry,
+ int mode,int attributes);
+
+/*
+ * symlinks can't do much...
+ */
+struct inode_operations ncp_symlink_inode_operations={
+ NULL, /* no file-operations */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ ncp_readlink, /* readlink */
+ ncp_follow_link, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL /* smap */
+};
+
+/* ----- follow a symbolic link ------------------------------------------ */
+
+static struct dentry *ncp_follow_link(struct dentry *dentry,
+ struct dentry *base,
+ unsigned int follow)
+{
+ struct inode *inode=dentry->d_inode;
+ int error, length, cnt;
+ char *link;
+
+#ifdef DEBUG
+ printk("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
+#endif
+
+ if(!S_ISLNK(inode->i_mode)) {
+ dput(base);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if(ncp_make_open(inode,O_RDONLY)) {
+ dput(base);
+ return ERR_PTR(-EIO);
+ }
+
+ for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1, GFP_NFS))==NULL; cnt++) {
+ if (cnt > 10) {
+ dput(base);
+ return ERR_PTR(-EAGAIN); /* -ENOMEM? */
+ }
+ schedule();
+ }
+
+ error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
+ 0,NCP_MAX_SYMLINK_SIZE,link,&length);
+
+ if (error!=0 || length<NCP_MIN_SYMLINK_SIZE ||
+ ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 || ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
+ dput(base);
+ kfree(link);
+ return ERR_PTR(-EIO);
+ }
+
+ link[length]=0;
+
+ vol2io(NCP_SERVER(inode), link+8, 0);
+
+ /* UPDATE_ATIME(inode); */
+ base=lookup_dentry(link+8, base, follow);
+ kfree(link);
+
+ return base;
+}
+
+/* ----- read symbolic link ---------------------------------------------- */
+
+static int ncp_readlink(struct dentry * dentry, char * buffer, int buflen)
+{
+ struct inode *inode=dentry->d_inode;
+ char *link;
+ int length,error;
+
+#ifdef DEBUG
+ printk("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
+#endif
+
+ if(!S_ISLNK(inode->i_mode))
+ return -EINVAL;
+
+ if(ncp_make_open(inode,O_RDONLY))
+ return -EIO;
+
+ if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1,GFP_NFS))==NULL)
+ return -ENOMEM;
+
+ error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
+ 0,NCP_MAX_SYMLINK_SIZE,link,&length);
+
+ if (error!=0 || length < NCP_MIN_SYMLINK_SIZE || buflen < (length-8) ||
+ ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
+ error = -EIO;
+ goto out;
+ }
+
+ link[length] = 0;
+
+ vol2io(NCP_SERVER(inode), link+8, 0);
+
+ error = length - 8;
+ if(copy_to_user(buffer, link+8, error))
+ error = -EFAULT;
+
+out:;
+ kfree(link);
+ return error;
+}
+
+/* ----- create a new symbolic link -------------------------------------- */
+
+int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
+ int i,length;
+ struct inode *inode;
+ char *link;
+
+#ifdef DEBUG
+ printk("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
+#endif
+
+ if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS))
+ return -EPERM; /* EPERM is returned by VFS if symlink procedure does not exist */
+
+ if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE)
+ return -EINVAL;
+
+ if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL)
+ return -ENOMEM;
+
+ if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN)) {
+ kfree(link);
+ return -EIO;
+ }
+
+ inode=dentry->d_inode;
+
+ ((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0;
+ ((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1;
+ memcpy(link+8, symname, length+1); /* including last zero for io2vol */
+
+ /* map to/from server charset, do not touch upper/lower case as
+ symlink can point out of ncp filesystem */
+ io2vol(NCP_SERVER(inode), link+8, 0);
+
+ if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
+ 0, length+8, link, &i) || i!=length+8) {
+ kfree(link);
+ return -EIO;
+ }
+
+ kfree(link);
+ return 0;
+}
+#endif
+
+/* ----- EOF ----- */
dfprintk(VFS, "NFS: nfs_dir_open(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
- return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+ return _nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
}
static ssize_t
goto out_bad;
/* Filehandle matches? */
- if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh)))
- goto out_bad;
+ if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) {
+ if (dentry->d_count < 2 || nfs_revalidate(dentry))
+ goto out_bad;
+ }
/* Ok, remeber that we successfully checked it.. */
nfs_renew_times(dentry);
static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *);
static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry);
+static int nfs_file_open(struct inode *inode, struct file *filp);
static struct file_operations nfs_file_operations = {
NULL, /* lseek - default */
NULL, /* select - default */
NULL, /* ioctl - default */
nfs_file_mmap, /* mmap */
- NULL, /* no special open is needed */
+ nfs_file_open, /* open */
nfs_file_flush, /* flush */
NULL, /* release */
nfs_fsync, /* fsync */
return status;
}
+/*
+ * Open the file.
+ * Just checks the cache is synchronized.
+ */
+static int
+nfs_file_open(struct inode *inode, struct file *filp)
+{
+ struct dentry *dentry = filp->f_dentry;
+
+ return _nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+}
+
+
static ssize_t
nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
{
server->rsize = nfs_block_size(data->rsize, NULL);
server->wsize = nfs_block_size(data->wsize, NULL);
server->flags = data->flags;
+
+ if (data->flags & NFS_MOUNT_NOAC) {
+ data->acregmin = data->acregmax = 0;
+ data->acdirmin = data->acdirmax = 0;
+ }
server->acregmin = data->acregmin*HZ;
server->acregmax = data->acregmax*HZ;
server->acdirmin = data->acdirmin*HZ;
int status = 0;
struct nfs_fattr fattr;
- /* Don't bother revalidating if we've done it recently */
- if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
- goto out;
-
dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
inode->i_ino);
# msdos and Joliet want NLS
if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
- -o "$CONFIG_NTFS_FS" != "n" ]; then
+ -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" ]; then
define_bool CONFIG_NLS y
else
define_bool CONFIG_NLS n
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
:"=m" (ADDR)
- :"ir" (nr));
+ :"Ir" (nr));
}
extern __inline__ void clear_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
:"=m" (ADDR)
- :"ir" (nr));
+ :"Ir" (nr));
}
extern __inline__ void change_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btcl %1,%0"
:"=m" (ADDR)
- :"ir" (nr));
+ :"Ir" (nr));
}
extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"ir" (nr));
+ :"Ir" (nr));
return oldbit;
}
__asm__ __volatile__( LOCK_PREFIX
"btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"ir" (nr));
+ :"Ir" (nr));
return oldbit;
}
__asm__ __volatile__( LOCK_PREFIX
"btcl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"ir" (nr));
+ :"Ir" (nr));
return oldbit;
}
__asm__ __volatile__(
"btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
- :"m" (ADDR),"ir" (nr));
+ :"m" (ADDR),"Ir" (nr));
return oldbit;
}
extern void update_atime (struct inode *inode);
#define UPDATE_ATIME(inode) update_atime (inode)
-extern void buffer_init(void);
+extern void buffer_init(unsigned long);
extern void inode_init(void);
extern void file_table_init(void);
extern void dcache_init(void);
};
/* misc.c */
-extern int is_binary(char conversion,char *extension);
+extern int fat_is_binary(char conversion,char *extension);
extern void lock_fat(struct super_block *sb);
extern void unlock_fat(struct super_block *sb);
extern int fat_add_cluster(struct inode *inode);
*
* Copyright (C) 1995 by Volker Lendecke
* Modified for sparc by J.F. Chadima
+ * Modified for __constant_ntoh by Frank A. Vorstenbosch
*
*/
/* these define the attribute byte as seen by NCP */
#define aRONLY (ntohl(0x01000000))
-#define aHIDDEN (ntohl(0x02000000))
-#define aSYSTEM (ntohl(0x04000000))
+#define aHIDDEN (__constant_ntohl(0x02000000))
+#define aSYSTEM (__constant_ntohl(0x04000000))
#define aEXECUTE (ntohl(0x08000000))
#define aDIR (ntohl(0x10000000))
#define aARCH (ntohl(0x20000000))
+#define aSHARED (ntohl(0x80000000))
+#define aDONTSUBALLOCATE (ntohl(1L<<(11+8)))
+#define aTRANSACTIONAL (ntohl(1L<<(12+8)))
+#define aPURGE (ntohl(1L<<(16-8)))
+#define aRENAMEINHIBIT (ntohl(1L<<(17-8)))
+#define aDELETEINHIBIT (ntohl(1L<<(18-8)))
+#define aDONTCOMPRESS (nothl(1L<<(27-24)))
+
+#define NCP_MIN_SYMLINK_SIZE 8
+#define NCP_MAX_SYMLINK_SIZE 512
#define AR_READ (ntohs(0x0100))
#define AR_WRITE (ntohs(0x0200))
#include <linux/types.h>
#include <linux/ncp_mount.h>
+
+/* NLS charsets by ioctl */
+#define NCP_IOCSNAME_LEN 20
+struct ncp_nls_ioctl
+{
+ unsigned char codepage[NCP_IOCSNAME_LEN+1];
+ unsigned char iocharset[NCP_IOCSNAME_LEN+1];
+};
+
#include <linux/ncp_fs_sb.h>
#include <linux/ncp_fs_i.h>
#define NCP_IOC_GETPRIVATEDATA _IOWR('n', 10, struct ncp_privatedata_ioctl)
#define NCP_IOC_SETPRIVATEDATA _IOR('n', 10, struct ncp_privatedata_ioctl)
+#define NCP_IOC_GETCHARSETS _IOWR('n', 11, struct ncp_nls_ioctl)
+#define NCP_IOC_SETCHARSETS _IOR('n', 11, struct ncp_nls_ioctl)
+
/*
* The packet size to allocate. One page should be enough.
*/
__u32 dirEntNum __attribute__((packed));
__u32 DosDirNum __attribute__((packed));
__u32 volNumber __attribute__((packed));
+#ifdef CONFIG_NCPFS_SMALLDOS
+ __u32 origNS;
+#endif
+#ifdef CONFIG_NCPFS_STRONG
+ __u32 nwattr;
+#endif
int opened;
int access;
__u32 server_file_handle __attribute__((packed));
return server->name_space[NCP_FINFO(inode)->volNumber];
}
-static inline int ncp_preserve_case(struct inode *i)
-{
+static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) {
#if defined(CONFIG_NCPFS_NFS_NS) || defined(CONFIG_NCPFS_OS2_NS)
int ns = ncp_namespace(i);
+#endif
+#if defined(CONFIG_NCPFS_SMALLDOS) && defined(CONFIG_NCPFS_OS2_NS)
+ if ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
+ return 0;
#endif
return
#ifdef CONFIG_NCPFS_OS2_NS
0;
}
+static inline int ncp_preserve_case(struct inode *i)
+{
+ return ncp_preserve_entry_case(i, NW_NS_OS2);
+}
+
static inline int ncp_case_sensitive(struct inode *i)
{
#ifdef CONFIG_NCPFS_NFS_NS
size_t len;
void* data;
} priv;
+
+ struct ncp_nls_ioctl nls_charsets; /* NLS user data */
+ struct nls_table *nls_vol; /* codepage used on volume */
+ struct nls_table *nls_io; /* charset used for input and display */
};
static inline int ncp_conn_valid(struct ncp_server *server)
#define NCP_MOUNT_VERSION 3
/* Values for flags */
-#define NCP_MOUNT_SOFT 0x0001
-#define NCP_MOUNT_INTR 0x0002
-#define NCP_MOUNT_STRONG 0x0004 /* enable delete/rename of r/o files */
-#define NCP_MOUNT_NO_OS2 0x0008
-#define NCP_MOUNT_NO_NFS 0x0010
+#define NCP_MOUNT_SOFT 0x0001
+#define NCP_MOUNT_INTR 0x0002
+#define NCP_MOUNT_STRONG 0x0004 /* enable delete/rename of r/o files */
+#define NCP_MOUNT_NO_OS2 0x0008 /* do not use OS/2 (LONG) namespace */
+#define NCP_MOUNT_NO_NFS 0x0010 /* do not use NFS namespace */
+#define NCP_MOUNT_EXTRAS 0x0020
+#define NCP_MOUNT_SYMLINKS 0x0040 /* enable symlinks */
struct ncp_mount_data {
int version;
#define PAGE_HASH_BITS 12
#define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS)
-#define PAGE_AGE_VALUE 16
-
extern unsigned long page_cache_size; /* # of pages currently in the hash table */
extern struct page * page_hash_table[PAGE_HASH_SIZE];
#define PCI_VENDOR_ID_CCUBE 0x123f
+#define PCI_VENDOR_ID_AVM 0x1244
+#define PCI_DEVICE_ID_AVM_A1 0x0a00
+
#define PCI_VENDOR_ID_DIPIX 0x1246
#define PCI_VENDOR_ID_STALLION 0x124d
filescache_init();
dcache_init();
vma_init();
- buffer_init();
+ buffer_init(memory_end-memory_start);
signals_init();
inode_init();
file_table_init();
for the ring buffers */
#define NR_MEM_LISTS 12
#else
-#define NR_MEM_LISTS 6
+#define NR_MEM_LISTS 10
#endif
/* The start of this MUST match the start of "struct page" */