Commit e70cad34 authored by Petr Vandrovec's avatar Petr Vandrovec

Return total/free space on ncpfs mounted volume.

parent 0a2b36e6
......@@ -566,12 +566,60 @@ static void ncp_put_super(struct super_block *sb)
static int ncp_statfs(struct super_block *sb, struct statfs *buf)
{
struct dentry* d;
struct inode* i;
struct ncp_inode_info* ni;
struct ncp_server* s;
struct ncp_volume_info vi;
int err;
__u8 dh;
d = sb->s_root;
if (!d) {
goto dflt;
}
i = d->d_inode;
if (!i) {
goto dflt;
}
ni = NCP_FINFO(i);
if (!ni) {
goto dflt;
}
s = NCP_SBP(sb);
if (!s) {
goto dflt;
}
if (!s->m.mounted_vol[0]) {
goto dflt;
}
err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
if (err) {
goto dflt;
}
err = ncp_get_directory_info(s, dh, &vi);
ncp_dirhandle_free(s, dh);
if (err) {
goto dflt;
}
buf->f_type = NCP_SUPER_MAGIC;
buf->f_bsize = vi.sectors_per_block * 512;
buf->f_blocks = vi.total_blocks;
buf->f_bfree = vi.free_blocks;
buf->f_bavail = vi.free_blocks;
buf->f_files = vi.total_dir_entries;
buf->f_ffree = vi.available_dir_entries;
buf->f_namelen = 12;
return 0;
/* We cannot say how much disk space is left on a mounted
NetWare Server, because free space is distributed over
volumes, and the current user might have disk quotas. So
free space is not that simple to determine. Our decision
here is to err conservatively. */
dflt:;
buf->f_type = NCP_SUPER_MAGIC;
buf->f_bsize = NCP_BLOCK_SIZE;
buf->f_blocks = 0;
......
......@@ -107,6 +107,10 @@ static __u32
return get_unaligned((__u32 *) ncp_reply_data(server, offset));
}
static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) {
return le32_to_cpu(ncp_reply_dword(server, offset));
}
int
ncp_negotiate_buffersize(struct ncp_server *server, int size, int *target)
{
......@@ -159,10 +163,8 @@ ncp_negotiate_size_and_options(struct ncp_server *server,
return 0;
}
int
ncp_get_volume_info_with_number(struct ncp_server *server, int n,
struct ncp_volume_info *target)
{
int ncp_get_volume_info_with_number(struct ncp_server* server,
int n, struct ncp_volume_info* target) {
int result;
int len;
......@@ -172,12 +174,12 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
if ((result = ncp_request(server, 22)) != 0) {
goto out;
}
target->total_blocks = ncp_reply_dword(server, 0);
target->free_blocks = ncp_reply_dword(server, 4);
target->purgeable_blocks = ncp_reply_dword(server, 8);
target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12);
target->total_dir_entries = ncp_reply_dword(server, 16);
target->available_dir_entries = ncp_reply_dword(server, 20);
target->total_blocks = ncp_reply_dword_lh(server, 0);
target->free_blocks = ncp_reply_dword_lh(server, 4);
target->purgeable_blocks = ncp_reply_dword_lh(server, 8);
target->not_yet_purgeable_blocks = ncp_reply_dword_lh(server, 12);
target->total_dir_entries = ncp_reply_dword_lh(server, 16);
target->available_dir_entries = ncp_reply_dword_lh(server, 20);
target->sectors_per_block = ncp_reply_byte(server, 28);
memset(&(target->volume_name), 0, sizeof(target->volume_name));
......@@ -195,6 +197,40 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
return result;
}
int ncp_get_directory_info(struct ncp_server* server, __u8 n,
struct ncp_volume_info* target) {
int result;
int len;
ncp_init_request_s(server, 45);
ncp_add_byte(server, n);
if ((result = ncp_request(server, 22)) != 0) {
goto out;
}
target->total_blocks = ncp_reply_dword_lh(server, 0);
target->free_blocks = ncp_reply_dword_lh(server, 4);
target->purgeable_blocks = 0;
target->not_yet_purgeable_blocks = 0;
target->total_dir_entries = ncp_reply_dword_lh(server, 8);
target->available_dir_entries = ncp_reply_dword_lh(server, 12);
target->sectors_per_block = ncp_reply_byte(server, 20);
memset(&(target->volume_name), 0, sizeof(target->volume_name));
result = -EIO;
len = ncp_reply_byte(server, 21);
if (len > NCP_VOLNAME_LEN) {
DPRINTK("ncpfs: volume name too long: %d\n", len);
goto out;
}
memcpy(&(target->volume_name), ncp_reply_data(server, 22), len);
result = 0;
out:
ncp_unlock_server(server);
return result;
}
int
ncp_close_file(struct ncp_server *server, const char *file_id)
{
......@@ -248,10 +284,37 @@ static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
}
}
int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __u32 dirent,
__u8* dirhandle) {
int result;
ncp_init_request(server);
ncp_add_byte(server, 12); /* subfunction */
ncp_add_byte(server, NW_NS_DOS);
ncp_add_byte(server, 0);
ncp_add_word(server, 0);
ncp_add_handle_path(server, volnum, dirent, 1, NULL);
if ((result = ncp_request(server, 87)) == 0) {
*dirhandle = ncp_reply_byte(server, 0);
}
ncp_unlock_server(server);
return result;
}
int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) {
int result;
ncp_init_request_s(server, 20);
ncp_add_byte(server, dirhandle);
result = ncp_request(server, 22);
ncp_unlock_server(server);
return result;
}
static void ncp_extract_file_info(void *structure, struct nw_info_struct *target)
{
__u8 *name_len;
const int info_struct_size = sizeof(struct nw_info_struct) - 257;
const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
memcpy(target, structure, info_struct_size);
name_len = structure + info_struct_size;
......
......@@ -44,8 +44,13 @@
int ncp_negotiate_buffersize(struct ncp_server *, int, int *);
int ncp_negotiate_size_and_options(struct ncp_server *server, int size,
int options, int *ret_size, int *ret_options);
int ncp_get_volume_info_with_number(struct ncp_server *, int,
struct ncp_volume_info *);
int ncp_get_volume_info_with_number(struct ncp_server* server, int n,
struct ncp_volume_info *target);
int ncp_get_directory_info(struct ncp_server* server, __u8 dirhandle,
struct ncp_volume_info* target);
int ncp_close_file(struct ncp_server *, const char *);
static inline int ncp_read_bounce_size(__u32 size) {
return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8;
......@@ -99,6 +104,8 @@ ncp_ClearPhysicalRecord(struct ncp_server *server,
int
ncp_mount_subdir(struct ncp_server *, struct nw_info_struct *,
__u8, __u8, __u32);
int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __u32 dirent, __u8 *dirhandle);
int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle);
#ifdef CONFIG_NCPFS_NLS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment