ncplib_kernel.c revision 32c419d95f3d1da891ab9bd032a214ee05b94ed4
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  ncplib_kernel.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1995, 1996 by Volker Lendecke
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Modified for big endian by J.F. Chadima and David S. Miller
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Modified 1999 Wolfram Pienkoss for NLS
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1432c419d95f3d1da891ab9bd032a214ee05b94ed4Al Viro#include "ncp_fs.h"
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void assert_server_locked(struct ncp_server *server)
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (server->lock == 0) {
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DPRINTK("ncpfs: server not locked!\n");
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ncp_add_byte(struct ncp_server *server, __u8 x)
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	assert_server_locked(server);
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*(__u8 *) (&(server->packet[server->current_size])) = x;
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->current_size += 1;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ncp_add_word(struct ncp_server *server, __le16 x)
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	assert_server_locked(server);
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_unaligned(x, (__le16 *) (&(server->packet[server->current_size])));
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->current_size += 2;
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ncp_add_be16(struct ncp_server *server, __u16 x)
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	assert_server_locked(server);
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_unaligned(cpu_to_be16(x), (__be16 *) (&(server->packet[server->current_size])));
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->current_size += 2;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ncp_add_dword(struct ncp_server *server, __le32 x)
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	assert_server_locked(server);
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_unaligned(x, (__le32 *) (&(server->packet[server->current_size])));
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->current_size += 4;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ncp_add_be32(struct ncp_server *server, __u32 x)
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	assert_server_locked(server);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_unaligned(cpu_to_be32(x), (__be32 *)(&(server->packet[server->current_size])));
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->current_size += 4;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void ncp_add_dword_lh(struct ncp_server *server, __u32 x) {
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, cpu_to_le32(x));
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ncp_add_mem(struct ncp_server *server, const void *source, int size)
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	assert_server_locked(server);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&(server->packet[server->current_size]), source, size);
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->current_size += size;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ncp_add_pstring(struct ncp_server *server, const char *s)
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len = strlen(s);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	assert_server_locked(server);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len > 255) {
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DPRINTK("ncpfs: string too long: %s\n", s);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = 255;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, len);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, s, len);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void ncp_init_request(struct ncp_server *server)
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_lock_server(server);
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->current_size = sizeof(struct ncp_request_header);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->has_subfunction = 0;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void ncp_init_request_s(struct ncp_server *server, int subfunction)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_lock_server(server);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->current_size = sizeof(struct ncp_request_header) + 2;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, subfunction);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->has_subfunction = 1;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline char *
10597a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrisonncp_reply_data(struct ncp_server *server, int offset)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1102e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecstatic inline u8 BVAL(const void *data)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1122e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	return *(const u8 *)data;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11597a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrisonstatic u8 ncp_reply_byte(struct ncp_server *server, int offset)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1172e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	return *(const u8 *)ncp_reply_data(server, offset);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1202e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecstatic inline u16 WVAL_LH(const void *data)
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12297a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison	return get_unaligned_le16(data);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12597a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrisonstatic u16
12697a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrisonncp_reply_le16(struct ncp_server *server, int offset)
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12897a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison	return get_unaligned_le16(ncp_reply_data(server, offset));
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13197a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrisonstatic u16
13297a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrisonncp_reply_be16(struct ncp_server *server, int offset)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13497a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison	return get_unaligned_be16(ncp_reply_data(server, offset));
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1372e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecstatic inline u32 DVAL_LH(const void *data)
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13997a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison	return get_unaligned_le32(data);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __le32
14397a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrisonncp_reply_dword(struct ncp_server *server, int offset)
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14597a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison	return get_unaligned((__le32 *)ncp_reply_data(server, offset));
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) {
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return le32_to_cpu(ncp_reply_dword(server, offset));
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_negotiate_buffersize(struct ncp_server *server, int size, int *target)
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, size);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 33)) != 0) {
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*target = min_t(unsigned int, ncp_reply_be16(server, 0), size);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* options:
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	bit 0	ipx checksum
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	bit 1	packet signing
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_negotiate_size_and_options(struct ncp_server *server,
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int size, int options, int *ret_size, int *ret_options) {
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* there is minimum */
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (size < NCP_BLOCK_SIZE) size = NCP_BLOCK_SIZE;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, size);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, options);
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 0x61)) != 0)
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* NCP over UDP returns 0 (!!!) */
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_reply_be16(server, 0);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result >= NCP_BLOCK_SIZE)
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size = min(result, size);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*ret_size = size;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*ret_options = ncp_reply_byte(server, 4);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_get_volume_info_with_number(struct ncp_server* server,
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     int n, struct ncp_volume_info* target) {
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request_s(server, 44);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, n);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 22)) != 0) {
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->total_blocks = ncp_reply_dword_lh(server, 0);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->free_blocks = ncp_reply_dword_lh(server, 4);
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->purgeable_blocks = ncp_reply_dword_lh(server, 8);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->not_yet_purgeable_blocks = ncp_reply_dword_lh(server, 12);
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->total_dir_entries = ncp_reply_dword_lh(server, 16);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->available_dir_entries = ncp_reply_dword_lh(server, 20);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->sectors_per_block = ncp_reply_byte(server, 28);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(&(target->volume_name), 0, sizeof(target->volume_name));
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = -EIO;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = ncp_reply_byte(server, 29);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len > NCP_VOLNAME_LEN) {
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DPRINTK("ncpfs: volume name too long: %d\n", len);
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = 0;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_get_directory_info(struct ncp_server* server, __u8 n,
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   struct ncp_volume_info* target) {
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request_s(server, 45);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, n);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 22)) != 0) {
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->total_blocks = ncp_reply_dword_lh(server, 0);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->free_blocks = ncp_reply_dword_lh(server, 4);
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->purgeable_blocks = 0;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->not_yet_purgeable_blocks = 0;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->total_dir_entries = ncp_reply_dword_lh(server, 8);
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->available_dir_entries = ncp_reply_dword_lh(server, 12);
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->sectors_per_block = ncp_reply_byte(server, 20);
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(&(target->volume_name), 0, sizeof(target->volume_name));
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = -EIO;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = ncp_reply_byte(server, 21);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len > NCP_VOLNAME_LEN) {
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DPRINTK("ncpfs: volume name too long: %d\n", len);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&(target->volume_name), ncp_reply_data(server, 22), len);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = 0;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_close_file(struct ncp_server *server, const char *file_id)
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 66);
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_make_closed(struct inode *inode)
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = 0;
2928e3f90459b7052c31a9669417b837fb14aa6d313Ingo Molnar	mutex_lock(&NCP_FINFO(inode)->open_mutex);
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (atomic_read(&NCP_FINFO(inode)->opened) == 1) {
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_set(&NCP_FINFO(inode)->opened, 0);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle);
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!err)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			PPRINTK("ncp_make_closed: volnum=%d, dirent=%u, error=%d\n",
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				NCP_FINFO(inode)->volNumber,
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				NCP_FINFO(inode)->dirEntNum, err);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3028e3f90459b7052c31a9669417b837fb14aa6d313Ingo Molnar	mutex_unlock(&NCP_FINFO(inode)->open_mutex);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__le32 dir_base, int have_dir_base,
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				const char *path)
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, vol_num);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, dir_base);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (have_dir_base != 0) {
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 1);	/* dir_base */
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 0xff);	/* no handle */
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (path != NULL) {
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 1);	/* 1 component */
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_pstring(server, path);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 0);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __le32 dirent,
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__u8* dirhandle) {
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 12);		/* subfunction */
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, NW_NS_DOS);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, 0);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, NULL);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) == 0) {
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*dirhandle = ncp_reply_byte(server, 0);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) {
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request_s(server, 20);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, dirhandle);
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 22);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3522e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecvoid ncp_extract_file_info(const void *structure, struct nw_info_struct *target)
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3542e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	const __u8 *name_len;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(target, structure, info_struct_size);
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	name_len = structure + info_struct_size;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->nameLen = *name_len;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(target->entryName, name_len + 1, *name_len);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->entryName[*name_len] = '\0';
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->volNumber = le32_to_cpu(target->volNumber);
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
3672e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecstatic inline void ncp_extract_nfs_info(const unsigned char *structure,
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 struct nw_nfs_info *target)
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->mode = DVAL_LH(structure);
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->rdev = DVAL_LH(structure + 8);
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_obtain_nfs_info(struct ncp_server *server,
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		        struct nw_info_struct *target)
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result = 0;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u32 volnum = target->volNumber;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ncp_is_nfs_extras(server, volnum)) {
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_init_request(server);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 19);	/* subfunction */
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, server->name_space[volnum]);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, NW_NS_NFS);
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 0);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, volnum);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword(server, target->dirEntNum);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We must retrieve both nlinks and rdev, otherwise some server versions
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   report zeroes instead of valid data */
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((result = ncp_request(server, 87)) == 0) {
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs);
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DPRINTK(KERN_DEBUG
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"ncp_obtain_nfs_info: (%s) mode=0%o, rdev=0x%x\n",
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				target->entryName, target->nfs.mode,
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				target->nfs.rdev);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			target->nfs.mode = 0;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			target->nfs.rdev = 0;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        ncp_unlock_server(server);
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		target->nfs.mode = 0;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		target->nfs.rdev = 0;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns information for a (one-component) name relative to
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the specified directory.
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4202e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecint ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path,
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct nw_info_struct *target)
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum = NCP_FINFO(dir)->volNumber;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (target == NULL) {
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "ncp_obtain_info: invalid call\n");
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 6);	/* subfunction */
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006));	/* get all */
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_ALL);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, path);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0)
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_extract_file_info(ncp_reply_data(server, 0), target);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_obtain_nfs_info(server, target);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_obtain_DOS_dir_base(struct ncp_server *server,
4552e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		__u8 ns, __u8 volnum, __le32 dirent,
4562e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		const char *path, /* At most 1 component */
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__le32 *DOS_dir_base)
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 6); /* subfunction */
4632e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_add_byte(server, ns);
4642e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_add_byte(server, ns);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_DIRECTORY);
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, path);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) == 0)
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   	if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34);
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_NCPFS_NFS_NS */
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_get_known_namespace(struct ncp_server *server, __u8 volume)
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS)
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8 *namespace;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u16 no_namespaces;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 24);	/* Subfunction: Get Name Spaces Loaded */
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, 0);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, volume);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0) {
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NW_NS_DOS; /* not result ?? */
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = NW_NS_DOS;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	no_namespaces = ncp_reply_le16(server, 0);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	namespace = ncp_reply_data(server, 2);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (no_namespaces > 0) {
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DPRINTK("get_namespaces: found %d on %d\n", *namespace, volume);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS))
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = NW_NS_NFS;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_NCPFS_NFS_NS */
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_OS2_NS
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2))
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = NW_NS_OS2;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_NCPFS_OS2_NS */
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		namespace += 1;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		no_namespaces -= 1;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else	/* neither OS2 nor NFS - only DOS */
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NW_NS_DOS;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5262e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecint
5272e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
5282e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec{
5292e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	int ns = ncp_get_known_namespace(server, volume);
5302e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5312e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	if (ret_ns)
5322e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		*ret_ns = ns;
5332e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5342e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	DPRINTK("lookup_vol: namespace[%d] = %d\n",
5352e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		volume, server->name_space[volume]);
5362e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5372e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	if (server->name_space[volume] == ns)
5382e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		return 0;
5392e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	server->name_space[volume] = ns;
5402e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	return 1;
5412e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec}
5422e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_ObtainSpecificDirBase(struct ncp_server *server,
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
5462e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		const char *path, /* At most 1 component */
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__le32 *dirEntNum, __le32 *DosDirNum)
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 6); /* subfunction */
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, nsSrc);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, nsDst);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_ALL);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, vol_num, dir_base, 1, path);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0)
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dirEntNum)
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*dirEntNum = ncp_reply_dword(server, 0x30);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (DosDirNum)
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*DosDirNum = ncp_reply_dword(server, 0x34);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_mount_subdir(struct ncp_server *server,
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 __u8 volNumber, __u8 srcNS, __le32 dirEntNum,
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 __u32* volume, __le32* newDirEnt, __le32* newDosEnt)
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int dstNS;
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
5802e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5812e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_update_known_namespace(server, volNumber, &dstNS);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber,
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*volume = volNumber;
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->m.mounted_vol[1] = 0;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->m.mounted_vol[0] = 'X';
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
5942e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecncp_get_volume_root(struct ncp_server *server,
5952e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		    const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent)
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 22);	/* Subfunction: Generate dir handle */
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* DOS namespace */
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* faked volume number */
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, 0);	/* faked dir_base */
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0xff);	/* Don't have a dir_base */
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* 1 path component */
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_pstring(server, volname);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0) {
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*dirent = *dosdirent = ncp_reply_dword(server, 4);
6192e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	*volume = ncp_reply_byte(server, 8);
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
6252e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecncp_lookup_volume(struct ncp_server *server,
6262e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		  const char *volname, struct nw_info_struct *target)
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(target, 0, sizeof(*target));
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_get_volume_root(server, volname,
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&target->volNumber, &target->dirEntNum, &target->DosDirNum);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result) {
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6362e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_update_known_namespace(server, target->volNumber, NULL);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->nameLen = strlen(volname);
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(target->entryName, volname, target->nameLen+1);
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->attributes = aDIR;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* set dates to Jan 1, 1986  00:00 */
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->creationTime = target->modifyTime = cpu_to_le16(0x0000);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21);
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->nfs.mode = 0;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    struct inode *dir,
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    const char *path,
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    __le32 info_mask,
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    const struct nw_modify_dos_info *info)
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum = NCP_FINFO(dir)->volNumber;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 7);	/* subfunction */
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006));	/* search attribs: all */
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, info_mask);
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, info, sizeof(*info));
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, path);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 87);
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       struct inode *dir,
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       __le32 info_mask,
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       const struct nw_modify_dos_info *info)
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL,
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info_mask, info);
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       __u32 mode, __u32 rdev)
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result = 0;
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6882e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_init_request(server);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (server->name_space[volnum] == NW_NS_NFS) {
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 25);	/* subfunction */
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, server->name_space[volnum]);
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, NW_NS_NFS);
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, volnum);
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword(server, dirent);
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* we must always operate on both nlinks and rdev, otherwise
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   rdev is not set */
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, mode);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, 1);	/* nlinks */
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, rdev);
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = ncp_request(server, 87);
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7032e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_unlock_server(server);
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_DeleteNSEntry(struct ncp_server *server,
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  __u8 have_dir_base, __u8 volnum, __le32 dirent,
7122e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		  const char* name, __u8 ns, __le16 attr)
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 8);	/* subfunction */
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, ns);
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, attr);	/* search attribs: all */
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, have_dir_base, name);
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 87);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_del_file_or_subdir2(struct ncp_server *server,
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct dentry *dentry)
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct inode *inode = dentry->d_inode;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!inode) {
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0xFF;	/* Any error */
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volnum = NCP_FINFO(inode)->volNumber;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dirent = NCP_FINFO(inode)->DosDirNum;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_del_file_or_subdir(struct ncp_server *server,
7462e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		       struct inode *dir, const char *name)
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum = NCP_FINFO(dir)->volNumber;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
7502e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	int name_space;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7522e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	name_space = server->name_space[volnum];
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
7542e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	if (name_space == NW_NS_NFS)
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	{
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		int result;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7582e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent);
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		if (result) return result;
7602e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		name = NULL;
7612e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		name_space = NW_NS_DOS;
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	}
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_NCPFS_NFS_NS */
7642e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006));
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le16 *dest = (__le16 *) ret;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dest[1] = cpu_to_le16(v0);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dest[2] = cpu_to_le16(v1);
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dest[0] = cpu_to_le16(v0 + 1);
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If both dir and name are NULL, then in target there's already a
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   looked-up entry that wants to be opened. */
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_open_create_file_or_subdir(struct ncp_server *server,
7792e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec				   struct inode *dir, const char *name,
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   int open_create_mode,
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   __le32 create_attributes,
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   __le16 desired_acc_rights,
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   struct ncp_entry_info *target)
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le16 search_attribs = cpu_to_le16(0x0006);
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volnum = NCP_FINFO(dir)->volNumber;
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dirent = NCP_FINFO(dir)->dirEntNum;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((create_attributes & aDIR) != 0) {
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		search_attribs |= cpu_to_le16(0x8000);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* subfunction */
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]);
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, open_create_mode);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, search_attribs);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_ALL);
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, create_attributes);
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The desired acc rights seem to be the inherited rights mask
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   for directories */
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, desired_acc_rights);
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, name);
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0)
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(create_attributes & aDIR))
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		target->opened = 1;
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* in target there's a new finfo to fill */
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->volume = target->i.volNumber;
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ConvertToNWfromDWORD(ncp_reply_le16(server, 0),
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     ncp_reply_le16(server, 2),
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     target->file_handle);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(void)ncp_obtain_nfs_info(server, &(target->i));
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_initialize_search(struct ncp_server *server, struct inode *dir,
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct nw_search_sequence *target)
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum = NCP_FINFO(dir)->volNumber;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 2);	/* subfunction */
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]);
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, NULL);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 87);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result)
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_search_for_fileset(struct ncp_server *server,
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   struct nw_search_sequence *seq,
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   int* more,
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   int* cnt,
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   char* buffer,
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   size_t bufsize,
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   char** rbuf,
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   size_t* rsize)
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 20);
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[seq->volNumber]);
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);		/* datastream */
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006));
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_ALL);
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(32767));	/* max returned items */
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, seq, 9);
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (server->name_space[seq->volNumber] == NW_NS_NFS) {
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 0);	/* 0 byte pattern */
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 2);	/* 2 byte pattern */
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 0xff);	/* following is a wildcard */
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, '*');
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request2(server, 87, buffer, bufsize);
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result) {
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (server->ncp_reply_size < 12) {
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0xFF;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*rsize = server->ncp_reply_size - 12;
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	buffer = buffer + sizeof(struct ncp_reply_header);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*rbuf = buffer + 12;
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*cnt = WVAL_LH(buffer + 10);
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*more = BVAL(buffer + 9);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(seq, buffer, 9);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_RenameNSEntry(struct ncp_server *server,
9042e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		  struct inode *old_dir, const char *old_name, __le16 old_type,
9052e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		  struct inode *new_dir, const char *new_name)
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result = -EINVAL;
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((old_dir == NULL) || (old_name == NULL) ||
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (new_dir == NULL) || (new_name == NULL))
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 4);	/* subfunction */
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[NCP_FINFO(old_dir)->volNumber]);
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* rename flag */
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, old_type);	/* search attributes */
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* source Handle Path */
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, NCP_FINFO(old_dir)->volNumber);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, NCP_FINFO(old_dir)->dirEntNum);
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* 1 source component */
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* dest Handle Path */
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, NCP_FINFO(new_dir)->volNumber);
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, NCP_FINFO(new_dir)->dirEntNum);
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* 1 destination component */
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* source path string */
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_pstring(server, old_name);
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* dest path string */
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_pstring(server, new_name);
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 87);
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
9432e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec				struct inode *old_dir, const char *old_name,
9442e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec				struct inode *new_dir, const char *new_name)
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int result;
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __le16 old_type = cpu_to_le16(0x06);
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	                                   new_dir, new_name);
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if (result == 0xFF)	/* File Not Found, try directory */
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_type = cpu_to_le16(0x16);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   new_dir, new_name);
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result != 0x92) return result;	/* All except NO_FILES_RENAMED */
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_del_file_or_subdir(server, new_dir, new_name);
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result != 0) return -EACCES;
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   new_dir, new_name);
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* We have to transfer to/from user space */
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_read_kernel(struct ncp_server *server, const char *file_id,
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     __u32 offset, __u16 to_read, char *target, int *bytes_read)
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9722e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	const char *source;
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, to_read);
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 72)) != 0) {
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*bytes_read = ncp_reply_be16(server, 0);
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	source = ncp_reply_data(server, 2 + (offset & 1));
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(target, source, *bytes_read);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* There is a problem... egrep and some other silly tools do:
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x = mmap(NULL, MAP_PRIVATE, PROT_READ|PROT_WRITE, <ncpfs fd>, 32768);
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	read(<ncpfs fd>, x, 32768);
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Now copying read result by copy_to_user causes pagefault. This pagefault
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   could not be handled because of server was locked due to read. So we have
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   to use temporary buffer. So ncp_unlock_server must be done before
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   copy_to_user (and for write, copy_from_user must be done before
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   ncp_init_request... same applies for send raw packet ioctl). Because of
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   file is normally read in bigger chunks, caller provides kmalloced
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   (vmalloced) chunk of memory with size >= to_read...
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_read_bounce(struct ncp_server *server, const char *file_id,
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 __u32 offset, __u16 to_read, char __user *target, int *bytes_read,
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 void* bounce, __u32 bufsize)
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, to_read);
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request2(server, 72, bounce, bufsize);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!result) {
101997a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison		int len = get_unaligned_be16((char *)bounce +
102097a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison			  sizeof(struct ncp_reply_header));
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = -EIO;
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (len <= to_read) {
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			char* source;
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			source = (char*)bounce +
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			         sizeof(struct ncp_reply_header) + 2 +
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			         (offset & 1);
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*bytes_read = len;
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = 0;
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (copy_to_user(target, source, len))
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				result = -EFAULT;
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_write_kernel(struct ncp_server *server, const char *file_id,
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 __u32 offset, __u16 to_write,
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 const char *source, int *bytes_written)
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, to_write);
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, source, to_write);
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 73)) == 0)
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*bytes_written = to_write;
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_IOCTL_LOCKING
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id,
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  __u8 locktype, __u32 offset, __u32 length, __u16 timeout)
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, locktype);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, length);
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, timeout);
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 0x1A)) != 0)
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  __u32 offset, __u32 length)
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* who knows... lanalyzer says that */
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, length);
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 0x1E)) != 0)
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_NCPFS_IOCTL_LOCKING */
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NLS
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This are the NLS conversion routines with inspirations and code parts
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from the vfat file system and hints from Petr Vandrovec.
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen,
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const unsigned char *iname, unsigned int ilen, int cc)
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nls_table *in = server->nls_io;
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nls_table *out = server->nls_vol;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *vname_start;
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *vname_end;
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const unsigned char *iname_end;
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iname_end = iname + ilen;
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vname_start = vname;
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vname_end = vname + *vlen - 1;
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (iname < iname_end) {
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int chl;
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wchar_t ec;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int k;
112774675a58507e769beee7d949dbed788af3c4139dAlan Stern			unicode_t u;
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
112974675a58507e769beee7d949dbed788af3c4139dAlan Stern			k = utf8_to_utf32(iname, iname_end - iname, &u);
113074675a58507e769beee7d949dbed788af3c4139dAlan Stern			if (k < 0 || u > MAX_WCHAR_T)
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EINVAL;
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iname += k;
113374675a58507e769beee7d949dbed788af3c4139dAlan Stern			ec = u;
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (*iname == NCP_ESC) {
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int k;
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (iname_end - iname < 5)
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto nospec;
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ec = 0;
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				for (k = 1; k < 5; k++) {
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					unsigned char nc;
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					nc = iname[k] - '0';
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (nc >= 10) {
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						nc -= 'A' - '0' - 10;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						if ((nc < 10) || (nc > 15)) {
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							goto nospec;
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						}
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ec = (ec << 4) | nc;
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iname += 5;
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnospec:;
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ( (chl = in->char2uni(iname, iname_end - iname, &ec)) < 0)
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return chl;
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iname += chl;
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* unitoupper should be here! */
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		chl = out->uni2char(ec, vname, vname_end - vname);
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (chl < 0)
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return chl;
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* this is wrong... */
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cc) {
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int chi;
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (chi = 0; chi < chl; chi++){
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vname[chi] = ncp_toupper(out, vname[chi]);
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname += chl;
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*vname = 0;
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*vlen = vname - vname_start;
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen,
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const unsigned char *vname, unsigned int vlen, int cc)
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nls_table *in = server->nls_vol;
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nls_table *out = server->nls_io;
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const unsigned char *vname_end;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *iname_start;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *iname_end;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *vname_cc;
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vname_cc = NULL;
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cc) {
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* this is wrong! */
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname_cc = kmalloc(vlen, GFP_KERNEL);
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!vname_cc)
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < vlen; i++)
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vname_cc[i] = ncp_tolower(in, vname[i]);
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname = vname_cc;
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iname_start = iname;
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iname_end = iname + *ilen - 1;
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vname_end = vname + vlen;
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (vname < vname_end) {
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wchar_t ec;
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int chl;
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ( (chl = in->char2uni(vname, vname_end - vname, &ec)) < 0) {
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = chl;
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto quit;
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname += chl;
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* unitolower should be here! */
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int k;
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
123074675a58507e769beee7d949dbed788af3c4139dAlan Stern			k = utf32_to_utf8(ec, iname, iname_end - iname);
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (k < 0) {
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = -ENAMETOOLONG;
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto quit;
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iname += k;
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ( (chl = out->uni2char(ec, iname, iname_end - iname)) >= 0) {
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iname += chl;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int k;
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (iname_end - iname < 5) {
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					err = -ENAMETOOLONG;
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto quit;
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*iname = NCP_ESC;
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				for (k = 4; k > 0; k--) {
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					unsigned char v;
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					v = (ec & 0xF) + '0';
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (v > '9') {
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						v += 'A' - '9' - 1;
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					iname[k] = v;
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ec >>= 4;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iname += 5;
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*iname = 0;
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*ilen = iname - iname_start;
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = 0;
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsquit:;
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cc)
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(vname_cc);
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp__io2vol(unsigned char *vname, unsigned int *vlen,
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const unsigned char *iname, unsigned int ilen, int cc)
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*vlen <= ilen)
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENAMETOOLONG;
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cc)
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < ilen; i++) {
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*vname = toupper(*iname);
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vname++;
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iname++;
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memmove(vname, iname, ilen);
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname += ilen;
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*vlen = ilen;
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*vname = 0;
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp__vol2io(unsigned char *iname, unsigned int *ilen,
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const unsigned char *vname, unsigned int vlen, int cc)
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*ilen <= vlen)
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENAMETOOLONG;
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cc)
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < vlen; i++) {
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*iname = tolower(*vname);
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iname++;
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vname++;
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memmove(iname, vname, vlen);
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iname += vlen;
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*ilen = vlen;
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*iname = 0;
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1324