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
12b41f8b84d01d32ea618dbbe5679bd07ce3444b88Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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) {
19d3b73ca1be3236fc33f896af7e2ba637a677d5c9Joe Perches		ncp_dbg(1, "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) {
78d3b73ca1be3236fc33f896af7e2ba637a677d5c9Joe Perches		ncp_dbg(1, "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) {
228d3b73ca1be3236fc33f896af7e2ba637a677d5c9Joe Perches		ncp_dbg(1, "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) {
262d3b73ca1be3236fc33f896af7e2ba637a677d5c9Joe Perches		ncp_dbg(1, "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)
298e45ca8baa33e0c0228e84126c3a20df3abfd1771Joe Perches			ncp_vdbg("volnum=%d, dirent=%u, error=%d\n",
299e45ca8baa33e0c0228e84126c3a20df3abfd1771Joe Perches				 NCP_FINFO(inode)->volNumber,
300e45ca8baa33e0c0228e84126c3a20df3abfd1771Joe Perches				 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);
397d3b73ca1be3236fc33f896af7e2ba637a677d5c9Joe Perches			ncp_dbg(1, "(%s) mode=0%o, rdev=0x%x\n",
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				target->entryName, target->nfs.mode,
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				target->nfs.rdev);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			target->nfs.mode = 0;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			target->nfs.rdev = 0;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        ncp_unlock_server(server);
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		target->nfs.mode = 0;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		target->nfs.rdev = 0;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns information for a (one-component) name relative to
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the specified directory.
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4192e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecint ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path,
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct nw_info_struct *target)
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum = NCP_FINFO(dir)->volNumber;
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (target == NULL) {
427b41f8b84d01d32ea618dbbe5679bd07ce3444b88Joe Perches		pr_err("%s: invalid call\n", __func__);
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 6);	/* subfunction */
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006));	/* get all */
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_ALL);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, path);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0)
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_extract_file_info(ncp_reply_data(server, 0), target);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_obtain_nfs_info(server, target);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_obtain_DOS_dir_base(struct ncp_server *server,
4542e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		__u8 ns, __u8 volnum, __le32 dirent,
4552e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		const char *path, /* At most 1 component */
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__le32 *DOS_dir_base)
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 6); /* subfunction */
4622e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_add_byte(server, ns);
4632e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_add_byte(server, ns);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_DIRECTORY);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, path);
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) == 0)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   	if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_NCPFS_NFS_NS */
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_get_known_namespace(struct ncp_server *server, __u8 volume)
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS)
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8 *namespace;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u16 no_namespaces;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 24);	/* Subfunction: Get Name Spaces Loaded */
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, 0);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, volume);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0) {
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NW_NS_DOS; /* not result ?? */
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = NW_NS_DOS;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	no_namespaces = ncp_reply_le16(server, 0);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	namespace = ncp_reply_data(server, 2);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (no_namespaces > 0) {
500d3b73ca1be3236fc33f896af7e2ba637a677d5c9Joe Perches		ncp_dbg(1, "found %d on %d\n", *namespace, volume);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS))
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = NW_NS_NFS;
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_NCPFS_NFS_NS */
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_OS2_NS
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2))
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = NW_NS_OS2;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_NCPFS_OS2_NS */
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		namespace += 1;
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		no_namespaces -= 1;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else	/* neither OS2 nor NFS - only DOS */
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NW_NS_DOS;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5252e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecint
5262e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
5272e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec{
5282e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	int ns = ncp_get_known_namespace(server, volume);
5292e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5302e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	if (ret_ns)
5312e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		*ret_ns = ns;
5322e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
533d3b73ca1be3236fc33f896af7e2ba637a677d5c9Joe Perches	ncp_dbg(1, "namespace[%d] = %d\n", volume, server->name_space[volume]);
5342e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5352e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	if (server->name_space[volume] == ns)
5362e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		return 0;
5372e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	server->name_space[volume] = ns;
5382e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	return 1;
5392e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec}
5402e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_ObtainSpecificDirBase(struct ncp_server *server,
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
5442e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		const char *path, /* At most 1 component */
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__le32 *dirEntNum, __le32 *DosDirNum)
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 6); /* subfunction */
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, nsSrc);
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, nsDst);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_ALL);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, vol_num, dir_base, 1, path);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0)
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dirEntNum)
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*dirEntNum = ncp_reply_dword(server, 0x30);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (DosDirNum)
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*DosDirNum = ncp_reply_dword(server, 0x34);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_mount_subdir(struct ncp_server *server,
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 __u8 volNumber, __u8 srcNS, __le32 dirEntNum,
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 __u32* volume, __le32* newDirEnt, __le32* newDosEnt)
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int dstNS;
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
5782e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec
5792e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_update_known_namespace(server, volNumber, &dstNS);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber,
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*volume = volNumber;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->m.mounted_vol[1] = 0;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	server->m.mounted_vol[0] = 'X';
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
5922e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecncp_get_volume_root(struct ncp_server *server,
5932e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		    const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent)
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
597d3b73ca1be3236fc33f896af7e2ba637a677d5c9Joe Perches	ncp_dbg(1, "looking up vol %s\n", volname);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 22);	/* Subfunction: Generate dir handle */
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* DOS namespace */
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* faked volume number */
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, 0);	/* faked dir_base */
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0xff);	/* Don't have a dir_base */
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* 1 path component */
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_pstring(server, volname);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0) {
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*dirent = *dosdirent = ncp_reply_dword(server, 4);
6172e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	*volume = ncp_reply_byte(server, 8);
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
6232e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovecncp_lookup_volume(struct ncp_server *server,
6242e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		  const char *volname, struct nw_info_struct *target)
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(target, 0, sizeof(*target));
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_get_volume_root(server, volname,
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&target->volNumber, &target->dirEntNum, &target->DosDirNum);
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result) {
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6342e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_update_known_namespace(server, target->volNumber, NULL);
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->nameLen = strlen(volname);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(target->entryName, volname, target->nameLen+1);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->attributes = aDIR;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* set dates to Jan 1, 1986  00:00 */
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->creationTime = target->modifyTime = cpu_to_le16(0x0000);
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21);
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->nfs.mode = 0;
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    struct inode *dir,
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    const char *path,
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    __le32 info_mask,
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    const struct nw_modify_dos_info *info)
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum = NCP_FINFO(dir)->volNumber;
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 7);	/* subfunction */
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006));	/* search attribs: all */
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, info_mask);
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, info, sizeof(*info));
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, path);
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 87);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       struct inode *dir,
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       __le32 info_mask,
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       const struct nw_modify_dos_info *info)
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL,
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info_mask, info);
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       __u32 mode, __u32 rdev)
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result = 0;
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6862e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_init_request(server);
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (server->name_space[volnum] == NW_NS_NFS) {
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 25);	/* subfunction */
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, server->name_space[volnum]);
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, NW_NS_NFS);
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, volnum);
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword(server, dirent);
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* we must always operate on both nlinks and rdev, otherwise
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   rdev is not set */
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, mode);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, 1);	/* nlinks */
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_dword_lh(server, rdev);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = ncp_request(server, 87);
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7012e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	ncp_unlock_server(server);
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_DeleteNSEntry(struct ncp_server *server,
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  __u8 have_dir_base, __u8 volnum, __le32 dirent,
7102e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		  const char* name, __u8 ns, __le16 attr)
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 8);	/* subfunction */
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, ns);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, attr);	/* search attribs: all */
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, have_dir_base, name);
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 87);
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_del_file_or_subdir2(struct ncp_server *server,
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct dentry *dentry)
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct inode *inode = dentry->d_inode;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!inode) {
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0xFF;	/* Any error */
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volnum = NCP_FINFO(inode)->volNumber;
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dirent = NCP_FINFO(inode)->DosDirNum;
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_del_file_or_subdir(struct ncp_server *server,
7442e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		       struct inode *dir, const char *name)
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum = NCP_FINFO(dir)->volNumber;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
7482e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	int name_space;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7502e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	name_space = server->name_space[volnum];
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
7522e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	if (name_space == NW_NS_NFS)
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	{
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		int result;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7562e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent);
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		if (result) return result;
7582e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		name = NULL;
7592e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		name_space = NW_NS_DOS;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	}
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_NCPFS_NFS_NS */
7622e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006));
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le16 *dest = (__le16 *) ret;
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dest[1] = cpu_to_le16(v0);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dest[2] = cpu_to_le16(v1);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dest[0] = cpu_to_le16(v0 + 1);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If both dir and name are NULL, then in target there's already a
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   looked-up entry that wants to be opened. */
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_open_create_file_or_subdir(struct ncp_server *server,
7772e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec				   struct inode *dir, const char *name,
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   int open_create_mode,
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   __le32 create_attributes,
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   __le16 desired_acc_rights,
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   struct ncp_entry_info *target)
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le16 search_attribs = cpu_to_le16(0x0006);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volnum = NCP_FINFO(dir)->volNumber;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dirent = NCP_FINFO(dir)->dirEntNum;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((create_attributes & aDIR) != 0) {
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		search_attribs |= cpu_to_le16(0x8000);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* subfunction */
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, open_create_mode);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, search_attribs);
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_ALL);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, create_attributes);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The desired acc rights seem to be the inherited rights mask
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   for directories */
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, desired_acc_rights);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, name);
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 87)) != 0)
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(create_attributes & aDIR))
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		target->opened = 1;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* in target there's a new finfo to fill */
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target->volume = target->i.volNumber;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ConvertToNWfromDWORD(ncp_reply_le16(server, 0),
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     ncp_reply_le16(server, 2),
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     target->file_handle);
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(void)ncp_obtain_nfs_info(server, &(target->i));
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_initialize_search(struct ncp_server *server, struct inode *dir,
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct nw_search_sequence *target)
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8  volnum = NCP_FINFO(dir)->volNumber;
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 2);	/* subfunction */
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[volnum]);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* reserved */
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_handle_path(server, volnum, dirent, 1, NULL);
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 87);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result)
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_search_for_fileset(struct ncp_server *server,
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   struct nw_search_sequence *seq,
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   int* more,
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   int* cnt,
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   char* buffer,
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   size_t bufsize,
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   char** rbuf,
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   size_t* rsize)
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 20);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[seq->volNumber]);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);		/* datastream */
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(0x8006));
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, RIM_ALL);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, cpu_to_le16(32767));	/* max returned items */
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, seq, 9);
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NFS_NS
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (server->name_space[seq->volNumber] == NW_NS_NFS) {
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 0);	/* 0 byte pattern */
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 2);	/* 2 byte pattern */
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, 0xff);	/* following is a wildcard */
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_add_byte(server, '*');
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request2(server, 87, buffer, bufsize);
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result) {
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (server->ncp_reply_size < 12) {
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0xFF;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*rsize = server->ncp_reply_size - 12;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	buffer = buffer + sizeof(struct ncp_reply_header);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*rbuf = buffer + 12;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*cnt = WVAL_LH(buffer + 10);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*more = BVAL(buffer + 9);
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(seq, buffer, 9);
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_RenameNSEntry(struct ncp_server *server,
9022e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		  struct inode *old_dir, const char *old_name, __le16 old_type,
9032e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec		  struct inode *new_dir, const char *new_name)
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result = -EINVAL;
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((old_dir == NULL) || (old_name == NULL) ||
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (new_dir == NULL) || (new_name == NULL))
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 4);	/* subfunction */
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, server->name_space[NCP_FINFO(old_dir)->volNumber]);
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* rename flag */
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_word(server, old_type);	/* search attributes */
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* source Handle Path */
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, NCP_FINFO(old_dir)->volNumber);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, NCP_FINFO(old_dir)->dirEntNum);
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* 1 source component */
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* dest Handle Path */
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, NCP_FINFO(new_dir)->volNumber);
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_dword(server, NCP_FINFO(new_dir)->dirEntNum);
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 1);	/* 1 destination component */
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* source path string */
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_pstring(server, old_name);
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* dest path string */
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_pstring(server, new_name);
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request(server, 87);
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
9412e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec				struct inode *old_dir, const char *old_name,
9422e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec				struct inode *new_dir, const char *new_name)
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int result;
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __le16 old_type = cpu_to_le16(0x06);
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	                                   new_dir, new_name);
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if (result == 0xFF)	/* File Not Found, try directory */
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_type = cpu_to_le16(0x16);
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   new_dir, new_name);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result != 0x92) return result;	/* All except NO_FILES_RENAMED */
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_del_file_or_subdir(server, new_dir, new_name);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result != 0) return -EACCES;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   new_dir, new_name);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* We have to transfer to/from user space */
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_read_kernel(struct ncp_server *server, const char *file_id,
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     __u32 offset, __u16 to_read, char *target, int *bytes_read)
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9702e54eb96e2c801f33d95b5dade15212ac4d6c4a5Petr Vandrovec	const char *source;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, to_read);
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 72)) != 0) {
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*bytes_read = ncp_reply_be16(server, 0);
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	source = ncp_reply_data(server, 2 + (offset & 1));
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(target, source, *bytes_read);
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* There is a problem... egrep and some other silly tools do:
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x = mmap(NULL, MAP_PRIVATE, PROT_READ|PROT_WRITE, <ncpfs fd>, 32768);
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	read(<ncpfs fd>, x, 32768);
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Now copying read result by copy_to_user causes pagefault. This pagefault
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   could not be handled because of server was locked due to read. So we have
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   to use temporary buffer. So ncp_unlock_server must be done before
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   copy_to_user (and for write, copy_from_user must be done before
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   ncp_init_request... same applies for send raw packet ioctl). Because of
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   file is normally read in bigger chunks, caller provides kmalloced
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   (vmalloced) chunk of memory with size >= to_read...
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_read_bounce(struct ncp_server *server, const char *file_id,
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 __u32 offset, __u16 to_read, char __user *target, int *bytes_read,
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 void* bounce, __u32 bufsize)
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, to_read);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = ncp_request2(server, 72, bounce, bufsize);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!result) {
101797a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison		int len = get_unaligned_be16((char *)bounce +
101897a4feb4a78ae5cd130be7d546471a0779f1aa14Harvey Harrison			  sizeof(struct ncp_reply_header));
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = -EIO;
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (len <= to_read) {
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			char* source;
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			source = (char*)bounce +
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			         sizeof(struct ncp_reply_header) + 2 +
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			         (offset & 1);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*bytes_read = len;
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = 0;
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (copy_to_user(target, source, len))
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				result = -EFAULT;
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_write_kernel(struct ncp_server *server, const char *file_id,
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 __u32 offset, __u16 to_write,
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 const char *source, int *bytes_written)
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, to_write);
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, source, to_write);
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 73)) == 0)
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*bytes_written = to_write;
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_IOCTL_LOCKING
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id,
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  __u8 locktype, __u32 offset, __u32 length, __u16 timeout)
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, locktype);
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, length);
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be16(server, timeout);
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 0x1A)) != 0)
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  __u32 offset, __u32 length)
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_init_request(server);
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_byte(server, 0);	/* who knows... lanalyzer says that */
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_mem(server, file_id, 6);
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, offset);
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_add_be32(server, length);
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((result = ncp_request(server, 0x1E)) != 0)
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ncp_unlock_server(server);
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return result;
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ncp_unlock_server(server);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_NCPFS_IOCTL_LOCKING */
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NCPFS_NLS
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This are the NLS conversion routines with inspirations and code parts
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from the vfat file system and hints from Petr Vandrovec.
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen,
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const unsigned char *iname, unsigned int ilen, int cc)
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nls_table *in = server->nls_io;
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nls_table *out = server->nls_vol;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *vname_start;
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *vname_end;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const unsigned char *iname_end;
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iname_end = iname + ilen;
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vname_start = vname;
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vname_end = vname + *vlen - 1;
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (iname < iname_end) {
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int chl;
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wchar_t ec;
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int k;
112574675a58507e769beee7d949dbed788af3c4139dAlan Stern			unicode_t u;
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
112774675a58507e769beee7d949dbed788af3c4139dAlan Stern			k = utf8_to_utf32(iname, iname_end - iname, &u);
112874675a58507e769beee7d949dbed788af3c4139dAlan Stern			if (k < 0 || u > MAX_WCHAR_T)
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EINVAL;
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iname += k;
113174675a58507e769beee7d949dbed788af3c4139dAlan Stern			ec = u;
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (*iname == NCP_ESC) {
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int k;
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (iname_end - iname < 5)
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto nospec;
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ec = 0;
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				for (k = 1; k < 5; k++) {
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					unsigned char nc;
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					nc = iname[k] - '0';
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (nc >= 10) {
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						nc -= 'A' - '0' - 10;
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						if ((nc < 10) || (nc > 15)) {
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							goto nospec;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						}
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ec = (ec << 4) | nc;
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iname += 5;
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnospec:;
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ( (chl = in->char2uni(iname, iname_end - iname, &ec)) < 0)
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return chl;
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iname += chl;
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* unitoupper should be here! */
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		chl = out->uni2char(ec, vname, vname_end - vname);
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (chl < 0)
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return chl;
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* this is wrong... */
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cc) {
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int chi;
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (chi = 0; chi < chl; chi++){
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vname[chi] = ncp_toupper(out, vname[chi]);
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname += chl;
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*vname = 0;
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*vlen = vname - vname_start;
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen,
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const unsigned char *vname, unsigned int vlen, int cc)
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nls_table *in = server->nls_vol;
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nls_table *out = server->nls_io;
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const unsigned char *vname_end;
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *iname_start;
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *iname_end;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *vname_cc;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vname_cc = NULL;
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cc) {
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* this is wrong! */
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname_cc = kmalloc(vlen, GFP_KERNEL);
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!vname_cc)
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < vlen; i++)
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vname_cc[i] = ncp_tolower(in, vname[i]);
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname = vname_cc;
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iname_start = iname;
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iname_end = iname + *ilen - 1;
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vname_end = vname + vlen;
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (vname < vname_end) {
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wchar_t ec;
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int chl;
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ( (chl = in->char2uni(vname, vname_end - vname, &ec)) < 0) {
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = chl;
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto quit;
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname += chl;
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* unitolower should be here! */
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int k;
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122874675a58507e769beee7d949dbed788af3c4139dAlan Stern			k = utf32_to_utf8(ec, iname, iname_end - iname);
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (k < 0) {
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = -ENAMETOOLONG;
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto quit;
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iname += k;
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ( (chl = out->uni2char(ec, iname, iname_end - iname)) >= 0) {
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iname += chl;
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int k;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (iname_end - iname < 5) {
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					err = -ENAMETOOLONG;
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto quit;
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*iname = NCP_ESC;
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				for (k = 4; k > 0; k--) {
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					unsigned char v;
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					v = (ec & 0xF) + '0';
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (v > '9') {
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						v += 'A' - '9' - 1;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					iname[k] = v;
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ec >>= 4;
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iname += 5;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*iname = 0;
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*ilen = iname - iname_start;
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = 0;
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsquit:;
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cc)
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(vname_cc);
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp__io2vol(unsigned char *vname, unsigned int *vlen,
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const unsigned char *iname, unsigned int ilen, int cc)
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*vlen <= ilen)
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENAMETOOLONG;
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cc)
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < ilen; i++) {
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*vname = toupper(*iname);
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vname++;
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iname++;
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memmove(vname, iname, ilen);
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vname += ilen;
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*vlen = ilen;
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*vname = 0;
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsncp__vol2io(unsigned char *iname, unsigned int *ilen,
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const unsigned char *vname, unsigned int vlen, int cc)
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*ilen <= vlen)
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENAMETOOLONG;
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cc)
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < vlen; i++) {
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*iname = tolower(*vname);
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iname++;
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vname++;
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memmove(iname, vname, vlen);
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iname += vlen;
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*ilen = vlen;
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*iname = 0;
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1322