1/*
2 * Copyright (c) 1999, Boris Popov
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33#include <sys/param.h>
34#include <sys/ioctl.h>
35#include <arpa/inet.h>
36#include <errno.h>
37#include <stdio.h>
38#include <fcntl.h>
39#include <unistd.h>
40#include <string.h>
41
42#include <netncp/ncp_lib.h>
43#include <netncp/ncp_file.h>
44#include <fs/nwfs/nwfs.h>
45
46int
47ncp_read(NWCONN_HANDLE connid, ncp_fh *fh, off_t offset, size_t count, char *target) {
48	int result;
49	struct ncp_rw rwrq;
50	DECLARE_RQ;
51
52	ncp_init_request(conn);
53	ncp_add_byte(conn, NCP_CONN_READ);
54	rwrq.nrw_fh = *fh;
55	rwrq.nrw_base = target;
56	rwrq.nrw_cnt = count;
57	rwrq.nrw_offset = offset;
58	ncp_add_mem(conn, &rwrq, sizeof(rwrq));
59	if ((result = ncp_conn_request(connid, conn)) < 0)
60		return -1;
61	return result;
62}
63
64int
65ncp_write(NWCONN_HANDLE connid, ncp_fh *fh, off_t offset, size_t count, char *source)
66{
67	int result;
68	struct ncp_rw rwrq;
69	DECLARE_RQ;
70
71	ncp_init_request(conn);
72	ncp_add_byte(conn, NCP_CONN_WRITE);
73	rwrq.nrw_fh = *fh;
74	rwrq.nrw_base = source;
75	rwrq.nrw_cnt = count;
76	rwrq.nrw_offset = offset;
77	ncp_add_mem(conn, &rwrq, sizeof(rwrq));
78
79	if ((result = ncp_conn_request(connid, conn)) < 0)
80		return -1;
81	return result;
82}
83
84int
85ncp_geteinfo(char *path, struct nw_entry_info *fi) {
86	int d, error;
87
88	if ((d = open(path, O_RDONLY)) < 0) return errno;
89	if ((error = ioctl(d, NWFSIOC_GETEINFO, fi)) != 0) return errno;
90	close(d);
91	return 0;
92}
93
94
95int
96ncp_AllocTempDirHandle(char *path, NWDIR_HANDLE *pdh) {
97	int d;
98
99	if ((d = open(path, O_RDONLY)) < 0) return errno;
100	*pdh = d;
101	return 0;
102}
103
104int
105ncp_DeallocateDirHandle(NWDIR_HANDLE dh) {
106	close(dh);
107	return 0;
108}
109
110int
111ncp_GetNSEntryInfo(NWDIR_HANDLE dh, struct nw_entry_info *fi, int *ns) {
112	int error;
113
114	if ((error = ioctl(dh, NWFSIOC_GETEINFO, fi)) != 0) return errno;
115	if ((error = ioctl(dh, NWFSIOC_GETNS, ns)) != 0) return errno;
116	return 0;
117}
118
119NWCCODE
120ncp_ScanForDeletedFiles(NWCONN_HANDLE cH, pnuint32 iterHandle,
121	pnuint32 volNum, pnuint32 dirBase, nuint8 ns,
122	NWDELETED_INFO *entryInfo)
123{
124	int error;
125	struct nw_entry_info *pfi;
126	DECLARE_RQ;
127#define	UNITEDT(d,t)	(((d) << 16) | (t))
128
129	bzero(entryInfo, sizeof(NWDELETED_INFO));
130	ncp_init_request(conn);
131	ncp_add_byte(conn, 16);
132	ncp_add_byte(conn, ns);
133	ncp_add_byte(conn, 0);		/* data stream */
134	ncp_add_dword_lh(conn, IM_ALL & ~(IM_SPACE_ALLOCATED | IM_TOTAL_SIZE | IM_EA | IM_DIRECTORY));
135	ncp_add_dword_lh(conn, *iterHandle);
136
137	ncp_add_byte(conn, *volNum);
138	ncp_add_dword_lh(conn, *dirBase);
139	ncp_add_byte(conn, NCP_HF_DIRBASE);	/* dirBase */
140	ncp_add_byte(conn, 0);			/* no component */
141	if ((error = ncp_request(cH, 87, conn)) != 0) {
142		return error;
143	}
144	if (conn->rpsize < 0x61) {
145		return EBADRPC;	/* EACCES ? */
146	}
147	*iterHandle = entryInfo->sequence = ncp_reply_dword_lh(conn, 0x00);
148	entryInfo->deletedTime = ncp_reply_word_lh(conn, 0x04);
149	entryInfo->deletedDateAndTime = UNITEDT(ncp_reply_word_lh(conn, 0x06), entryInfo->deletedTime);
150	entryInfo->deletorID = ncp_reply_dword_hl(conn, 0x08);
151	*volNum = ncp_reply_dword_lh(conn, 0x0C);
152	*dirBase = ncp_reply_dword_lh(conn, 0x10);
153	entryInfo->parent = ncp_reply_dword_lh(conn, 0x10);
154	pfi = (struct nw_entry_info*) ncp_reply_data(conn, 0x14);
155	entryInfo->nameLength = pfi->nameLen;
156	memcpy(entryInfo->name, pfi->entryName, pfi->nameLen);
157	return error;
158}
159
160NWCCODE
161ncp_PurgeDeletedFile(NWCONN_HANDLE cH, nuint32 iterHandle,
162	nuint32 volNum, nuint32 dirBase, nuint8 ns)
163{
164	DECLARE_RQ;
165
166	ncp_init_request(conn);
167	ncp_add_byte(conn, 18);
168	ncp_add_byte(conn, ns);
169	ncp_add_byte(conn, 0);		/* reserved */
170	ncp_add_dword_lh(conn, iterHandle);
171	ncp_add_dword_lh(conn, volNum);
172	ncp_add_dword_lh(conn, dirBase);
173	return ncp_request(cH, 87, conn);
174}
175
176
177static void
178ncp_extract_entryInfo(char *data, NW_ENTRY_INFO *entry) {
179	u_char l;
180	const int info_struct_size = sizeof(NW_ENTRY_INFO) - 257;
181
182	memcpy(entry, data, info_struct_size);
183	data += info_struct_size;
184	l = *data++;
185	entry->nameLen = l;
186	memcpy(entry->entryName, data, l);
187	entry->entryName[l] = '\0';
188	return;
189}
190
191NWCCODE
192ncp_ScanNSEntryInfo(NWCONN_HANDLE cH,
193	nuint8 namSpc, nuint16 attrs, SEARCH_SEQUENCE *seq,
194	pnstr8 searchPattern, nuint32 retInfoMask, NW_ENTRY_INFO *entryInfo)
195{
196	int error, l;
197	DECLARE_RQ;
198
199	if (seq->searchDirNumber == -1) {
200		seq->searchDirNumber = 0;
201		ncp_init_request(conn);
202		ncp_add_byte(conn, 2);
203		ncp_add_byte(conn, namSpc);
204		ncp_add_byte(conn, 0);
205		ncp_add_handle_path(conn, seq->volNumber, seq->dirNumber,
206		    NCP_HF_DIRBASE, NULL);
207		error = ncp_request(cH, 87, conn);
208		if (error) return error;
209		memcpy(seq, ncp_reply_data(conn, 0), 9);
210	}
211	ncp_init_request(conn);
212	ncp_add_byte(conn, 3);
213	ncp_add_byte(conn, namSpc);
214	ncp_add_byte(conn, 0);		/* dataStream */
215	ncp_add_word_lh(conn, attrs);	/* SearchAttributes */
216	ncp_add_dword_lh(conn, retInfoMask);
217	ncp_add_mem(conn, seq, sizeof(*seq));
218	l = strlen(searchPattern);
219	ncp_add_byte(conn, l);
220	ncp_add_mem(conn, searchPattern, l);
221	error = ncp_request(cH, 87, conn);
222	if (error) return error;
223	memcpy(seq, ncp_reply_data(conn, 0), sizeof(*seq));
224	ncp_extract_entryInfo(ncp_reply_data(conn, 10), entryInfo);
225	return 0;
226}
227
228int
229ncp_NSEntryInfo(NWCONN_HANDLE cH, nuint8 ns, nuint8 vol, nuint32 dirent,
230    NW_ENTRY_INFO *entryInfo)
231{
232	DECLARE_RQ;
233	int error;
234
235	ncp_init_request(conn);
236	ncp_add_byte(conn, 6);
237	ncp_add_byte(conn, ns);
238	ncp_add_byte(conn, ns);	/* DestNameSpace */
239	ncp_add_word_lh(conn, htons(0xff00));	/* get all */
240	ncp_add_dword_lh(conn, IM_ALL);
241	ncp_add_handle_path(conn, vol, dirent, NCP_HF_DIRBASE, NULL);
242	error = ncp_request(cH, 87, conn);
243	if (error) return error;
244	ncp_extract_entryInfo(ncp_reply_data(conn, 0), entryInfo);
245	return 0;
246}
247
248NWCCODE
249NWGetVolumeName(NWCONN_HANDLE cH, u_char volume, char *name) {
250	int error, len;
251	DECLARE_RQ;
252
253	ncp_init_request_s(conn, 44);
254	ncp_add_byte(conn, volume);
255	error = ncp_request(cH, 22, conn);
256	if (error) return error;
257	len = ncp_reply_byte(conn, 29);
258	if (len == 0)
259		return ENOENT;
260	bcopy(ncp_reply_data(conn, 30), name, len);
261	name[len] = 0;
262	return 0;
263}
264