/*
|
/*
|
* ncplib_kernel.c
|
* ncplib_kernel.c
|
*
|
*
|
* Copyright (C) 1995, 1996 by Volker Lendecke
|
* Copyright (C) 1995, 1996 by Volker Lendecke
|
*
|
*
|
*/
|
*/
|
|
|
#include <linux/config.h>
|
#include <linux/config.h>
|
|
|
#include "ncplib_kernel.h"
|
#include "ncplib_kernel.h"
|
|
|
typedef __u8 byte;
|
typedef __u8 byte;
|
typedef __u16 word;
|
typedef __u16 word;
|
typedef __u32 dword;
|
typedef __u32 dword;
|
|
|
static inline int min(int a, int b)
|
static inline int min(int a, int b)
|
{
|
{
|
return a<b ? a : b;
|
return a<b ? a : b;
|
}
|
}
|
|
|
static void
|
static void
|
assert_server_locked(struct ncp_server *server)
|
assert_server_locked(struct ncp_server *server)
|
{
|
{
|
if (server->lock == 0)
|
if (server->lock == 0)
|
{
|
{
|
DPRINTK("ncpfs: server not locked!\n");
|
DPRINTK("ncpfs: server not locked!\n");
|
}
|
}
|
}
|
}
|
|
|
static void
|
static void
|
ncp_add_byte(struct ncp_server *server, byte x)
|
ncp_add_byte(struct ncp_server *server, byte x)
|
{
|
{
|
assert_server_locked(server);
|
assert_server_locked(server);
|
*(byte *)(&(server->packet[server->current_size])) = x;
|
*(byte *)(&(server->packet[server->current_size])) = x;
|
server->current_size += 1;
|
server->current_size += 1;
|
return;
|
return;
|
}
|
}
|
|
|
static void
|
static void
|
ncp_add_word(struct ncp_server *server, word x)
|
ncp_add_word(struct ncp_server *server, word x)
|
{
|
{
|
assert_server_locked(server);
|
assert_server_locked(server);
|
*(word *)(&(server->packet[server->current_size])) = x;
|
*(word *)(&(server->packet[server->current_size])) = x;
|
server->current_size += 2;
|
server->current_size += 2;
|
return;
|
return;
|
}
|
}
|
|
|
static void
|
static void
|
ncp_add_dword(struct ncp_server *server, dword x)
|
ncp_add_dword(struct ncp_server *server, dword x)
|
{
|
{
|
assert_server_locked(server);
|
assert_server_locked(server);
|
*(dword *)(&(server->packet[server->current_size])) = x;
|
*(dword *)(&(server->packet[server->current_size])) = x;
|
server->current_size += 4;
|
server->current_size += 4;
|
return;
|
return;
|
}
|
}
|
|
|
static void
|
static void
|
ncp_add_mem(struct ncp_server *server, const void *source, int size)
|
ncp_add_mem(struct ncp_server *server, const void *source, int size)
|
{
|
{
|
assert_server_locked(server);
|
assert_server_locked(server);
|
memcpy(&(server->packet[server->current_size]), source, size);
|
memcpy(&(server->packet[server->current_size]), source, size);
|
server->current_size += size;
|
server->current_size += size;
|
return;
|
return;
|
}
|
}
|
|
|
static void
|
static void
|
ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size)
|
ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size)
|
{
|
{
|
assert_server_locked(server);
|
assert_server_locked(server);
|
memcpy_fromfs(&(server->packet[server->current_size]), source, size);
|
memcpy_fromfs(&(server->packet[server->current_size]), source, size);
|
server->current_size += size;
|
server->current_size += size;
|
return;
|
return;
|
}
|
}
|
|
|
static void
|
static void
|
ncp_add_pstring(struct ncp_server *server, const char *s)
|
ncp_add_pstring(struct ncp_server *server, const char *s)
|
{
|
{
|
int len = strlen(s);
|
int len = strlen(s);
|
assert_server_locked(server);
|
assert_server_locked(server);
|
if (len > 255)
|
if (len > 255)
|
{
|
{
|
DPRINTK("ncpfs: string too long: %s\n", s);
|
DPRINTK("ncpfs: string too long: %s\n", s);
|
len = 255;
|
len = 255;
|
}
|
}
|
ncp_add_byte(server, len);
|
ncp_add_byte(server, len);
|
ncp_add_mem(server, s, len);
|
ncp_add_mem(server, s, len);
|
return;
|
return;
|
}
|
}
|
|
|
static void
|
static void
|
ncp_init_request(struct ncp_server *server)
|
ncp_init_request(struct ncp_server *server)
|
{
|
{
|
ncp_lock_server(server);
|
ncp_lock_server(server);
|
|
|
server->current_size = sizeof(struct ncp_request_header);
|
server->current_size = sizeof(struct ncp_request_header);
|
server->has_subfunction = 0;
|
server->has_subfunction = 0;
|
}
|
}
|
|
|
static void
|
static void
|
ncp_init_request_s(struct ncp_server *server, int subfunction)
|
ncp_init_request_s(struct ncp_server *server, int subfunction)
|
{
|
{
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_word(server, 0); /* preliminary size */
|
ncp_add_word(server, 0); /* preliminary size */
|
|
|
ncp_add_byte(server, subfunction);
|
ncp_add_byte(server, subfunction);
|
|
|
server->has_subfunction = 1;
|
server->has_subfunction = 1;
|
}
|
}
|
|
|
static char *
|
static char *
|
ncp_reply_data(struct ncp_server *server, int offset)
|
ncp_reply_data(struct ncp_server *server, int offset)
|
{
|
{
|
return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
|
return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
|
}
|
}
|
|
|
static byte
|
static byte
|
ncp_reply_byte(struct ncp_server *server, int offset)
|
ncp_reply_byte(struct ncp_server *server, int offset)
|
{
|
{
|
return *(byte *)(ncp_reply_data(server, offset));
|
return *(byte *)(ncp_reply_data(server, offset));
|
}
|
}
|
|
|
static word
|
static word
|
ncp_reply_word(struct ncp_server *server, int offset)
|
ncp_reply_word(struct ncp_server *server, int offset)
|
{
|
{
|
return *(word *)(ncp_reply_data(server, offset));
|
return *(word *)(ncp_reply_data(server, offset));
|
}
|
}
|
|
|
static dword
|
static dword
|
ncp_reply_dword(struct ncp_server *server, int offset)
|
ncp_reply_dword(struct ncp_server *server, int offset)
|
{
|
{
|
return *(dword *)(ncp_reply_data(server, offset));
|
return *(dword *)(ncp_reply_data(server, offset));
|
}
|
}
|
|
|
|
|
/* options:
|
/* options:
|
* bit 0 ipx checksum
|
* bit 0 ipx checksum
|
* bit 1 packet signing
|
* bit 1 packet signing
|
*/
|
*/
|
int
|
int
|
ncp_negotiate_size_and_options(struct ncp_server *server,
|
ncp_negotiate_size_and_options(struct ncp_server *server,
|
int size, int options, int *ret_size, int *ret_options) {
|
int size, int options, int *ret_size, int *ret_options) {
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_word(server, htons(size));
|
ncp_add_word(server, htons(size));
|
ncp_add_byte(server, options);
|
ncp_add_byte(server, options);
|
|
|
if ((result = ncp_request(server, 0x61)) != 0)
|
if ((result = ncp_request(server, 0x61)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
*ret_size = min(ntohs(ncp_reply_word(server, 0)), size);
|
*ret_size = min(ntohs(ncp_reply_word(server, 0)), size);
|
*ret_options = ncp_reply_byte(server, 4);
|
*ret_options = ncp_reply_byte(server, 4);
|
|
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_negotiate_buffersize(struct ncp_server *server,
|
ncp_negotiate_buffersize(struct ncp_server *server,
|
int size, int *target)
|
int size, int *target)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_word(server, htons(size));
|
ncp_add_word(server, htons(size));
|
|
|
if ((result = ncp_request(server, 33)) != 0)
|
if ((result = ncp_request(server, 33)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
*target =min(ntohs(ncp_reply_word(server, 0)), size);
|
*target =min(ntohs(ncp_reply_word(server, 0)), size);
|
|
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
struct ncp_volume_info *target)
|
struct ncp_volume_info *target)
|
{
|
{
|
int result;
|
int result;
|
int len;
|
int len;
|
|
|
ncp_init_request_s(server, 44);
|
ncp_init_request_s(server, 44);
|
ncp_add_byte(server, n);
|
ncp_add_byte(server, n);
|
|
|
if ((result = ncp_request(server, 22)) != 0)
|
if ((result = ncp_request(server, 22)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
target->total_blocks = ncp_reply_dword(server, 0);
|
target->total_blocks = ncp_reply_dword(server, 0);
|
target->free_blocks = ncp_reply_dword(server, 4);
|
target->free_blocks = ncp_reply_dword(server, 4);
|
target->purgeable_blocks = ncp_reply_dword(server, 8);
|
target->purgeable_blocks = ncp_reply_dword(server, 8);
|
target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12);
|
target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12);
|
target->total_dir_entries = ncp_reply_dword(server, 16);
|
target->total_dir_entries = ncp_reply_dword(server, 16);
|
target->available_dir_entries = ncp_reply_dword(server, 20);
|
target->available_dir_entries = ncp_reply_dword(server, 20);
|
target->sectors_per_block = ncp_reply_byte(server, 28);
|
target->sectors_per_block = ncp_reply_byte(server, 28);
|
|
|
memset(&(target->volume_name), 0, sizeof(target->volume_name));
|
memset(&(target->volume_name), 0, sizeof(target->volume_name));
|
|
|
len = ncp_reply_byte(server, 29);
|
len = ncp_reply_byte(server, 29);
|
if (len > NCP_VOLNAME_LEN)
|
if (len > NCP_VOLNAME_LEN)
|
{
|
{
|
DPRINTK("ncpfs: volume name too long: %d\n", len);
|
DPRINTK("ncpfs: volume name too long: %d\n", len);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return -EIO;
|
return -EIO;
|
}
|
}
|
|
|
memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
|
memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_close_file(struct ncp_server *server, const char *file_id)
|
ncp_close_file(struct ncp_server *server, const char *file_id)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 0);
|
ncp_add_byte(server, 0);
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_mem(server, file_id, 6);
|
|
|
result = ncp_request(server, 66);
|
result = ncp_request(server, 66);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
static void
|
static void
|
ncp_add_handle_path(struct ncp_server *server,
|
ncp_add_handle_path(struct ncp_server *server,
|
__u8 vol_num,
|
__u8 vol_num,
|
__u32 dir_base, int have_dir_base,
|
__u32 dir_base, int have_dir_base,
|
char *path)
|
char *path)
|
{
|
{
|
ncp_add_byte(server, vol_num);
|
ncp_add_byte(server, vol_num);
|
ncp_add_dword(server, dir_base);
|
ncp_add_dword(server, dir_base);
|
if (have_dir_base != 0)
|
if (have_dir_base != 0)
|
{
|
{
|
ncp_add_byte(server, 1); /* dir_base */
|
ncp_add_byte(server, 1); /* dir_base */
|
}
|
}
|
else
|
else
|
{
|
{
|
ncp_add_byte(server, 0xff); /* no handle */
|
ncp_add_byte(server, 0xff); /* no handle */
|
}
|
}
|
if (path != NULL)
|
if (path != NULL)
|
{
|
{
|
ncp_add_byte(server, 1); /* 1 component */
|
ncp_add_byte(server, 1); /* 1 component */
|
ncp_add_pstring(server, path);
|
ncp_add_pstring(server, path);
|
}
|
}
|
else
|
else
|
{
|
{
|
ncp_add_byte(server, 0);
|
ncp_add_byte(server, 0);
|
}
|
}
|
}
|
}
|
|
|
static void
|
static void
|
ncp_extract_file_info(void *structure, struct nw_info_struct *target)
|
ncp_extract_file_info(void *structure, struct nw_info_struct *target)
|
{
|
{
|
__u8 *name_len;
|
__u8 *name_len;
|
const int info_struct_size = sizeof(struct nw_info_struct) - 257;
|
const int info_struct_size = sizeof(struct nw_info_struct) - 257;
|
|
|
memcpy(target, structure, info_struct_size);
|
memcpy(target, structure, info_struct_size);
|
name_len = structure + info_struct_size;
|
name_len = structure + info_struct_size;
|
target->nameLen = *name_len;
|
target->nameLen = *name_len;
|
strncpy(target->entryName, name_len+1, *name_len);
|
strncpy(target->entryName, name_len+1, *name_len);
|
target->entryName[*name_len] = '\0';
|
target->entryName[*name_len] = '\0';
|
return;
|
return;
|
}
|
}
|
|
|
int
|
int
|
ncp_obtain_info(struct ncp_server *server,
|
ncp_obtain_info(struct ncp_server *server,
|
__u8 vol_num, __u32 dir_base,
|
__u8 vol_num, __u32 dir_base,
|
char *path, /* At most 1 component */
|
char *path, /* At most 1 component */
|
struct nw_info_struct *target)
|
struct nw_info_struct *target)
|
{
|
{
|
int result;
|
int result;
|
|
|
if (target == NULL)
|
if (target == NULL)
|
{
|
{
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 6); /* subfunction */
|
ncp_add_byte(server, 6); /* subfunction */
|
ncp_add_byte(server, server->name_space[vol_num]);
|
ncp_add_byte(server, server->name_space[vol_num]);
|
ncp_add_byte(server, server->name_space[vol_num]);
|
ncp_add_byte(server, server->name_space[vol_num]);
|
ncp_add_word(server, 0x8006); /* get all */
|
ncp_add_word(server, 0x8006); /* get all */
|
ncp_add_dword(server, RIM_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)
|
if ((result = ncp_request(server, 87)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
ncp_extract_file_info(ncp_reply_data(server, 0), target);
|
ncp_extract_file_info(ncp_reply_data(server, 0), target);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
static inline int
|
static inline int
|
ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
|
ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
|
{
|
{
|
#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS)
|
#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS)
|
int result;
|
int result;
|
__u8 *namespace;
|
__u8 *namespace;
|
__u16 no_namespaces;
|
__u16 no_namespaces;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */
|
ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */
|
ncp_add_word(server, 0);
|
ncp_add_word(server, 0);
|
ncp_add_byte(server, volume);
|
ncp_add_byte(server, volume);
|
|
|
if ((result = ncp_request(server, 87)) != 0)
|
if ((result = ncp_request(server, 87)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return NW_NS_DOS;
|
return NW_NS_DOS;
|
}
|
}
|
|
|
result=NW_NS_DOS;
|
result=NW_NS_DOS;
|
no_namespaces = ncp_reply_word(server, 0);
|
no_namespaces = ncp_reply_word(server, 0);
|
namespace = ncp_reply_data(server, 2);
|
namespace = ncp_reply_data(server, 2);
|
|
|
while (no_namespaces > 0)
|
while (no_namespaces > 0)
|
{
|
{
|
DPRINTK("get_namespaces: found %d on %d\n", *namespace,volume);
|
DPRINTK("get_namespaces: found %d on %d\n", *namespace,volume);
|
|
|
#ifdef CONFIG_NCPFS_NFS_NS
|
#ifdef CONFIG_NCPFS_NFS_NS
|
if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS))
|
if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS))
|
{
|
{
|
result = NW_NS_NFS;
|
result = NW_NS_NFS;
|
break;
|
break;
|
}
|
}
|
#endif /* CONFIG_NCPFS_NFS_NS */
|
#endif /* CONFIG_NCPFS_NFS_NS */
|
#ifdef CONFIG_NCPFS_OS2_NS
|
#ifdef CONFIG_NCPFS_OS2_NS
|
if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2))
|
if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2))
|
{
|
{
|
result = NW_NS_OS2;
|
result = NW_NS_OS2;
|
}
|
}
|
#endif /* CONFIG_NCPFS_OS2_NS */
|
#endif /* CONFIG_NCPFS_OS2_NS */
|
namespace += 1;
|
namespace += 1;
|
no_namespaces -= 1;
|
no_namespaces -= 1;
|
}
|
}
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
#else /* neither OS2 nor NFS - only DOS */
|
#else /* neither OS2 nor NFS - only DOS */
|
return NW_NS_DOS;
|
return NW_NS_DOS;
|
#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
|
#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
|
}
|
}
|
|
|
static int
|
static int
|
ncp_ObtainSpecificDirBase(struct ncp_server *server,
|
ncp_ObtainSpecificDirBase(struct ncp_server *server,
|
__u8 nsSrc, __u8 nsDst, __u8 vol_num, __u32 dir_base,
|
__u8 nsSrc, __u8 nsDst, __u8 vol_num, __u32 dir_base,
|
char *path, /* At most 1 component */
|
char *path, /* At most 1 component */
|
__u32 *dirEntNum)
|
__u32 *dirEntNum)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 6); /* subfunction */
|
ncp_add_byte(server, 6); /* subfunction */
|
ncp_add_byte(server, nsSrc);
|
ncp_add_byte(server, nsSrc);
|
ncp_add_byte(server, nsDst);
|
ncp_add_byte(server, nsDst);
|
ncp_add_word(server, 0x8006); /* get all */
|
ncp_add_word(server, 0x8006); /* get all */
|
ncp_add_dword(server, RIM_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)
|
if ((result = ncp_request(server, 87)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
if (dirEntNum)
|
if (dirEntNum)
|
*dirEntNum = ncp_reply_dword(server, 0x30);
|
*dirEntNum = ncp_reply_dword(server, 0x30);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_mount_subdir(struct ncp_server *server,
|
ncp_mount_subdir(struct ncp_server *server,
|
__u8 volNumber,
|
__u8 volNumber,
|
__u8 srcNS, __u32 dirEntNum)
|
__u8 srcNS, __u32 dirEntNum)
|
{
|
{
|
int dstNS;
|
int dstNS;
|
int result;
|
int result;
|
__u32 newDirEnt;
|
__u32 newDirEnt;
|
|
|
dstNS = ncp_get_known_namespace(server, volNumber);
|
dstNS = ncp_get_known_namespace(server, volNumber);
|
if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber,
|
if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber,
|
dirEntNum, NULL, &newDirEnt)) != 0)
|
dirEntNum, NULL, &newDirEnt)) != 0)
|
{
|
{
|
return result;
|
return result;
|
}
|
}
|
server->name_space[volNumber] = dstNS;
|
server->name_space[volNumber] = dstNS;
|
server->root.finfo.i.volNumber = volNumber;
|
server->root.finfo.i.volNumber = volNumber;
|
server->root.finfo.i.dirEntNum = newDirEnt;
|
server->root.finfo.i.dirEntNum = newDirEnt;
|
server->m.mounted_vol[1] = 0;
|
server->m.mounted_vol[1] = 0;
|
server->m.mounted_vol[0] = 'X';
|
server->m.mounted_vol[0] = 'X';
|
return 0;
|
return 0;
|
}
|
}
|
|
|
static int
|
static int
|
ncp_obtain_DOS_dir_base(struct ncp_server *server,
|
ncp_obtain_DOS_dir_base(struct ncp_server *server,
|
struct nw_info_struct* file,
|
struct nw_info_struct* file,
|
char *path, /* At most 1 component */
|
char *path, /* At most 1 component */
|
__u32 *DOS_dir_base)
|
__u32 *DOS_dir_base)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 6); /* subfunction */
|
ncp_add_byte(server, 6); /* subfunction */
|
ncp_add_byte(server, server->name_space[file->volNumber]);
|
ncp_add_byte(server, server->name_space[file->volNumber]);
|
ncp_add_byte(server, server->name_space[file->volNumber]);
|
ncp_add_byte(server, server->name_space[file->volNumber]);
|
ncp_add_word(server, 0x8006); /* get all */
|
ncp_add_word(server, 0x8006); /* get all */
|
ncp_add_dword(server, RIM_DIRECTORY);
|
ncp_add_dword(server, RIM_DIRECTORY);
|
ncp_add_handle_path(server, file->volNumber, file->dirEntNum, 1, path);
|
ncp_add_handle_path(server, file->volNumber, file->dirEntNum, 1, path);
|
|
|
if ((result = ncp_request(server, 87)) != 0)
|
if ((result = ncp_request(server, 87)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34);
|
if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_lookup_volume(struct ncp_server *server,
|
ncp_lookup_volume(struct ncp_server *server,
|
char *volname,
|
char *volname,
|
struct nw_info_struct *target)
|
struct nw_info_struct *target)
|
{
|
{
|
int result;
|
int result;
|
int volnum;
|
int volnum;
|
|
|
DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
|
DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
|
ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
|
ncp_add_byte(server, 0); /* DOS namespace */
|
ncp_add_byte(server, 0); /* DOS namespace */
|
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_byte(server, 0); /* reserved */
|
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_byte(server, 0); /* faked volume number */
|
ncp_add_dword(server, 0); /* faked dir_base */
|
ncp_add_dword(server, 0); /* faked dir_base */
|
ncp_add_byte(server, 0xff); /* Don't have a dir_base */
|
ncp_add_byte(server, 0xff); /* Don't have a dir_base */
|
ncp_add_byte(server, 1); /* 1 path component */
|
ncp_add_byte(server, 1); /* 1 path component */
|
ncp_add_pstring(server, volname);
|
ncp_add_pstring(server, volname);
|
|
|
if ((result = ncp_request(server, 87)) != 0)
|
if ((result = ncp_request(server, 87)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
memset(target, 0, sizeof(*target));
|
memset(target, 0, sizeof(*target));
|
target->DosDirNum = target->dirEntNum = ncp_reply_dword(server, 4);
|
target->DosDirNum = target->dirEntNum = ncp_reply_dword(server, 4);
|
target->volNumber = volnum = ncp_reply_byte(server, 8);
|
target->volNumber = volnum = ncp_reply_byte(server, 8);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
|
|
server->name_space[volnum] =
|
server->name_space[volnum] =
|
ncp_get_known_namespace(server, volnum);
|
ncp_get_known_namespace(server, volnum);
|
|
|
DPRINTK("lookup_vol: namespace[%d] = %d\n",
|
DPRINTK("lookup_vol: namespace[%d] = %d\n",
|
volnum, server->name_space[volnum]);
|
volnum, server->name_space[volnum]);
|
|
|
target->nameLen = strlen(volname);
|
target->nameLen = strlen(volname);
|
strcpy(target->entryName, volname);
|
strcpy(target->entryName, volname);
|
target->attributes = aDIR;
|
target->attributes = aDIR;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
struct nw_info_struct *file,
|
struct nw_info_struct *file,
|
__u32 info_mask,
|
__u32 info_mask,
|
struct nw_modify_dos_info *info)
|
struct nw_modify_dos_info *info)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 7); /* subfunction */
|
ncp_add_byte(server, 7); /* subfunction */
|
ncp_add_byte(server, server->name_space[file->volNumber]);
|
ncp_add_byte(server, server->name_space[file->volNumber]);
|
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_word(server, 0x8006); /* search attribs: all */
|
ncp_add_word(server, 0x8006); /* search attribs: all */
|
|
|
ncp_add_dword(server, info_mask);
|
ncp_add_dword(server, info_mask);
|
ncp_add_mem(server, info, sizeof(*info));
|
ncp_add_mem(server, info, sizeof(*info));
|
ncp_add_handle_path(server, file->volNumber,
|
ncp_add_handle_path(server, file->volNumber,
|
file->dirEntNum, 1, NULL);
|
file->dirEntNum, 1, NULL);
|
|
|
result = ncp_request(server, 87);
|
result = ncp_request(server, 87);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
static int
|
static int
|
ncp_DeleteNSEntry(struct ncp_server *server,
|
ncp_DeleteNSEntry(struct ncp_server *server,
|
__u8 have_dir_base, __u8 volume, __u32 dir_base,
|
__u8 have_dir_base, __u8 volume, __u32 dir_base,
|
char* name, __u8 ns, int attr)
|
char* name, __u8 ns, int attr)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 8); /* subfunction */
|
ncp_add_byte(server, 8); /* subfunction */
|
ncp_add_byte(server, ns); /* namespace */
|
ncp_add_byte(server, ns); /* namespace */
|
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_word(server, attr); /* search attribs */
|
ncp_add_word(server, attr); /* search attribs */
|
ncp_add_handle_path(server, volume, dir_base, have_dir_base, name);
|
ncp_add_handle_path(server, volume, dir_base, have_dir_base, name);
|
|
|
result = ncp_request(server, 87);
|
result = ncp_request(server, 87);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
int
|
int
|
ncp_del_file_or_subdir(struct ncp_server *server,
|
ncp_del_file_or_subdir(struct ncp_server *server,
|
struct nw_info_struct *dir, char *name)
|
struct nw_info_struct *dir, char *name)
|
{
|
{
|
#ifdef CONFIG_NCPFS_NFS_NS
|
#ifdef CONFIG_NCPFS_NFS_NS
|
if (server->name_space[dir->volNumber]==NW_NS_NFS)
|
if (server->name_space[dir->volNumber]==NW_NS_NFS)
|
{
|
{
|
__u32 DOS_dir_base;
|
__u32 DOS_dir_base;
|
int result;
|
int result;
|
|
|
result=ncp_obtain_DOS_dir_base(server, dir, name, &DOS_dir_base);
|
result=ncp_obtain_DOS_dir_base(server, dir, name, &DOS_dir_base);
|
if (result) return result;
|
if (result) return result;
|
return ncp_DeleteNSEntry(server, 1, dir->volNumber, DOS_dir_base, NULL, NW_NS_DOS, 0x8006);
|
return ncp_DeleteNSEntry(server, 1, dir->volNumber, DOS_dir_base, NULL, NW_NS_DOS, 0x8006);
|
}
|
}
|
else
|
else
|
#endif /* CONFIG_NCPFS_NFS_NS */
|
#endif /* CONFIG_NCPFS_NFS_NS */
|
return ncp_DeleteNSEntry(server, 1, dir->volNumber, dir->dirEntNum, name, server->name_space[dir->volNumber], 0x8006);
|
return ncp_DeleteNSEntry(server, 1, dir->volNumber, dir->dirEntNum, name, server->name_space[dir->volNumber], 0x8006);
|
}
|
}
|
|
|
static inline void
|
static inline void
|
ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] )
|
ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] )
|
{
|
{
|
__u16 *dest = (__u16 *) ret;
|
__u16 *dest = (__u16 *) ret;
|
memcpy(&(dest[1]), &sfd, 4);
|
memcpy(&(dest[1]), &sfd, 4);
|
dest[0] = dest[1] + 1;
|
dest[0] = dest[1] + 1;
|
return;
|
return;
|
}
|
}
|
|
|
/* If both dir and name are NULL, then in target there's already a
|
/* If both dir and name are NULL, then in target there's already a
|
looked-up entry that wants to be opened. */
|
looked-up entry that wants to be opened. */
|
int
|
int
|
ncp_open_create_file_or_subdir(struct ncp_server *server,
|
ncp_open_create_file_or_subdir(struct ncp_server *server,
|
struct nw_info_struct *dir, char *name,
|
struct nw_info_struct *dir, char *name,
|
int open_create_mode,
|
int open_create_mode,
|
__u32 create_attributes,
|
__u32 create_attributes,
|
int desired_acc_rights,
|
int desired_acc_rights,
|
struct nw_file_info *target)
|
struct nw_file_info *target)
|
{
|
{
|
int result;
|
int result;
|
__u16 search_attribs = 0x0006;
|
__u16 search_attribs = 0x0006;
|
__u8 volume = (dir != NULL) ? dir->volNumber : target->i.volNumber;
|
__u8 volume = (dir != NULL) ? dir->volNumber : target->i.volNumber;
|
|
|
if ((create_attributes & aDIR) != 0)
|
if ((create_attributes & aDIR) != 0)
|
{
|
{
|
search_attribs |= 0x8000;
|
search_attribs |= 0x8000;
|
}
|
}
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 1); /* subfunction */
|
ncp_add_byte(server, 1); /* subfunction */
|
ncp_add_byte(server, server->name_space[volume]);
|
ncp_add_byte(server, server->name_space[volume]);
|
ncp_add_byte(server, open_create_mode);
|
ncp_add_byte(server, open_create_mode);
|
ncp_add_word(server, search_attribs);
|
ncp_add_word(server, search_attribs);
|
ncp_add_dword(server, RIM_ALL);
|
ncp_add_dword(server, RIM_ALL);
|
ncp_add_dword(server, create_attributes);
|
ncp_add_dword(server, create_attributes);
|
/* The desired acc rights seem to be the inherited rights mask
|
/* The desired acc rights seem to be the inherited rights mask
|
for directories */
|
for directories */
|
ncp_add_word(server, desired_acc_rights);
|
ncp_add_word(server, desired_acc_rights);
|
|
|
if (dir != NULL)
|
if (dir != NULL)
|
{
|
{
|
ncp_add_handle_path(server, volume, dir->dirEntNum, 1, name);
|
ncp_add_handle_path(server, volume, dir->dirEntNum, 1, name);
|
}
|
}
|
else
|
else
|
{
|
{
|
ncp_add_handle_path(server, volume, target->i.dirEntNum,
|
ncp_add_handle_path(server, volume, target->i.dirEntNum,
|
1, NULL);
|
1, NULL);
|
}
|
}
|
|
|
if ((result = ncp_request(server, 87)) != 0)
|
if ((result = ncp_request(server, 87)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
target->opened = 1;
|
target->opened = 1;
|
target->server_file_handle = ncp_reply_dword(server, 0);
|
target->server_file_handle = ncp_reply_dword(server, 0);
|
target->open_create_action = ncp_reply_byte(server, 4);
|
target->open_create_action = ncp_reply_byte(server, 4);
|
|
|
if (dir != NULL)
|
if (dir != NULL)
|
{
|
{
|
/* in target there's a new finfo to fill */
|
/* in target there's a new finfo to fill */
|
ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
|
ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
|
}
|
}
|
|
|
ConvertToNWfromDWORD(target->server_file_handle, target->file_handle);
|
ConvertToNWfromDWORD(target->server_file_handle, target->file_handle);
|
|
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
int
|
int
|
ncp_initialize_search(struct ncp_server *server,
|
ncp_initialize_search(struct ncp_server *server,
|
struct nw_info_struct *dir,
|
struct nw_info_struct *dir,
|
struct nw_search_sequence *target)
|
struct nw_search_sequence *target)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 2); /* subfunction */
|
ncp_add_byte(server, 2); /* subfunction */
|
ncp_add_byte(server, server->name_space[dir->volNumber]);
|
ncp_add_byte(server, server->name_space[dir->volNumber]);
|
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_handle_path(server, dir->volNumber, dir->dirEntNum, 1, NULL);
|
ncp_add_handle_path(server, dir->volNumber, dir->dirEntNum, 1, NULL);
|
|
|
if ((result = ncp_request(server, 87)) != 0)
|
if ((result = ncp_request(server, 87)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
|
memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
|
|
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Search for everything */
|
/* Search for everything */
|
int
|
int
|
ncp_search_for_file_or_subdir(struct ncp_server *server,
|
ncp_search_for_file_or_subdir(struct ncp_server *server,
|
struct nw_search_sequence *seq,
|
struct nw_search_sequence *seq,
|
struct nw_info_struct *target)
|
struct nw_info_struct *target)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 3); /* subfunction */
|
ncp_add_byte(server, 3); /* subfunction */
|
ncp_add_byte(server, server->name_space[seq->volNumber]);
|
ncp_add_byte(server, server->name_space[seq->volNumber]);
|
ncp_add_byte(server, 0); /* data stream (???) */
|
ncp_add_byte(server, 0); /* data stream (???) */
|
ncp_add_word(server, 0x8006); /* Search attribs */
|
ncp_add_word(server, 0x8006); /* Search attribs */
|
ncp_add_dword(server, RIM_ALL); /* return info mask */
|
ncp_add_dword(server, RIM_ALL); /* return info mask */
|
ncp_add_mem(server, seq, 9);
|
ncp_add_mem(server, seq, 9);
|
#ifdef CONFIG_NCPFS_NFS_NS
|
#ifdef CONFIG_NCPFS_NFS_NS
|
if (server->name_space[seq->volNumber]==NW_NS_NFS)
|
if (server->name_space[seq->volNumber]==NW_NS_NFS)
|
{
|
{
|
ncp_add_byte(server, 0);
|
ncp_add_byte(server, 0);
|
}
|
}
|
else
|
else
|
#endif /* CONFIG_NCPFS_NFS_NS */
|
#endif /* CONFIG_NCPFS_NFS_NS */
|
{
|
{
|
ncp_add_byte(server, 2); /* 2 byte pattern */
|
ncp_add_byte(server, 2); /* 2 byte pattern */
|
ncp_add_byte(server, 0xff); /* following is a wildcard */
|
ncp_add_byte(server, 0xff); /* following is a wildcard */
|
ncp_add_byte(server, '*');
|
ncp_add_byte(server, '*');
|
}
|
}
|
|
|
if ((result = ncp_request(server, 87)) != 0)
|
if ((result = ncp_request(server, 87)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
|
memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
|
ncp_extract_file_info(ncp_reply_data(server, 10), target);
|
ncp_extract_file_info(ncp_reply_data(server, 10), target);
|
|
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_RenameNSEntry(struct ncp_server *server,
|
ncp_RenameNSEntry(struct ncp_server *server,
|
struct nw_info_struct *old_dir, char *old_name, int old_type,
|
struct nw_info_struct *old_dir, char *old_name, int old_type,
|
struct nw_info_struct *new_dir, char *new_name)
|
struct nw_info_struct *new_dir, char *new_name)
|
{
|
{
|
int result;
|
int result;
|
|
|
if ( (old_dir == NULL) || (old_name == NULL)
|
if ( (old_dir == NULL) || (old_name == NULL)
|
|| (new_dir == NULL) || (new_name == NULL))
|
|| (new_dir == NULL) || (new_name == NULL))
|
return -EINVAL;
|
return -EINVAL;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 4); /* subfunction */
|
ncp_add_byte(server, 4); /* subfunction */
|
ncp_add_byte(server, server->name_space[old_dir->volNumber]);
|
ncp_add_byte(server, server->name_space[old_dir->volNumber]);
|
ncp_add_byte(server, 1); /* rename flag */
|
ncp_add_byte(server, 1); /* rename flag */
|
ncp_add_word(server, old_type); /* search attributes */
|
ncp_add_word(server, old_type); /* search attributes */
|
|
|
/* source Handle Path */
|
/* source Handle Path */
|
ncp_add_byte(server, old_dir->volNumber);
|
ncp_add_byte(server, old_dir->volNumber);
|
ncp_add_dword(server, old_dir->dirEntNum);
|
ncp_add_dword(server, old_dir->dirEntNum);
|
ncp_add_byte(server, 1);
|
ncp_add_byte(server, 1);
|
ncp_add_byte(server, 1); /* 1 source component */
|
ncp_add_byte(server, 1); /* 1 source component */
|
|
|
/* dest Handle Path */
|
/* dest Handle Path */
|
ncp_add_byte(server, new_dir->volNumber);
|
ncp_add_byte(server, new_dir->volNumber);
|
ncp_add_dword(server, new_dir->dirEntNum);
|
ncp_add_dword(server, new_dir->dirEntNum);
|
ncp_add_byte(server, 1);
|
ncp_add_byte(server, 1);
|
ncp_add_byte(server, 1); /* 1 destination component */
|
ncp_add_byte(server, 1); /* 1 destination component */
|
|
|
/* source path string */
|
/* source path string */
|
ncp_add_pstring(server, old_name);
|
ncp_add_pstring(server, old_name);
|
/* dest path string */
|
/* dest path string */
|
ncp_add_pstring(server, new_name);
|
ncp_add_pstring(server, new_name);
|
|
|
result = ncp_request(server, 87);
|
result = ncp_request(server, 87);
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
int
|
int
|
ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
|
ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
|
struct nw_info_struct *old_dir, char *old_name,
|
struct nw_info_struct *old_dir, char *old_name,
|
struct nw_info_struct *new_dir, char *new_name)
|
struct nw_info_struct *new_dir, char *new_name)
|
{
|
{
|
int result;
|
int result;
|
int old_type = 0x0006;
|
int old_type = 0x0006;
|
|
|
/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */
|
/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */
|
result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
|
result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
|
new_dir, new_name);
|
new_dir, new_name);
|
if (result == 0xFF) /* File Not Found, try directory */
|
if (result == 0xFF) /* File Not Found, try directory */
|
{
|
{
|
old_type = 0x0016;
|
old_type = 0x0016;
|
result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
|
result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
|
new_dir, new_name);
|
new_dir, new_name);
|
}
|
}
|
if (result != 0x92) return result; /* All except NO_FILES_RENAMED */
|
if (result != 0x92) return result; /* All except NO_FILES_RENAMED */
|
result = ncp_del_file_or_subdir(server, new_dir, new_name);
|
result = ncp_del_file_or_subdir(server, new_dir, new_name);
|
if (result != 0) return -EACCES;
|
if (result != 0) return -EACCES;
|
result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
|
result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
|
new_dir, new_name);
|
new_dir, new_name);
|
return result;
|
return result;
|
}
|
}
|
|
|
|
|
/* We have to transfer to/from user space */
|
/* We have to transfer to/from user space */
|
int
|
int
|
ncp_read(struct ncp_server *server, const char *file_id,
|
ncp_read(struct ncp_server *server, const char *file_id,
|
__u32 offset, __u16 to_read,
|
__u32 offset, __u16 to_read,
|
char *target, int *bytes_read)
|
char *target, int *bytes_read)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 0);
|
ncp_add_byte(server, 0);
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_dword(server, htonl(offset));
|
ncp_add_dword(server, htonl(offset));
|
ncp_add_word(server, htons(to_read));
|
ncp_add_word(server, htons(to_read));
|
|
|
if ((result = ncp_request(server, 72)) != 0)
|
if ((result = ncp_request(server, 72)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
*bytes_read = ntohs(ncp_reply_word(server, 0));
|
*bytes_read = ntohs(ncp_reply_word(server, 0));
|
|
|
memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
|
memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
|
|
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_write(struct ncp_server *server, const char *file_id,
|
ncp_write(struct ncp_server *server, const char *file_id,
|
__u32 offset, __u16 to_write,
|
__u32 offset, __u16 to_write,
|
const char *source, int *bytes_written)
|
const char *source, int *bytes_written)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 0);
|
ncp_add_byte(server, 0);
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_dword(server, htonl(offset));
|
ncp_add_dword(server, htonl(offset));
|
ncp_add_word(server, htons(to_write));
|
ncp_add_word(server, htons(to_write));
|
ncp_add_mem_fromfs(server, source, to_write);
|
ncp_add_mem_fromfs(server, source, to_write);
|
|
|
if ((result = ncp_request(server, 73)) != 0)
|
if ((result = ncp_request(server, 73)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
|
|
*bytes_written = to_write;
|
*bytes_written = to_write;
|
|
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
#ifdef CONFIG_NCPFS_IOCTL_LOCKING
|
#ifdef CONFIG_NCPFS_IOCTL_LOCKING
|
int
|
int
|
ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id,
|
ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id,
|
__u8 locktype, __u32 offset, __u32 length, __u16 timeout)
|
__u8 locktype, __u32 offset, __u32 length, __u16 timeout)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, locktype);
|
ncp_add_byte(server, locktype);
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_dword(server, htonl(offset));
|
ncp_add_dword(server, htonl(offset));
|
ncp_add_dword(server, htonl(length));
|
ncp_add_dword(server, htonl(length));
|
ncp_add_word(server, htons(timeout));
|
ncp_add_word(server, htons(timeout));
|
|
|
if ((result = ncp_request(server, 0x1A)) != 0)
|
if ((result = ncp_request(server, 0x1A)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
|
ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
|
__u32 offset, __u32 length)
|
__u32 offset, __u32 length)
|
{
|
{
|
int result;
|
int result;
|
|
|
ncp_init_request(server);
|
ncp_init_request(server);
|
ncp_add_byte(server, 0); /* who knows... lanalyzer says that */
|
ncp_add_byte(server, 0); /* who knows... lanalyzer says that */
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_mem(server, file_id, 6);
|
ncp_add_dword(server, htonl(offset));
|
ncp_add_dword(server, htonl(offset));
|
ncp_add_dword(server, htonl(length));
|
ncp_add_dword(server, htonl(length));
|
|
|
if ((result = ncp_request(server, 0x1E)) != 0)
|
if ((result = ncp_request(server, 0x1E)) != 0)
|
{
|
{
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return result;
|
return result;
|
}
|
}
|
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
return 0;
|
return 0;
|
}
|
}
|
#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
|
#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
|
|
|
|
|