Import ncpfs 0.17
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* ncp_fs.h
|
||||
* ncp.h
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
|
||||
@@ -42,6 +42,7 @@ struct ncp_fs_info {
|
||||
|
||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
||||
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
||||
#define NCP_IOC_CONN_LOGGED_IN _IO('l', 1)
|
||||
|
||||
#define NCP_GET_FS_INFO_VERSION (1)
|
||||
#define NCP_IOC_GET_FS_INFO _IOWR('i', 1, unsigned char *)
|
||||
@@ -126,9 +127,12 @@ extern struct inode_operations ncp_dir_inode_operations;
|
||||
void ncp_free_inode_info(struct ncp_inode_info *i);
|
||||
void ncp_free_all_inodes(struct ncp_server *server);
|
||||
void ncp_init_root(struct ncp_server *server);
|
||||
int ncp_conn_logged_in(struct ncp_server *server);
|
||||
int ncp_stat_root(struct ncp_server *server);
|
||||
void ncp_init_dir_cache(void);
|
||||
void ncp_invalid_dir_cache(unsigned long ino);
|
||||
void ncp_invalid_dir_cache(struct inode *ino);
|
||||
struct ncp_inode_info *ncp_find_inode(struct inode *inode);
|
||||
ino_t ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info);
|
||||
void ncp_invalidate_all_inodes(struct ncp_server *server);
|
||||
void ncp_free_dir_cache(void);
|
||||
int ncp_date_dos2unix(__u16 time, __u16 date);
|
||||
|
||||
@@ -28,6 +28,7 @@ struct ncp_inode_info {
|
||||
number of references in memory */
|
||||
struct ncp_inode_info *dir;
|
||||
struct ncp_inode_info *next, *prev;
|
||||
struct inode *inode;
|
||||
struct nw_file_info finfo;
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ struct ncp_server {
|
||||
it completely. */
|
||||
|
||||
struct file *ncp_filp; /* File pointer to ncp socket */
|
||||
|
||||
struct file *wdog_filp; /* File pointer to wdog socket */
|
||||
void *data_ready; /* The wdog socket gets a new
|
||||
data_ready callback. We store the
|
||||
@@ -35,7 +34,8 @@ struct ncp_server {
|
||||
|
||||
u8 completion; /* Status message from server */
|
||||
u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
|
||||
requests allowed anymore */
|
||||
requests allowed anymore.
|
||||
Bit 0 = 1 ==> Server is down. */
|
||||
|
||||
int buffer_size; /* Negotiated bufsize */
|
||||
|
||||
@@ -56,6 +56,18 @@ struct ncp_server {
|
||||
char root_path; /* '\0' */
|
||||
};
|
||||
|
||||
static inline int
|
||||
ncp_conn_valid(struct ncp_server *server)
|
||||
{
|
||||
return ((server->conn_status & 0x11) == 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ncp_invalidate_conn(struct ncp_server *server)
|
||||
{
|
||||
server->conn_status |= 0x01;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs_i.h>
|
||||
|
||||
#define NCP_MOUNT_VERSION 1
|
||||
#define NCP_MOUNT_VERSION 2
|
||||
|
||||
#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN)
|
||||
#define NCP_PASSWORD_LEN 20
|
||||
@@ -26,14 +26,14 @@ struct ncp_mount_data {
|
||||
int version;
|
||||
unsigned int ncp_fd; /* The socket to the ncp port */
|
||||
unsigned int wdog_fd; /* Watchdog packets come here */
|
||||
unsigned int message_fd; /* Not used yet, maybe for messages */
|
||||
unsigned int message_fd; /* Message notifications come here */
|
||||
uid_t mounted_uid; /* Who may umount() this filesystem? */
|
||||
|
||||
struct sockaddr_ipx serv_addr;
|
||||
unsigned char server_name[49];
|
||||
unsigned char server_name[NCP_BINDERY_NAME_LEN];
|
||||
|
||||
unsigned char username[NCP_USERNAME_LEN+1];
|
||||
unsigned char password[NCP_PASSWORD_LEN+1];
|
||||
unsigned char mount_point[PATH_MAX+1];
|
||||
unsigned char mounted_vol[NCP_VOLNAME_LEN+1];
|
||||
|
||||
unsigned int time_out; /* How long should I wait after
|
||||
sending a NCP request? */
|
||||
|
||||
@@ -47,7 +47,7 @@ static struct inode *
|
||||
ncp_iget(struct inode *dir, struct nw_file_info *finfo);
|
||||
|
||||
static struct ncp_inode_info *
|
||||
ncp_find_inode(struct inode *dir, const char *name);
|
||||
ncp_find_dir_inode(struct inode *dir, const char *name);
|
||||
|
||||
static int
|
||||
ncp_lookup(struct inode *dir, const char *__name,
|
||||
@@ -102,7 +102,7 @@ static struct file_operations ncp_dir_operations = {
|
||||
NULL, /* write - bad */
|
||||
ncp_readdir, /* readdir */
|
||||
NULL, /* select - default */
|
||||
ncp_ioctl, /* ioctl - default */
|
||||
ncp_ioctl, /* ioctl */
|
||||
NULL, /* mmap */
|
||||
NULL, /* no special open code */
|
||||
NULL, /* no special release code */
|
||||
@@ -129,6 +129,58 @@ struct inode_operations ncp_dir_inode_operations = {
|
||||
};
|
||||
|
||||
|
||||
/* Here we encapsulate the inode number handling that depends upon the
|
||||
* mount mode: When we mount a complete server, the memory address of
|
||||
* the npc_inode_info is used as an inode. When only a single volume
|
||||
* is mounted, then the DosDirNum 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.
|
||||
*/
|
||||
|
||||
static inline int
|
||||
ncp_single_volume(struct ncp_server *server)
|
||||
{
|
||||
return (server->m.mounted_vol[0] != '\0');
|
||||
}
|
||||
|
||||
inline ino_t
|
||||
ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info)
|
||||
{
|
||||
return ncp_single_volume(server)
|
||||
? info->finfo.i.DosDirNum : (ino_t)info;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ncp_is_server_root(struct inode *inode)
|
||||
{
|
||||
struct ncp_server *s = NCP_SERVER(inode);
|
||||
|
||||
return ( (!ncp_single_volume(s))
|
||||
&& (inode->i_ino == ncp_info_ino(s, &(s->root))));
|
||||
}
|
||||
|
||||
struct ncp_inode_info *
|
||||
ncp_find_inode(struct inode *inode)
|
||||
{
|
||||
struct ncp_server *server = NCP_SERVER(inode);
|
||||
struct ncp_inode_info *root = &(server->root);
|
||||
struct ncp_inode_info *this = root;
|
||||
|
||||
ino_t ino = inode->i_ino;
|
||||
|
||||
do
|
||||
{
|
||||
if (ino == ncp_info_ino(server, this))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
this = this->next;
|
||||
}
|
||||
while (this != root);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
|
||||
{
|
||||
@@ -142,6 +194,7 @@ ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
|
||||
all inodes that are in memory. That's why it's enough to index the
|
||||
directory cache by the inode number. */
|
||||
|
||||
static int c_dev = 0;
|
||||
static unsigned long c_ino = 0;
|
||||
static int c_size;
|
||||
static int c_seen_eof;
|
||||
@@ -156,7 +209,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
int index = 0;
|
||||
struct ncp_dirent *entry = NULL;
|
||||
struct ncp_server *server = NCP_SERVER(inode);
|
||||
struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
|
||||
struct ncp_inode_info *dir = NCP_INOP(inode);
|
||||
|
||||
int filldir(struct dirent *dirent,
|
||||
const char *name, int len,
|
||||
@@ -170,9 +223,9 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
return 1;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
|
||||
DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
|
||||
inode->i_ino, c_ino);
|
||||
DPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
|
||||
DPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
|
||||
inode->i_ino, c_ino);
|
||||
|
||||
if (!inode || !S_ISDIR(inode->i_mode))
|
||||
{
|
||||
@@ -180,6 +233,11 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (!ncp_conn_valid(server))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (c_entry == NULL)
|
||||
{
|
||||
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
|
||||
@@ -193,8 +251,9 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
|
||||
if (filp->f_pos == 0)
|
||||
{
|
||||
ncp_invalid_dir_cache(inode->i_ino);
|
||||
if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0)
|
||||
ncp_invalid_dir_cache(inode);
|
||||
if (filldir(dirent,".",1, filp->f_pos,
|
||||
ncp_info_ino(server, dir)) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -204,7 +263,8 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
|
||||
if (filp->f_pos == 1)
|
||||
{
|
||||
if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0)
|
||||
if (filldir(dirent,"..",2, filp->f_pos,
|
||||
ncp_info_ino(server, dir->dir)) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -212,7 +272,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
||||
}
|
||||
|
||||
if (inode->i_ino == c_ino)
|
||||
if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino))
|
||||
{
|
||||
for (i = 0; i < c_size; i++)
|
||||
{
|
||||
@@ -234,7 +294,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
{
|
||||
DDPRINTK("ncp_readdir: Not found in cache.\n");
|
||||
|
||||
if (inode->i_ino == (int)&(server->root))
|
||||
if (ncp_is_server_root(inode))
|
||||
{
|
||||
result = ncp_read_volume_list(server, filp->f_pos,
|
||||
NCP_READDIR_CACHE_SIZE);
|
||||
@@ -251,6 +311,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
c_dev = 0;
|
||||
c_ino = 0;
|
||||
return result;
|
||||
}
|
||||
@@ -258,6 +319,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
if (result > 0)
|
||||
{
|
||||
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
|
||||
c_dev = inode->i_dev;
|
||||
c_ino = inode->i_ino;
|
||||
c_size = result;
|
||||
entry = c_entry;
|
||||
@@ -282,24 +344,35 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
/* We found it. For getwd(), we have to return the
|
||||
correct inode in d_ino if the inode is currently in
|
||||
use. Otherwise the inode number does not
|
||||
matter. (You can argue a lot about this..) */
|
||||
matter. (You can argue a lot about this..) */
|
||||
|
||||
struct ncp_inode_info *ino_info;
|
||||
ino_info = ncp_find_inode(inode, entry->i.entryName);
|
||||
ino_t ino;
|
||||
|
||||
/* Some programs seem to be confused about a zero
|
||||
inode number, so we set it to one. Thanks to
|
||||
Gordon Chaffee for this one. */
|
||||
if (ino_info == NULL)
|
||||
if (ncp_single_volume(server))
|
||||
{
|
||||
ino_info = (struct ncp_inode_info *) 1;
|
||||
}
|
||||
ino = (ino_t)(entry->i.DosDirNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ncp_inode_info *ino_info;
|
||||
ino_info = ncp_find_dir_inode(inode,
|
||||
entry->i.entryName);
|
||||
|
||||
DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
|
||||
DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
|
||||
/* Some programs seem to be confused about a
|
||||
* zero inode number, so we set it to one.
|
||||
* Thanks to Gordon Chaffee for this one. */
|
||||
if (ino_info == NULL)
|
||||
{
|
||||
ino_info = (struct ncp_inode_info *) 1;
|
||||
}
|
||||
ino = (ino_t)(ino_info);
|
||||
}
|
||||
|
||||
DPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
|
||||
DPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
|
||||
|
||||
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
|
||||
entry->f_pos, (ino_t)ino_info) < 0)
|
||||
entry->f_pos, ino) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -353,9 +426,9 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
|
||||
DPRINTK("ncp_read_volumes: found vol: %s\n",
|
||||
info.volume_name);
|
||||
|
||||
if (ncp_do_lookup(server, NULL,
|
||||
info.volume_name,
|
||||
&(entry->i)) != 0)
|
||||
if (ncp_lookup_volume(server,
|
||||
info.volume_name,
|
||||
&(entry->i)) != 0)
|
||||
{
|
||||
printk("ncpfs: could not lookup vol "
|
||||
"%s\n", info.volume_name);
|
||||
@@ -438,15 +511,17 @@ ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
|
||||
void
|
||||
ncp_init_dir_cache(void)
|
||||
{
|
||||
c_dev = 0;
|
||||
c_ino = 0;
|
||||
c_entry = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ncp_invalid_dir_cache(unsigned long ino)
|
||||
ncp_invalid_dir_cache(struct inode *inode)
|
||||
{
|
||||
if (ino == c_ino)
|
||||
if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino))
|
||||
{
|
||||
c_dev = 0;
|
||||
c_ino = 0;
|
||||
c_seen_eof = 0;
|
||||
}
|
||||
@@ -517,7 +592,8 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
|
||||
root->next->prev = new_inode_info;
|
||||
root->next = new_inode_info;
|
||||
|
||||
if (!(inode = iget(dir->i_sb, (int)new_inode_info)))
|
||||
if (!(inode = iget(dir->i_sb, ncp_info_ino(NCP_SERVER(dir),
|
||||
new_inode_info))))
|
||||
{
|
||||
printk("ncp_iget: iget failed!");
|
||||
return NULL;
|
||||
@@ -567,6 +643,7 @@ ncp_init_root(struct ncp_server *server)
|
||||
root->finfo.opened = 0;
|
||||
i->attributes = aDIR;
|
||||
i->dataStreamSize = 1024;
|
||||
i->DosDirNum = 0;
|
||||
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));
|
||||
@@ -581,6 +658,25 @@ ncp_init_root(struct ncp_server *server)
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_conn_logged_in(struct ncp_server *server)
|
||||
{
|
||||
if (server->m.mounted_vol[0] == '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
str_upper(server->m.mounted_vol);
|
||||
if (ncp_lookup_volume(server, server->m.mounted_vol,
|
||||
&(server->root.finfo.i)) != 0)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
str_lower(server->root.finfo.i.entryName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ncp_free_all_inodes(struct ncp_server *server)
|
||||
{
|
||||
@@ -611,7 +707,7 @@ ncp_free_all_inodes(struct ncp_server *server)
|
||||
complete linear search through the inodes belonging to this
|
||||
filesystem. This has to be fixed. */
|
||||
static struct ncp_inode_info *
|
||||
ncp_find_inode(struct inode *dir, const char *name)
|
||||
ncp_find_dir_inode(struct inode *dir, const char *name)
|
||||
{
|
||||
struct ncp_server *server = NCP_SERVER(dir);
|
||||
struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
|
||||
@@ -658,9 +754,14 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
|
||||
|
||||
server = NCP_SERVER(dir);
|
||||
if (!ncp_conn_valid(server))
|
||||
{
|
||||
iput(dir);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
|
||||
|
||||
/* Fast cheat for . */
|
||||
if (len == 0 || (len == 1 && __name[0] == '.'))
|
||||
@@ -679,7 +780,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
parent->state = NCP_INODE_LOOKED_UP;
|
||||
}
|
||||
|
||||
*result = iget(dir->i_sb, (int)parent);
|
||||
*result = iget(dir->i_sb, ncp_info_ino(server, parent));
|
||||
iput(dir);
|
||||
if (*result == 0)
|
||||
{
|
||||
@@ -694,7 +795,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
memcpy(name, __name, len);
|
||||
name[len] = 0;
|
||||
|
||||
result_info = ncp_find_inode(dir, name);
|
||||
result_info = ncp_find_dir_inode(dir, name);
|
||||
|
||||
if (result_info != 0)
|
||||
{
|
||||
@@ -706,7 +807,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
/* Here we convert the inode_info address into an
|
||||
inode number */
|
||||
|
||||
*result = iget(dir->i_sb, (int)result_info);
|
||||
*result = iget(dir->i_sb, ncp_info_ino(server, result_info));
|
||||
iput(dir);
|
||||
|
||||
if (*result == NULL)
|
||||
@@ -722,7 +823,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
|
||||
found_in_cache = 0;
|
||||
|
||||
if (dir->i_ino == c_ino)
|
||||
if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino))
|
||||
{
|
||||
int first = c_last_returned_index;
|
||||
int i;
|
||||
@@ -747,15 +848,24 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
|
||||
if (found_in_cache == 0)
|
||||
{
|
||||
int res;
|
||||
str_upper(name);
|
||||
|
||||
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
|
||||
NCP_ISTRUCT(dir)->entryName, name);
|
||||
|
||||
if (ncp_do_lookup(server,
|
||||
dir->i_ino == (int)&(NCP_SERVER(dir)->root)
|
||||
? NULL : NCP_ISTRUCT(dir),
|
||||
name, &(finfo.i)) != 0)
|
||||
if (ncp_is_server_root(dir))
|
||||
{
|
||||
res = ncp_lookup_volume(server, name, &(finfo.i));
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ncp_obtain_info(server,
|
||||
NCP_ISTRUCT(dir)->volNumber,
|
||||
NCP_ISTRUCT(dir)->DosDirNum,
|
||||
name, &(finfo.i));
|
||||
}
|
||||
if (res != 0)
|
||||
{
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
@@ -790,6 +900,11 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (!ncp_conn_valid(NCP_SERVER(dir)))
|
||||
{
|
||||
iput(dir);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
@@ -806,7 +921,7 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
ncp_invalid_dir_cache(dir);
|
||||
|
||||
str_lower(finfo.i.entryName);
|
||||
finfo.access = O_RDWR;
|
||||
@@ -847,6 +962,11 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (!ncp_conn_valid(NCP_SERVER(dir)))
|
||||
{
|
||||
iput(dir);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir), _name,
|
||||
@@ -858,7 +978,7 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|
||||
else
|
||||
{
|
||||
error = 0;
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
ncp_invalid_dir_cache(dir);
|
||||
}
|
||||
|
||||
iput(dir);
|
||||
@@ -877,8 +997,14 @@ ncp_rmdir(struct inode *dir, const char *name, int len)
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (ncp_find_inode(dir, name) != NULL)
|
||||
if (!ncp_conn_valid(NCP_SERVER(dir)))
|
||||
{
|
||||
iput(dir);
|
||||
return -EIO;
|
||||
}
|
||||
if (ncp_find_dir_inode(dir, name) != NULL)
|
||||
{
|
||||
iput(dir);
|
||||
error = -EBUSY;
|
||||
}
|
||||
else
|
||||
@@ -892,7 +1018,7 @@ ncp_rmdir(struct inode *dir, const char *name, int len)
|
||||
NCP_ISTRUCT(dir),
|
||||
_name)) == 0)
|
||||
{
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
ncp_invalid_dir_cache(dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -915,8 +1041,14 @@ ncp_unlink(struct inode *dir, const char *name, int len)
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (ncp_find_inode(dir, name) != NULL)
|
||||
if (!ncp_conn_valid(NCP_SERVER(dir)))
|
||||
{
|
||||
iput(dir);
|
||||
return -EIO;
|
||||
}
|
||||
if (ncp_find_dir_inode(dir, name) != NULL)
|
||||
{
|
||||
iput(dir);
|
||||
error = -EBUSY;
|
||||
}
|
||||
else
|
||||
@@ -929,7 +1061,7 @@ ncp_unlink(struct inode *dir, const char *name, int len)
|
||||
NCP_ISTRUCT(dir),
|
||||
_name)) == 0)
|
||||
{
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
ncp_invalid_dir_cache(dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -955,6 +1087,12 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (!ncp_conn_valid(NCP_SERVER(old_dir)))
|
||||
{
|
||||
res = -EIO;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (!new_dir || !S_ISDIR(new_dir->i_mode))
|
||||
{
|
||||
printk("ncp_rename: new inode is NULL or not a directory\n");
|
||||
@@ -962,8 +1100,8 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if ( (ncp_find_inode(old_dir, old_name) != NULL)
|
||||
|| (ncp_find_inode(new_dir, new_name) != NULL))
|
||||
if ( (ncp_find_dir_inode(old_dir, old_name) != NULL)
|
||||
|| (ncp_find_dir_inode(new_dir, new_name) != NULL))
|
||||
{
|
||||
res = -EBUSY;
|
||||
goto finished;
|
||||
@@ -983,8 +1121,8 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
ncp_invalid_dir_cache(old_dir->i_ino);
|
||||
ncp_invalid_dir_cache(new_dir->i_ino);
|
||||
ncp_invalid_dir_cache(old_dir);
|
||||
ncp_invalid_dir_cache(new_dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -99,6 +99,10 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
DPRINTK("ncp_file_read: inode = NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
{
|
||||
@@ -178,6 +182,10 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
||||
DPRINTK("ncp_file_write: inode = NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
{
|
||||
@@ -239,6 +247,7 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
||||
if (pos > inode->i_size)
|
||||
{
|
||||
inode->i_size = pos;
|
||||
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
|
||||
}
|
||||
|
||||
DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
|
||||
@@ -61,50 +61,25 @@ ncp_read_inode(struct inode *inode)
|
||||
inode->i_ino. Just to make sure everything went well, we
|
||||
check it's there. */
|
||||
|
||||
struct ncp_inode_info *inode_info
|
||||
= (struct ncp_inode_info *)(inode->i_ino);
|
||||
struct ncp_inode_info *inode_info = ncp_find_inode(inode);
|
||||
|
||||
#if 1
|
||||
struct ncp_inode_info *root = &(NCP_SERVER(inode)->root);
|
||||
struct ncp_inode_info *check_info = root;
|
||||
|
||||
do
|
||||
if (inode_info == NULL)
|
||||
{
|
||||
if (inode_info == check_info)
|
||||
{
|
||||
if (check_info->state == NCP_INODE_LOOKED_UP)
|
||||
{
|
||||
DDPRINTK("ncp_read_inode: found it!\n");
|
||||
goto good;
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("ncp_read_inode: "
|
||||
"state != NCP_INODE_LOOKED_UP\n");
|
||||
goto good;
|
||||
}
|
||||
}
|
||||
check_info = check_info->next;
|
||||
}
|
||||
while (check_info != root);
|
||||
/* Ok, now we're in trouble. The inode info is not there. What
|
||||
should we do now??? */
|
||||
printk("ncp_read_inode: inode info not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ok, now we're in trouble. The inode info is not there. What
|
||||
should we do now??? */
|
||||
printk("ncp_read_inode: inode info not found\n");
|
||||
return;
|
||||
|
||||
good:
|
||||
DDPRINTK("ncp_read_inode: read entry %s\n",
|
||||
inode_info->finfo.i.entryName);
|
||||
#endif
|
||||
inode_info->state = NCP_INODE_VALID;
|
||||
|
||||
NCP_INOP(inode) = inode_info;
|
||||
inode_info->inode = inode;
|
||||
|
||||
if (NCP_ISTRUCT(inode)->attributes & aDIR)
|
||||
{
|
||||
inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
|
||||
/* for directories in dataStreamSize seems to be some
|
||||
/* for directories dataStreamSize seems to be some
|
||||
Object ID ??? */
|
||||
inode->i_size = 512;
|
||||
}
|
||||
@@ -176,7 +151,7 @@ ncp_put_inode(struct inode *inode)
|
||||
{
|
||||
DDPRINTK("ncp_put_inode: put directory %ld\n",
|
||||
inode->i_ino);
|
||||
ncp_invalid_dir_cache(inode->i_ino);
|
||||
ncp_invalid_dir_cache(inode);
|
||||
}
|
||||
|
||||
clear_inode(inode);
|
||||
@@ -204,6 +179,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
printk("ncp warning: mount version %s than kernel\n",
|
||||
(data->version < NCP_MOUNT_VERSION) ?
|
||||
"older" : "newer");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( (data->ncp_fd >= NR_OPEN)
|
||||
@@ -253,6 +230,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
server->wait = NULL;
|
||||
server->packet = NULL;
|
||||
server->buffer_size = 0;
|
||||
server->conn_status = 0;
|
||||
|
||||
server->m = *data;
|
||||
server->m.file_mode = (server->m.file_mode &
|
||||
@@ -302,7 +280,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
|
||||
DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
|
||||
|
||||
if (!(sb->s_mounted = iget(sb, (int)&(server->root))))
|
||||
if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
|
||||
{
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: get root inode failed\n");
|
||||
@@ -393,6 +371,11 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
int info_mask;
|
||||
struct nw_modify_dos_info info;
|
||||
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((result = inode_change_ok(inode, attr)) < 0)
|
||||
return result;
|
||||
|
||||
@@ -480,7 +463,7 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
result = 0;
|
||||
}
|
||||
|
||||
ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir));
|
||||
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,16 @@ ncp_ioctl (struct inode * inode, struct file * filp,
|
||||
|
||||
return server->reply_size;
|
||||
|
||||
case NCP_IOC_CONN_LOGGED_IN:
|
||||
|
||||
if ( (permission(inode, MAY_WRITE) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return ncp_conn_logged_in(server);
|
||||
|
||||
case NCP_IOC_GET_FS_INFO:
|
||||
|
||||
if ( (permission(inode, MAY_WRITE) != 0)
|
||||
|
||||
@@ -135,6 +135,11 @@ ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
|
||||
{
|
||||
DPRINTK("ncp_mmap: called\n");
|
||||
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* only PAGE_COW or read-only supported now */
|
||||
if (vma->vm_flags & VM_SHARED)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -266,56 +266,19 @@ ncp_extract_file_info(void *structure, struct nw_info_struct *target)
|
||||
target->entryName[*name_len] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ncp_do_lookup(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target)
|
||||
ncp_obtain_info(struct ncp_server *server,
|
||||
__u8 vol_num, __u32 dir_base,
|
||||
char *path, /* At most 1 component */
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
__u8 vol_num;
|
||||
__u32 dir_base;
|
||||
int result;
|
||||
char *volname = NULL;
|
||||
|
||||
if (target == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dir == NULL)
|
||||
{
|
||||
|
||||
DDPRINTK("ncp_do_lookup: looking up vol %s\n", path);
|
||||
|
||||
/* Access a volume's root directory */
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 22); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_handle_path(server, 0, 0, 0, /* no handle */
|
||||
path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
dir_base = ncp_reply_dword(server, 4);
|
||||
vol_num = ncp_reply_byte (server, 8);
|
||||
ncp_unlock_server(server);
|
||||
volname = path;
|
||||
path = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
vol_num = dir->volNumber;
|
||||
dir_base = dir->DosDirNum;
|
||||
}
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 6); /* subfunction */
|
||||
@@ -323,8 +286,7 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
ncp_add_byte(server, 0); /* dos name space as dest */
|
||||
ncp_add_word(server, 0xff); /* get all */
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
ncp_add_handle_path(server, vol_num, dir_base, 1,
|
||||
path);
|
||||
ncp_add_handle_path(server, vol_num, dir_base, 1, path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
@@ -333,14 +295,54 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
}
|
||||
|
||||
ncp_extract_file_info(ncp_reply_data(server, 0), target);
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (volname != NULL)
|
||||
int
|
||||
ncp_lookup_volume(struct ncp_server *server,
|
||||
char *volname,
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
int result;
|
||||
__u8 vol_num;
|
||||
__u32 dir_base;
|
||||
|
||||
DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
|
||||
ncp_add_byte(server, 0); /* DOS name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
|
||||
ncp_add_byte(server, 0); /* faked volume number */
|
||||
ncp_add_dword(server, 0); /* faked dir_base */
|
||||
ncp_add_byte(server, 0xff); /* Don't have a dir_base */
|
||||
ncp_add_byte(server, 1); /* 1 path component */
|
||||
ncp_add_pstring(server, volname);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
dir_base = ncp_reply_dword(server, 4);
|
||||
vol_num = ncp_reply_byte(server, 8);
|
||||
ncp_unlock_server(server);
|
||||
|
||||
if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
|
||||
target)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
|
||||
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,10 +114,16 @@ ncp_write(struct ncp_server *server, const char *file_id,
|
||||
const char *source, int *bytes_written);
|
||||
|
||||
int
|
||||
ncp_do_lookup(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target);
|
||||
ncp_obtain_info(struct ncp_server *server,
|
||||
__u8 vol_num, __u32 dir_base,
|
||||
char *path, /* At most 1 component */
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_lookup_volume(struct ncp_server *server,
|
||||
char *volname,
|
||||
struct nw_info_struct *target);
|
||||
|
||||
|
||||
int
|
||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
|
||||
@@ -491,7 +491,7 @@ ncp_request(struct ncp_server *server, int function)
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
DPRINTK("ncp_completion_code: %d\n", result);
|
||||
DPRINTK("ncp_completion_code: %x\n", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user