]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.suse/novfs-add-the-novell-filesystem-client-kernel-module.patch
Move xen patchset to new version's subdir.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / novfs-add-the-novell-filesystem-client-kernel-module.patch
CommitLineData
00e5a55c
BS
1From 9297af3ffd8a1c98f35fb7a273386576e061ff16 Mon Sep 17 00:00:00 2001
2From: Greg Kroah-Hartman <gregkh@suse.de>
3Date: Thu, 27 Mar 2008 10:40:48 -0700
4Subject: novfs: Add the Novell filesystem client kernel module
5Patch-mainline: not yet, being worked on.
6
7This adds the Novell filesystem client kernel module.
8
9Things to do before it can be submitted:
10 - coding style cleanups
11 - remove typedefs
12 - function name lowercase
13 - 80 chars wide
14 - sparse cleanups
15 - __user markings
16 - endian markings
17 - remove functions that are never called and structures never used
18 - yeah, there are a lot of them...
19 - remove wrapper functions
20 - private kmalloc/free?
21 - resolve FIXME markings that have been added to the code
22 - wrong types passed to functions!!!
23 - userspace interface revisit
24 - uses /proc/novfs, not nice.
25 - might need userspace tools rework
26
27Cc: Lonnie Iverson <ldiverson@novell.com>
28Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
29
30---
31 fs/Kconfig | 9
32 fs/Makefile | 1
33 fs/novfs/Makefile | 19
34 fs/novfs/commands.h | 1087 ++++++++++
35 fs/novfs/daemon.c | 2400 ++++++++++++++++++++++
36 fs/novfs/file.c | 1964 ++++++++++++++++++
37 fs/novfs/inode.c | 5563 ++++++++++++++++++++++++++++++++++++++++++++++++++++
38 fs/novfs/nwcapi.c | 2537 +++++++++++++++++++++++
39 fs/novfs/nwcapi.h | 2213 ++++++++++++++++++++
40 fs/novfs/nwerror.h | 658 ++++++
41 fs/novfs/proc.c | 152 +
42 fs/novfs/profile.c | 687 ++++++
43 fs/novfs/scope.c | 675 ++++++
44 fs/novfs/vfs.h | 436 ++++
45 14 files changed, 18401 insertions(+)
46
47--- a/fs/Kconfig
48+++ b/fs/Kconfig
49@@ -2123,6 +2123,15 @@ config 9P_FS
50
51 If unsure, say N.
52
53+config NOVFS
54+ tristate "Novell Netware Filesystem support (novfs) (EXPERIMENTAL)"
55+ depends on INET && EXPERIMENTAL
56+ help
57+ If you say Y here, you will get an experimental Novell Netware
58+ filesystem driver.
59+
60+ If unsure, say N.
61+
62 endif # NETWORK_FILESYSTEMS
63
64 if BLOCK
65--- a/fs/Makefile
66+++ b/fs/Makefile
67@@ -125,3 +125,4 @@ obj-$(CONFIG_HPPFS) += hppfs/
68 obj-$(CONFIG_DEBUG_FS) += debugfs/
69 obj-$(CONFIG_OCFS2_FS) += ocfs2/
70 obj-$(CONFIG_GFS2_FS) += gfs2/
71+obj-$(CONFIG_NOVFS) += novfs/
72--- /dev/null
73+++ b/fs/novfs/Makefile
74@@ -0,0 +1,19 @@
75+#
76+# Makefile for the Novell NetWare Client for Linux filesystem.
77+#
78+
79+NOVFS_VFS_MAJOR = 2
80+NOVFS_VFS_MINOR = 0
81+NOVFS_VFS_SUB = 0
82+NOVFS_VFS_RELEASE = 440
83+
84+EXTRA_CFLAGS += -DNOVFS_VFS_MAJOR=$(NOVFS_VFS_MAJOR)
85+EXTRA_CFLAGS += -DNOVFS_VFS_MINOR=$(NOVFS_VFS_MINOR)
86+EXTRA_CFLAGS += -DNOVFS_VFS_SUB=$(NOVFS_VFS_SUB)
87+EXTRA_CFLAGS += -DNOVFS_VFS_PATCH=$(NOVFS_VFS_PATCH)
88+EXTRA_CFLAGS += -DNOVFS_VFS_RELEASE=$(NOVFS_VFS_RELEASE)
89+
90+obj-$(CONFIG_NOVFS) += novfs.o
91+
92+novfs-objs := inode.o proc.o profile.o daemon.o file.o scope.o nwcapi.o
93+
94--- /dev/null
95+++ b/fs/novfs/commands.h
96@@ -0,0 +1,1087 @@
97+/*
98+ * NetWare Redirector for Linux
99+ * Author: James Turner/Richard Williams
100+ *
101+ * This file contains all defined commands.
102+ *
103+ * Copyright (C) 2005 Novell, Inc.
104+ *
105+ * This program is free software; you can redistribute it and/or
106+ * modify it under the terms of the GNU General Public License
107+ * as published by the Free Software Foundation; either version 2
108+ * of the License, or (at your option) any later version.
109+ */
110+
111+#ifndef __NOVFS_COMMANDS_H
112+#define __NOVFS_COMMANDS_H
113+
114+#define VFS_COMMAND_GET_CONNECTED_SERVER_LIST 0
115+#define VFS_COMMAND_GET_SERVER_VOLUME_LIST 1
116+#define VFS_COMMAND_VERIFY_FILE 2
117+#define VFS_COMMAND_OPEN_CONNECTION_BY_ADDR 3
118+#define VFS_COMMAND_LOGIN_IDENTITY 4
119+#define VFS_COMMAND_ENUMERATE_DIRECTORY 5
120+#define VFS_COMMAND_OPEN_FILE 6
121+#define VFS_COMMAND_CREATE_FILE 7
122+#define VFS_COMMAND_CLOSE_FILE 8
123+#define VFS_COMMAND_READ_FILE 9
124+#define VFS_COMMAND_WRITE_FILE 10
125+#define VFS_COMMAND_DELETE_FILE 11
126+#define VFS_COMMAND_CREATE_DIRECOTRY 12
127+#define VFS_COMMAND_START_ENUMERATE 13
128+#define VFS_COMMAND_END_ENUMERATE 14
129+#define VFS_COMMAND_LOGIN_USER 15
130+#define VFS_COMMAND_LOGOUT_USER 16
131+#define VFS_COMMAND_CREATE_CONTEXT 17
132+#define VFS_COMMAND_DESTROY_CONTEXT 18
133+#define VFS_COMMAND_SET_FILE_INFO 19
134+#define VFS_COMMAND_TRUNCATE_FILE 20
135+#define VFS_COMMAND_OPEN_CONNECTION_BY_NAME 21
136+#define VFS_COMMAND_XPLAT_CALL 22
137+#define VFS_COMMAND_RENAME_FILE 23
138+#define VFS_COMMAND_ENUMERATE_DIRECTORY_EX 24
139+#define VFS_COMMAND_GETPWUD 25
140+#define VFS_COMMAND_ENUM_XCONN 26
141+#define VFS_COMMAND_READ_STREAM 27
142+#define VFS_COMMAND_WRITE_STREAM 28
143+#define VFS_COMMAND_CLOSE_STREAM 29
144+#define VFS_COMMAND_GET_VERSION 30
145+#define VFS_COMMAND_SET_MOUNT_PATH 31
146+#define VFS_COMMAND_GET_USER_SPACE 32
147+#define VFS_COMMAND_DBG 33
148+#define VFS_COMMAND_GET_CACHE_FLAG 34
149+#define VFS_COMMAND_GET_EXTENDED_ATTRIBUTE 35
150+#define VFS_COMMAND_LIST_EXTENDED_ATTRIBUTES 36
151+#define VFS_COMMAND_SET_EXTENDED_ATTRIBUTE 37
152+#define VFS_COMMAND_SET_FILE_LOCK 38
153+
154+#define NWD_ACCESS_QUERY 0x00000001
155+#define NWD_ACCESS_READ 0x00000002
156+#define NWD_ACCESS_WRITE 0x00000004
157+#define NWD_ACCESS_EXECUTE 0x00000008
158+#define NWD_ACCESS_VALID 0x0000000F
159+
160+/*
161+ Share Mode
162+
163+ A value of zero in a shared mode field specifies the caller
164+ desires exclusive access to the object.
165+*/
166+
167+#define NWD_SHARE_READ 0x00000001
168+#define NWD_SHARE_WRITE 0x00000002
169+#define NWD_SHARE_DELETE 0x00000004
170+#define NWD_SHARE_VALID 0x00000007
171+
172+/*
173+ Creates a new file. The create API will fail if the specified
174+ file already exists.
175+*/
176+#define NWD_DISP_CREATE_NEW 0x00000001
177+
178+/*
179+ Creates a new file. If the specified file already exists,
180+ the create API will overwrite the old file and clear the
181+ existing attributes.
182+*/
183+#define NWD_DISP_CREATE_ALWAYS 0x00000002
184+
185+/*
186+ Opens the file. The API will fail if the file does not exist.
187+*/
188+#define NWD_DISP_OPEN_EXISTING 0x00000003
189+
190+/*
191+ Opens the file. If the file does not exist, the API will
192+ create the file.
193+*/
194+#define NWD_DISP_OPEN_ALWAYS 0x00000004
195+
196+/*
197+ Opens the file. When the file is opened the API will truncate
198+ the stream to zero bytes. The API will fail if the file
199+ does not exist.
200+*/
201+#define NWD_DISP_TRUNCATE_EXISTING 0x00000005
202+#define NWD_DISP_MAXIMUM 0x00000005
203+
204+/*
205+ Open/Create returned information values
206+
207+ The bottom two bytes of NWD_ACTION are returned
208+ as a value. All values are mutually exclusive.
209+*/
210+
211+#define NWD_ACTION_OPENED 0x00000001
212+#define NWD_ACTION_CREATED 0x00000002
213+
214+#define MAX_IO_SIZE (1024 * 32)
215+
216+#define MAX_XATTR_NAME_LEN 255
217+#define MAX_PATH_LENGTH 255
218+#define ENOATTR ENODATA
219+/*===[ Type definitions ]=================================================*/
220+
221+/*===[ Function prototypes ]==============================================*/
222+
223+#pragma pack(push, 1)
224+
225+#ifndef NWHANDLE
226+typedef void *NWHANDLE;
227+#endif
228+
229+/*typedef struct _ncl_string
230+{
231+ unsigned int type;
232+ unsigned char *buffer;
233+ unsigned int len;
234+
235+} NclString, *PNclString;
236+*/
237+typedef struct _ncl_string {
238+ unsigned int type;
239+ unsigned char *buffer;
240+ u32 len;
241+
242+} NclString, *PNclString;
243+
244+typedef struct _nwd_string {
245+ unsigned int type;
246+ unsigned int len;
247+ unsigned int boffset;
248+
249+} NwdString, *PNwdString;
250+
251+typedef struct _COMMAND_REQUEST_HEADER {
252+ unsigned int CommandType;
253+ unsigned long SequenceNumber;
254+ struct schandle SessionId;
255+} COMMAND_REQUEST_HEADER, *PCOMMAND_REQUEST_HEADER;
256+
257+typedef struct _COMMAND_REPLY_HEADER {
258+ unsigned long Sequence_Number;
259+ unsigned int ErrorCode;
260+
261+} COMMAND_REPLY_HEADER, *PCOMMAND_REPLY_HEADER;
262+
263+typedef struct _CLOSE_REQUEST {
264+ COMMAND_REQUEST_HEADER Command;
265+ NWHANDLE FileHandle;
266+} CLOSE_REQUEST, *PCLOSE_REQUEST;
267+
268+typedef struct _CLOSE_REPLY {
269+ COMMAND_REPLY_HEADER Reply;
270+} CLOSE_REPLY, *PCLOSE_REPLY;
271+
272+typedef struct _DELETE_FILE_REQUEST {
273+ COMMAND_REQUEST_HEADER Command;
274+ unsigned int isDirectory;
275+ unsigned int pathlength;
276+ unsigned char path[1];
277+} DELETE_FILE_REQUEST, *PDELETE_FILE_REQUEST;
278+
279+typedef struct _DELETE_FILE_REPLY {
280+ COMMAND_REPLY_HEADER Reply;
281+} DELETE_FILE_REPLY, *PDELETE_FILE_REPLY;
282+
283+typedef struct _FLUSH_REQUEST {
284+ COMMAND_REQUEST_HEADER Command;
285+ NWHANDLE FileHandle;
286+} FLUSH_REQUEST, *PFLUSH_REQUEST;
287+
288+typedef struct _FLUSH_REPLY {
289+ COMMAND_REPLY_HEADER Reply;
290+} FLUSH_REPLY, *PFLUSH_REPLY;
291+
292+typedef struct _GET_FILEINFO_REQUEST {
293+ COMMAND_REQUEST_HEADER Command;
294+ NWHANDLE FileHandle;
295+} GET_FILEINFO_REQUEST, *PGET_FILEINFO_REQUEST;
296+
297+typedef struct _GET_FILEINFO_REPLY {
298+ COMMAND_REPLY_HEADER Reply;
299+} GET_FILEINFO_REPLY, *PGET_FILEINFO_REPLY;
300+
301+typedef struct _GET_CONNECTED_SERVER_LIST_REQUEST {
302+ COMMAND_REQUEST_HEADER Command;
303+} GET_CONNECTED_SERVER_LIST_REQUEST, *PGET_CONNECTED_SERVER_LIST_REQUEST;
304+
305+typedef struct _GET_CONNECTED_SERVER_LIST_REPLY {
306+ COMMAND_REPLY_HEADER Reply;
307+ unsigned char List[1];
308+} GET_CONNECTED_SERVER_LIST_REPLY, *PGET_CONNECTED_SERVER_LIST_REPLY;
309+
310+typedef struct _GET_CONNECTED_SERVER_LIST_REQUEST_EX {
311+ COMMAND_REQUEST_HEADER Command;
312+} GET_CONNECTED_SERVER_LIST_REQUEST_EX, *PGET_CONNECTED_SERVER_LIST_REQUEST_EX;
313+
314+typedef struct _GET_CONNECTED_SERVER_LIST_REPLY_EX {
315+ COMMAND_REPLY_HEADER Reply;
316+ unsigned int bufferLen;
317+ unsigned char List[1];
318+
319+} GET_CONNECTED_SERVER_LIST_REPLY_EX, *PGET_CONNECTED_SERVER_LIST_REPLY_EX;
320+
321+typedef struct _GET_SERVER_VOLUME_LIST_REQUEST {
322+ COMMAND_REQUEST_HEADER Command;
323+ unsigned int Length;
324+ unsigned char Name[1];
325+} GET_SERVER_VOLUME_LIST_REQUEST, *PGET_SERVER_VOLUME_LIST_REQUEST;
326+
327+typedef struct _GET_SERVER_VOLUME_LIST_REPLY {
328+ COMMAND_REPLY_HEADER Reply;
329+ unsigned char List[1];
330+} GET_SERVER_VOLUME_LIST_REPLY, *PGET_SERVER_VOLUME_LIST_REPLY;
331+
332+typedef struct _OPEN_CONNECTION_BY_ADDR_REQUEST {
333+ COMMAND_REQUEST_HEADER Command;
334+ unsigned int address;
335+
336+} OPEN_CONNECTION_BY_ADDR_REQUEST, *POPEN_CONNECTION_BY_ADDR_REQUEST;
337+
338+typedef struct _OPEN_CONNECTION_BY_ADDR_REPLY {
339+ COMMAND_REPLY_HEADER Reply;
340+ unsigned char serverName[64];
341+ unsigned char treeName[64];
342+ NWHANDLE connHandle;
343+
344+} OPEN_CONNECTION_BY_ADDR_REPLY, *POPEN_CONNECTION_BY_ADDR_REPLY;
345+
346+typedef struct _OPEN_CONNECTION_BY_NAME_REQUEST {
347+ COMMAND_REQUEST_HEADER Command;
348+ unsigned int NameLen;
349+ unsigned char Name[1];
350+
351+} OPEN_CONNECTION_BY_NAME_REQUEST, *POPEN_CONNECTION_BY_NAME_REQUEST;
352+
353+typedef struct _OPEN_CONNECTION_BY_NAME_REPLY {
354+ COMMAND_REPLY_HEADER Reply;
355+ unsigned char treeName[64];
356+ NWHANDLE connHandle;
357+
358+} OPEN_CONNECTION_BY_NAME_REPLY, *POPEN_CONNECTION_BY_NAME_REPLY;
359+
360+/*
361+typedef struct _LOGIN_IDENTITY_REQUEST
362+{
363+ COMMAND_REQUEST_HEADER Command;
364+ unsigned int treeFlags;
365+ unsigned char treeName[64];
366+ unsigned int serverFlags;
367+ unsigned char serverName[64];
368+ unsigned int userFlags;
369+ unsigned char userName[512];
370+ unsigned int passwordFlags;
371+ unsigned char password[128];
372+
373+} LOGIN_IDENTITY_REQUEST, *PLOGIN_IDENTITY_REQUEST;
374+
375+typedef struct _LOGIN_IDENTITY_REPLY
376+{
377+ COMMAND_REPLY_HEADER Reply;
378+ unsigned char serverName[64];
379+ unsigned char treeName[64];
380+ NWHANDLE connHandle;
381+
382+} LOGIN_IDENTITY_REPLY, *PLOGIN_IDENTITY_REPLY;
383+*/
384+
385+typedef struct _VERIFY_FILE_REQUEST {
386+ COMMAND_REQUEST_HEADER Command;
387+ unsigned int pathLen;
388+ unsigned char path[1];
389+
390+} VERIFY_FILE_REQUEST, *PVERIFY_FILE_REQUEST;
391+
392+typedef struct _VERIFY_FILE_REPLY {
393+ COMMAND_REPLY_HEADER Reply;
394+ unsigned int lastAccessTime;
395+ unsigned int modifyTime;
396+ unsigned int createTime;
397+ unsigned long long fileSize;
398+ unsigned int fileMode;
399+
400+} VERIFY_FILE_REPLY, *PVERIFY_FILE_REPLY;
401+
402+typedef struct _BEGIN_ENUMERATE_DIRECTORY_REQUEST {
403+ COMMAND_REQUEST_HEADER Command;
404+ unsigned int pathLen;
405+ unsigned char path[1];
406+
407+} BEGIN_ENUMERATE_DIRECTORY_REQUEST, *PBEGIN_ENUMERATE_DIRECTORY_REQUEST;
408+
409+typedef struct _BEGIN_ENUMERATE_DIRECTORY_REPLY {
410+ COMMAND_REPLY_HEADER Reply;
411+ HANDLE enumerateHandle;
412+
413+} BEGIN_ENUMERATE_DIRECTORY_REPLY, *PBEGIN_ENUMERATE_DIRECTORY_REPLY;
414+
415+typedef struct _END_ENUMERATE_DIRECTORY_REQUEST {
416+ COMMAND_REQUEST_HEADER Command;
417+ HANDLE enumerateHandle;
418+
419+} END_ENUMERATE_DIRECTORY_REQUEST, *PEND_ENUMERATE_DIRECTORY_REQUEST;
420+
421+typedef struct _END_ENUMERATE_DIRECTORY_REPLY {
422+ COMMAND_REPLY_HEADER Reply;
423+
424+} END_ENUMERATE_DIRECTORY_REPLY, *PEND_ENUMERATE_DIRECTORY_REPLY;
425+
426+typedef struct _ENUMERATE_DIRECTORY_REQUEST {
427+ COMMAND_REQUEST_HEADER Command;
428+ HANDLE enumerateHandle;
429+ unsigned int pathLen;
430+ unsigned char path[1];
431+
432+} ENUMERATE_DIRECTORY_REQUEST, *PENUMERATE_DIRECTORY_REQUEST;
433+
434+typedef struct _ENUMERATE_DIRECTORY_REPLY {
435+ COMMAND_REPLY_HEADER Reply;
436+ HANDLE enumerateHandle;
437+ unsigned int lastAccessTime;
438+ unsigned int modifyTime;
439+ unsigned int createTime;
440+ unsigned long long size;
441+ unsigned int mode;
442+ unsigned int nameLen;
443+ unsigned char name[1];
444+
445+} ENUMERATE_DIRECTORY_REPLY, *PENUMERATE_DIRECTORY_REPLY;
446+
447+typedef struct _ENUMERATE_DIRECTORY_EX_REQUEST {
448+ COMMAND_REQUEST_HEADER Command;
449+ HANDLE enumerateHandle;
450+ unsigned int pathLen;
451+ unsigned char path[1];
452+
453+} ENUMERATE_DIRECTORY_EX_REQUEST, *PENUMERATE_DIRECTORY_EX_REQUEST;
454+
455+typedef struct _ENUMERATE_DIRECTORY_EX_DATA {
456+ unsigned int length;
457+ unsigned int lastAccessTime;
458+ unsigned int modifyTime;
459+ unsigned int createTime;
460+ unsigned long long size;
461+ unsigned int mode;
462+ unsigned int nameLen;
463+ unsigned char name[1];
464+
465+} ENUMERATE_DIRECTORY_EX_DATA, *PENUMERATE_DIRECTORY_EX_DATA;
466+
467+typedef struct _ENUMERATE_DIRECTORY_EX_REPLY {
468+ COMMAND_REPLY_HEADER Reply;
469+ HANDLE enumerateHandle;
470+ unsigned int enumCount;
471+
472+} ENUMERATE_DIRECTORY_EX_REPLY, *PENUMERATE_DIRECTORY_EX_REPLY;
473+
474+typedef struct _OPEN_FILE_REQUEST {
475+ COMMAND_REQUEST_HEADER Command;
476+ unsigned int access; /* File Access */
477+ unsigned int mode; /* Sharing Mode */
478+ unsigned int disp; /* Create Disposition */
479+ unsigned int pathLen;
480+ unsigned char path[1];
481+
482+} OPEN_FILE_REQUEST, *POPEN_FILE_REQUEST;
483+
484+typedef struct _OPEN_FILE_REPLY {
485+ COMMAND_REPLY_HEADER Reply;
486+ HANDLE handle;
487+ unsigned int lastAccessTime;
488+ unsigned int modifyTime;
489+ unsigned int createTime;
490+ unsigned int attributes;
491+ loff_t size;
492+
493+} OPEN_FILE_REPLY, *POPEN_FILE_REPLY;
494+
495+typedef struct _CREATE_FILE_REQUEST {
496+
497+ COMMAND_REQUEST_HEADER Command;
498+ unsigned int pathlength;
499+ unsigned char path[1];
500+
501+} CREATE_FILE_REQUEST, *PCREATE_FILE_REQUEST;
502+
503+typedef struct _CREATE_FILE_REPLY {
504+ COMMAND_REPLY_HEADER Reply;
505+
506+} CREATE_FILE_REPLY, *PCREATE_FILE_REPLY;
507+
508+typedef struct _CLOSE_FILE_REQUEST {
509+ COMMAND_REQUEST_HEADER Command;
510+ HANDLE handle;
511+
512+} CLOSE_FILE_REQUEST, *PCLOSE_FILE_REQUEST;
513+
514+typedef struct _CLOSE_FILE_REPLY {
515+ COMMAND_REPLY_HEADER Reply;
516+
517+} CLOSE_FILE_REPLY, *PCLOSE_FILE_REPLY;
518+
519+typedef struct _READ_FILE_REQUEST {
520+ COMMAND_REQUEST_HEADER Command;
521+ HANDLE handle;
522+ loff_t offset;
523+ size_t len;
524+
525+} READ_FILE_REQUEST, *PREAD_FILE_REQUEST;
526+
527+typedef struct _READ_FILE_REPLY {
528+ COMMAND_REPLY_HEADER Reply;
529+ unsigned long long bytesRead;
530+ unsigned char data[1];
531+
532+} READ_FILE_REPLY, *PREAD_FILE_REPLY;
533+
534+typedef struct _WRITE_FILE_REQUEST {
535+ COMMAND_REQUEST_HEADER Command;
536+ HANDLE handle;
537+ loff_t offset;
538+ size_t len;
539+ unsigned char data[1];
540+
541+} WRITE_FILE_REQUEST, *PWRITE_FILE_REQUEST;
542+
543+typedef struct _WRITE_FILE_REPLY {
544+ COMMAND_REPLY_HEADER Reply;
545+ unsigned long long bytesWritten;
546+} WRITE_FILE_REPLY, *PWRITE_FILE_REPLY;
547+
548+typedef struct _READ_STREAM_REQUEST {
549+ COMMAND_REQUEST_HEADER Command;
550+ HANDLE connection;
551+ unsigned char handle[6];
552+ loff_t offset;
553+ size_t len;
554+} READ_STREAM_REQUEST, *PREAD_STREAM_REQUEST;
555+
556+typedef struct _READ_STREAM_REPLY {
557+ COMMAND_REPLY_HEADER Reply;
558+ size_t bytesRead;
559+ unsigned char data[1];
560+} READ_STREAM_REPLY, *PREAD_STREAM_REPLY;
561+
562+typedef struct _WRITE_STREAM_REQUEST {
563+ COMMAND_REQUEST_HEADER Command;
564+ HANDLE connection;
565+ unsigned char handle[6];
566+ loff_t offset;
567+ size_t len;
568+ unsigned char data[1];
569+} WRITE_STREAM_REQUEST, *PWRITE_STREAM_REQUEST;
570+
571+typedef struct _WRITE_STREAM_REPLY {
572+ COMMAND_REPLY_HEADER Reply;
573+ size_t bytesWritten;
574+} WRITE_STREAM_REPLY, *PWRITE_STREAM_REPLY;
575+
576+typedef struct _CLOSE_STREAM_REQUEST {
577+ COMMAND_REQUEST_HEADER Command;
578+ HANDLE connection;
579+ unsigned char handle[6];
580+} CLOSE_STREAM_REQUEST, *PCLOSE_STREAM_REQUEST;
581+
582+typedef struct _CLOSE_STREAM_REPLY {
583+ COMMAND_REPLY_HEADER Reply;
584+
585+} CLOSE_STREAM_REPLY, *PCLOSE_STREAM_REPLY;
586+
587+typedef struct _CREATE_DIRECTORY_REQUEST {
588+
589+ COMMAND_REQUEST_HEADER Command;
590+ unsigned int pathlength;
591+ unsigned char path[1];
592+
593+} CREATE_DIRECTORY_REQUEST, *PCREATE_DIRECTORY_REQUEST;
594+
595+typedef struct _CREATE_DIRECTORY_REPLY {
596+ COMMAND_REPLY_HEADER Reply;
597+
598+} CREATE_DIRECTORY_REPLY, *PCREATE_DIRECTORY_REPLY;
599+
600+typedef struct _LOGIN_USER_REQUEST {
601+ COMMAND_REQUEST_HEADER Command;
602+ unsigned int srvNameType;
603+ unsigned int serverLength;
604+ unsigned int serverOffset;
605+ unsigned int usrNameType;
606+ unsigned int userNameLength;
607+ unsigned int userNameOffset;
608+ unsigned int pwdNameType;
609+ unsigned int passwordLength;
610+ unsigned int passwordOffset;
611+
612+} LOGIN_USER_REQUEST, *PLOGIN_USER_REQUEST;
613+
614+typedef struct _LOGIN_USER_REPLY {
615+ COMMAND_REPLY_HEADER Reply;
616+ unsigned int connectionHandle;
617+ HANDLE loginIdentity;
618+
619+} LOGIN_USER_REPLY, *PLOGIN_USER_REPLY;
620+
621+typedef struct _LOGOUT_REQUEST {
622+ COMMAND_REQUEST_HEADER Command;
623+ unsigned int length;
624+ unsigned char Name[1];
625+
626+} LOGOUT_REQUEST, *PLOGOUT_REQUEST;
627+
628+typedef struct _LOGOUT_REPLY {
629+ COMMAND_REPLY_HEADER Reply;
630+
631+} LOGOUT_REPLY, *PLOGOUT_REPLY;
632+
633+typedef struct _CREATE_CONTEXT_REQUEST {
634+ COMMAND_REQUEST_HEADER Command;
635+
636+} CREATE_CONTEXT_REQUEST, *PCREATE_CONTEXT_REQUEST;
637+
638+typedef struct _CREATE_CONTEXT_REPLY {
639+ COMMAND_REPLY_HEADER Reply;
640+ struct schandle SessionId;
641+} CREATE_CONTEXT_REPLY, *PCREATE_CONTEXT_REPLY;
642+
643+typedef struct _DESTROY_CONTEXT_REQUEST {
644+ COMMAND_REQUEST_HEADER Command;
645+
646+} DESTROY_CONTEXT_REQUEST, *PDESTROY_CONTEXT_REQUEST;
647+
648+typedef struct _DESTROY_CONTEXT_REPLY {
649+ COMMAND_REPLY_HEADER Reply;
650+
651+} DESTROY_CONTEXT_REPLY, *PDESTROY_CONTEXT_REPLY;
652+
653+/*
654+ * Attribute flags. These should be or-ed together to figure out what
655+ * has been changed!
656+ */
657+#ifndef ATTR_MODE
658+#define ATTR_MODE 1
659+#define ATTR_UID 2
660+#define ATTR_GID 4
661+#define ATTR_SIZE 8
662+#define ATTR_ATIME 16
663+#define ATTR_MTIME 32
664+#define ATTR_CTIME 64
665+#define ATTR_ATIME_SET 128
666+#define ATTR_MTIME_SET 256
667+#define ATTR_FORCE 512 /* Not a change, but a change it */
668+#define ATTR_ATTR_FLAG 1024
669+#endif
670+
671+typedef struct _LNX_FILE_INFO {
672+ unsigned int ia_valid;
673+ unsigned int ia_mode;
674+ uid_t ia_uid;
675+ gid_t ia_gid;
676+ loff_t ia_size;
677+ time_t ia_atime;
678+ time_t ia_mtime;
679+ time_t ia_ctime;
680+ unsigned int ia_attr_flags;
681+
682+} LX_FILE_INFO, *PLX_FILE_INFO;
683+
684+typedef struct _SET_FILE_INFO_REQUEST {
685+ COMMAND_REQUEST_HEADER Command;
686+ LX_FILE_INFO fileInfo;
687+ unsigned int pathlength;
688+ char path[1];
689+
690+} SET_FILE_INFO_REQUEST, *PSET_FILE_INFO_REQUEST;
691+
692+typedef struct _SET_FILE_INFO_REPLY {
693+ COMMAND_REPLY_HEADER Reply;
694+
695+} SET_FILE_INFO_REPLY, *PSET_FILE_INFO_REPLY;
696+
697+typedef struct _TRUNCATE_FILE_REQUEST {
698+ COMMAND_REQUEST_HEADER Command;
699+ unsigned int pathLen;
700+ char path[1];
701+
702+} TRUNCATE_FILE_REQUEST, *PTRUNCATE_FILE_REQUEST;
703+
704+typedef struct _TRUNCATE_FILE_REPLY {
705+ COMMAND_REPLY_HEADER Reply;
706+
707+} TRUNCATE_FILE_REPLY, *PTRUNCATE_FILE_REPLY;
708+
709+typedef struct _GETPWUID_REQUEST {
710+ COMMAND_REQUEST_HEADER Command;
711+ unsigned int uid;
712+} GETPWUID_REQUEST, *PGETPWUID_REQUEST;
713+
714+typedef struct _GETPWUID_REPLY {
715+ COMMAND_REPLY_HEADER Reply;
716+ unsigned char UserName[1];
717+} GETPWUID_REPLY, *PGETPWUID_REPLY;
718+
719+typedef struct _GET_VERSION_REQUEST {
720+ COMMAND_REQUEST_HEADER Command;
721+} GET_VERSION_REQUEST, *PGET_VERSION_REQUEST;
722+
723+typedef struct _GET_VERSION_REPLY {
724+ COMMAND_REPLY_HEADER Reply;
725+ unsigned char Version[1];
726+} GET_VERSION_REPLY, *PGET_VERSION_REPLY;
727+
728+typedef struct _SET_MOUNT_PATH {
729+ COMMAND_REQUEST_HEADER Command;
730+ unsigned int PathLength;
731+ unsigned char Path[1];
732+} SET_MOUNT_PATH_REQUEST, *PSET_MOUNT_PATH_REQUEST;
733+
734+typedef struct _SET_MOUNT_PATH_REPLY {
735+ COMMAND_REPLY_HEADER Reply;
736+} SET_MOUNT_PATH, *PSET_MOUNT_PATH_REPLY;
737+
738+typedef struct _GET_USER_SPACE {
739+ COMMAND_REQUEST_HEADER Command;
740+} GET_USER_SPACE_REQUEST, *PGET_USER_SPACE_REQUEST;
741+
742+typedef struct _GET_USER_SPACE_REPLY {
743+ COMMAND_REPLY_HEADER Reply;
744+ uint64_t TotalSpace;
745+ uint64_t FreeSpace;
746+ uint64_t TotalEnties;
747+ uint64_t FreeEnties;
748+} GET_USER_SPACE_REPLY, *PGET_USER_SPACE_REPLY;
749+
750+typedef struct _XPLAT_CALL_REQUEST {
751+ COMMAND_REQUEST_HEADER Command;
752+ unsigned int NwcCommand;
753+ unsigned long dataLen;
754+ unsigned char data[1];
755+
756+} XPLAT_CALL_REQUEST, *PXPLAT_CALL_REQUEST;
757+
758+typedef struct _XPLAT_CALL_REPLY {
759+ COMMAND_REPLY_HEADER Reply;
760+ unsigned long dataLen;
761+ unsigned char data[1];
762+
763+} XPLAT_CALL_REPLY, *PXPLAT_CALL_REPLY;
764+
765+/* XPlat NWC structures used by the daemon */
766+
767+typedef struct _NWD_OPEN_CONN_BY_NAME {
768+ HANDLE ConnHandle;
769+ unsigned int nameLen;
770+ unsigned int oName; /* Ofset to the Name */
771+ unsigned int serviceLen;
772+ unsigned int oServiceType; /* Offset to service Type; */
773+ unsigned int uConnFlags;
774+ unsigned int uTranType;
775+ HANDLE newConnHandle;
776+
777+} NwdCOpenConnByName, *PNwdCOpenConnByName;
778+
779+typedef struct _NWD_TRAN_ADDR {
780+ unsigned int uTransportType;
781+ unsigned int uAddressLength;
782+ unsigned int oAddress;
783+
784+} NwdCTranAddr, *PNwdCTranAddr;
785+
786+typedef struct _NWD_OPEN_CONN_BY_ADDR {
787+ HANDLE ConnHandle;
788+ unsigned int oServiceType;
789+ unsigned int uConnFlags;
790+ NwdCTranAddr TranAddr;
791+
792+} NwdCOpenConnByAddr, *PNwdCOpenConnByAddr;
793+
794+typedef struct _NWD_CLOSE_CONN {
795+ HANDLE ConnHandle;
796+
797+} NwdCCloseConn, *PNwdCCloseConn;
798+
799+typedef struct _NWD_NCP_REQ {
800+ HANDLE ConnHandle;
801+ unsigned int replyLen;
802+ unsigned int requestLen;
803+ unsigned int function;
804+/* unsigned int subFunction; */
805+/* unsigned int verb; */
806+ unsigned int flags;
807+ unsigned char data[1];
808+
809+} NwdCNCPReq, *PNwdCNCPReq;
810+
811+typedef struct _NWD_NCP_REP {
812+ unsigned int replyLen;
813+ unsigned char data[1];
814+
815+} NwdCNCPRep, *PNwdCNCPRep;
816+
817+typedef struct _NWC_AUTH_WID {
818+ HANDLE ConnHandle;
819+ u32 AuthenticationId;
820+
821+} NwdCAuthenticateWithId, *PNwdCAuthenticateWithId;
822+
823+typedef struct _NWC_AUTHENTICATE {
824+ HANDLE ConnHandle;
825+ unsigned int uAuthenticationType;
826+ unsigned int userNameOffset;
827+ unsigned int passwordOffset;
828+ unsigned int MaxInfoLength;
829+ unsigned int InfoLength;
830+ unsigned int authenInfoOffset;
831+
832+} NwdCAuthenticate, *PNwdCAuthenticate;
833+
834+typedef struct _NWC_UNAUTHENTICATE {
835+ HANDLE ConnHandle;
836+ unsigned int AuthenticationId;
837+
838+} NwdCUnauthenticate, *PNwdCUnauthenticate;
839+
840+typedef struct _NWC_LISC_ID {
841+ HANDLE ConnHandle;
842+
843+} NwdCLicenseConn, *PNwdCLicenseConn;
844+
845+typedef struct _NWC_UNLIC_CONN {
846+ HANDLE ConnHandle;
847+
848+} NwdCUnlicenseConn, *PNwdCUnlicenseConn;
849+
850+typedef struct _NWC_GET_IDENT_INFO {
851+ u32 AuthenticationId;
852+ unsigned int AuthType;
853+ unsigned int NameType;
854+ unsigned short int ObjectType;
855+ unsigned int IdentityFlags;
856+ unsigned int domainLen;
857+ unsigned int pDomainNameOffset;
858+ unsigned int objectLen;
859+ unsigned int pObjectNameOffset;
860+
861+} NwdCGetIdentityInfo, *PNwdCGetIdentityInfo;
862+
863+typedef struct _NWC_LO_ID {
864+ u32 AuthenticationId;
865+
866+} NwdCLogoutIdentity, *PNwdCLogoutIdentity;
867+
868+typedef struct _RENAME_FILE_REQUEST {
869+ COMMAND_REQUEST_HEADER Command;
870+ int directoryFlag;
871+ unsigned int newnameLen;
872+ unsigned char newname[256];
873+ unsigned int oldnameLen;
874+ unsigned char oldname[256];
875+} RENAME_FILE_REQUEST, *PRENAME_FILE_REQUEST;
876+
877+typedef struct _RENAME_FILE_REPLY {
878+ COMMAND_REPLY_HEADER Reply;
879+
880+} RENAME_FILE_REPLY, *PRENAME_FILE_REPLY;
881+
882+typedef struct __NwdServerVersion {
883+ unsigned int uMajorVersion;
884+ unsigned short int uMinorVersion;
885+ unsigned short int uRevision;
886+
887+} NwdServerVersion, *PNwdServerVersion;
888+
889+#define MAX_ADDRESS_LENGTH 32
890+
891+typedef struct tagNwdTranAddrEx {
892+ unsigned int uTransportType;
893+ unsigned int uAddressLength;
894+ unsigned char Buffer[MAX_ADDRESS_LENGTH];
895+
896+} NwdTranAddr, *PNwdTranAddr;
897+
898+typedef struct __NWD_CONN_INFO {
899+ unsigned int uInfoVersion;
900+ unsigned int uAuthenticationState;
901+ unsigned int uBroadcastState;
902+ u32 uConnectionReference;
903+ unsigned int pTreeNameOffset;
904+/* unsigned int pWorkGroupIdOffset; Not used */
905+ unsigned int uSecurityState;
906+ unsigned int uConnectionNumber;
907+ unsigned int uUserId;
908+ unsigned int pServerNameOffset;
909+ unsigned int uNdsState;
910+ unsigned int uMaxPacketSize;
911+ unsigned int uLicenseState;
912+ unsigned int uPublicState;
913+ unsigned int bcastState;
914+ unsigned int pServiceTypeOffset;
915+ unsigned int uDistance;
916+ u32 uAuthId;
917+ unsigned int uDisconnected;
918+ NwdServerVersion ServerVersion;
919+ NwdTranAddr TranAddress;
920+
921+} NwdConnInfo, *PNwdConnInfo;
922+
923+typedef struct _nwd_conn_info {
924+ HANDLE ConnHandle;
925+ unsigned int uInfoLevel;
926+ unsigned int uInfoLength;
927+
928+} NwdCGetConnInfo, *PNwdCGetConnInfo;
929+
930+typedef struct nwd_open_conn_by_Ref {
931+ HANDLE uConnReference;
932+ unsigned int uConnFlags;
933+ HANDLE ConnHandle;
934+
935+} NwdCOpenConnByRef, *PNwdCOpenConnByRef;
936+
937+typedef struct nwd_get_reqversion {
938+ unsigned int uMajorVersion;
939+ unsigned int uMinorVersion;
940+ unsigned int uRevision;
941+
942+} NwdCGetRequesterVersion, *PNwdCGetRequesterVersion;
943+
944+typedef struct _nwc_scan_conn_info {
945+ unsigned int uScanIndex;
946+ unsigned int uScanInfoLevel;
947+ unsigned int uScanInfoLen;
948+ unsigned int uScanConnInfoOffset;
949+ unsigned int uScanFlags;
950+ unsigned int uReturnInfoLevel;
951+ unsigned int uReturnInfoLength;
952+ unsigned int uConnectionReference;
953+ unsigned int uReturnConnInfoOffset;
954+
955+} NwdCScanConnInfo, *PNwdCScanConnInfo;
956+
957+typedef struct nwc_get_pref_ds_tree {
958+ unsigned int uTreeLength;
959+ unsigned int DsTreeNameOffset;
960+
961+} NwdCGetPreferredDsTree, *PNwdCGetPreferredDsTree;
962+
963+typedef struct nwc_set_pref_ds_tree {
964+ unsigned int uTreeLength;
965+ unsigned int DsTreeNameOffset;
966+
967+} NwdCSetPreferredDsTree, *PNwdCSetPreferredDsTree;
968+
969+typedef struct nwc_set_def_name_ctx {
970+ unsigned int uTreeLength;
971+ unsigned int TreeOffset;
972+ unsigned int uNameLength;
973+ unsigned int NameContextOffset;
974+
975+} NwdCSetDefaultNameContext, *PNwdCSetDefaultNameContext;
976+
977+typedef struct nwc_get_def_name_ctx {
978+ unsigned int uTreeLength;
979+ unsigned int TreeOffset;
980+ unsigned int uNameLength;
981+ unsigned int NameContextOffset;
982+
983+} NwdCGetDefaultNameContext, *PNwdCGetDefaultNameContext;
984+
985+typedef struct _nwc_get_treemonitored_connref {
986+ NwdString TreeName;
987+ HANDLE uConnReference;
988+
989+} NwdCGetTreeMonitoredConnRef, *PNwdCGetTreeMonitoredConnRef;
990+
991+typedef struct _nwc_enumerate_identities {
992+ unsigned int Iterator;
993+ unsigned int domainNameLen;
994+ unsigned int domainNameOffset;
995+ unsigned int AuthType;
996+ unsigned int objectNameLen;
997+ unsigned int objectNameOffset;
998+ unsigned int NameType;
999+ unsigned short int ObjectType;
1000+ unsigned int IdentityFlags;
1001+ u32 AuthenticationId;
1002+
1003+} NwdCDEnumerateIdentities, *PNwdCEnumerateIdentities;
1004+
1005+typedef struct nwd_change_key {
1006+ unsigned int domainNameOffset;
1007+ unsigned int domainNameLen;
1008+ unsigned int AuthType;
1009+ unsigned int objectNameOffset;
1010+ unsigned int objectNameLen;
1011+ unsigned int NameType;
1012+ unsigned short int ObjectType;
1013+ unsigned int verifyPasswordOffset;
1014+ unsigned int verifyPasswordLen;
1015+ unsigned int newPasswordOffset;
1016+ unsigned int newPasswordLen;
1017+
1018+} NwdCChangeKey, *PNwdCChangeKey;
1019+
1020+typedef struct _nwd_get_primary_conn {
1021+ HANDLE uConnReference;
1022+
1023+} NwdCGetPrimaryConnection, *PNwdCGetPrimaryConnection;
1024+
1025+typedef struct _nwd_set_primary_conn {
1026+ HANDLE ConnHandle;
1027+
1028+} NwdCSetPrimaryConnection, *PNwdCSetPrimaryConnection;
1029+
1030+typedef struct _nwd_map_drive_ex {
1031+ u32 ConnHandle;
1032+ u32 localUid;
1033+ u32 linkOffsetLength;
1034+ u32 linkOffset;
1035+ u32 dirPathOffsetLength;
1036+ u32 dirPathOffset;
1037+
1038+} NwdCMapDriveEx, *PNwdCMapDriveEx;
1039+
1040+typedef struct _nwd_unmap_drive_ex {
1041+ unsigned int linkLen;
1042+ char linkPath[1];
1043+
1044+} NwdCUnmapDriveEx, *PNwdCUnmapDriveEx;
1045+
1046+typedef struct _nwd_enum_links {
1047+ unsigned int totalLen;
1048+ unsigned int linkCount;
1049+
1050+} NwdCEnumLinks, *PNwdCEnumLinks;
1051+
1052+typedef struct nwd_getbroadcastnotification {
1053+ unsigned int uMessageFlags;
1054+ HANDLE uConnReference;
1055+ unsigned int messageLen;
1056+ char message[1];
1057+
1058+} NwdCGetBroadcastNotification, *PNwdCGetBroadcastNotification;
1059+
1060+typedef struct _enum_entry {
1061+ unsigned int entryLen;
1062+ u32 connHdl;
1063+ char data[0];
1064+} NwdCEnumEntry, *PNwdCEnumEntry;
1065+
1066+typedef struct _nwd_set_conn_info {
1067+ HANDLE ConnHandle;
1068+ unsigned int uInfoLevel;
1069+ unsigned int uInfoLength;
1070+ unsigned int offsetConnInfo;
1071+
1072+} NwdCSetConnInfo, *PNwdCSetConnInfo;
1073+
1074+typedef struct _len_string {
1075+ u32 stLen;
1076+ char string[1];
1077+
1078+} LString, *PLString;
1079+
1080+typedef struct _DEBUG_REQUEST {
1081+ COMMAND_REQUEST_HEADER Command;
1082+ int cmdlen;
1083+ char dbgcmd[1];
1084+
1085+} DEBUG_REQUEST, *PDEBUG_REQUEST;
1086+
1087+typedef struct _DEBUG_REPLY {
1088+ COMMAND_REPLY_HEADER Reply;
1089+
1090+} DEBUG_REPLY, *PDEBUG_REPLY;
1091+
1092+typedef struct _Nwd_Set_Key {
1093+ HANDLE ConnHandle;
1094+ unsigned int AuthenticationId;
1095+ unsigned int objectNameLen;
1096+ unsigned int objectNameOffset;
1097+ unsigned short int ObjectType;
1098+ unsigned int newPasswordLen;
1099+ unsigned int newPasswordOffset;
1100+
1101+} NwdCSetKey, *PNwdCSetKey;
1102+
1103+typedef struct _Nwd_Verify_Key {
1104+ unsigned int AuthType;
1105+ unsigned int NameType;
1106+ unsigned short int ObjectType;
1107+ unsigned int domainNameLen;
1108+ unsigned int domainNameOffset;
1109+ unsigned int objectNameLen;
1110+ unsigned int objectNameOffset;
1111+ unsigned int verifyPasswordLen;
1112+ unsigned int verifyPasswordOffset;
1113+
1114+} NwdCVerifyKey, *PNwdCVerifyKey;
1115+
1116+typedef struct _GET_CACHE_FLAG {
1117+ COMMAND_REQUEST_HEADER Command;
1118+ int pathLen;
1119+ unsigned char path[0];
1120+
1121+} GET_CACHE_FLAG_REQUEST, *PGET_CACHE_FLAG_REQUEST;
1122+
1123+typedef struct _GET_CACHE_FLAG_REPLY {
1124+ COMMAND_REPLY_HEADER Reply;
1125+ int CacheFlag;
1126+
1127+} GET_CACHE_FLAG_REPLY, *PGET_CACHE_FLAG_REPLY;
1128+
1129+typedef struct _XA_LIST_REPLY {
1130+ COMMAND_REPLY_HEADER Reply;
1131+ unsigned char *pData;
1132+
1133+} XA_LIST_REPLY, *PXA_LIST_REPLY;
1134+
1135+typedef struct _XA_GET_REQUEST {
1136+ COMMAND_REQUEST_HEADER Command;
1137+ unsigned int pathLen;
1138+ unsigned int nameLen;
1139+ unsigned char data[1]; //hold path, attribute name
1140+
1141+} XA_GET_REQUEST, *PXA_GET_REQUEST;
1142+
1143+typedef struct _XA_GET_REPLY {
1144+ COMMAND_REPLY_HEADER Reply;
1145+ unsigned char *pData;
1146+
1147+} XA_GET_REPLY, *PXA_GET_REPLY;
1148+
1149+typedef struct _XA_SET_REQUEST {
1150+ COMMAND_REQUEST_HEADER Command;
1151+ unsigned int TtlWriteDataSize;
1152+ unsigned int WritePosition;
1153+ int flags;
1154+ unsigned int pathLen;
1155+ unsigned int nameLen;
1156+ unsigned int valueLen;
1157+ unsigned char data[1]; //hold path, attribute name, value data
1158+
1159+} XA_SET_REQUEST, *PXA_SET_REQUEST;
1160+
1161+typedef struct _XA_SET_REPLY {
1162+ COMMAND_REPLY_HEADER Reply;
1163+ unsigned char *pData;
1164+
1165+} XA_SET_REPLY, *PXA_SET_REPLY;
1166+
1167+typedef struct _SET_FILE_LOCK_REQUEST {
1168+ COMMAND_REQUEST_HEADER Command;
1169+ HANDLE handle;
1170+ unsigned char fl_type;
1171+ loff_t fl_start;
1172+ loff_t fl_len;
1173+
1174+} SET_FILE_LOCK_REQUEST, *PSET_FILE_LOCK_REQUEST;
1175+
1176+typedef struct _SET_FILE_LOCK_REPLY {
1177+ COMMAND_REPLY_HEADER Reply;
1178+
1179+} SET_FILE_LOCK_REPLY, *PSET_FILE_LOCK_REPLY;
1180+
1181+#pragma pack(pop)
1182+
1183+#endif /* __NOVFS_COMMANDS_H */
1184--- /dev/null
1185+++ b/fs/novfs/daemon.c
1186@@ -0,0 +1,2400 @@
1187+/*
1188+ * Novell NCP Redirector for Linux
1189+ * Author: James Turner
1190+ *
1191+ * This file contains all the functions necessary for sending commands to our
1192+ * daemon module.
1193+ *
1194+ * Copyright (C) 2005 Novell, Inc.
1195+ *
1196+ * This program is free software; you can redistribute it and/or
1197+ * modify it under the terms of the GNU General Public License
1198+ * as published by the Free Software Foundation; either version 2
1199+ * of the License, or (at your option) any later version.
1200+ */
1201+
1202+#include <linux/module.h>
1203+#include <linux/fs.h>
1204+#include <linux/slab.h>
1205+#include <linux/string.h>
1206+#include <linux/list.h>
1207+#include <linux/timer.h>
1208+#include <linux/poll.h>
1209+#include <linux/pagemap.h>
1210+#include <linux/smp_lock.h>
1211+#include <linux/semaphore.h>
1212+#include <asm/uaccess.h>
1213+#include <asm/atomic.h>
1214+#include <linux/time.h>
1215+
1216+#include "vfs.h"
1217+#include "nwcapi.h"
1218+#include "commands.h"
1219+#include "nwerror.h"
1220+
1221+#define QUEUE_SENDING 0
1222+#define QUEUE_WAITING 1
1223+#define QUEUE_TIMEOUT 2
1224+#define QUEUE_ACKED 3
1225+#define QUEUE_DONE 4
1226+
1227+#define TIMEOUT_VALUE 10
1228+
1229+#define DH_TYPE_UNDEFINED 0
1230+#define DH_TYPE_STREAM 1
1231+#define DH_TYPE_CONNECTION 2
1232+
1233+/*===[ Type definitions ]=================================================*/
1234+typedef struct _DAEMON_QUEUE {
1235+ struct list_head list; /* Must be first entry */
1236+ spinlock_t lock; /* Used to control access to list */
1237+ struct semaphore semaphore; /* Used to signal when data is available */
1238+} daemon_queue_t;
1239+
1240+typedef struct _DAEMON_COMMAND {
1241+ struct list_head list; /* Must be first entry */
1242+ atomic_t reference;
1243+ unsigned int status;
1244+ unsigned int flags;
1245+ struct semaphore semaphore;
1246+ unsigned long sequence;
1247+ struct timer_list timer;
1248+ void *request;
1249+ unsigned long reqlen;
1250+ void *data;
1251+ int datalen;
1252+ void *reply;
1253+ unsigned long replen;
1254+} daemon_command_t;
1255+
1256+typedef struct _DAEMON_HANDLE_ {
1257+ struct list_head list;
1258+ rwlock_t lock;
1259+ session_t session;
1260+} daemon_handle_t;
1261+
1262+typedef struct _DAEMON_RESOURCE_ {
1263+ struct list_head list;
1264+ int type;
1265+ HANDLE connection;
1266+ unsigned char handle[6];
1267+ mode_t mode;
1268+ loff_t size;
1269+} daemon_resource_t;
1270+
1271+typedef struct _DRIVE_MAP_ {
1272+ struct list_head list; /* Must be first item */
1273+ session_t session;
1274+ unsigned long hash;
1275+ int namelen;
1276+ char name[1];
1277+} drive_map_t;
1278+
1279+/*===[ Function prototypes ]==============================================*/
1280+int Daemon_Close_Control(struct inode *Inode, struct file *File);
1281+int Daemon_Library_close(struct inode *inode, struct file *file);
1282+int Daemon_Library_open(struct inode *inode, struct file *file);
1283+loff_t Daemon_Library_llseek(struct file *file, loff_t offset, int origin);
1284+int Daemon_Open_Control(struct inode *Inode, struct file *File);
1285+uint Daemon_Poll(struct file *file, struct poll_table_struct *poll_table);
1286+int Daemon_Remove_Resource(daemon_handle_t * DHandle, int Type, HANDLE CHandle,
1287+ unsigned long FHandle);
1288+
1289+int Daemon_SetMountPoint(char *Path);
1290+void Daemon_Timer(unsigned long data);
1291+int Daemon_getpwuid(uid_t uid, int unamelen, char *uname);
1292+int Queue_Daemon_Command(void *request, unsigned long reqlen, void *data, int dlen,
1293+ void **reply, unsigned long * replen, int interruptible);
1294+void Queue_get(daemon_command_t * que);
1295+void Queue_put(daemon_command_t * que);
1296+void Uninit_Daemon_Queue(void);
1297+daemon_command_t *find_queue(unsigned long sequence);
1298+daemon_command_t *get_next_queue(int Set_Queue_Waiting);
1299+int NwdConvertNetwareHandle(PXPLAT pdata, daemon_handle_t * DHandle);
1300+int NwdConvertLocalHandle(PXPLAT pdata, daemon_handle_t * DHandle);
1301+int NwdGetMountPath(PXPLAT pdata);
1302+static int NwdSetMapDrive(PXPLAT pdata, session_t Session);
1303+static int NwdUnMapDrive(PXPLAT pdata, session_t Session);
1304+void RemoveDriveMaps(void);
1305+int local_unlink(const char *pathname);
1306+
1307+/*===[ Global variables ]=================================================*/
1308+static daemon_queue_t Daemon_Queue;
1309+
1310+static DECLARE_WAIT_QUEUE_HEAD(Read_waitqueue);
1311+
1312+static atomic_t Sequence = ATOMIC_INIT(-1);
1313+static atomic_t Daemon_Open_Count = ATOMIC_INIT(0);
1314+
1315+static unsigned long Daemon_Command_Timeout = TIMEOUT_VALUE;
1316+
1317+static DECLARE_MUTEX(DriveMapLock);
1318+static LIST_HEAD(DriveMapList);
1319+
1320+int MaxIoSize = PAGE_SIZE;
1321+
1322+void Init_Daemon_Queue(void)
1323+{
1324+ INIT_LIST_HEAD(&Daemon_Queue.list);
1325+ spin_lock_init(&Daemon_Queue.lock);
1326+ init_MUTEX_LOCKED(&Daemon_Queue.semaphore);
1327+}
1328+
1329+/*++======================================================================*/
1330+void Uninit_Daemon_Queue(void)
1331+/*
1332+ *
1333+ * Arguments:
1334+ *
1335+ * Returns:
1336+ *
1337+ * Abstract:
1338+ *
1339+ * Notes:
1340+ *
1341+ * Environment:
1342+ *
1343+ *========================================================================*/
1344+{
1345+ /* Does nothing for now but we maybe should clear the queue. */
1346+}
1347+
1348+/*++======================================================================*/
1349+void Daemon_Timer(unsigned long data)
1350+/*
1351+ *
1352+ * Arguments:
1353+ *
1354+ * Returns:
1355+ *
1356+ * Abstract:
1357+ *
1358+ * Notes:
1359+ *
1360+ * Environment:
1361+ *
1362+ *========================================================================*/
1363+{
1364+ daemon_command_t *que = (daemon_command_t *) data;
1365+
1366+ if (QUEUE_ACKED != que->status) {
1367+ que->status = QUEUE_TIMEOUT;
1368+ }
1369+ up(&que->semaphore);
1370+}
1371+
1372+int Queue_Daemon_Command(void *request, unsigned long reqlen, void *data, int dlen,
1373+ void **reply, unsigned long * replen, int interruptible)
1374+/*
1375+ * Arguments: void *request - pointer to the request that is to be sent. Needs to be kernel memory.
1376+ * int reqlen - length of the request.
1377+ *========================================================================*/
1378+{
1379+ daemon_command_t *que;
1380+ int retCode = 0;
1381+ uint64_t ts1, ts2;
1382+
1383+ ts1 = get_nanosecond_time();
1384+
1385+ DbgPrint("Queue_Daemon_Command: 0x%p %d\n", request, reqlen);
1386+
1387+ if (atomic_read(&Daemon_Open_Count)) {
1388+
1389+ que = kmalloc(sizeof(*que), GFP_KERNEL);
1390+ DbgPrint("Queue_Daemon_Command: que=0x%p\n", que);
1391+ if (que) {
1392+ atomic_set(&que->reference, 0);
1393+ que->status = QUEUE_SENDING;
1394+ que->flags = 0;
1395+
1396+ init_MUTEX_LOCKED(&que->semaphore);
1397+
1398+ que->sequence = atomic_inc_return(&Sequence);
1399+
1400+ ((PCOMMAND_REQUEST_HEADER) request)->SequenceNumber =
1401+ que->sequence;
1402+
1403+ /*
1404+ * Setup and start que timer
1405+ */
1406+ init_timer(&que->timer);
1407+ que->timer.expires = jiffies + (HZ * Daemon_Command_Timeout);
1408+ que->timer.data = (unsigned long) que;
1409+ que->timer.function = Daemon_Timer;
1410+ add_timer(&que->timer);
1411+
1412+ /*
1413+ * Setup request
1414+ */
1415+ que->request = request;
1416+ que->reqlen = reqlen;
1417+ que->data = data;
1418+ que->datalen = dlen;
1419+ que->reply = NULL;
1420+ que->replen = 0;
1421+
1422+ /*
1423+ * Added entry to queue.
1424+ */
1425+ /*
1426+ * Check to see if interruptible and set flags.
1427+ */
1428+ if (interruptible) {
1429+ que->flags |= INTERRUPTIBLE;
1430+ }
1431+
1432+ Queue_get(que);
1433+
1434+ spin_lock(&Daemon_Queue.lock);
1435+ list_add_tail(&que->list, &Daemon_Queue.list);
1436+ spin_unlock(&Daemon_Queue.lock);
1437+
1438+ /*
1439+ * Signal that there is data to be read
1440+ */
1441+ up(&Daemon_Queue.semaphore);
1442+
1443+ /*
1444+ * Give a change to the other processes.
1445+ */
1446+ yield();
1447+
1448+ /*
1449+ * Block waiting for reply or timeout
1450+ */
1451+ down(&que->semaphore);
1452+
1453+ if (QUEUE_ACKED == que->status) {
1454+ que->status = QUEUE_WAITING;
1455+ mod_timer(&que->timer,
1456+ jiffies +
1457+ (HZ * 2 * Daemon_Command_Timeout));
1458+ if (interruptible) {
1459+ retCode =
1460+ down_interruptible(&que->semaphore);
1461+ } else {
1462+ down(&que->semaphore);
1463+ }
1464+ }
1465+
1466+ /*
1467+ * Delete timer
1468+ */
1469+ del_timer(&que->timer);
1470+
1471+ /*
1472+ * Check for timeout
1473+ */
1474+ if ((QUEUE_TIMEOUT == que->status)
1475+ && (NULL == que->reply)) {
1476+ DbgPrint("Queue_Daemon_Command: Timeout\n");
1477+ retCode = -ETIME;
1478+ }
1479+ *reply = que->reply;
1480+ *replen = que->replen;
1481+
1482+ /*
1483+ * Remove item from queue
1484+ */
1485+ Queue_put(que);
1486+
1487+ } else { /* Error case with no memory */
1488+
1489+ retCode = -ENOMEM;
1490+ *reply = NULL;
1491+ *replen = 0;
1492+ }
1493+ } else {
1494+ retCode = -EIO;
1495+ *reply = NULL;
1496+ *replen = 0;
1497+
1498+ }
1499+ ts2 = get_nanosecond_time();
1500+ ts2 = ts2 - ts1;
1501+
1502+ DbgPrint("Queue_Daemon_Command: %llu retCode=%d \n", ts2, retCode);
1503+ return (retCode);
1504+}
1505+
1506+/*++======================================================================*/
1507+void Queue_get(daemon_command_t * Que)
1508+/*
1509+ *
1510+ * Arguments:
1511+ *
1512+ * Returns:
1513+ *
1514+ * Abstract:
1515+ *
1516+ * Notes:
1517+ *
1518+ * Environment:
1519+ *
1520+ *========================================================================*/
1521+{
1522+ DbgPrint("Queue_get: que=0x%p %d\n", Que, atomic_read(&Que->reference));
1523+ atomic_inc(&Que->reference);
1524+}
1525+
1526+/*++======================================================================*/
1527+void Queue_put(daemon_command_t * Que)
1528+/*
1529+ *
1530+ * Arguments:
1531+ *
1532+ * Returns:
1533+ *
1534+ * Abstract:
1535+ *
1536+ * Notes:
1537+ *
1538+ * Environment:
1539+ *
1540+ *========================================================================*/
1541+{
1542+
1543+ DbgPrint("Queue_put: que=0x%p %d\n", Que, atomic_read(&Que->reference));
1544+ spin_lock(&Daemon_Queue.lock);
1545+
1546+ if (atomic_dec_and_test(&Que->reference)) {
1547+ /*
1548+ * Remove item from queue
1549+ */
1550+ list_del(&Que->list);
1551+ spin_unlock(&Daemon_Queue.lock);
1552+
1553+ /*
1554+ * Free item memory
1555+ */
1556+ kfree(Que);
1557+ } else {
1558+ spin_unlock(&Daemon_Queue.lock);
1559+ }
1560+}
1561+
1562+/*++======================================================================*/
1563+daemon_command_t *get_next_queue(int Set_Queue_Waiting)
1564+/*
1565+ *
1566+ * Arguments:
1567+ *
1568+ * Returns:
1569+ *
1570+ * Abstract:
1571+ *
1572+ * Notes:
1573+ *
1574+ * Environment:
1575+ *
1576+ *========================================================================*/
1577+{
1578+ daemon_command_t *que;
1579+
1580+ DbgPrint("get_next_queue: que=0x%p\n", Daemon_Queue.list.next);
1581+
1582+ spin_lock(&Daemon_Queue.lock);
1583+ que = (daemon_command_t *) Daemon_Queue.list.next;
1584+
1585+ while (que && (que != (daemon_command_t *) & Daemon_Queue.list.next)
1586+ && (que->status != QUEUE_SENDING)) {
1587+ que = (daemon_command_t *) que->list.next;
1588+ }
1589+
1590+ if ((NULL == que) || (que == (daemon_command_t *) & Daemon_Queue.list)
1591+ || (que->status != QUEUE_SENDING)) {
1592+ que = NULL;
1593+ } else if (Set_Queue_Waiting) {
1594+ que->status = QUEUE_WAITING;
1595+ }
1596+
1597+ if (que) {
1598+ atomic_inc(&que->reference);
1599+ }
1600+
1601+ spin_unlock(&Daemon_Queue.lock);
1602+
1603+ DbgPrint("get_next_queue: return=0x%p\n", que);
1604+ return (que);
1605+}
1606+
1607+/*++======================================================================*/
1608+daemon_command_t *find_queue(unsigned long sequence)
1609+/*
1610+ *
1611+ * Arguments:
1612+ *
1613+ * Returns:
1614+ *
1615+ * Abstract:
1616+ *
1617+ * Notes:
1618+ *
1619+ * Environment:
1620+ *
1621+ *========================================================================*/
1622+{
1623+ daemon_command_t *que;
1624+
1625+ DbgPrint("find_queue: 0x%x\n", sequence);
1626+
1627+ spin_lock(&Daemon_Queue.lock);
1628+ que = (daemon_command_t *) Daemon_Queue.list.next;
1629+
1630+ while (que && (que != (daemon_command_t *) & Daemon_Queue.list.next)
1631+ && (que->sequence != sequence)) {
1632+ que = (daemon_command_t *) que->list.next;
1633+ }
1634+
1635+ if ((NULL == que)
1636+ || (que == (daemon_command_t *) & Daemon_Queue.list.next)
1637+ || (que->sequence != sequence)) {
1638+ que = NULL;
1639+ }
1640+
1641+ if (que) {
1642+ atomic_inc(&que->reference);
1643+ }
1644+
1645+ spin_unlock(&Daemon_Queue.lock);
1646+
1647+ DbgPrint("find_queue: return 0x%p\n", que);
1648+ return (que);
1649+}
1650+
1651+/*++======================================================================*/
1652+int Daemon_Open_Control(struct inode *Inode, struct file *File)
1653+/*
1654+ *
1655+ * Arguments:
1656+ *
1657+ * Returns:
1658+ *
1659+ * Abstract:
1660+ *
1661+ * Notes:
1662+ *
1663+ * Environment:
1664+ *
1665+ *========================================================================*/
1666+{
1667+ DbgPrint("Daemon_Open_Control: pid=%d Count=%d\n", current->pid,
1668+ atomic_read(&Daemon_Open_Count));
1669+ atomic_inc(&Daemon_Open_Count);
1670+
1671+ return (0);
1672+}
1673+
1674+/*++======================================================================*/
1675+int Daemon_Close_Control(struct inode *Inode, struct file *File)
1676+/*
1677+ *
1678+ * Arguments:
1679+ *
1680+ * Returns:
1681+ *
1682+ * Abstract:
1683+ *
1684+ * Notes:
1685+ *
1686+ * Environment:
1687+ *
1688+ *========================================================================*/
1689+{
1690+ daemon_command_t *que;
1691+
1692+ DbgPrint("Daemon_Close_Control: pid=%d Count=%d\n", current->pid,
1693+ atomic_read(&Daemon_Open_Count));
1694+
1695+ if (atomic_dec_and_test(&Daemon_Open_Count)) {
1696+ /*
1697+ * Signal any pending que itmes.
1698+ */
1699+
1700+ spin_lock(&Daemon_Queue.lock);
1701+ que = (daemon_command_t *) Daemon_Queue.list.next;
1702+
1703+ while (que
1704+ && (que != (daemon_command_t *) & Daemon_Queue.list.next)
1705+ && (que->status != QUEUE_DONE)) {
1706+ que->status = QUEUE_TIMEOUT;
1707+ up(&que->semaphore);
1708+
1709+ que = (daemon_command_t *) que->list.next;
1710+ }
1711+ spin_unlock(&Daemon_Queue.lock);
1712+
1713+ RemoveDriveMaps();
1714+
1715+ Scope_Cleanup();
1716+ }
1717+
1718+ return (0);
1719+}
1720+
1721+ssize_t Daemon_Send_Command(struct file *file, char __user *buf, size_t len, loff_t * off)
1722+{
1723+ daemon_command_t *que;
1724+ size_t retValue = 0;
1725+ int Finished = 0;
1726+ struct data_list *dlist;
1727+ int i, dcnt, bcnt, ccnt, error;
1728+ char *vadr;
1729+ unsigned long cpylen;
1730+
1731+ DbgPrint("Daemon_Send_Command: %u %lld\n", len, *off);
1732+ if (len > MaxIoSize) {
1733+ MaxIoSize = len;
1734+ }
1735+
1736+ while (!Finished) {
1737+ que = get_next_queue(1);
1738+ DbgPrint("Daemon_Send_Command: 0x%p\n", que);
1739+ if (que) {
1740+ retValue = que->reqlen;
1741+ if (retValue > len) {
1742+ retValue = len;
1743+ }
1744+ if (retValue > 0x80)
1745+ mydump(0x80, que->request);
1746+ else
1747+ mydump(retValue, que->request);
1748+
1749+ cpylen = copy_to_user(buf, que->request, retValue);
1750+ if (que->datalen && (retValue < len)) {
1751+ buf += retValue;
1752+ dlist = que->data;
1753+ dcnt = que->datalen;
1754+ for (i = 0; i < dcnt; i++, dlist++) {
1755+ if (DLREAD == dlist->rwflag) {
1756+ bcnt = dlist->len;
1757+ DbgPrint
1758+ ("Daemon_Send_Command%d: page=0x%p offset=0x%p len=%d\n",
1759+ i, dlist->page,
1760+ dlist->offset, dlist->len);
1761+ if ((bcnt + retValue) <= len) {
1762+ void *km_adr = NULL;
1763+
1764+ if (dlist->page) {
1765+ km_adr =
1766+ kmap(dlist->
1767+ page);
1768+ vadr = km_adr;
1769+ vadr +=
1770+ (unsigned long)
1771+ dlist->
1772+ offset;
1773+ } else {
1774+ vadr =
1775+ dlist->
1776+ offset;
1777+ }
1778+
1779+ ccnt =
1780+ copy_to_user(buf,
1781+ vadr,
1782+ bcnt);
1783+
1784+ DbgPrint
1785+ ("Daemon_Send_Command: Copy %d from 0x%p to 0x%p.\n",
1786+ bcnt, vadr, buf);
1787+ if (bcnt > 0x80)
1788+ mydump(0x80,
1789+ vadr);
1790+ else
1791+ mydump(bcnt,
1792+ vadr);
1793+
1794+ if (km_adr) {
1795+ kunmap(dlist->
1796+ page);
1797+ }
1798+
1799+ retValue += bcnt;
1800+ buf += bcnt;
1801+ } else {
1802+ break;
1803+ }
1804+ }
1805+ }
1806+ }
1807+ Queue_put(que);
1808+ break;
1809+ }
1810+
1811+ if (O_NONBLOCK & file->f_flags) {
1812+ retValue = -EAGAIN;
1813+ break;
1814+ } else {
1815+ if ((error =
1816+ down_interruptible(&Daemon_Queue.semaphore))) {
1817+ DbgPrint
1818+ ("Daemon_Send_Command: after down_interruptible error...%d\n",
1819+ error);
1820+ retValue = -EINTR;
1821+ break;
1822+ }
1823+ DbgPrint
1824+ ("Daemon_Send_Command: after down_interruptible\n");
1825+ }
1826+ }
1827+
1828+ *off = *off;
1829+
1830+ DbgPrint("Daemon_Send_Command: return 0x%x\n", retValue);
1831+
1832+ return (retValue);
1833+}
1834+
1835+ssize_t Daemon_Receive_Reply(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
1836+{
1837+ daemon_command_t *que;
1838+ size_t retValue = 0;
1839+ void *reply;
1840+ unsigned long sequence, cpylen;
1841+
1842+ struct data_list *dlist;
1843+ char *vadr;
1844+ int i;
1845+
1846+ DbgPrint("Daemon_Receive_Reply: buf=0x%p nbytes=%d ppos=%llx\n", buf,
1847+ nbytes, *ppos);
1848+
1849+ /*
1850+ * Get sequence number from reply buffer
1851+ */
1852+
1853+ cpylen = copy_from_user(&sequence, buf, sizeof(sequence));
1854+
1855+ /*
1856+ * Find item based on sequence number
1857+ */
1858+ que = find_queue(sequence);
1859+
1860+ DbgPrint("Daemon_Receive_Reply: 0x%x 0x%p %d\n", sequence, que, nbytes);
1861+ if (que) {
1862+ do {
1863+ retValue = nbytes;
1864+ /*
1865+ * Ack packet from novfsd. Remove timer and
1866+ * return
1867+ */
1868+ if (nbytes == sizeof(sequence)) {
1869+ que->status = QUEUE_ACKED;
1870+ break;
1871+ }
1872+
1873+ if (NULL != (dlist = que->data)) {
1874+ int thiscopy, left = nbytes;
1875+ retValue = 0;
1876+
1877+ DbgPrint
1878+ ("Daemon_Receive_Reply: dlist=0x%p count=%d\n",
1879+ dlist, que->datalen);
1880+ for (i = 0;
1881+ (i < que->datalen) && (retValue < nbytes);
1882+ i++, dlist++) {
1883+ DbgPrint("Daemon_Receive_Reply:\n"
1884+ " dlist[%d].page: 0x%p\n"
1885+ " dlist[%d].offset: 0x%p\n"
1886+ " dlist[%d].len: 0x%x\n"
1887+ " dlist[%d].rwflag: 0x%x\n",
1888+ i, dlist->page, i,
1889+ dlist->offset, i, dlist->len,
1890+ i, dlist->rwflag);
1891+
1892+ if (DLWRITE == dlist->rwflag) {
1893+ void *km_adr = NULL;
1894+
1895+ if (dlist->page) {
1896+ km_adr =
1897+ kmap(dlist->page);
1898+ vadr = km_adr;
1899+ vadr +=
1900+ (unsigned long) dlist->
1901+ offset;
1902+ } else {
1903+ vadr = dlist->offset;
1904+ }
1905+
1906+ thiscopy = dlist->len;
1907+ if (thiscopy > left) {
1908+ thiscopy = left;
1909+ dlist->len = left;
1910+ }
1911+ cpylen =
1912+ copy_from_user(vadr, buf,
1913+ thiscopy);
1914+
1915+ if (thiscopy > 0x80)
1916+ mydump(0x80, vadr);
1917+ else
1918+ mydump(thiscopy, vadr);
1919+
1920+ if (km_adr) {
1921+ kunmap(dlist->page);
1922+ }
1923+
1924+ left -= thiscopy;
1925+ retValue += thiscopy;
1926+ buf += thiscopy;
1927+ }
1928+ }
1929+ que->replen = retValue;
1930+ } else {
1931+ reply = kmalloc(nbytes, GFP_KERNEL);
1932+ DbgPrint("Daemon_Receive_Reply: reply=0x%p\n", reply);
1933+ if (reply) {
1934+ retValue = nbytes;
1935+ que->reply = reply;
1936+ que->replen = nbytes;
1937+
1938+ retValue -= copy_from_user(reply, buf, retValue);
1939+ if (retValue > 0x80)
1940+ mydump(0x80, reply);
1941+ else
1942+ mydump(retValue, reply);
1943+
1944+ } else {
1945+ retValue = -ENOMEM;
1946+ }
1947+ }
1948+
1949+ /*
1950+ * Set status that packet is done.
1951+ */
1952+ que->status = QUEUE_DONE;
1953+
1954+ } while (0);
1955+ up(&que->semaphore);
1956+ Queue_put(que);
1957+ }
1958+
1959+ DbgPrint("Daemon_Receive_Reply: return 0x%x\n", retValue);
1960+
1961+ return (retValue);
1962+}
1963+
1964+int do_login(NclString *Server, NclString *Username, NclString *Password, HANDLE *lgnId, struct schandle *Session)
1965+{
1966+ PLOGIN_USER_REQUEST cmd;
1967+ PLOGIN_USER_REPLY reply;
1968+ unsigned long replylen = 0;
1969+ int retCode, cmdlen, datalen;
1970+ unsigned char *data;
1971+
1972+ datalen = Server->len + Username->len + Password->len;
1973+ cmdlen = sizeof(*cmd) + datalen;
1974+ cmd = kmalloc(cmdlen, GFP_KERNEL);
1975+ if (!cmd)
1976+ return -ENOMEM;
1977+
1978+ data = (unsigned char *) cmd + sizeof(*cmd);
1979+ cmd->Command.CommandType = VFS_COMMAND_LOGIN_USER;
1980+ cmd->Command.SequenceNumber = 0;
1981+ memcpy(&cmd->Command.SessionId, Session, sizeof(*Session));
1982+
1983+ cmd->srvNameType = Server->type;
1984+ cmd->serverLength = Server->len;
1985+ cmd->serverOffset = (unsigned long) (data - (unsigned char *) cmd);
1986+ memcpy(data, Server->buffer, Server->len);
1987+ data += Server->len;
1988+
1989+ cmd->usrNameType = Username->type;
1990+ cmd->userNameLength = Username->len;
1991+ cmd->userNameOffset = (unsigned long) (data - (unsigned char *) cmd);
1992+ memcpy(data, Username->buffer, Username->len);
1993+ data += Username->len;
1994+
1995+ cmd->pwdNameType = Password->type;
1996+ cmd->passwordLength = Password->len;
1997+ cmd->passwordOffset = (unsigned long) (data - (unsigned char *) cmd);
1998+ memcpy(data, Password->buffer, Password->len);
1999+ data += Password->len;
2000+
2001+ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
2002+ &replylen, INTERRUPTIBLE);
2003+ if (reply) {
2004+ if (reply->Reply.ErrorCode) {
2005+ retCode = reply->Reply.ErrorCode;
2006+ } else {
2007+ retCode = 0;
2008+ if (lgnId) {
2009+ *lgnId = reply->loginIdentity;
2010+ }
2011+ }
2012+ kfree(reply);
2013+ }
2014+ memset(cmd, 0, cmdlen);
2015+ kfree(cmd);
2016+ return retCode;
2017+
2018+}
2019+
2020+int do_logout(struct qstr *Server, struct schandle *Session)
2021+{
2022+ PLOGOUT_REQUEST cmd;
2023+ PLOGOUT_REPLY reply;
2024+ unsigned long replylen = 0;
2025+ int retCode, cmdlen;
2026+
2027+ cmdlen = offsetof(LOGOUT_REQUEST, Name) + Server->len;
2028+ cmd = kmalloc(cmdlen, GFP_KERNEL);
2029+ if (!cmd)
2030+ return -ENOMEM;
2031+
2032+ cmd->Command.CommandType = VFS_COMMAND_LOGOUT_USER;
2033+ cmd->Command.SequenceNumber = 0;
2034+ memcpy(&cmd->Command.SessionId, Session, sizeof(*Session));
2035+ cmd->length = Server->len;
2036+ memcpy(cmd->Name, Server->name, Server->len);
2037+
2038+ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE);
2039+ if (reply) {
2040+ if (reply->Reply.ErrorCode) {
2041+ retCode = -EIO;
2042+ }
2043+ kfree(reply);
2044+ }
2045+ kfree(cmd);
2046+ return (retCode);
2047+
2048+}
2049+
2050+/*++======================================================================*/
2051+int Daemon_getpwuid(uid_t uid, int unamelen, char *uname)
2052+/*
2053+ *
2054+ * Arguments:
2055+ *
2056+ * Returns:
2057+ *
2058+ * Abstract:
2059+ *
2060+ * Notes:
2061+ *
2062+ * Environment:
2063+ *
2064+ *========================================================================*/
2065+{
2066+ GETPWUID_REQUEST cmd;
2067+ PGETPWUID_REPLY reply;
2068+ unsigned long replylen = 0;
2069+ int retCode;
2070+
2071+ cmd.Command.CommandType = VFS_COMMAND_GETPWUD;
2072+ cmd.Command.SequenceNumber = 0;
2073+ SC_INITIALIZE(cmd.Command.SessionId);
2074+ cmd.uid = uid;
2075+
2076+ retCode =
2077+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
2078+ &replylen, INTERRUPTIBLE);
2079+ if (reply) {
2080+ if (reply->Reply.ErrorCode) {
2081+ retCode = -EIO;
2082+ } else {
2083+ retCode = 0;
2084+ memset(uname, 0, unamelen);
2085+ replylen = replylen - offsetof(GETPWUID_REPLY, UserName);
2086+ if (replylen) {
2087+ if (replylen > unamelen) {
2088+ retCode = -EINVAL;
2089+ replylen = unamelen - 1;
2090+ }
2091+ memcpy(uname, reply->UserName, replylen);
2092+ }
2093+ }
2094+ kfree(reply);
2095+ }
2096+ return (retCode);
2097+
2098+}
2099+
2100+/*++======================================================================*/
2101+int Daemon_getversion(char *Buf, int length)
2102+/*
2103+ *
2104+ * Arguments:
2105+ *
2106+ * Returns:
2107+ *
2108+ * Abstract:
2109+ *
2110+ * Notes:
2111+ *
2112+ * Environment:
2113+ *
2114+ *========================================================================*/
2115+{
2116+ GET_VERSION_REQUEST cmd;
2117+ PGET_VERSION_REPLY reply;
2118+ unsigned long replylen = 0;
2119+ int retVal = 0;
2120+
2121+ cmd.Command.CommandType = VFS_COMMAND_GET_VERSION;
2122+ cmd.Command.SequenceNumber = 0;
2123+ SC_INITIALIZE(cmd.Command.SessionId);
2124+
2125+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
2126+ &replylen, INTERRUPTIBLE);
2127+ if (reply) {
2128+ if (reply->Reply.ErrorCode) {
2129+ retVal = -EIO;
2130+ } else {
2131+ retVal = replylen - offsetof(GET_VERSION_REPLY, Version);
2132+ if (retVal < length) {
2133+ memcpy(Buf, reply->Version, retVal);
2134+ Buf[retVal] = '\0';
2135+ }
2136+ }
2137+ kfree(reply);
2138+ }
2139+ return (retVal);
2140+
2141+}
2142+
2143+static int daemon_login(struct login *Login, struct schandle *Session)
2144+{
2145+ int retCode = -ENOMEM;
2146+ struct login lLogin;
2147+ NclString server;
2148+ NclString username;
2149+ NclString password;
2150+
2151+ if (!copy_from_user(&lLogin, Login, sizeof(lLogin))) {
2152+ server.buffer = kmalloc(lLogin.Server.length, GFP_KERNEL);
2153+ if (server.buffer) {
2154+ server.len = lLogin.Server.length;
2155+ server.type = NWC_STRING_TYPE_ASCII;
2156+ if (!copy_from_user((void *)server.buffer, lLogin.Server.data, server.len)) {
2157+ username.buffer = kmalloc(lLogin.UserName.length, GFP_KERNEL);
2158+ if (username.buffer) {
2159+ username.len = lLogin.UserName.length;
2160+ username.type = NWC_STRING_TYPE_ASCII;
2161+ if (!copy_from_user((void *)username.buffer, lLogin.UserName.data, username.len)) {
2162+ password.buffer = kmalloc(lLogin.Password.length, GFP_KERNEL);
2163+ if (password.buffer) {
2164+ password.len = lLogin.Password.length;
2165+ password.type = NWC_STRING_TYPE_ASCII;
2166+ if (!copy_from_user((void *)password.buffer, lLogin.Password.data, password.len)) {
2167+ retCode = do_login (&server, &username, &password, NULL, Session);
2168+ if (!retCode) {
2169+ char *name;
2170+ name = Scope_Get_UserName();
2171+ if (name)
2172+ Novfs_Add_to_Root(name);
2173+ }
2174+ }
2175+ memset(password.buffer, 0, password.len);
2176+ kfree(password.buffer);
2177+ }
2178+ }
2179+ memset(username.buffer, 0, username.len);
2180+ kfree(username.buffer);
2181+ }
2182+ }
2183+ kfree(server.buffer);
2184+ }
2185+ }
2186+
2187+ return (retCode);
2188+}
2189+
2190+static int daemon_logout(struct logout *Logout, struct schandle *Session)
2191+{
2192+ struct logout lLogout;
2193+ struct qstr server;
2194+ int retCode = -ENOMEM;
2195+
2196+ if (copy_from_user(&lLogout, Logout, sizeof(lLogout)))
2197+ return -EFAULT;
2198+
2199+ server.name = kmalloc(lLogout.Server.length, GFP_KERNEL);
2200+ if (!server.name)
2201+ return -ENOMEM;
2202+ server.len = lLogout.Server.length;
2203+ if (copy_from_user((void *)server.name, lLogout.Server.data, server.len))
2204+ goto exit;
2205+
2206+ retCode = do_logout(&server, Session);
2207+exit:
2208+ kfree(server.name);
2209+ return retCode;
2210+}
2211+
2212+int Daemon_CreateSessionId(struct schandle *SessionId)
2213+{
2214+ CREATE_CONTEXT_REQUEST cmd;
2215+ PCREATE_CONTEXT_REPLY reply;
2216+ unsigned long replylen = 0;
2217+ int retCode = 0;
2218+
2219+ DbgPrint("Daemon_CreateSessionId: %d\n", current->pid);
2220+
2221+ cmd.Command.CommandType = VFS_COMMAND_CREATE_CONTEXT;
2222+ cmd.Command.SequenceNumber = 0;
2223+ SC_INITIALIZE(cmd.Command.SessionId);
2224+
2225+ retCode =
2226+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
2227+ &replylen, INTERRUPTIBLE);
2228+ if (reply) {
2229+ if (!reply->Reply.ErrorCode
2230+ && replylen > sizeof(COMMAND_REPLY_HEADER)) {
2231+ *SessionId = reply->SessionId;
2232+ retCode = 0;
2233+ } else {
2234+ SessionId->hTypeId = 0;
2235+ SessionId->hId = 0;
2236+ retCode = -EIO;
2237+ }
2238+ kfree(reply);
2239+ }
2240+ DbgPrint("Daemon_CreateSessionId: SessionId=0x%llx\n", *SessionId);
2241+ return (retCode);
2242+}
2243+
2244+int Daemon_DestroySessionId(struct schandle *SessionId)
2245+{
2246+ DESTROY_CONTEXT_REQUEST cmd;
2247+ PDESTROY_CONTEXT_REPLY reply;
2248+ unsigned long replylen = 0;
2249+ int retCode = 0;
2250+
2251+ DbgPrint("Daemon_DestroySessionId: 0x%p:%p\n",
2252+ SessionId->hTypeId, SessionId->hId);
2253+
2254+ cmd.Command.CommandType = VFS_COMMAND_DESTROY_CONTEXT;
2255+ cmd.Command.SequenceNumber = 0;
2256+ memcpy(&cmd.Command.SessionId, SessionId, sizeof (*SessionId));
2257+
2258+ retCode =
2259+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
2260+ &replylen, INTERRUPTIBLE);
2261+ if (reply) {
2262+ if (!reply->Reply.ErrorCode) {
2263+ drive_map_t *dm;
2264+ struct list_head *list;
2265+
2266+ retCode = 0;
2267+
2268+ /*
2269+ * When destroying the session check to see if there are any
2270+ * mapped drives. If there are then remove them.
2271+ */
2272+ down(&DriveMapLock);
2273+ list_for_each(list, &DriveMapList) {
2274+ struct schandle *temp;
2275+
2276+ dm = list_entry(list, drive_map_t, list);
2277+ temp = &dm->session;
2278+ if (SC_EQUAL(SessionId, temp)) {
2279+ local_unlink(dm->name);
2280+ list = list->prev;
2281+ list_del(&dm->list);
2282+ kfree(dm);
2283+ }
2284+
2285+ }
2286+ up(&DriveMapLock);
2287+
2288+ } else {
2289+ retCode = -EIO;
2290+ }
2291+ kfree(reply);
2292+ }
2293+ return (retCode);
2294+}
2295+
2296+int Daemon_Get_UserSpace(struct schandle *SessionId, uint64_t * TotalSize,
2297+ uint64_t * Free, uint64_t * TotalEnties,
2298+ uint64_t * FreeEnties)
2299+{
2300+ GET_USER_SPACE_REQUEST cmd;
2301+ PGET_USER_SPACE_REPLY reply;
2302+ unsigned long replylen = 0;
2303+ int retCode = 0;
2304+
2305+ DbgPrint("Daemon_Get_UserSpace: 0x%p:%p\n",
2306+ SessionId->hTypeId, SessionId->hId);
2307+
2308+ cmd.Command.CommandType = VFS_COMMAND_GET_USER_SPACE;
2309+ cmd.Command.SequenceNumber = 0;
2310+ memcpy(&cmd.Command.SessionId, SessionId, sizeof (*SessionId));
2311+
2312+ retCode =
2313+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
2314+ &replylen, INTERRUPTIBLE);
2315+ if (reply) {
2316+ if (!reply->Reply.ErrorCode) {
2317+
2318+ DbgPrint("TotalSpace: %llu\n", reply->TotalSpace);
2319+ DbgPrint("FreeSpace: %llu\n", reply->FreeSpace);
2320+ DbgPrint("TotalEnties: %llu\n", reply->TotalEnties);
2321+ DbgPrint("FreeEnties: %llu\n", reply->FreeEnties);
2322+
2323+ if (TotalSize)
2324+ *TotalSize = reply->TotalSpace;
2325+ if (Free)
2326+ *Free = reply->FreeSpace;
2327+ if (TotalEnties)
2328+ *TotalEnties = reply->TotalEnties;
2329+ if (FreeEnties)
2330+ *FreeEnties = reply->FreeEnties;
2331+ retCode = 0;
2332+ } else {
2333+ retCode = -EIO;
2334+ }
2335+ kfree(reply);
2336+ }
2337+ return (retCode);
2338+}
2339+
2340+/*++======================================================================*/
2341+int Daemon_SetMountPoint(char *Path)
2342+/*
2343+ *
2344+ * Arguments:
2345+ *
2346+ * Returns:
2347+ *
2348+ * Abstract:
2349+ *
2350+ * Notes:
2351+ *
2352+ * Environment:
2353+ *
2354+ *========================================================================*/
2355+{
2356+ PSET_MOUNT_PATH_REQUEST cmd;
2357+ PSET_MOUNT_PATH_REPLY reply;
2358+ unsigned long replylen, cmdlen;
2359+ int retCode = -ENOMEM;
2360+
2361+ DbgPrint("Daemon_SetMountPoint: %s\n", Path);
2362+
2363+ replylen = strlen(Path);
2364+ cmdlen = sizeof(SET_MOUNT_PATH_REQUEST) + replylen;
2365+
2366+ cmd = kmalloc(cmdlen, GFP_KERNEL);
2367+ if (!cmd)
2368+ return -ENOMEM;
2369+
2370+ cmd->Command.CommandType = VFS_COMMAND_SET_MOUNT_PATH;
2371+ cmd->Command.SequenceNumber = 0;
2372+ SC_INITIALIZE(cmd->Command.SessionId);
2373+ cmd->PathLength = replylen;
2374+
2375+ strcpy(cmd->Path, Path);
2376+
2377+ replylen = 0;
2378+
2379+ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE);
2380+ if (reply) {
2381+ if (!reply->Reply.ErrorCode) {
2382+ retCode = 0;
2383+ } else {
2384+ retCode = -EIO;
2385+ }
2386+ kfree(reply);
2387+ }
2388+ kfree(cmd);
2389+ return retCode;
2390+}
2391+
2392+/*++======================================================================*/
2393+int Daemon_SendDebugCmd(char *Command)
2394+/*
2395+ *
2396+ * Arguments:
2397+ *
2398+ * Returns:
2399+ *
2400+ * Abstract:
2401+ *
2402+ * Notes:
2403+ *
2404+ * Environment:
2405+ *
2406+ *========================================================================*/
2407+{
2408+ DEBUG_REQUEST cmd;
2409+ PDEBUG_REPLY reply;
2410+ DEBUG_REPLY lreply;
2411+ unsigned long replylen, cmdlen;
2412+ struct data_list dlist[2];
2413+
2414+ int retCode = -ENOMEM;
2415+
2416+ DbgPrint("Daemon_SendDebugCmd: %s\n", Command);
2417+
2418+ dlist[0].page = NULL;
2419+ dlist[0].offset = (char *)Command;
2420+ dlist[0].len = strlen(Command);
2421+ dlist[0].rwflag = DLREAD;
2422+
2423+ dlist[1].page = NULL;
2424+ dlist[1].offset = (char *)&lreply;
2425+ dlist[1].len = sizeof(lreply);
2426+ dlist[1].rwflag = DLWRITE;
2427+
2428+ cmdlen = offsetof(DEBUG_REQUEST, dbgcmd);
2429+
2430+ cmd.Command.CommandType = VFS_COMMAND_DBG;
2431+ cmd.Command.SequenceNumber = 0;
2432+ SC_INITIALIZE(cmd.Command.SessionId);
2433+ cmd.cmdlen = strlen(Command);
2434+
2435+ replylen = 0;
2436+
2437+ retCode = Queue_Daemon_Command(&cmd, cmdlen, dlist, 2, (void *)&reply, &replylen, INTERRUPTIBLE);
2438+ if (reply) {
2439+ kfree(reply);
2440+ }
2441+ if (0 == retCode) {
2442+ retCode = lreply.Reply.ErrorCode;
2443+ }
2444+
2445+ return (retCode);
2446+}
2447+
2448+int Daemon_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
2449+{
2450+ int retCode = -ENOSYS;
2451+ unsigned long cpylen;
2452+ struct schandle session_id;
2453+
2454+ session_id = Scope_Get_SessionId(NULL);
2455+
2456+ switch (cmd) {
2457+ case IOC_LOGIN:
2458+ retCode = daemon_login((struct login *)arg, &session_id);
2459+ break;
2460+
2461+ case IOC_LOGOUT:
2462+ retCode = daemon_logout((struct logout *) arg, &session_id);
2463+ break;
2464+ case IOC_DEBUGPRINT:
2465+ {
2466+ struct Ioctl_Debug {
2467+ int length;
2468+ char *data;
2469+ } io;
2470+ char *buf;
2471+ io.length = 0;
2472+ cpylen = copy_from_user(&io, (char *)arg, sizeof(io));
2473+ if (io.length) {
2474+ buf = kmalloc(io.length + 1, GFP_KERNEL);
2475+ if (buf) {
2476+ buf[0] = 0;
2477+ cpylen =
2478+ copy_from_user(buf, io.data,
2479+ io.length);
2480+ buf[io.length] = '\0';
2481+ DbgPrint("%s", buf);
2482+ kfree(buf);
2483+ retCode = 0;
2484+ }
2485+ }
2486+ break;
2487+ }
2488+
2489+ case IOC_XPLAT:
2490+ {
2491+ XPLAT data;
2492+
2493+ cpylen =
2494+ copy_from_user(&data, (void *)arg, sizeof(data));
2495+ retCode = ((data.xfunction & 0x0000FFFF) | 0xCC000000);
2496+
2497+ switch (data.xfunction) {
2498+ case NWC_GET_MOUNT_PATH:
2499+ DbgPrint
2500+ ("[Daemon_ioctl] Call NwdGetMountPath\n");
2501+ retCode = NwdGetMountPath(&data);
2502+ break;
2503+ }
2504+
2505+ DbgPrint("[NOVFS XPLAT] status Code = %X\n", retCode);
2506+ break;
2507+ }
2508+
2509+ }
2510+ return (retCode);
2511+}
2512+
2513+int Daemon_Added_Resource(daemon_handle_t *DHandle, int Type, HANDLE CHandle, unsigned char *FHandle, unsigned long Mode, unsigned long Size)
2514+{
2515+ daemon_resource_t *resource;
2516+
2517+ if (FHandle)
2518+ DbgPrint("Daemon_Added_Resource: DHandle=0x%p Type=%d CHandle=0x%p FHandle=0x%x Mode=0x%x Size=%d\n", DHandle, Type, CHandle, *(u32 *) & FHandle[2], Mode, Size);
2519+ else
2520+ DbgPrint("Daemon_Added_Resource: DHandle=0x%p Type=%d CHandle=0x%p\n", DHandle, Type, CHandle);
2521+
2522+ resource = kmalloc(sizeof(daemon_resource_t), GFP_KERNEL);
2523+ if (!resource)
2524+ return -ENOMEM;
2525+
2526+ resource->type = Type;
2527+ resource->connection = CHandle;
2528+ if (FHandle)
2529+ memcpy(resource->handle, FHandle, sizeof(resource->handle));
2530+ else
2531+ memset(resource->handle, 0, sizeof(resource->handle));
2532+ resource->mode = Mode;
2533+ resource->size = Size;
2534+ write_lock(&DHandle->lock);
2535+ list_add(&resource->list, &DHandle->list);
2536+ write_unlock(&DHandle->lock);
2537+ DbgPrint("Daemon_Added_Resource: Adding resource=0x%p\n", resource);
2538+
2539+ return 0;
2540+}
2541+
2542+/*++======================================================================*/
2543+int Daemon_Remove_Resource(daemon_handle_t * DHandle, int Type, HANDLE CHandle,
2544+ unsigned long FHandle)
2545+/*
2546+ *
2547+ * Arguments:
2548+ *
2549+ * Returns:
2550+ *
2551+ * Abstract:
2552+ *
2553+ * Notes:
2554+ *
2555+ * Environment:
2556+ *
2557+ *========================================================================*/
2558+{
2559+ daemon_resource_t *resource;
2560+ struct list_head *l;
2561+ int retVal = -ENOMEM;
2562+
2563+ DbgPrint
2564+ ("Daemon_Remove_Resource: DHandle=0x%p Type=%d CHandle=0x%p FHandle=0x%x\n",
2565+ DHandle, Type, CHandle, FHandle);
2566+
2567+ write_lock(&DHandle->lock);
2568+
2569+ list_for_each(l, &DHandle->list) {
2570+ resource = list_entry(l, daemon_resource_t, list);
2571+
2572+ if ((Type == resource->type) &&
2573+ (resource->connection == CHandle)) {
2574+ DbgPrint
2575+ ("Daemon_Remove_Resource: Found resource=0x%p\n",
2576+ resource);
2577+ l = l->prev;
2578+ list_del(&resource->list);
2579+ kfree(resource);
2580+ break;
2581+ }
2582+ }
2583+
2584+ write_unlock(&DHandle->lock);
2585+
2586+ return (retVal);
2587+}
2588+
2589+int Daemon_Library_open(struct inode *inode, struct file *file)
2590+{
2591+ daemon_handle_t *dh;
2592+
2593+ DbgPrint("Daemon_Library_open: inode=0x%p file=0x%p\n", inode, file);
2594+
2595+ dh = kmalloc(sizeof(daemon_handle_t), GFP_KERNEL);
2596+ if (!dh)
2597+ return -ENOMEM;
2598+
2599+ file->private_data = dh;
2600+ INIT_LIST_HEAD(&dh->list);
2601+ rwlock_init(&dh->lock);
2602+ dh->session = Scope_Get_SessionId(NULL);
2603+
2604+ return 0;
2605+}
2606+
2607+/*++======================================================================*/
2608+int Daemon_Library_close(struct inode *inode, struct file *file)
2609+/*
2610+ *
2611+ * Arguments:
2612+ *
2613+ * Returns:
2614+ *
2615+ * Abstract:
2616+ *
2617+ * Notes:
2618+ *
2619+ * Environment:
2620+ *
2621+ *========================================================================*/
2622+{
2623+ daemon_handle_t *dh;
2624+ daemon_resource_t *resource;
2625+ struct list_head *l;
2626+
2627+ char commanddata[sizeof(XPLAT_CALL_REQUEST) + sizeof(NwdCCloseConn)];
2628+ PXPLAT_CALL_REQUEST cmd;
2629+ PXPLAT_CALL_REPLY reply;
2630+ PNwdCCloseConn nwdClose;
2631+ unsigned long cmdlen, replylen;
2632+
2633+ DbgPrint("Daemon_Library_close: inode=0x%p file=0x%p\n", inode, file);
2634+ if (file->private_data) {
2635+ dh = (daemon_handle_t *) file->private_data;
2636+
2637+ list_for_each(l, &dh->list) {
2638+ resource = list_entry(l, daemon_resource_t, list);
2639+
2640+ if (DH_TYPE_STREAM == resource->type) {
2641+ Novfs_Close_Stream(resource->connection,
2642+ resource->handle,
2643+ dh->session);
2644+ } else if (DH_TYPE_CONNECTION == resource->type) {
2645+ cmd = (PXPLAT_CALL_REQUEST) commanddata;
2646+ cmdlen =
2647+ offsetof(XPLAT_CALL_REQUEST,
2648+ data) + sizeof(NwdCCloseConn);
2649+ cmd->Command.CommandType =
2650+ VFS_COMMAND_XPLAT_CALL;
2651+ cmd->Command.SequenceNumber = 0;
2652+ cmd->Command.SessionId = dh->session;
2653+ cmd->NwcCommand = NWC_CLOSE_CONN;
2654+
2655+ cmd->dataLen = sizeof(NwdCCloseConn);
2656+ nwdClose = (PNwdCCloseConn) cmd->data;
2657+ nwdClose->ConnHandle =
2658+ (HANDLE) resource->connection;
2659+
2660+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL,
2661+ 0, (void **)&reply,
2662+ &replylen, 0);
2663+ if (reply)
2664+ kfree(reply);
2665+ }
2666+ l = l->prev;
2667+ list_del(&resource->list);
2668+ kfree(resource);
2669+ }
2670+ kfree(dh);
2671+ file->private_data = NULL;
2672+ }
2673+
2674+ return (0);
2675+}
2676+
2677+ssize_t Daemon_Library_read(struct file *file, char __user *buf, size_t len, loff_t *off)
2678+{
2679+ daemon_handle_t *dh;
2680+ daemon_resource_t *resource;
2681+
2682+ size_t thisread, totalread = 0;
2683+ loff_t offset = *off;
2684+
2685+ DbgPrint("Daemon_Library_read: file=0x%p len=%d off=%lld\n", file, len,
2686+ *off);
2687+
2688+ if (file->private_data) {
2689+ dh = file->private_data;
2690+ read_lock(&dh->lock);
2691+ if (&dh->list != dh->list.next) {
2692+ resource =
2693+ list_entry(dh->list.next, daemon_resource_t, list);
2694+
2695+ if (DH_TYPE_STREAM == resource->type) {
2696+ while (len > 0 && (offset < resource->size)) {
2697+ thisread = len;
2698+ if (Novfs_Read_Stream
2699+ (resource->connection,
2700+ resource->handle, buf, &thisread,
2701+ &offset, 1, dh->session)
2702+ || !thisread) {
2703+ break;
2704+ }
2705+ len -= thisread;
2706+ buf += thisread;
2707+ offset += thisread;
2708+ totalread += thisread;
2709+ }
2710+ }
2711+ }
2712+ read_unlock(&dh->lock);
2713+ }
2714+ *off = offset;
2715+ DbgPrint("Daemon_Library_read return = 0x%x\n", totalread);
2716+ return (totalread);
2717+}
2718+
2719+ssize_t Daemon_Library_write(struct file *file, const char __user *buf, size_t len, loff_t *off)
2720+{
2721+ daemon_handle_t *dh;
2722+ daemon_resource_t *resource;
2723+
2724+ size_t thiswrite, totalwrite = -EINVAL;
2725+ loff_t offset = *off;
2726+ int status;
2727+
2728+ DbgPrint("Daemon_Library_write: file=0x%p len=%d off=%lld\n", file, len,
2729+ *off);
2730+
2731+ if (file->private_data) {
2732+ dh = file->private_data;
2733+ write_lock(&dh->lock);
2734+ if (&dh->list != dh->list.next) {
2735+ resource =
2736+ list_entry(dh->list.next, daemon_resource_t, list);
2737+
2738+ if ((DH_TYPE_STREAM == resource->type) && (len >= 0)) {
2739+ totalwrite = 0;
2740+ do {
2741+ thiswrite = len;
2742+ status =
2743+ Novfs_Write_Stream(resource->
2744+ connection,
2745+ resource->handle,
2746+ (void *)buf,
2747+ &thiswrite,
2748+ &offset,
2749+ dh->session);
2750+ if (status || !thiswrite) {
2751+ /*
2752+ * If len is zero then the file will have just been
2753+ * truncated to offset. Update size.
2754+ */
2755+ if (!status && !len) {
2756+ resource->size = offset;
2757+ }
2758+ totalwrite = status;
2759+ break;
2760+ }
2761+ len -= thiswrite;
2762+ buf += thiswrite;
2763+ offset += thiswrite;
2764+ totalwrite += thiswrite;
2765+ if (offset > resource->size) {
2766+ resource->size = offset;
2767+ }
2768+ } while (len > 0);
2769+ }
2770+ }
2771+ write_unlock(&dh->lock);
2772+ }
2773+ *off = offset;
2774+ DbgPrint("Daemon_Library_write return = 0x%x\n", totalwrite);
2775+
2776+ return (totalwrite);
2777+}
2778+
2779+/*++======================================================================*/
2780+loff_t Daemon_Library_llseek(struct file * file, loff_t offset, int origin)
2781+/*
2782+ *
2783+ * Arguments:
2784+ *
2785+ * Returns:
2786+ *
2787+ * Abstract:
2788+ *
2789+ * Notes:
2790+ *
2791+ * Environment:
2792+ *
2793+ *========================================================================*/
2794+{
2795+ daemon_handle_t *dh;
2796+ daemon_resource_t *resource;
2797+
2798+ loff_t retVal = -EINVAL;
2799+
2800+ DbgPrint("Daemon_Library_llseek: file=0x%p offset=%lld origin=%d\n",
2801+ file, offset, origin);
2802+
2803+ if (file->private_data) {
2804+ dh = file->private_data;
2805+ read_lock(&dh->lock);
2806+ if (&dh->list != dh->list.next) {
2807+ resource =
2808+ list_entry(dh->list.next, daemon_resource_t, list);
2809+
2810+ if (DH_TYPE_STREAM == resource->type) {
2811+ switch (origin) {
2812+ case 2:
2813+ offset += resource->size;
2814+ break;
2815+ case 1:
2816+ offset += file->f_pos;
2817+ }
2818+ if (offset >= 0) {
2819+ if (offset != file->f_pos) {
2820+ file->f_pos = offset;
2821+ file->f_version = 0;
2822+ }
2823+ retVal = offset;
2824+ }
2825+ }
2826+ }
2827+ read_unlock(&dh->lock);
2828+ }
2829+
2830+ DbgPrint("Daemon_Library_llseek: ret %lld\n", retVal);
2831+
2832+ return retVal;
2833+}
2834+
2835+int Daemon_Library_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
2836+{
2837+ int retCode = -ENOSYS;
2838+ daemon_handle_t *dh;
2839+ HANDLE handle = NULL;
2840+ unsigned long cpylen;
2841+
2842+ dh = file->private_data;
2843+
2844+ DbgPrint("Daemon_Library_ioctl: file=0x%p 0x%x 0x%p dh=0x%p\n", file,
2845+ cmd, arg, dh);
2846+
2847+ if (dh) {
2848+
2849+ switch (cmd) {
2850+ case IOC_LOGIN:
2851+ retCode = daemon_login((struct login *)arg, &dh->session);
2852+ break;
2853+
2854+ case IOC_LOGOUT:
2855+ retCode = daemon_logout((struct logout *)arg, &dh->session);
2856+ break;
2857+
2858+ case IOC_DEBUGPRINT:
2859+ {
2860+ struct Ioctl_Debug {
2861+ int length;
2862+ char *data;
2863+ } io;
2864+ char *buf;
2865+ io.length = 0;
2866+ cpylen =
2867+ copy_from_user(&io, (void *)arg,
2868+ sizeof(io));
2869+ if (io.length) {
2870+ buf = kmalloc(io.length + 1, GFP_KERNEL);
2871+ if (buf) {
2872+ buf[0] = 0;
2873+ cpylen = copy_from_user(buf, io.data, io.length);
2874+ buf[io.length] = '\0';
2875+ DbgPrint("%s", buf);
2876+ kfree(buf);
2877+ retCode = 0;
2878+ }
2879+ }
2880+ break;
2881+ }
2882+
2883+ case IOC_XPLAT:
2884+ {
2885+ XPLAT data;
2886+
2887+ cpylen =
2888+ copy_from_user(&data, (void *)arg,
2889+ sizeof(data));
2890+ retCode =
2891+ ((data.
2892+ xfunction & 0x0000FFFF) | 0xCC000000);
2893+
2894+ switch (data.xfunction) {
2895+ case NWC_OPEN_CONN_BY_NAME:
2896+ DbgPrint("[VFS XPLAT] Call NwOpenConnByName\n");
2897+ retCode = NwOpenConnByName(&data, &handle, dh->session);
2898+ if (!retCode)
2899+ Daemon_Added_Resource(dh, DH_TYPE_CONNECTION, handle, NULL, 0, 0);
2900+ break;
2901+
2902+ case NWC_OPEN_CONN_BY_ADDRESS:
2903+ DbgPrint("[VFS XPLAT] Call NwOpenConnByAddress\n");
2904+ retCode = NwOpenConnByAddr(&data, &handle, dh->session);
2905+ if (!retCode)
2906+ Daemon_Added_Resource(dh, DH_TYPE_CONNECTION, handle, NULL, 0, 0);
2907+ break;
2908+
2909+ case NWC_OPEN_CONN_BY_REFERENCE:
2910+ DbgPrint("[VFS XPLAT] Call NwOpenConnByReference\n");
2911+ retCode = NwOpenConnByRef(&data, &handle, dh->session);
2912+ if (!retCode)
2913+ Daemon_Added_Resource(dh,
2914+ DH_TYPE_CONNECTION,
2915+ handle, NULL,
2916+ 0, 0);
2917+ break;
2918+
2919+ case NWC_SYS_CLOSE_CONN:
2920+ DbgPrint("[VFS XPLAT] Call NwSysCloseConn\n");
2921+ retCode = NwSysConnClose(&data, (unsigned long *)&handle, dh->session);
2922+ Daemon_Remove_Resource(dh, DH_TYPE_CONNECTION, handle, 0);
2923+ break;
2924+
2925+ case NWC_CLOSE_CONN:
2926+ DbgPrint
2927+ ("[VFS XPLAT] Call NwCloseConn\n");
2928+ retCode =
2929+ NwConnClose(&data, &handle,
2930+ dh->session);
2931+ Daemon_Remove_Resource(dh,
2932+ DH_TYPE_CONNECTION,
2933+ handle, 0);
2934+ break;
2935+
2936+ case NWC_LOGIN_IDENTITY:
2937+ DbgPrint("[VFS XPLAT] Call NwLoginIdentity\n");
2938+ retCode = NwLoginIdentity(&data, &dh->session);
2939+ break;
2940+
2941+ case NWC_RAW_NCP_REQUEST:
2942+ DbgPrint("[VFS XPLAT] Send Raw NCP Request\n");
2943+ retCode = NwRawSend(&data, dh->session);
2944+ break;
2945+
2946+ case NWC_AUTHENTICATE_CONN_WITH_ID:
2947+ DbgPrint
2948+ ("[VFS XPLAT] Authenticate Conn With ID\n");
2949+ retCode =
2950+ NwAuthConnWithId(&data,
2951+ dh->session);
2952+ break;
2953+
2954+ case NWC_UNAUTHENTICATE_CONN:
2955+ DbgPrint
2956+ ("[VFS XPLAT] UnAuthenticate Conn With ID\n");
2957+ retCode =
2958+ NwUnAuthenticate(&data,
2959+ dh->session);
2960+ break;
2961+
2962+ case NWC_LICENSE_CONN:
2963+ DbgPrint("Call NwLicenseConn\n");
2964+ retCode =
2965+ NwLicenseConn(&data, dh->session);
2966+ break;
2967+
2968+ case NWC_LOGOUT_IDENTITY:
2969+ DbgPrint
2970+ ("[VFS XPLAT] Call NwLogoutIdentity\n");
2971+ retCode =
2972+ NwLogoutIdentity(&data,
2973+ dh->session);
2974+ break;
2975+
2976+ case NWC_UNLICENSE_CONN:
2977+ DbgPrint
2978+ ("[VFS XPLAT] Call NwUnlicense\n");
2979+ retCode =
2980+ NwUnlicenseConn(&data, dh->session);
2981+ break;
2982+
2983+ case NWC_GET_CONN_INFO:
2984+ DbgPrint
2985+ ("[VFS XPLAT] Call NwGetConnInfo\n");
2986+ retCode =
2987+ NwGetConnInfo(&data, dh->session);
2988+ break;
2989+
2990+ case NWC_SET_CONN_INFO:
2991+ DbgPrint
2992+ ("[VFS XPLAT] Call NwGetConnInfo\n");
2993+ retCode =
2994+ NwSetConnInfo(&data, dh->session);
2995+ break;
2996+
2997+ case NWC_SCAN_CONN_INFO:
2998+ DbgPrint
2999+ ("[VFS XPLAT] Call NwScanConnInfo\n");
3000+ retCode =
3001+ NwScanConnInfo(&data, dh->session);
3002+ break;
3003+
3004+ case NWC_GET_IDENTITY_INFO:
3005+ DbgPrint
3006+ ("[VFS XPLAT] Call NwGetIdentityInfo\n");
3007+ retCode =
3008+ NwGetIdentityInfo(&data,
3009+ dh->session);
3010+ break;
3011+
3012+ case NWC_GET_REQUESTER_VERSION:
3013+ DbgPrint
3014+ ("[VFS XPLAT] Call NwGetDaemonVersion\n");
3015+ retCode =
3016+ NwGetDaemonVersion(&data,
3017+ dh->session);
3018+ break;
3019+
3020+ case NWC_GET_PREFERRED_DS_TREE:
3021+ DbgPrint
3022+ ("[VFS XPLAT] Call NwcGetPreferredDsTree\n");
3023+ retCode =
3024+ NwcGetPreferredDSTree(&data,
3025+ dh->session);
3026+ break;
3027+
3028+ case NWC_SET_PREFERRED_DS_TREE:
3029+ DbgPrint
3030+ ("[VFS XPLAT] Call NwcSetPreferredDsTree\n");
3031+ retCode =
3032+ NwcSetPreferredDSTree(&data,
3033+ dh->session);
3034+ break;
3035+
3036+ case NWC_GET_DEFAULT_NAME_CONTEXT:
3037+ DbgPrint
3038+ ("[VFS XPLAT] Call NwcGetDefaultNameContext\n");
3039+ retCode =
3040+ NwcGetDefaultNameCtx(&data,
3041+ dh->session);
3042+ break;
3043+
3044+ case NWC_SET_DEFAULT_NAME_CONTEXT:
3045+ DbgPrint
3046+ ("[VFS XPLAT] Call NwcSetDefaultNameContext\n");
3047+ retCode =
3048+ NwcSetDefaultNameCtx(&data,
3049+ dh->session);
3050+ break;
3051+
3052+ case NWC_QUERY_FEATURE:
3053+ DbgPrint
3054+ ("[VFS XPLAT] Call NwQueryFeature\n");
3055+ retCode =
3056+ NwQueryFeature(&data, dh->session);
3057+ break;
3058+
3059+ case NWC_GET_TREE_MONITORED_CONN_REF:
3060+ DbgPrint
3061+ ("[VFS XPLAT] Call NwcGetTreeMonitoredConn\n");
3062+ retCode =
3063+ NwcGetTreeMonitoredConn(&data,
3064+ dh->
3065+ session);
3066+ break;
3067+
3068+ case NWC_ENUMERATE_IDENTITIES:
3069+ DbgPrint
3070+ ("[VFS XPLAT] Call NwcEnumerateIdentities\n");
3071+ retCode =
3072+ NwcEnumIdentities(&data,
3073+ dh->session);
3074+ break;
3075+
3076+ case NWC_CHANGE_KEY:
3077+ DbgPrint
3078+ ("[VFS XPLAT] Call NwcChangeAuthKey\n");
3079+ retCode =
3080+ NwcChangeAuthKey(&data,
3081+ dh->session);
3082+ break;
3083+
3084+ case NWC_CONVERT_LOCAL_HANDLE:
3085+ DbgPrint
3086+ ("[VFS XPLAT] Call NwdConvertLocalHandle\n");
3087+ retCode =
3088+ NwdConvertLocalHandle(&data, dh);
3089+ break;
3090+
3091+ case NWC_CONVERT_NETWARE_HANDLE:
3092+ DbgPrint
3093+ ("[VFS XPLAT] Call NwdConvertNetwareHandle\n");
3094+ retCode =
3095+ NwdConvertNetwareHandle(&data, dh);
3096+ break;
3097+
3098+ case NWC_SET_PRIMARY_CONN:
3099+ DbgPrint
3100+ ("[VFS XPLAT] Call NwcSetPrimaryConn\n");
3101+ retCode =
3102+ NwcSetPrimaryConn(&data,
3103+ dh->session);
3104+ break;
3105+
3106+ case NWC_GET_PRIMARY_CONN:
3107+ DbgPrint
3108+ ("[VFS XPLAT] Call NwcGetPrimaryConn\n");
3109+ retCode =
3110+ NwcGetPrimaryConn(&data,
3111+ dh->session);
3112+ break;
3113+
3114+ case NWC_MAP_DRIVE:
3115+ DbgPrint("[VFS XPLAT] Call NwcMapDrive\n");
3116+ retCode = NwdSetMapDrive(&data, dh->session);
3117+ break;
3118+
3119+ case NWC_UNMAP_DRIVE:
3120+ DbgPrint
3121+ ("[VFS XPLAT] Call NwcUnMapDrive\n");
3122+ retCode = NwdUnMapDrive(&data, dh->session);
3123+ break;
3124+
3125+ case NWC_ENUMERATE_DRIVES:
3126+ DbgPrint
3127+ ("[VFS XPLAT] Call NwcEnumerateDrives\n");
3128+ retCode =
3129+ NwcEnumerateDrives(&data,
3130+ dh->session);
3131+ break;
3132+
3133+ case NWC_GET_MOUNT_PATH:
3134+ DbgPrint
3135+ ("[VFS XPLAT] Call NwdGetMountPath\n");
3136+ retCode = NwdGetMountPath(&data);
3137+ break;
3138+
3139+ case NWC_GET_BROADCAST_MESSAGE:
3140+ DbgPrint
3141+ ("[VSF XPLAT Call NwdGetBroadcastMessage\n");
3142+ retCode =
3143+ NwcGetBroadcastMessage(&data,
3144+ dh->session);
3145+ break;
3146+
3147+ case NWC_SET_KEY:
3148+ DbgPrint("[VSF XPLAT Call NwdSetKey\n");
3149+ retCode =
3150+ NwdSetKeyValue(&data, dh->session);
3151+ break;
3152+
3153+ case NWC_VERIFY_KEY:
3154+ DbgPrint
3155+ ("[VSF XPLAT Call NwdVerifyKey\n");
3156+ retCode =
3157+ NwdVerifyKeyValue(&data,
3158+ dh->session);
3159+ break;
3160+
3161+ case NWC_RAW_NCP_REQUEST_ALL:
3162+ case NWC_NDS_RESOLVE_NAME_TO_ID:
3163+ case NWC_FRAGMENT_REQUEST:
3164+ case NWC_GET_CONFIGURED_NSPS:
3165+ default:
3166+ break;
3167+
3168+ }
3169+
3170+ DbgPrint("[NOVFS XPLAT] status Code = %X\n",
3171+ retCode);
3172+ break;
3173+ }
3174+ }
3175+ }
3176+
3177+ return (retCode);
3178+}
3179+
3180+unsigned int Daemon_Poll(struct file *file, struct poll_table_struct *poll_table)
3181+{
3182+ daemon_command_t *que;
3183+ unsigned int mask = POLLOUT | POLLWRNORM;
3184+
3185+ que = get_next_queue(0);
3186+ if (que)
3187+ mask |= (POLLIN | POLLRDNORM);
3188+ return mask;
3189+}
3190+
3191+int NwdConvertNetwareHandle(PXPLAT pdata, daemon_handle_t *DHandle)
3192+{
3193+ int retVal;
3194+ NwcConvertNetWareHandle nh;
3195+ unsigned long cpylen;
3196+
3197+ DbgPrint("NwdConvertNetwareHandle: DHandle=0x%p\n", DHandle);
3198+
3199+ cpylen = copy_from_user(&nh, pdata->reqData, sizeof(NwcConvertNetWareHandle));
3200+
3201+ retVal = Daemon_Added_Resource(DHandle, DH_TYPE_STREAM,
3202+ Uint32toHandle(nh.ConnHandle),
3203+ nh.NetWareHandle, nh.uAccessMode,
3204+ nh.uFileSize);
3205+
3206+ return retVal;
3207+}
3208+
3209+/*++======================================================================*/
3210+int NwdConvertLocalHandle(PXPLAT pdata, daemon_handle_t * DHandle)
3211+/*
3212+ *
3213+ * Arguments:
3214+ *
3215+ * Returns:
3216+ *
3217+ * Abstract:
3218+ *
3219+ * Notes:
3220+ *
3221+ * Environment:
3222+ *
3223+ *========================================================================*/
3224+{
3225+ int retVal = NWE_REQUESTER_FAILURE;
3226+ daemon_resource_t *resource;
3227+ NwcConvertLocalHandle lh;
3228+ struct list_head *l;
3229+ unsigned long cpylen;
3230+
3231+ DbgPrint("NwdConvertLocalHandle: DHandle=0x%p\n", DHandle);
3232+
3233+ read_lock(&DHandle->lock);
3234+
3235+ list_for_each(l, &DHandle->list) {
3236+ resource = list_entry(l, daemon_resource_t, list);
3237+
3238+ if (DH_TYPE_STREAM == resource->type) {
3239+ lh.uConnReference =
3240+ HandletoUint32(resource->connection);
3241+
3242+//sgled memcpy(lh.NwWareHandle, resource->handle, sizeof(resource->handle));
3243+ memcpy(lh.NetWareHandle, resource->handle, sizeof(resource->handle)); //sgled
3244+ if (pdata->repLen >= sizeof(NwcConvertLocalHandle)) {
3245+ cpylen =
3246+ copy_to_user(pdata->repData, &lh,
3247+ sizeof(NwcConvertLocalHandle));
3248+ retVal = 0;
3249+ } else {
3250+ retVal = NWE_BUFFER_OVERFLOW;
3251+ }
3252+ break;
3253+ }
3254+ }
3255+
3256+ read_unlock(&DHandle->lock);
3257+
3258+ return (retVal);
3259+}
3260+
3261+/*++======================================================================*/
3262+int NwdGetMountPath(PXPLAT pdata)
3263+/*
3264+ *
3265+ * Arguments:
3266+ *
3267+ * Returns:
3268+ *
3269+ * Abstract:
3270+ *
3271+ * Notes:
3272+ *
3273+ * Environment:
3274+ *
3275+ *========================================================================*/
3276+{
3277+ int retVal = NWE_REQUESTER_FAILURE;
3278+ int len;
3279+ unsigned long cpylen;
3280+ NwcGetMountPath mp;
3281+
3282+ cpylen = copy_from_user(&mp, pdata->reqData, pdata->reqLen);
3283+
3284+ if (Novfs_CurrentMount) {
3285+
3286+ len = strlen(Novfs_CurrentMount) + 1;
3287+ if ((len > mp.MountPathLen) && mp.pMountPath) {
3288+ retVal = NWE_BUFFER_OVERFLOW;
3289+ } else {
3290+ if (mp.pMountPath) {
3291+ cpylen =
3292+ copy_to_user(mp.pMountPath,
3293+ Novfs_CurrentMount, len);
3294+ }
3295+ retVal = 0;
3296+ }
3297+
3298+ mp.MountPathLen = len;
3299+
3300+ if (pdata->repData && (pdata->repLen >= sizeof(mp))) {
3301+ cpylen = copy_to_user(pdata->repData, &mp, sizeof(mp));
3302+ }
3303+ }
3304+
3305+ return (retVal);
3306+}
3307+
3308+static int NwdSetMapDrive(PXPLAT pdata, session_t Session)
3309+{
3310+ int retVal;
3311+ NwcMapDriveEx symInfo;
3312+ char *path;
3313+ drive_map_t *drivemap, *dm;
3314+ struct list_head *list;
3315+
3316+ retVal = NwcSetMapDrive(pdata, Session);
3317+ if (retVal)
3318+ return retVal;
3319+
3320+ if (copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)))
3321+ return -EFAULT;
3322+
3323+ drivemap = kmalloc(sizeof(drive_map_t) + symInfo.linkOffsetLength, GFP_KERNEL);
3324+ if (!drivemap)
3325+ return -ENOMEM;
3326+
3327+ path = (char *)pdata->reqData;
3328+ path += symInfo.linkOffset;
3329+ if (copy_from_user(drivemap->name, path, symInfo.linkOffsetLength)) {
3330+ kfree(drivemap);
3331+ return -EFAULT;
3332+ }
3333+
3334+ drivemap->session = Session;
3335+ drivemap->hash = full_name_hash(drivemap->name, symInfo.linkOffsetLength - 1);
3336+ drivemap->namelen = symInfo.linkOffsetLength - 1;
3337+ DbgPrint("NwdSetMapDrive: hash=0x%x path=%s\n", drivemap->hash, drivemap->name);
3338+
3339+ dm = (drive_map_t *) & DriveMapList.next;
3340+
3341+ down(&DriveMapLock);
3342+
3343+ list_for_each(list, &DriveMapList) {
3344+ dm = list_entry(list, drive_map_t, list);
3345+ DbgPrint("NwdSetMapDrive: dm=0x%p\n"
3346+ " hash: 0x%x\n"
3347+ " namelen: %d\n"
3348+ " name: %s\n",
3349+ dm, dm->hash, dm->namelen, dm->name);
3350+
3351+ if (drivemap->hash == dm->hash) {
3352+ if (0 ==
3353+ strcmp(dm->name, drivemap->name)) {
3354+ dm = NULL;
3355+ break;
3356+ }
3357+ } else if (drivemap->hash < dm->hash) {
3358+ break;
3359+ }
3360+ }
3361+
3362+ if (dm) {
3363+ if ((dm == (drive_map_t *) & DriveMapList) ||
3364+ (dm->hash < drivemap->hash)) {
3365+ list_add(&drivemap->list, &dm->list);
3366+ } else {
3367+ list_add_tail(&drivemap->list,
3368+ &dm->list);
3369+ }
3370+ } else {
3371+ kfree(drivemap);
3372+ }
3373+ up(&DriveMapLock);
3374+
3375+ return (retVal);
3376+}
3377+
3378+static int NwdUnMapDrive(PXPLAT pdata, session_t Session)
3379+{
3380+ int retVal = NWE_REQUESTER_FAILURE;
3381+ NwcUnmapDriveEx symInfo;
3382+ char *path;
3383+ drive_map_t *dm;
3384+ struct list_head *list;
3385+ unsigned long hash;
3386+
3387+ retVal = NwcUnMapDrive(pdata, Session);
3388+ if (retVal)
3389+ return retVal;
3390+
3391+ if (copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)))
3392+ return -EFAULT;
3393+
3394+ path = kmalloc(symInfo.linkLen, GFP_KERNEL);
3395+ if (!path)
3396+ return -ENOMEM;
3397+
3398+ if (copy_from_user(path, ((NwcUnmapDriveEx *)pdata->reqData)->linkData, symInfo.linkLen)) {
3399+ kfree(path);
3400+ return -EFAULT;
3401+ }
3402+
3403+ hash = full_name_hash(path, symInfo.linkLen - 1);
3404+ DbgPrint("NwdUnMapDrive: hash=0x%x path=%s\n", hash, path);
3405+
3406+ dm = NULL;
3407+
3408+ down(&DriveMapLock);
3409+
3410+ list_for_each(list, &DriveMapList) {
3411+ dm = list_entry(list, drive_map_t, list);
3412+ DbgPrint("NwdUnMapDrive: dm=0x%p %s\n"
3413+ " hash: 0x%x\n"
3414+ " namelen: %d\n",
3415+ dm, dm->name, dm->hash, dm->namelen);
3416+
3417+ if (hash == dm->hash) {
3418+ if (0 == strcmp(dm->name, path)) {
3419+ break;
3420+ }
3421+ } else if (hash < dm->hash) {
3422+ dm = NULL;
3423+ break;
3424+ }
3425+ }
3426+
3427+ if (dm) {
3428+ DbgPrint("NwdUnMapDrive: Remove dm=0x%p %s\n"
3429+ " hash: 0x%x\n"
3430+ " namelen: %d\n",
3431+ dm, dm->name, dm->hash, dm->namelen);
3432+ list_del(&dm->list);
3433+ kfree(dm);
3434+ }
3435+
3436+ up(&DriveMapLock);
3437+
3438+ return retVal;
3439+}
3440+
3441+/*++======================================================================*/
3442+void RemoveDriveMaps(void)
3443+/*
3444+ *
3445+ * Arguments:
3446+ *
3447+ * Returns:
3448+ *
3449+ * Abstract:
3450+ *
3451+ * Notes:
3452+ *
3453+ * Environment:
3454+ *
3455+ *========================================================================*/
3456+{
3457+ drive_map_t *dm;
3458+ struct list_head *list;
3459+
3460+ down(&DriveMapLock);
3461+ list_for_each(list, &DriveMapList) {
3462+ dm = list_entry(list, drive_map_t, list);
3463+
3464+ DbgPrint("RemoveDriveMap: dm=0x%p\n"
3465+ " hash: 0x%x\n"
3466+ " namelen: %d\n"
3467+ " name: %s\n",
3468+ dm, dm->hash, dm->namelen, dm->name);
3469+ local_unlink(dm->name);
3470+ list = list->prev;
3471+ list_del(&dm->list);
3472+ kfree(dm);
3473+ }
3474+ up(&DriveMapLock);
3475+}
3476+
3477+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
3478+/*++======================================================================*/
3479+int local_unlink(const char *pathname)
3480+{
3481+ int error;
3482+ struct dentry *dentry;
3483+ struct nameidata nd;
3484+ struct inode *inode = NULL;
3485+
3486+ DbgPrint("local_unlink: %s\n", pathname);
3487+ error = path_lookup(pathname, LOOKUP_PARENT, &nd);
3488+ DbgPrint("local_unlink: path_lookup %d\n", error);
3489+ if (!error) {
3490+ error = -EISDIR;
3491+ if (nd.last_type == LAST_NORM) {
3492+ dentry = lookup_create(&nd, 1);
3493+ DbgPrint("local_unlink: lookup_hash 0x%p\n", dentry);
3494+
3495+ error = PTR_ERR(dentry);
3496+ if (!IS_ERR(dentry)) {
3497+ if (nd.last.name[nd.last.len]) {
3498+ error =
3499+ !dentry->
3500+ d_inode ? -ENOENT : S_ISDIR(dentry->
3501+ d_inode->
3502+ i_mode)
3503+ ? -EISDIR : -ENOTDIR;
3504+ } else {
3505+ inode = dentry->d_inode;
3506+ if (inode) {
3507+ atomic_inc(&inode->i_count);
3508+ }
3509+ error = vfs_unlink(nd.path.dentry->d_inode, dentry, nd.path.mnt);
3510+ DbgPrint
3511+ ("local_unlink: vfs_unlink %d\n",
3512+ error);
3513+ }
3514+ dput(dentry);
3515+ }
3516+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
3517+
3518+ }
3519+ path_put(&nd.path);
3520+ }
3521+
3522+ if (inode) {
3523+ iput(inode); /* truncate the inode here */
3524+ }
3525+
3526+ DbgPrint("local_unlink: error=%d\n", error);
3527+ return error;
3528+}
3529+
3530+#else
3531+/*++======================================================================*/
3532+int local_unlink(const char *pathname)
3533+{
3534+ int error;
3535+ struct dentry *dentry;
3536+ struct nameidata nd;
3537+ struct inode *inode = NULL;
3538+
3539+ DbgPrint("local_unlink: %s\n", pathname);
3540+ error = path_lookup(pathname, LOOKUP_PARENT, &nd);
3541+ DbgPrint("local_unlink: path_lookup %d\n", error);
3542+ if (!error) {
3543+ error = -EISDIR;
3544+ if (nd.last_type == LAST_NORM) {
3545+ down(&nd.dentry->d_inode->i_sem);
3546+ dentry =
3547+ lookup_one_len(&nd.last, nd.dentry,
3548+ sizeof(nd.last));
3549+ DbgPrint("local_unlink: lookup_hash 0x%p\n", dentry);
3550+
3551+ error = PTR_ERR(dentry);
3552+ if (!IS_ERR(dentry)) {
3553+ if (nd.last.name[nd.last.len]) {
3554+ error =
3555+ !dentry->
3556+ d_inode ? -ENOENT : S_ISDIR(dentry->
3557+ d_inode->
3558+ i_mode)
3559+ ? -EISDIR : -ENOTDIR;
3560+ } else {
3561+ inode = dentry->d_inode;
3562+ if (inode) {
3563+ atomic_inc(&inode->i_count);
3564+ }
3565+ error =
3566+ vfs_unlink(nd.dentry->d_inode,
3567+ dentry);
3568+ DbgPrint
3569+ ("local_unlink: vfs_unlink %d\n",
3570+ error);
3571+ }
3572+ dput(dentry);
3573+ }
3574+ up(&nd.dentry->d_inode->i_sem);
3575+ }
3576+ path_release(&nd);
3577+ }
3578+
3579+ if (inode) {
3580+ iput(inode); /* truncate the inode here */
3581+ }
3582+
3583+ DbgPrint("local_unlink: error=%d\n", error);
3584+ return error;
3585+}
3586+#endif
3587--- /dev/null
3588+++ b/fs/novfs/file.c
3589@@ -0,0 +1,1964 @@
3590+/*
3591+ * Novell NCP Redirector for Linux
3592+ * Author: James Turner
3593+ *
3594+ * This file contains functions for accessing files through the daemon.
3595+ *
3596+ * Copyright (C) 2005 Novell, Inc.
3597+ *
3598+ * This program is free software; you can redistribute it and/or
3599+ * modify it under the terms of the GNU General Public License
3600+ * as published by the Free Software Foundation; either version 2
3601+ * of the License, or (at your option) any later version.
3602+ */
3603+
3604+#include <linux/module.h>
3605+#include <linux/kthread.h>
3606+#include <linux/fs.h>
3607+#include <linux/file.h>
3608+#include <linux/sched.h>
3609+#include <linux/dcache.h>
3610+#include <linux/pagemap.h>
3611+#include <linux/stat.h>
3612+#include <linux/slab.h>
3613+#include <asm/uaccess.h>
3614+
3615+#include "vfs.h"
3616+#include "commands.h"
3617+#include "nwerror.h"
3618+
3619+/*===[ Function prototypes ]==============================================*/
3620+int Novfs_get_alltrees(struct dentry *parent);
3621+ssize_t Novfs_tree_read(struct file *file, char *buf, size_t len, loff_t * off);
3622+
3623+int Novfs_Find_Name_In_List(struct qstr *Name, unsigned char * List);
3624+
3625+int Novfs_Create(unsigned char * Path, int DirectoryFlag, session_t SessionId);
3626+int Novfs_Close_File(HANDLE Handle, session_t SessionId);
3627+int Novfs_Read_File(HANDLE Handle, unsigned char * Buffer, size_t * Bytes,
3628+ loff_t * Offset, session_t SessionId);
3629+int Novfs_Write_File(HANDLE Handle, unsigned char * Buffer, size_t * Bytes,
3630+ loff_t * Offset, session_t SessionId);
3631+int Novfs_Write_Page(HANDLE Handle, struct page *Page, session_t SessionId);
3632+int Novfs_Read_Stream(HANDLE ConnHandle, unsigned char * Handle, unsigned char * Buffer,
3633+ size_t * Bytes, loff_t * Offset, int User,
3634+ session_t SessionId);
3635+int Novfs_Write_Stream(HANDLE ConnHandle, unsigned char * Handle, unsigned char * Buffer,
3636+ size_t * Bytes, loff_t * Offset, session_t SessionId);
3637+int Novfs_Close_Stream(HANDLE ConnHandle, unsigned char * Handle, session_t SessionId);
3638+int Novfs_Delete(unsigned char * Path, int DirectoryFlag, session_t SessionId);
3639+int Novfs_Truncate_File(unsigned char * Path, int PathLen, session_t SessionId);
3640+int Novfs_Truncate_File_Ex(HANDLE Handle, loff_t Offset, session_t SessionId);
3641+int Novfs_Rename_File(int DirectoryFlag, unsigned char * OldName, int OldLen,
3642+ unsigned char * NewName, int NewLen, session_t SessionId);
3643+int Novfs_Set_Attr(unsigned char * Path, struct iattr *Attr, session_t SessionId);
3644+int Novfs_Get_File_Cache_Flag(unsigned char * Path, session_t SessionId);
3645+
3646+static struct file_operations Novfs_tree_operations = {
3647+ read:Novfs_tree_read,
3648+};
3649+
3650+/*
3651+ * StripTrailingDots was added because some apps will
3652+ * try and create a file name with a trailing dot. NetWare
3653+ * doesn't like this and will return an error.
3654+ */
3655+static int StripTrailingDots = 1;
3656+
3657+int Novfs_get_alltrees(struct dentry *parent)
3658+{
3659+ unsigned char *p;
3660+ PCOMMAND_REPLY_HEADER reply = NULL;
3661+ unsigned long replylen = 0;
3662+ COMMAND_REQUEST_HEADER cmd;
3663+ int retCode;
3664+ struct dentry *entry;
3665+ struct qstr name;
3666+ struct inode *inode;
3667+
3668+ cmd.CommandType = 0;
3669+ cmd.SequenceNumber = 0;
3670+//sg ??? cmd.SessionId = 0x1234;
3671+ SC_INITIALIZE(cmd.SessionId);
3672+
3673+ DbgPrint("Novfs_get_alltrees:\n");
3674+
3675+ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE);
3676+ DbgPrint("Novfs_get_alltrees: relpy=0x%p replylen=%d\n", reply,
3677+ replylen);
3678+ if (reply) {
3679+ mydump(replylen, reply);
3680+ if (!reply->ErrorCode
3681+ && (replylen > sizeof(COMMAND_REPLY_HEADER))) {
3682+ p = (char *)reply + 8;
3683+ while (*p) {
3684+ DbgPrint("Novfs_get_alltrees: %s\n", p);
3685+ name.len = strlen(p);
3686+ name.name = p;
3687+ name.hash = full_name_hash(name.name, name.len);
3688+ entry = d_lookup(parent, &name);
3689+ if (NULL == entry) {
3690+ DbgPrint("Novfs_get_alltrees: adding %s\n", p);
3691+ entry = d_alloc(parent, &name);
3692+ if (entry) {
3693+ entry->d_op = &Novfs_dentry_operations;
3694+ inode = Novfs_get_inode(parent->d_sb, S_IFREG | 0400, 0, 0, 0, &name);
3695+ if (inode) {
3696+ inode->i_fop = &Novfs_tree_operations;
3697+ d_add(entry, inode);
3698+ }
3699+ }
3700+ }
3701+ p += (name.len + 1);
3702+ }
3703+ }
3704+ kfree(reply);
3705+ }
3706+ return (retCode);
3707+}
3708+
3709+ssize_t Novfs_tree_read(struct file * file, char *buf, size_t len, loff_t * off)
3710+{
3711+ if (file->f_pos != 0) {
3712+ return (0);
3713+ }
3714+ if (copy_to_user(buf, "Tree\n", 5)) {
3715+ return (0);
3716+ }
3717+ return (5);
3718+}
3719+
3720+int Novfs_Get_Connected_Server_List(unsigned char ** ServerList, struct schandle *SessionId)
3721+{
3722+ GET_CONNECTED_SERVER_LIST_REQUEST req;
3723+ PGET_CONNECTED_SERVER_LIST_REPLY reply = NULL;
3724+ unsigned long replylen = 0;
3725+ int retCode = 0;
3726+
3727+ *ServerList = NULL;
3728+
3729+ req.Command.CommandType = VFS_COMMAND_GET_CONNECTED_SERVER_LIST;
3730+ memcpy(&req.Command.SessionId, SessionId, sizeof(*SessionId));
3731+
3732+ retCode =
3733+ Queue_Daemon_Command(&req, sizeof(req), NULL, 0, (void *)&reply,
3734+ &replylen, INTERRUPTIBLE);
3735+ if (reply) {
3736+ DbgPrint("Novfs_Get_Connected_Server_List: reply\n");
3737+ replylen -= sizeof(COMMAND_REPLY_HEADER);
3738+ if (!reply->Reply.ErrorCode && replylen) {
3739+ memcpy(reply, reply->List, replylen);
3740+ *ServerList = (unsigned char *) reply;
3741+ retCode = 0;
3742+ } else {
3743+ kfree(reply);
3744+ retCode = -ENOENT;
3745+ }
3746+ }
3747+ return (retCode);
3748+}
3749+
3750+int Novfs_Get_Server_Volume_List(struct qstr *Server, unsigned char ** VolumeList,
3751+ struct schandle *SessionId)
3752+{
3753+ PGET_SERVER_VOLUME_LIST_REQUEST req;
3754+ PGET_SERVER_VOLUME_LIST_REPLY reply = NULL;
3755+ unsigned long replylen = 0, reqlen;
3756+ int retCode;
3757+
3758+ *VolumeList = NULL;
3759+ reqlen = sizeof(GET_SERVER_VOLUME_LIST_REQUEST) + Server->len;
3760+ req = kmalloc(reqlen, GFP_KERNEL);
3761+ if (!req)
3762+ return -ENOMEM;
3763+ req->Command.CommandType = VFS_COMMAND_GET_SERVER_VOLUME_LIST;
3764+ req->Length = Server->len;
3765+ memcpy(req->Name, Server->name, Server->len);
3766+ memcpy(&req->Command.SessionId, SessionId, sizeof(*SessionId));
3767+
3768+ retCode = Queue_Daemon_Command(req, reqlen, NULL, 0, (void *)&reply,
3769+ &replylen, INTERRUPTIBLE);
3770+ if (reply) {
3771+ DbgPrint("Novfs_Get_Server_Volume_List: reply\n");
3772+ mydump(replylen, reply);
3773+ replylen -= sizeof(COMMAND_REPLY_HEADER);
3774+
3775+ if (!reply->Reply.ErrorCode && replylen) {
3776+ memcpy(reply, reply->List, replylen);
3777+ *VolumeList = (unsigned char *) reply;
3778+ retCode = 0;
3779+ } else {
3780+ kfree(reply);
3781+ retCode = -ENOENT;
3782+ }
3783+ }
3784+ kfree(req);
3785+ return retCode;
3786+}
3787+
3788+int Novfs_Find_Name_In_List(struct qstr *Name, unsigned char * List)
3789+{
3790+ int len;
3791+ int retCode = 0;
3792+
3793+ while (*List) {
3794+ len = strlen(List);
3795+ if ((len == Name->len) && !strncmp(Name->name, List, len)) {
3796+ retCode = 1;
3797+ break;
3798+ }
3799+ List += (len + 1);
3800+ }
3801+ return (retCode);
3802+}
3803+
3804+int Novfs_Get_File_Info(unsigned char * Path, struct entry_info *Info, struct schandle *SessionId)
3805+{
3806+ PVERIFY_FILE_REPLY reply = NULL;
3807+ unsigned long replylen = 0;
3808+ PVERIFY_FILE_REQUEST cmd;
3809+ int cmdlen;
3810+ int retCode = -ENOENT;
3811+ int pathlen;
3812+
3813+ DbgPrint("%s: Path = %s\n", __func__, Path);
3814+
3815+ Info->mode = S_IFDIR | 0700;
3816+ Info->uid = current->uid;
3817+ Info->gid = current->gid;
3818+ Info->size = 0;
3819+ Info->atime = Info->mtime = Info->ctime = CURRENT_TIME;
3820+
3821+ if (Path && *Path) {
3822+ pathlen = strlen(Path);
3823+ if (StripTrailingDots) {
3824+ if ('.' == Path[pathlen - 1])
3825+ pathlen--;
3826+ }
3827+ cmdlen = offsetof(VERIFY_FILE_REQUEST, path) + pathlen;
3828+ cmd = (PVERIFY_FILE_REQUEST) Novfs_Malloc(cmdlen, GFP_KERNEL);
3829+ if (cmd) {
3830+ cmd->Command.CommandType = VFS_COMMAND_VERIFY_FILE;
3831+ cmd->Command.SequenceNumber = 0;
3832+ memcpy(&cmd->Command.SessionId, SessionId, sizeof(*SessionId));
3833+ cmd->pathLen = pathlen;
3834+ memcpy(cmd->path, Path, cmd->pathLen);
3835+
3836+ retCode =
3837+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0,
3838+ (void *)&reply, &replylen,
3839+ INTERRUPTIBLE);
3840+
3841+ if (reply) {
3842+
3843+ if (reply->Reply.ErrorCode) {
3844+ retCode = -ENOENT;
3845+ } else {
3846+ Info->type = 3;
3847+ Info->mode = S_IRWXU;
3848+
3849+ if (reply->
3850+ fileMode & NW_ATTRIBUTE_DIRECTORY) {
3851+ Info->mode |= S_IFDIR;
3852+ } else {
3853+ Info->mode |= S_IFREG;
3854+ }
3855+
3856+ if (reply->
3857+ fileMode & NW_ATTRIBUTE_READ_ONLY) {
3858+ Info->mode &= ~(S_IWUSR);
3859+ }
3860+
3861+ Info->uid = current->euid;
3862+ Info->gid = current->egid;
3863+ Info->size = reply->fileSize;
3864+ Info->atime.tv_sec =
3865+ reply->lastAccessTime;
3866+ Info->atime.tv_nsec = 0;
3867+ Info->mtime.tv_sec = reply->modifyTime;
3868+ Info->mtime.tv_nsec = 0;
3869+ Info->ctime.tv_sec = reply->createTime;
3870+ Info->ctime.tv_nsec = 0;
3871+ DbgPrint("%s: replylen=%d sizeof(VERIFY_FILE_REPLY)=%d\n", __func__, replylen, sizeof(VERIFY_FILE_REPLY));
3872+ if (replylen > sizeof(VERIFY_FILE_REPLY)) {
3873+ unsigned int *lp = &reply->fileMode;
3874+ lp++;
3875+ DbgPrint("%s: extra data 0x%x\n", __func__, *lp);
3876+ Info->mtime.tv_nsec = *lp;
3877+ }
3878+ retCode = 0;
3879+ }
3880+
3881+ kfree(reply);
3882+ }
3883+ kfree(cmd);
3884+ }
3885+ }
3886+
3887+ DbgPrint("%s: return 0x%x\n", __func__, retCode);
3888+ return (retCode);
3889+}
3890+
3891+int Novfs_GetX_File_Info(char *Path, const char *Name, char *buffer,
3892+ ssize_t buffer_size, ssize_t * dataLen,
3893+ session_t *SessionId)
3894+{
3895+ PXA_GET_REPLY reply = NULL;
3896+ unsigned long replylen = 0;
3897+ PXA_GET_REQUEST cmd;
3898+ int cmdlen;
3899+ int retCode = -ENOENT;
3900+
3901+ int namelen = strlen(Name);
3902+ int pathlen = strlen(Path);
3903+
3904+ DbgPrint("%s: xattr: Path = %s, pathlen = %i, Name = %s, namelen = %i\n", __func__, Path, pathlen, Name, namelen);
3905+
3906+ if (namelen > MAX_XATTR_NAME_LEN) {
3907+ return ENOATTR;
3908+ }
3909+
3910+ cmdlen = offsetof(XA_GET_REQUEST, data) + pathlen + 1 + namelen + 1; // two '\0'
3911+ cmd = (PXA_GET_REQUEST) Novfs_Malloc(cmdlen, GFP_KERNEL);
3912+ if (cmd) {
3913+ cmd->Command.CommandType = VFS_COMMAND_GET_EXTENDED_ATTRIBUTE;
3914+ cmd->Command.SequenceNumber = 0;
3915+ memcpy(&cmd->Command.SessionId, SessionId, sizeof(*SessionId));
3916+
3917+ cmd->pathLen = pathlen;
3918+ memcpy(cmd->data, Path, cmd->pathLen + 1); //+ '\0'
3919+
3920+ cmd->nameLen = namelen;
3921+ memcpy(cmd->data + cmd->pathLen + 1, Name, cmd->nameLen + 1);
3922+
3923+ DbgPrint("%s xattr: PXA_GET_REQUEST BEGIN\n", __func__);
3924+ DbgPrint("%s xattr: Queue_Daemon_Command %d\n", __func__, cmd->Command.CommandType);
3925+ DbgPrint("%s xattr: Command.SessionId = %d\n", __func__, cmd->Command.SessionId);
3926+ DbgPrint("%s xattr: pathLen = %d\n", __func__, cmd->pathLen);
3927+ DbgPrint("%s xattr: Path = %s\n", __func__, cmd->data);
3928+ DbgPrint("%s xattr: nameLen = %d\n", __func__, cmd->nameLen);
3929+ DbgPrint("%s xattr: name = %s\n", __func__, (cmd->data + cmd->pathLen + 1));
3930+ DbgPrint("%s xattr: PXA_GET_REQUEST END\n", __func__);
3931+
3932+ retCode =
3933+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
3934+ &replylen, INTERRUPTIBLE);
3935+
3936+ if (reply) {
3937+
3938+ if (reply->Reply.ErrorCode) {
3939+ DbgPrint("%s xattr: reply->Reply.ErrorCode=%d, %X\n", __func__, reply->Reply.ErrorCode, reply->Reply.ErrorCode);
3940+ DbgPrint("%s xattr: replylen=%d\n", __func__, replylen);
3941+
3942+ //0xC9 = EA not found (C9), 0xD1 = EA access denied
3943+ if ((reply->Reply.ErrorCode == 0xC9)
3944+ || (reply->Reply.ErrorCode == 0xD1)) {
3945+ retCode = -ENOATTR;
3946+ } else {
3947+ retCode = -ENOENT;
3948+ }
3949+ } else {
3950+
3951+ *dataLen =
3952+ replylen - sizeof(COMMAND_REPLY_HEADER);
3953+ DbgPrint("%s xattr: replylen=%u, dataLen=%u\n", __func__, replylen, *dataLen);
3954+
3955+ if (buffer_size >= *dataLen) {
3956+ DbgPrint("%s xattr: copying to buffer from &reply->pData\n", __func__);
3957+ memcpy(buffer, &reply->pData, *dataLen);
3958+
3959+ retCode = 0;
3960+ } else {
3961+ DbgPrint("%s xattr: (!!!) buffer is smaller then reply\n", __func__);
3962+ retCode = -ERANGE;
3963+ }
3964+ DbgPrint("%s xattr: /dumping buffer\n", __func__);
3965+ mydump(*dataLen, buffer);
3966+ DbgPrint("%s xattr: \\after dumping buffer\n", __func__);
3967+ }
3968+
3969+ kfree(reply);
3970+ } else {
3971+ DbgPrint("%s xattr: reply = NULL\n", __func__);
3972+ }
3973+ kfree(cmd);
3974+
3975+ }
3976+
3977+ return retCode;
3978+}
3979+
3980+int Novfs_SetX_File_Info(char *Path, const char *Name, const void *Value,
3981+ unsigned long valueLen, unsigned long *bytesWritten,
3982+ int flags, struct schandle *SessionId)
3983+{
3984+ PXA_SET_REPLY reply = NULL;
3985+ unsigned long replylen = 0;
3986+ PXA_SET_REQUEST cmd;
3987+ int cmdlen;
3988+ int retCode = -ENOENT;
3989+
3990+ int namelen = strlen(Name);
3991+ int pathlen = strlen(Path);
3992+
3993+ DbgPrint("%s xattr: Path = %s, pathlen = %i, Name = %s, namelen = %i, value len = %u\n", __func__,
3994+ Path, pathlen, Name, namelen, valueLen);
3995+
3996+ if (namelen > MAX_XATTR_NAME_LEN) {
3997+ return ENOATTR;
3998+ }
3999+
4000+ cmdlen = offsetof(XA_SET_REQUEST, data) + pathlen + 1 + namelen + 1 + valueLen;
4001+ cmd = (PXA_SET_REQUEST) Novfs_Malloc(cmdlen, GFP_KERNEL);
4002+ if (cmd) {
4003+ cmd->Command.CommandType = VFS_COMMAND_SET_EXTENDED_ATTRIBUTE;
4004+ cmd->Command.SequenceNumber = 0;
4005+ memcpy(&cmd->Command.SessionId, SessionId, sizeof(*SessionId));
4006+
4007+ cmd->flags = flags;
4008+ cmd->pathLen = pathlen;
4009+ memcpy(cmd->data, Path, cmd->pathLen + 1); //+ '\0'
4010+
4011+ cmd->nameLen = namelen;
4012+ memcpy(cmd->data + cmd->pathLen + 1, Name, cmd->nameLen + 1);
4013+
4014+ cmd->valueLen = valueLen;
4015+ memcpy(cmd->data + cmd->pathLen + 1 + cmd->nameLen + 1, Value,
4016+ valueLen);
4017+
4018+ DbgPrint("%s xattr: PXA_SET_REQUEST BEGIN\n", __func__);
4019+ DbgPrint("%s xattr: Queue_Daemon_Command %d\n", __func__, cmd->Command.CommandType);
4020+ DbgPrint("%s xattr: Command.SessionId = %d\n", __func__, cmd->Command.SessionId);
4021+ DbgPrint("%s xattr: pathLen = %d\n", __func__, cmd->pathLen);
4022+ DbgPrint("%s xattr: Path = %s\n", __func__, cmd->data);
4023+ DbgPrint("%s xattr: nameLen = %d\n", __func__, cmd->nameLen);
4024+ DbgPrint("%s xattr: name = %s\n", __func__, (cmd->data + cmd->pathLen + 1));
4025+ mydump(valueLen < 16 ? valueLen : 16, (char *)Value);
4026+
4027+ DbgPrint("%s xattr: PXA_SET_REQUEST END\n", __func__);
4028+
4029+ retCode =
4030+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
4031+ &replylen, INTERRUPTIBLE);
4032+
4033+ if (reply) {
4034+
4035+ if (reply->Reply.ErrorCode) {
4036+ DbgPrint("%s xattr: reply->Reply.ErrorCode=%d, %X\n", __func__, reply->Reply.ErrorCode, reply->Reply.ErrorCode);
4037+ DbgPrint("%s xattr: replylen=%d\n", __func__, replylen);
4038+
4039+ retCode = -reply->Reply.ErrorCode; //-ENOENT;
4040+ } else {
4041+
4042+ DbgPrint("%s xattr: replylen=%u, real len = %u\n", __func__, replylen, replylen - sizeof(COMMAND_REPLY_HEADER));
4043+ memcpy(bytesWritten, &reply->pData,
4044+ replylen - sizeof(COMMAND_REPLY_HEADER));
4045+
4046+ retCode = 0;
4047+ }
4048+
4049+ kfree(reply);
4050+ } else {
4051+ DbgPrint("%s xattr: reply = NULL\n", __func__);
4052+ }
4053+ kfree(cmd);
4054+
4055+ }
4056+
4057+ return retCode;
4058+}
4059+
4060+int Novfs_ListX_File_Info(char *Path, char *buffer, ssize_t buffer_size, ssize_t * dataLen, struct schandle *SessionId)
4061+{
4062+ PXA_LIST_REPLY reply = NULL;
4063+ unsigned long replylen = 0;
4064+ PVERIFY_FILE_REQUEST cmd;
4065+ int cmdlen;
4066+ int retCode = -ENOENT;
4067+
4068+ int pathlen = strlen(Path);
4069+ DbgPrint("%s xattr: Path = %s, pathlen = %i\n", __func__, Path, pathlen);
4070+
4071+ *dataLen = 0;
4072+ cmdlen = offsetof(VERIFY_FILE_REQUEST, path) + pathlen;
4073+ cmd = (PVERIFY_FILE_REQUEST) Novfs_Malloc(cmdlen, GFP_KERNEL);
4074+ if (cmd) {
4075+ cmd->Command.CommandType = VFS_COMMAND_LIST_EXTENDED_ATTRIBUTES;
4076+ cmd->Command.SequenceNumber = 0;
4077+ memcpy(&cmd->Command.SessionId, SessionId, sizeof(*SessionId));
4078+ cmd->pathLen = pathlen;
4079+ memcpy(cmd->path, Path, cmd->pathLen + 1); //+ '\0'
4080+ DbgPrint("%s xattr: PVERIFY_FILE_REQUEST BEGIN\n", __func__);
4081+ DbgPrint("%s xattr: Queue_Daemon_Command %d\n", __func__, cmd->Command.CommandType);
4082+ DbgPrint("%s xattr: Command.SessionId = %d\n", __func__, cmd->Command.SessionId);
4083+ DbgPrint("%s xattr: pathLen = %d\n", __func__, cmd->pathLen);
4084+ DbgPrint("%s xattr: Path = %s\n", __func__, cmd->path);
4085+ DbgPrint("%s xattr: PVERIFY_FILE_REQUEST END\n", __func__);
4086+
4087+ retCode =
4088+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
4089+ &replylen, INTERRUPTIBLE);
4090+
4091+ if (reply) {
4092+
4093+ if (reply->Reply.ErrorCode) {
4094+ DbgPrint("%s xattr: reply->Reply.ErrorCode=%d, %X\n", __func__, reply->Reply.ErrorCode, reply->Reply.ErrorCode);
4095+ DbgPrint("%s xattr: replylen=%d\n", __func__, replylen);
4096+
4097+ retCode = -ENOENT;
4098+ } else {
4099+ *dataLen = replylen - sizeof(COMMAND_REPLY_HEADER);
4100+ DbgPrint("%s xattr: replylen=%u, dataLen=%u\n", __func__, replylen, *dataLen);
4101+
4102+ if (buffer_size >= *dataLen) {
4103+ DbgPrint("%s xattr: copying to buffer from &reply->pData\n", __func__);
4104+ memcpy(buffer, &reply->pData, *dataLen);
4105+ } else {
4106+ DbgPrint("%s xattr: (!!!) buffer is smaller then reply\n", __func__);
4107+ retCode = -ERANGE;
4108+ }
4109+ DbgPrint("%s xattr: /dumping buffer\n", __func__);
4110+ mydump(*dataLen, buffer);
4111+ DbgPrint("%s xattr: \\after dumping buffer\n", __func__);
4112+
4113+ retCode = 0;
4114+ }
4115+
4116+ kfree(reply);
4117+ } else {
4118+ DbgPrint("%s xattr: reply = NULL\n", __func__);
4119+ }
4120+ kfree(cmd);
4121+
4122+ }
4123+
4124+ return retCode;
4125+}
4126+
4127+static int begin_directory_enumerate(unsigned char *Path, int PathLen, HANDLE *EnumHandle, struct schandle *SessionId)
4128+{
4129+ PBEGIN_ENUMERATE_DIRECTORY_REQUEST cmd;
4130+ PBEGIN_ENUMERATE_DIRECTORY_REPLY reply = NULL;
4131+ unsigned long replylen = 0;
4132+ int retCode, cmdlen;
4133+
4134+ *EnumHandle = 0;
4135+
4136+ cmdlen = offsetof(BEGIN_ENUMERATE_DIRECTORY_REQUEST, path) + PathLen;
4137+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
4138+ if (cmd) {
4139+ cmd->Command.CommandType = VFS_COMMAND_START_ENUMERATE;
4140+ cmd->Command.SequenceNumber = 0;
4141+ memcpy(&cmd->Command.SessionId, SessionId, sizeof(*SessionId));
4142+
4143+ cmd->pathLen = PathLen;
4144+ memcpy(cmd->path, Path, PathLen);
4145+
4146+ retCode =
4147+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
4148+ &replylen, INTERRUPTIBLE);
4149+/*
4150+ * retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, 0);
4151+ */
4152+ if (reply) {
4153+ if (reply->Reply.ErrorCode) {
4154+ retCode = -EIO;
4155+ } else {
4156+ *EnumHandle = reply->enumerateHandle;
4157+ retCode = 0;
4158+ }
4159+ kfree(reply);
4160+ }
4161+ kfree(cmd);
4162+ } else {
4163+ retCode = -ENOMEM;
4164+ }
4165+ return (retCode);
4166+}
4167+
4168+static int end_directory_enumerate(HANDLE EnumHandle, struct schandle *SessionId)
4169+{
4170+ END_ENUMERATE_DIRECTORY_REQUEST cmd;
4171+ PEND_ENUMERATE_DIRECTORY_REPLY reply = NULL;
4172+ unsigned long replylen = 0;
4173+ int retCode;
4174+
4175+ cmd.Command.CommandType = VFS_COMMAND_END_ENUMERATE;
4176+ cmd.Command.SequenceNumber = 0;
4177+ copy_session_id(&cmd.Command.SessionId, SessionId);
4178+
4179+ cmd.enumerateHandle = EnumHandle;
4180+
4181+ retCode =
4182+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
4183+ &replylen, 0);
4184+ if (reply) {
4185+ retCode = 0;
4186+ if (reply->Reply.ErrorCode) {
4187+ retCode = -EIO;
4188+ }
4189+ kfree(reply);
4190+ }
4191+
4192+ return (retCode);
4193+}
4194+
4195+int directory_enumerate(HANDLE * EnumHandle, struct entry_info *Info,
4196+ session_t SessionId)
4197+{
4198+ ENUMERATE_DIRECTORY_REQUEST cmd;
4199+ PENUMERATE_DIRECTORY_REPLY reply = NULL;
4200+ unsigned long replylen = 0;
4201+ int retCode;
4202+
4203+ cmd.Command.CommandType = VFS_COMMAND_ENUMERATE_DIRECTORY;
4204+ cmd.Command.SequenceNumber = 0;
4205+ cmd.Command.SessionId = SessionId;
4206+
4207+ cmd.enumerateHandle = *EnumHandle;
4208+ cmd.pathLen = 0;
4209+ cmd.path[0] = '\0';
4210+
4211+ retCode =
4212+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
4213+ &replylen, INTERRUPTIBLE);
4214+
4215+ if (reply) {
4216+ /*
4217+ * The VFS_COMMAND_ENUMERATE_DIRECTORY call can return an
4218+ * error but there could still be valid data.
4219+ */
4220+ if (!reply->Reply.ErrorCode ||
4221+ ((replylen > sizeof(COMMAND_REPLY_HEADER)) &&
4222+ (reply->nameLen > 0))) {
4223+ Info->type = 3;
4224+ Info->mode = S_IRWXU;
4225+
4226+ if (reply->mode & NW_ATTRIBUTE_DIRECTORY) {
4227+ Info->mode |= S_IFDIR;
4228+ Info->mode |= S_IXUSR;
4229+ } else {
4230+ Info->mode |= S_IFREG;
4231+ }
4232+
4233+ if (reply->mode & NW_ATTRIBUTE_READ_ONLY) {
4234+ Info->mode &= ~(S_IWUSR);
4235+ }
4236+
4237+ if (reply->mode & NW_ATTRIBUTE_EXECUTE) {
4238+ Info->mode |= S_IXUSR;
4239+ }
4240+
4241+ Info->uid = current->uid;
4242+ Info->gid = current->gid;
4243+ Info->size = reply->size;
4244+ Info->atime.tv_sec = reply->lastAccessTime;
4245+ Info->atime.tv_nsec = 0;
4246+ Info->mtime.tv_sec = reply->modifyTime;
4247+ Info->mtime.tv_nsec = 0;
4248+ Info->ctime.tv_sec = reply->createTime;
4249+ Info->ctime.tv_nsec = 0;
4250+ Info->namelength = reply->nameLen;
4251+ memcpy(Info->name, reply->name, reply->nameLen);
4252+ retCode = 0;
4253+ if (reply->Reply.ErrorCode) {
4254+ retCode = -1; /* Eof of data */
4255+ }
4256+ *EnumHandle = reply->enumerateHandle;
4257+ } else {
4258+ retCode = -ENODATA;
4259+ }
4260+ kfree(reply);
4261+ }
4262+
4263+ return (retCode);
4264+}
4265+
4266+static int directory_enumerate_ex(HANDLE *EnumHandle, struct schandle *SessionId, int *Count, struct entry_info **PInfo, int Interrupt)
4267+{
4268+ ENUMERATE_DIRECTORY_EX_REQUEST cmd;
4269+ PENUMERATE_DIRECTORY_EX_REPLY reply = NULL;
4270+ unsigned long replylen = 0;
4271+ int retCode = 0;
4272+ struct entry_info *info;
4273+ PENUMERATE_DIRECTORY_EX_DATA data;
4274+ int isize;
4275+
4276+ if (PInfo) {
4277+ *PInfo = NULL;
4278+ }
4279+ *Count = 0;
4280+
4281+ cmd.Command.CommandType = VFS_COMMAND_ENUMERATE_DIRECTORY_EX;
4282+ cmd.Command.SequenceNumber = 0;
4283+ copy_session_id(&cmd.Command.SessionId, SessionId);
4284+
4285+ cmd.enumerateHandle = *EnumHandle;
4286+ cmd.pathLen = 0;
4287+ cmd.path[0] = '\0';
4288+
4289+ retCode =
4290+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
4291+ &replylen, Interrupt);
4292+
4293+ if (reply) {
4294+ retCode = 0;
4295+ /*
4296+ * The VFS_COMMAND_ENUMERATE_DIRECTORY call can return an
4297+ * error but there could still be valid data.
4298+ */
4299+
4300+ if (!reply->Reply.ErrorCode ||
4301+ ((replylen > sizeof(COMMAND_REPLY_HEADER)) &&
4302+ (reply->enumCount > 0))) {
4303+ DbgPrint("directory_enumerate_ex: isize=%d\n",
4304+ replylen);
4305+ data = (PENUMERATE_DIRECTORY_EX_DATA) ((char *)reply + sizeof(ENUMERATE_DIRECTORY_EX_REPLY));
4306+ isize = replylen - sizeof(PENUMERATE_DIRECTORY_EX_REPLY) - reply->enumCount * offsetof(ENUMERATE_DIRECTORY_EX_DATA, name);
4307+ isize += (reply->enumCount * offsetof(struct entry_info, name));
4308+
4309+ if (PInfo) {
4310+ *PInfo = info = Novfs_Malloc(isize, GFP_KERNEL);
4311+ if (*PInfo) {
4312+ DbgPrint("directory_enumerate_ex1: data=0x%p info=0x%p\n", data, info);
4313+ *Count = reply->enumCount;
4314+ do {
4315+ DbgPrint("directory_enumerate_ex2: data=0x%p length=%d\n", data);
4316+
4317+ info->type = 3;
4318+ info->mode = S_IRWXU;
4319+
4320+ if (data->mode & NW_ATTRIBUTE_DIRECTORY) {
4321+ info->mode |= S_IFDIR;
4322+ info->mode |= S_IXUSR;
4323+ } else {
4324+ info->mode |= S_IFREG;
4325+ }
4326+
4327+ if (data->mode & NW_ATTRIBUTE_READ_ONLY) {
4328+ info->mode &= ~(S_IWUSR);
4329+ }
4330+
4331+ if (data->mode & NW_ATTRIBUTE_EXECUTE) {
4332+ info->mode |= S_IXUSR;
4333+ }
4334+
4335+ info->uid = current->euid;
4336+ info->gid = current->egid;
4337+ info->size = data->size;
4338+ info->atime.tv_sec = data->lastAccessTime;
4339+ info->atime.tv_nsec = 0;
4340+ info->mtime.tv_sec = data->modifyTime;
4341+ info->mtime.tv_nsec = 0;
4342+ info->ctime.tv_sec = data->createTime;
4343+ info->ctime.tv_nsec = 0;
4344+ info->namelength = data->nameLen;
4345+ memcpy(info->name, data->name, data->nameLen);
4346+ data = (PENUMERATE_DIRECTORY_EX_DATA)&data->name[data->nameLen];
4347+ replylen = (int)((char *)&info->name[info->namelength] - (char *)info);
4348+ DbgPrint("directory_enumerate_ex3: info=0x%p\n", info);
4349+ mydump(replylen, info);
4350+
4351+ info = (struct entry_info *)&info->name[info->namelength];
4352+
4353+ } while (--reply->enumCount);
4354+ }
4355+ }
4356+
4357+ if (reply->Reply.ErrorCode) {
4358+ retCode = -1; /* Eof of data */
4359+ }
4360+ *EnumHandle = reply->enumerateHandle;
4361+ } else {
4362+ retCode = -ENODATA;
4363+ }
4364+ kfree(reply);
4365+ }
4366+
4367+ return (retCode);
4368+}
4369+
4370+int Novfs_Get_Directory_ListEx(unsigned char * Path, HANDLE * EnumHandle, int *Count,
4371+ struct entry_info **Info, struct schandle *SessionId)
4372+{
4373+ int retCode = -ENOENT;
4374+
4375+ if (Count)
4376+ *Count = 0;
4377+ if (Info)
4378+ *Info = NULL;
4379+
4380+ if ((HANDLE) - 1 == *EnumHandle) {
4381+ return (-ENODATA);
4382+ }
4383+
4384+ if (0 == *EnumHandle)
4385+ retCode = begin_directory_enumerate(Path, strlen(Path), EnumHandle, SessionId);
4386+
4387+ if (*EnumHandle) {
4388+ retCode = directory_enumerate_ex(EnumHandle, SessionId, Count, Info, INTERRUPTIBLE);
4389+ if (retCode) {
4390+ end_directory_enumerate(*EnumHandle, SessionId);
4391+ if (-1 == retCode) {
4392+ retCode = 0;
4393+ *EnumHandle = Uint32toHandle(-1);
4394+ }
4395+ }
4396+ }
4397+ return (retCode);
4398+}
4399+
4400+int Novfs_Open_File(unsigned char * Path, int Flags, struct entry_info *Info, HANDLE * Handle,
4401+ session_t SessionId)
4402+{
4403+ POPEN_FILE_REQUEST cmd;
4404+ POPEN_FILE_REPLY reply;
4405+ unsigned long replylen = 0;
4406+ int retCode, cmdlen, pathlen;
4407+
4408+ pathlen = strlen(Path);
4409+
4410+ if (StripTrailingDots) {
4411+ if ('.' == Path[pathlen - 1])
4412+ pathlen--;
4413+ }
4414+
4415+ *Handle = 0;
4416+
4417+ cmdlen = offsetof(OPEN_FILE_REQUEST, path) + pathlen;
4418+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
4419+ if (cmd) {
4420+ cmd->Command.CommandType = VFS_COMMAND_OPEN_FILE;
4421+ cmd->Command.SequenceNumber = 0;
4422+ cmd->Command.SessionId = SessionId;
4423+
4424+ cmd->access = 0;
4425+
4426+ if (!(Flags & O_WRONLY) || (Flags & O_RDWR)) {
4427+ cmd->access |= NWD_ACCESS_READ;
4428+ }
4429+
4430+ if ((Flags & O_WRONLY) || (Flags & O_RDWR)) {
4431+ cmd->access |= NWD_ACCESS_WRITE;
4432+ }
4433+
4434+ switch (Flags & (O_CREAT | O_EXCL | O_TRUNC)) {
4435+ case O_CREAT:
4436+ cmd->disp = NWD_DISP_OPEN_ALWAYS;
4437+ break;
4438+
4439+ case O_CREAT | O_EXCL:
4440+ cmd->disp = NWD_DISP_CREATE_NEW;
4441+ break;
4442+
4443+ case O_TRUNC:
4444+ cmd->disp = NWD_DISP_CREATE_ALWAYS;
4445+ break;
4446+
4447+ case O_CREAT | O_TRUNC:
4448+ cmd->disp = NWD_DISP_CREATE_ALWAYS;
4449+ break;
4450+
4451+ case O_CREAT | O_EXCL | O_TRUNC:
4452+ cmd->disp = NWD_DISP_CREATE_NEW;
4453+ break;
4454+
4455+ default:
4456+ cmd->disp = NWD_DISP_OPEN_EXISTING;
4457+ break;
4458+ }
4459+
4460+ cmd->mode = NWD_SHARE_READ | NWD_SHARE_WRITE | NWD_SHARE_DELETE;
4461+
4462+ cmd->pathLen = pathlen;
4463+ memcpy(cmd->path, Path, pathlen);
4464+
4465+ retCode =
4466+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
4467+ &replylen, INTERRUPTIBLE);
4468+
4469+ if (reply) {
4470+ if (reply->Reply.ErrorCode) {
4471+ if (NWE_OBJECT_EXISTS == reply->Reply.ErrorCode) {
4472+ retCode = -EEXIST;
4473+ } else if (NWE_ACCESS_DENIED ==
4474+ reply->Reply.ErrorCode) {
4475+ retCode = -EACCES;
4476+ } else if (NWE_FILE_IN_USE ==
4477+ reply->Reply.ErrorCode) {
4478+ retCode = -EBUSY;
4479+ } else {
4480+ retCode = -ENOENT;
4481+ }
4482+ } else {
4483+ *Handle = reply->handle;
4484+ retCode = 0;
4485+ }
4486+ kfree(reply);
4487+ }
4488+ kfree(cmd);
4489+ } else {
4490+ retCode = -ENOMEM;
4491+ }
4492+ return (retCode);
4493+}
4494+
4495+int Novfs_Create(unsigned char * Path, int DirectoryFlag, session_t SessionId)
4496+{
4497+ PCREATE_FILE_REQUEST cmd;
4498+ PCREATE_FILE_REPLY reply;
4499+ unsigned long replylen = 0;
4500+ int retCode, cmdlen, pathlen;
4501+
4502+ pathlen = strlen(Path);
4503+
4504+ if (StripTrailingDots) {
4505+ if ('.' == Path[pathlen - 1])
4506+ pathlen--;
4507+ }
4508+
4509+ cmdlen = offsetof(CREATE_FILE_REQUEST, path) + pathlen;
4510+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
4511+ if (cmd) {
4512+ cmd->Command.CommandType = VFS_COMMAND_CREATE_FILE;
4513+ if (DirectoryFlag) {
4514+ cmd->Command.CommandType = VFS_COMMAND_CREATE_DIRECOTRY;
4515+ }
4516+ cmd->Command.SequenceNumber = 0;
4517+ cmd->Command.SessionId = SessionId;
4518+
4519+ cmd->pathlength = pathlen;
4520+ memcpy(cmd->path, Path, pathlen);
4521+
4522+ retCode =
4523+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
4524+ &replylen, INTERRUPTIBLE);
4525+
4526+ if (reply) {
4527+ retCode = 0;
4528+ if (reply->Reply.ErrorCode) {
4529+ retCode = -EIO;
4530+ }
4531+ kfree(reply);
4532+ }
4533+ kfree(cmd);
4534+ } else {
4535+ retCode = -ENOMEM;
4536+ }
4537+ return (retCode);
4538+}
4539+
4540+int Novfs_Close_File(HANDLE Handle, session_t SessionId)
4541+{
4542+ CLOSE_FILE_REQUEST cmd;
4543+ PCLOSE_FILE_REPLY reply;
4544+ unsigned long replylen = 0;
4545+ int retCode;
4546+
4547+ cmd.Command.CommandType = VFS_COMMAND_CLOSE_FILE;
4548+ cmd.Command.SequenceNumber = 0;
4549+ cmd.Command.SessionId = SessionId;
4550+
4551+ cmd.handle = Handle;
4552+
4553+ retCode =
4554+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
4555+ &replylen, 0);
4556+ if (reply) {
4557+ retCode = 0;
4558+ if (reply->Reply.ErrorCode) {
4559+ retCode = -EIO;
4560+ }
4561+ kfree(reply);
4562+ }
4563+ return (retCode);
4564+}
4565+
4566+int Novfs_Read_File(HANDLE Handle, unsigned char * Buffer, size_t * Bytes,
4567+ loff_t * Offset, session_t SessionId)
4568+{
4569+ READ_FILE_REQUEST cmd;
4570+ PREAD_FILE_REPLY reply = NULL;
4571+ unsigned long replylen = 0;
4572+ int retCode = 0;
4573+ size_t len;
4574+
4575+ len = *Bytes;
4576+ *Bytes = 0;
4577+
4578+ if ((offsetof(READ_FILE_REPLY, data) + len) > MaxIoSize) {
4579+ len = MaxIoSize - offsetof(READ_FILE_REPLY, data);
4580+ len = (len / PAGE_SIZE) * PAGE_SIZE;
4581+ }
4582+
4583+ cmd.Command.CommandType = VFS_COMMAND_READ_FILE;
4584+ cmd.Command.SequenceNumber = 0;
4585+ cmd.Command.SessionId = SessionId;
4586+
4587+ cmd.handle = Handle;
4588+ cmd.len = len;
4589+ cmd.offset = *Offset;
4590+
4591+ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE);
4592+
4593+ DbgPrint("Novfs_Read_File: Queue_Daemon_Command 0x%x replylen=%d\n", retCode, replylen);
4594+
4595+ if (!retCode) {
4596+ if (reply->Reply.ErrorCode) {
4597+ if (NWE_FILE_IO_LOCKED == reply->Reply.ErrorCode) {
4598+ retCode = -EBUSY;
4599+ } else {
4600+ retCode = -EIO;
4601+ }
4602+ } else {
4603+ replylen -= offsetof(READ_FILE_REPLY, data);
4604+ if (replylen > 0) {
4605+ replylen -= copy_to_user(Buffer, reply->data, replylen);
4606+ *Bytes = replylen;
4607+ }
4608+ }
4609+ }
4610+
4611+ if (reply) {
4612+ kfree(reply);
4613+ }
4614+
4615+ DbgPrint("Novfs_Read_File *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode);
4616+
4617+ return (retCode);
4618+}
4619+
4620+int Novfs_Read_Pages(HANDLE Handle, struct data_list *DList, int DList_Cnt,
4621+ size_t * Bytes, loff_t * Offset, session_t SessionId)
4622+{
4623+ READ_FILE_REQUEST cmd;
4624+ PREAD_FILE_REPLY reply = NULL;
4625+ READ_FILE_REPLY lreply;
4626+ unsigned long replylen = 0;
4627+ int retCode = 0;
4628+ size_t len;
4629+
4630+ len = *Bytes;
4631+ *Bytes = 0;
4632+
4633+ DbgPrint
4634+ ("Novfs_Read_Pages: Handle=0x%p Dlst=0x%p Dlcnt=%d Bytes=%d Offset=%lld SessionId=0x%p:%p\n",
4635+ Handle, DList, DList_Cnt, len, *Offset, SessionId.hTypeId,
4636+ SessionId.hId);
4637+
4638+ cmd.Command.CommandType = VFS_COMMAND_READ_FILE;
4639+ cmd.Command.SequenceNumber = 0;
4640+ cmd.Command.SessionId = SessionId;
4641+
4642+ cmd.handle = Handle;
4643+ cmd.len = len;
4644+ cmd.offset = *Offset;
4645+
4646+ /*
4647+ * Dlst first entry is reserved for reply header.
4648+ */
4649+ DList[0].page = NULL;
4650+ DList[0].offset = &lreply;
4651+ DList[0].len = offsetof(READ_FILE_REPLY, data);
4652+ DList[0].rwflag = DLWRITE;
4653+
4654+ retCode =
4655+ Queue_Daemon_Command(&cmd, sizeof(cmd), DList, DList_Cnt,
4656+ (void *)&reply, &replylen, INTERRUPTIBLE);
4657+
4658+ DbgPrint("Novfs_Read_Pages: Queue_Daemon_Command 0x%x\n", retCode);
4659+
4660+ if (!retCode) {
4661+ if (reply) {
4662+ memcpy(&lreply, reply, sizeof(lreply));
4663+ }
4664+
4665+ if (lreply.Reply.ErrorCode) {
4666+ if (NWE_FILE_IO_LOCKED == lreply.Reply.ErrorCode) {
4667+ retCode = -EBUSY;
4668+ } else {
4669+ retCode = -EIO;
4670+ }
4671+ }
4672+ *Bytes = replylen - offsetof(READ_FILE_REPLY, data);
4673+ }
4674+
4675+ if (reply) {
4676+ kfree(reply);
4677+ }
4678+
4679+ DbgPrint("Novfs_Read_Pages: retCode=0x%x\n", retCode);
4680+
4681+ return (retCode);
4682+}
4683+
4684+int Novfs_Write_File(HANDLE Handle, unsigned char * Buffer, size_t * Bytes,
4685+ loff_t * Offset, session_t SessionId)
4686+{
4687+ WRITE_FILE_REQUEST cmd;
4688+ PWRITE_FILE_REPLY reply = NULL;
4689+ unsigned long replylen = 0;
4690+ int retCode = 0, cmdlen;
4691+ size_t len;
4692+
4693+ unsigned long boff;
4694+ struct page **pages;
4695+ struct data_list *dlist;
4696+ int res = 0, npage, i;
4697+ WRITE_FILE_REPLY lreply;
4698+
4699+ len = *Bytes;
4700+ cmdlen = offsetof(WRITE_FILE_REQUEST, data);
4701+
4702+ *Bytes = 0;
4703+
4704+ memset(&lreply, 0, sizeof(lreply));
4705+
4706+ DbgPrint("Novfs_Write_File cmdlen=%ld len=%ld\n", cmdlen, len);
4707+
4708+ if ((cmdlen + len) > MaxIoSize) {
4709+ len = MaxIoSize - cmdlen;
4710+ len = (len / PAGE_SIZE) * PAGE_SIZE;
4711+ }
4712+ cmd.Command.CommandType = VFS_COMMAND_WRITE_FILE;
4713+ cmd.Command.SequenceNumber = 0;
4714+ cmd.Command.SessionId = SessionId;
4715+ cmd.handle = Handle;
4716+ cmd.len = len;
4717+ cmd.offset = *Offset;
4718+
4719+ DbgPrint("Novfs_Write_File cmdlen=%ld len=%ld\n", cmdlen, len);
4720+
4721+ npage =
4722+ (((unsigned long)Buffer & ~PAGE_MASK) + len +
4723+ (PAGE_SIZE - 1)) >> PAGE_SHIFT;
4724+
4725+ dlist = Novfs_Malloc(sizeof(struct data_list) * (npage + 1), GFP_KERNEL);
4726+ if (NULL == dlist) {
4727+ return (-ENOMEM);
4728+ }
4729+
4730+ pages = Novfs_Malloc(sizeof(struct page *) * npage, GFP_KERNEL);
4731+
4732+ if (NULL == pages) {
4733+ kfree(dlist);
4734+ return (-ENOMEM);
4735+ }
4736+
4737+ down_read(&current->mm->mmap_sem);
4738+
4739+ res = get_user_pages(current, current->mm, (unsigned long)Buffer, npage, 0, /* read type */
4740+ 0, /* don't force */
4741+ pages, NULL);
4742+
4743+ up_read(&current->mm->mmap_sem);
4744+
4745+ DbgPrint("Novfs_Write_File res=%d\n", res);
4746+
4747+ if (res > 0) {
4748+ boff = (unsigned long)Buffer & ~PAGE_MASK;
4749+
4750+ flush_dcache_page(pages[0]);
4751+ dlist[0].page = pages[0];
4752+ dlist[0].offset = (char *)boff;
4753+ dlist[0].len = PAGE_SIZE - boff;
4754+ dlist[0].rwflag = DLREAD;
4755+
4756+ if (dlist[0].len > len) {
4757+ dlist[0].len = len;
4758+ }
4759+
4760+ DbgPrint("Novfs_Write_File0: page=0x%p offset=0x%p len=%d\n",
4761+ dlist[0].page, dlist[0].offset, dlist[0].len);
4762+
4763+ boff = dlist[0].len;
4764+
4765+ DbgPrint("Novfs_Write_File len=%d boff=%d\n", len, boff);
4766+
4767+ for (i = 1; (i < res) && (boff < len); i++) {
4768+ flush_dcache_page(pages[i]);
4769+
4770+ dlist[i].page = pages[i];
4771+ dlist[i].offset = NULL;
4772+ dlist[i].len = len - boff;
4773+ if (dlist[i].len > PAGE_SIZE) {
4774+ dlist[i].len = PAGE_SIZE;
4775+ }
4776+ dlist[i].rwflag = DLREAD;
4777+
4778+ boff += dlist[i].len;
4779+ DbgPrint
4780+ ("Novfs_Write_File%d: page=0x%p offset=0x%p len=%d\n",
4781+ i, dlist[i].page, dlist[i].offset, dlist[i].len);
4782+ }
4783+
4784+ dlist[i].page = NULL;
4785+ dlist[i].offset = &lreply;
4786+ dlist[i].len = sizeof(lreply);
4787+ dlist[i].rwflag = DLWRITE;
4788+ res++;
4789+
4790+ DbgPrint("Novfs_Write_File Buffer=0x%p boff=0x%x len=%d\n",
4791+ Buffer, boff, len);
4792+
4793+ retCode =
4794+ Queue_Daemon_Command(&cmd, cmdlen, dlist, res,
4795+ (void *)&reply, &replylen,
4796+ INTERRUPTIBLE);
4797+
4798+ } else {
4799+ char *kdata;
4800+
4801+ res = 0;
4802+
4803+ kdata = Novfs_Malloc(len, GFP_KERNEL);
4804+ if (kdata) {
4805+ len -= copy_from_user(kdata, Buffer, len);
4806+ dlist[0].page = NULL;
4807+ dlist[0].offset = kdata;
4808+ dlist[0].len = len;
4809+ dlist[0].rwflag = DLREAD;
4810+
4811+ dlist[1].page = NULL;
4812+ dlist[1].offset = &lreply;
4813+ dlist[1].len = sizeof(lreply);
4814+ dlist[1].rwflag = DLWRITE;
4815+
4816+ retCode =
4817+ Queue_Daemon_Command(&cmd, cmdlen, dlist, 2,
4818+ (void *)&reply, &replylen,
4819+ INTERRUPTIBLE);
4820+
4821+ kfree(kdata);
4822+ }
4823+ }
4824+
4825+ DbgPrint("Novfs_Write_File retCode=0x%x reply=0x%p\n", retCode, reply);
4826+
4827+ if (!retCode) {
4828+ switch (lreply.Reply.ErrorCode) {
4829+ case 0:
4830+ *Bytes = (size_t) lreply.bytesWritten;
4831+ retCode = 0;
4832+ break;
4833+
4834+ case NWE_INSUFFICIENT_SPACE:
4835+ retCode = -ENOSPC;
4836+ break;
4837+
4838+ case NWE_ACCESS_DENIED:
4839+ retCode = -EACCES;
4840+ break;
4841+
4842+ default:
4843+ retCode = -EIO;
4844+ break;
4845+ }
4846+ }
4847+
4848+ if (res) {
4849+ for (i = 0; i < res; i++) {
4850+ if (dlist[i].page) {
4851+ page_cache_release(dlist[i].page);
4852+ }
4853+ }
4854+ }
4855+
4856+ kfree(pages);
4857+ kfree(dlist);
4858+
4859+ DbgPrint("Novfs_Write_File *Bytes=0x%x retCode=0x%x\n", *Bytes,
4860+ retCode);
4861+
4862+ return (retCode);
4863+}
4864+
4865+/*
4866+ * Arguments: HANDLE Handle - novfsd file handle
4867+ * struct page *Page - Page to be written out
4868+ * session_t SessionId - novfsd session handle
4869+ *
4870+ * Returns: 0 - Success
4871+ * -ENOSPC - Out of space on server
4872+ * -EACCES - Access denied
4873+ * -EIO - Any other error
4874+ *
4875+ * Abstract: Write page to file.
4876+ */
4877+int Novfs_Write_Page(HANDLE Handle, struct page *Page, session_t SessionId)
4878+{
4879+ WRITE_FILE_REQUEST cmd;
4880+ WRITE_FILE_REPLY lreply;
4881+ PWRITE_FILE_REPLY reply = NULL;
4882+ unsigned long replylen = 0;
4883+ int retCode = 0, cmdlen;
4884+ struct data_list dlst[2];
4885+
4886+ DbgPrint
4887+ ("Novfs_Write_Page: Handle=0x%p Page=0x%p Index=%lu SessionId=0x%llx\n",
4888+ Handle, Page, Page->index, SessionId);
4889+
4890+ dlst[0].page = NULL;
4891+ dlst[0].offset = &lreply;
4892+ dlst[0].len = sizeof(lreply);
4893+ dlst[0].rwflag = DLWRITE;
4894+
4895+ dlst[1].page = Page;
4896+ dlst[1].offset = 0;
4897+ dlst[1].len = PAGE_CACHE_SIZE;
4898+ dlst[1].rwflag = DLREAD;
4899+
4900+ cmdlen = offsetof(WRITE_FILE_REQUEST, data);
4901+
4902+ cmd.Command.CommandType = VFS_COMMAND_WRITE_FILE;
4903+ cmd.Command.SequenceNumber = 0;
4904+ cmd.Command.SessionId = SessionId;
4905+
4906+ cmd.handle = Handle;
4907+ cmd.len = PAGE_CACHE_SIZE;
4908+ cmd.offset = (loff_t) Page->index << PAGE_CACHE_SHIFT;;
4909+
4910+ retCode =
4911+ Queue_Daemon_Command(&cmd, cmdlen, &dlst, 2, (void *)&reply,
4912+ &replylen, INTERRUPTIBLE);
4913+ if (!retCode) {
4914+ if (reply) {
4915+ memcpy(&lreply, reply, sizeof(lreply));
4916+ }
4917+ switch (lreply.Reply.ErrorCode) {
4918+ case 0:
4919+ retCode = 0;
4920+ break;
4921+
4922+ case NWE_INSUFFICIENT_SPACE:
4923+ retCode = -ENOSPC;
4924+ break;
4925+
4926+ case NWE_ACCESS_DENIED:
4927+ retCode = -EACCES;
4928+ break;
4929+
4930+ default:
4931+ retCode = -EIO;
4932+ break;
4933+ }
4934+ }
4935+
4936+ if (reply) {
4937+ kfree(reply);
4938+ }
4939+
4940+ DbgPrint("Novfs_Write_Page retCode=0x%x\n", retCode);
4941+
4942+ return (retCode);
4943+}
4944+
4945+int Novfs_Write_Pages(HANDLE Handle, struct data_list *DList, int DList_Cnt,
4946+ size_t Bytes, loff_t Offset, session_t SessionId)
4947+{
4948+ WRITE_FILE_REQUEST cmd;
4949+ WRITE_FILE_REPLY lreply;
4950+ PWRITE_FILE_REPLY reply = NULL;
4951+ unsigned long replylen = 0;
4952+ int retCode = 0, cmdlen;
4953+ size_t len;
4954+
4955+ DbgPrint
4956+ ("Novfs_Write_Pages: Handle=0x%p Dlst=0x%p Dlcnt=%d Bytes=%d Offset=%lld SessionId=0x%llx\n",
4957+ Handle, DList, DList_Cnt, Bytes, Offset, SessionId);
4958+
4959+ DList[0].page = NULL;
4960+ DList[0].offset = &lreply;
4961+ DList[0].len = sizeof(lreply);
4962+ DList[0].rwflag = DLWRITE;
4963+
4964+ len = Bytes;
4965+ cmdlen = offsetof(WRITE_FILE_REQUEST, data);
4966+
4967+ if (len) {
4968+ cmd.Command.CommandType = VFS_COMMAND_WRITE_FILE;
4969+ cmd.Command.SequenceNumber = 0;
4970+ cmd.Command.SessionId = SessionId;
4971+
4972+ cmd.handle = Handle;
4973+ cmd.len = len;
4974+ cmd.offset = Offset;
4975+
4976+ retCode =
4977+ Queue_Daemon_Command(&cmd, cmdlen, DList, DList_Cnt,
4978+ (void *)&reply, &replylen,
4979+ INTERRUPTIBLE);
4980+ if (!retCode) {
4981+ if (reply) {
4982+ memcpy(&lreply, reply, sizeof(lreply));
4983+ }
4984+ switch (lreply.Reply.ErrorCode) {
4985+ case 0:
4986+ retCode = 0;
4987+ break;
4988+
4989+ case NWE_INSUFFICIENT_SPACE:
4990+ retCode = -ENOSPC;
4991+ break;
4992+
4993+ case NWE_ACCESS_DENIED:
4994+ retCode = -EACCES;
4995+ break;
4996+
4997+ default:
4998+ retCode = -EIO;
4999+ break;
5000+ }
5001+ }
5002+ if (reply) {
5003+ kfree(reply);
5004+ }
5005+ }
5006+ DbgPrint("Novfs_Write_Pages retCode=0x%x\n", retCode);
5007+
5008+ return (retCode);
5009+}
5010+
5011+int Novfs_Read_Stream(HANDLE ConnHandle, unsigned char * Handle, unsigned char * Buffer,
5012+ size_t * Bytes, loff_t * Offset, int User,
5013+ session_t SessionId)
5014+{
5015+ READ_STREAM_REQUEST cmd;
5016+ PREAD_STREAM_REPLY reply = NULL;
5017+ unsigned long replylen = 0;
5018+ int retCode = 0;
5019+ size_t len;
5020+
5021+ len = *Bytes;
5022+ *Bytes = 0;
5023+
5024+ if ((offsetof(READ_FILE_REPLY, data) + len) > MaxIoSize) {
5025+ len = MaxIoSize - offsetof(READ_FILE_REPLY, data);
5026+ len = (len / PAGE_SIZE) * PAGE_SIZE;
5027+ }
5028+
5029+ cmd.Command.CommandType = VFS_COMMAND_READ_STREAM;
5030+ cmd.Command.SequenceNumber = 0;
5031+ cmd.Command.SessionId = SessionId;
5032+
5033+ cmd.connection = ConnHandle;
5034+ memcpy(cmd.handle, Handle, sizeof(cmd.handle));
5035+ cmd.len = len;
5036+ cmd.offset = *Offset;
5037+
5038+ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE);
5039+
5040+ DbgPrint("Novfs_Read_Stream: Queue_Daemon_Command 0x%x replylen=%d\n", retCode, replylen);
5041+
5042+ if (reply) {
5043+ retCode = 0;
5044+ if (reply->Reply.ErrorCode) {
5045+ retCode = -EIO;
5046+ } else {
5047+ replylen -= offsetof(READ_STREAM_REPLY, data);
5048+ if (replylen > 0) {
5049+ if (User)
5050+ replylen -= copy_to_user(Buffer, reply->data, replylen);
5051+ else
5052+ memcpy(Buffer, reply->data, replylen);
5053+ *Bytes = replylen;
5054+ }
5055+ }
5056+ kfree(reply);
5057+ }
5058+
5059+ DbgPrint("Novfs_Read_Stream *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode);
5060+
5061+ return (retCode);
5062+}
5063+
5064+int Novfs_Write_Stream(HANDLE ConnHandle, unsigned char * Handle, unsigned char * Buffer,
5065+ size_t * Bytes, loff_t * Offset, session_t SessionId)
5066+{
5067+ PWRITE_STREAM_REQUEST cmd;
5068+ PWRITE_STREAM_REPLY reply = NULL;
5069+ unsigned long replylen = 0;
5070+ int retCode = 0, cmdlen;
5071+ size_t len;
5072+
5073+ len = *Bytes;
5074+ cmdlen = len + offsetof(WRITE_STREAM_REQUEST, data);
5075+ *Bytes = 0;
5076+
5077+ if (cmdlen > MaxIoSize) {
5078+ cmdlen = MaxIoSize;
5079+ len = cmdlen - offsetof(WRITE_STREAM_REQUEST, data);
5080+ }
5081+
5082+ DbgPrint("Novfs_Write_Stream cmdlen=%d len=%d\n", cmdlen, len);
5083+
5084+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
5085+
5086+ if (cmd) {
5087+ if (Buffer && len) {
5088+ len -= copy_from_user(cmd->data, Buffer, len);
5089+ }
5090+
5091+ DbgPrint("Novfs_Write_Stream len=%d\n", len);
5092+
5093+ cmd->Command.CommandType = VFS_COMMAND_WRITE_STREAM;
5094+ cmd->Command.SequenceNumber = 0;
5095+ cmd->Command.SessionId = SessionId;
5096+
5097+ cmd->connection = ConnHandle;
5098+ memcpy(cmd->handle, Handle, sizeof(cmd->handle));
5099+ cmd->len = len;
5100+ cmd->offset = *Offset;
5101+
5102+ retCode =
5103+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
5104+ &replylen, INTERRUPTIBLE);
5105+ if (reply) {
5106+ switch (reply->Reply.ErrorCode) {
5107+ case 0:
5108+ retCode = 0;
5109+ break;
5110+
5111+ case NWE_INSUFFICIENT_SPACE:
5112+ retCode = -ENOSPC;
5113+ break;
5114+
5115+ case NWE_ACCESS_DENIED:
5116+ retCode = -EACCES;
5117+ break;
5118+
5119+ default:
5120+ retCode = -EIO;
5121+ break;
5122+ }
5123+ DbgPrint
5124+ ("Novfs_Write_Stream reply->bytesWritten=0x%lx\n",
5125+ reply->bytesWritten);
5126+ *Bytes = reply->bytesWritten;
5127+ kfree(reply);
5128+ }
5129+ kfree(cmd);
5130+ }
5131+ DbgPrint("Novfs_Write_Stream *Bytes=0x%x retCode=0x%x\n", *Bytes,
5132+ retCode);
5133+
5134+ return (retCode);
5135+}
5136+
5137+int Novfs_Close_Stream(HANDLE ConnHandle, unsigned char * Handle, session_t SessionId)
5138+{
5139+ CLOSE_STREAM_REQUEST cmd;
5140+ PCLOSE_STREAM_REPLY reply;
5141+ unsigned long replylen = 0;
5142+ int retCode;
5143+
5144+ cmd.Command.CommandType = VFS_COMMAND_CLOSE_STREAM;
5145+ cmd.Command.SequenceNumber = 0;
5146+ cmd.Command.SessionId = SessionId;
5147+
5148+ cmd.connection = ConnHandle;
5149+ memcpy(cmd.handle, Handle, sizeof(cmd.handle));
5150+
5151+ retCode =
5152+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
5153+ &replylen, 0);
5154+ if (reply) {
5155+ retCode = 0;
5156+ if (reply->Reply.ErrorCode) {
5157+ retCode = -EIO;
5158+ }
5159+ kfree(reply);
5160+ }
5161+ return (retCode);
5162+}
5163+
5164+int Novfs_Delete(unsigned char * Path, int DirectoryFlag, session_t SessionId)
5165+{
5166+ PDELETE_FILE_REQUEST cmd;
5167+ PDELETE_FILE_REPLY reply;
5168+ unsigned long replylen = 0;
5169+ int retCode, cmdlen, pathlen;
5170+
5171+ pathlen = strlen(Path);
5172+
5173+ if (StripTrailingDots) {
5174+ if ('.' == Path[pathlen - 1])
5175+ pathlen--;
5176+ }
5177+
5178+ cmdlen = offsetof(DELETE_FILE_REQUEST, path) + pathlen;
5179+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
5180+ if (cmd) {
5181+ cmd->Command.CommandType = VFS_COMMAND_DELETE_FILE;
5182+ cmd->Command.SequenceNumber = 0;
5183+ cmd->Command.SessionId = SessionId;
5184+
5185+ cmd->isDirectory = DirectoryFlag;
5186+ cmd->pathlength = pathlen;
5187+ memcpy(cmd->path, Path, pathlen);
5188+
5189+ retCode =
5190+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
5191+ &replylen, INTERRUPTIBLE);
5192+ if (reply) {
5193+ retCode = 0;
5194+ if (reply->Reply.ErrorCode) {
5195+ if ((reply->Reply.ErrorCode & 0xFFFF) == 0x0006) { /* Access Denied Error */
5196+ retCode = -EACCES;
5197+ } else {
5198+ retCode = -EIO;
5199+ }
5200+ }
5201+ kfree(reply);
5202+ }
5203+ kfree(cmd);
5204+ } else {
5205+ retCode = -ENOMEM;
5206+ }
5207+ return (retCode);
5208+}
5209+
5210+int Novfs_Truncate_File(unsigned char * Path, int PathLen, session_t SessionId)
5211+{
5212+ PTRUNCATE_FILE_REQUEST cmd;
5213+ PTRUNCATE_FILE_REPLY reply;
5214+ unsigned long replylen = 0;
5215+ int retCode, cmdlen;
5216+
5217+ if (StripTrailingDots) {
5218+ if ('.' == Path[PathLen - 1])
5219+ PathLen--;
5220+ }
5221+ cmdlen = offsetof(TRUNCATE_FILE_REQUEST, path) + PathLen;
5222+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
5223+ if (cmd) {
5224+ cmd->Command.CommandType = VFS_COMMAND_TRUNCATE_FILE;
5225+ cmd->Command.SequenceNumber = 0;
5226+ cmd->Command.SessionId = SessionId;
5227+
5228+ cmd->pathLen = PathLen;
5229+ memcpy(cmd->path, Path, PathLen);
5230+
5231+ retCode =
5232+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
5233+ &replylen, INTERRUPTIBLE);
5234+ if (reply) {
5235+ if (reply->Reply.ErrorCode) {
5236+ retCode = -EIO;
5237+ }
5238+ kfree(reply);
5239+ }
5240+ kfree(cmd);
5241+ } else {
5242+ retCode = -ENOMEM;
5243+ }
5244+ return (retCode);
5245+}
5246+
5247+int Novfs_Truncate_File_Ex(HANDLE Handle, loff_t Offset, session_t SessionId)
5248+{
5249+ WRITE_FILE_REQUEST cmd;
5250+ PWRITE_FILE_REPLY reply = NULL;
5251+ unsigned long replylen = 0;
5252+ int retCode = 0, cmdlen;
5253+
5254+ DbgPrint("Novfs_Truncate_File_Ex Handle=0x%p Offset=%lld\n", Handle,
5255+ Offset);
5256+
5257+ cmdlen = offsetof(WRITE_FILE_REQUEST, data);
5258+
5259+ cmd.Command.CommandType = VFS_COMMAND_WRITE_FILE;
5260+ cmd.Command.SequenceNumber = 0;
5261+ cmd.Command.SessionId = SessionId;
5262+ cmd.handle = Handle;
5263+ cmd.len = 0;
5264+ cmd.offset = Offset;
5265+
5266+ retCode =
5267+ Queue_Daemon_Command(&cmd, cmdlen, NULL, 0, (void *)&reply,
5268+ &replylen, INTERRUPTIBLE);
5269+
5270+ DbgPrint("Novfs_Truncate_File_Ex retCode=0x%x reply=0x%p\n", retCode,
5271+ reply);
5272+
5273+ if (!retCode) {
5274+ switch (reply->Reply.ErrorCode) {
5275+ case 0:
5276+ retCode = 0;
5277+ break;
5278+
5279+ case NWE_INSUFFICIENT_SPACE:
5280+ retCode = -ENOSPC;
5281+ break;
5282+
5283+ case NWE_ACCESS_DENIED:
5284+ retCode = -EACCES;
5285+ break;
5286+
5287+ case NWE_FILE_IO_LOCKED:
5288+ retCode = -EBUSY;
5289+ break;
5290+
5291+ default:
5292+ retCode = -EIO;
5293+ break;
5294+ }
5295+ }
5296+
5297+ if (reply) {
5298+ kfree(reply);
5299+ }
5300+
5301+ DbgPrint("Novfs_Truncate_File_Ex retCode=%d\n", retCode);
5302+
5303+ return (retCode);
5304+}
5305+
5306+int Novfs_Rename_File(int DirectoryFlag, unsigned char * OldName, int OldLen,
5307+ unsigned char * NewName, int NewLen, session_t SessionId)
5308+{
5309+ RENAME_FILE_REQUEST cmd;
5310+ PRENAME_FILE_REPLY reply;
5311+ unsigned long replylen = 0;
5312+ int retCode;
5313+
5314+ DbgPrint("Novfs_Rename_File:\n"
5315+ " DirectoryFlag: %d\n"
5316+ " OldName: %.*s\n"
5317+ " NewName: %.*s\n"
5318+ " SessionId: 0x%llx\n",
5319+ DirectoryFlag, OldLen, OldName, NewLen, NewName, SessionId);
5320+
5321+ cmd.Command.CommandType = VFS_COMMAND_RENAME_FILE;
5322+ cmd.Command.SequenceNumber = 0;
5323+ cmd.Command.SessionId = SessionId;
5324+
5325+ cmd.directoryFlag = DirectoryFlag;
5326+
5327+ if (StripTrailingDots) {
5328+ if ('.' == OldName[OldLen - 1])
5329+ OldLen--;
5330+ if ('.' == NewName[NewLen - 1])
5331+ NewLen--;
5332+ }
5333+
5334+ cmd.newnameLen = NewLen;
5335+ memcpy(cmd.newname, NewName, NewLen);
5336+
5337+ cmd.oldnameLen = OldLen;
5338+ memcpy(cmd.oldname, OldName, OldLen);
5339+
5340+ retCode =
5341+ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply,
5342+ &replylen, INTERRUPTIBLE);
5343+ if (reply) {
5344+ retCode = 0;
5345+ if (reply->Reply.ErrorCode) {
5346+ retCode = -ENOENT;
5347+ }
5348+ kfree(reply);
5349+ }
5350+ return (retCode);
5351+}
5352+
5353+int Novfs_Set_Attr(unsigned char * Path, struct iattr *Attr, session_t SessionId)
5354+{
5355+ PSET_FILE_INFO_REQUEST cmd;
5356+ PSET_FILE_INFO_REPLY reply;
5357+ unsigned long replylen = 0;
5358+ int retCode, cmdlen, pathlen;
5359+
5360+ pathlen = strlen(Path);
5361+
5362+ if (StripTrailingDots) {
5363+ if ('.' == Path[pathlen - 1])
5364+ pathlen--;
5365+ }
5366+
5367+ cmdlen = offsetof(SET_FILE_INFO_REQUEST, path) + pathlen;
5368+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
5369+ if (cmd) {
5370+ cmd->Command.CommandType = VFS_COMMAND_SET_FILE_INFO;
5371+ cmd->Command.SequenceNumber = 0;
5372+ cmd->Command.SessionId = SessionId;
5373+ cmd->fileInfo.ia_valid = Attr->ia_valid;
5374+ cmd->fileInfo.ia_mode = Attr->ia_mode;
5375+ cmd->fileInfo.ia_uid = Attr->ia_uid;
5376+ cmd->fileInfo.ia_gid = Attr->ia_uid;
5377+ cmd->fileInfo.ia_size = Attr->ia_size;
5378+ cmd->fileInfo.ia_atime = Attr->ia_atime.tv_sec;
5379+ cmd->fileInfo.ia_mtime = Attr->ia_mtime.tv_sec;;
5380+ cmd->fileInfo.ia_ctime = Attr->ia_ctime.tv_sec;;
5381+/*
5382+ cmd->fileInfo.ia_attr_flags = Attr->ia_attr_flags;
5383+*/
5384+ cmd->fileInfo.ia_attr_flags = 0;
5385+
5386+ cmd->pathlength = pathlen;
5387+ memcpy(cmd->path, Path, pathlen);
5388+
5389+ retCode =
5390+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply,
5391+ &replylen, INTERRUPTIBLE);
5392+ if (reply) {
5393+ switch (reply->Reply.ErrorCode) {
5394+ case 0:
5395+ retCode = 0;
5396+ break;
5397+
5398+ case NWE_PARAM_INVALID:
5399+ retCode = -EINVAL;
5400+ break;
5401+
5402+ case NWE_FILE_IO_LOCKED:
5403+ retCode = -EBUSY;
5404+ break;
5405+
5406+ default:
5407+ retCode = -EIO;
5408+ break;
5409+ }
5410+ kfree(reply);
5411+ }
5412+ kfree(cmd);
5413+ } else {
5414+ retCode = -ENOMEM;
5415+ }
5416+ return (retCode);
5417+}
5418+
5419+int Novfs_Get_File_Cache_Flag(unsigned char * Path, session_t SessionId)
5420+{
5421+ PGET_CACHE_FLAG_REQUEST cmd;
5422+ PGET_CACHE_FLAG_REPLY reply = NULL;
5423+ unsigned long replylen = 0;
5424+ int cmdlen;
5425+ int retCode = 0;
5426+ int pathlen;
5427+
5428+ DbgPrint("Novfs_Get_File_Cache_Flag: Path = %s\n", Path);
5429+
5430+ if (Path && *Path) {
5431+ pathlen = strlen(Path);
5432+ if (StripTrailingDots) {
5433+ if ('.' == Path[pathlen - 1])
5434+ pathlen--;
5435+ }
5436+ cmdlen = offsetof(GET_CACHE_FLAG_REQUEST, path) + pathlen;
5437+ cmd = (PGET_CACHE_FLAG_REQUEST) Novfs_Malloc(cmdlen, GFP_KERNEL);
5438+ if (cmd) {
5439+ cmd->Command.CommandType = VFS_COMMAND_GET_CACHE_FLAG;
5440+ cmd->Command.SequenceNumber = 0;
5441+ cmd->Command.SessionId = SessionId;
5442+ cmd->pathLen = pathlen;
5443+ memcpy(cmd->path, Path, cmd->pathLen);
5444+
5445+ Queue_Daemon_Command(cmd, cmdlen, NULL, 0,
5446+ (void *)&reply, &replylen,
5447+ INTERRUPTIBLE);
5448+
5449+ if (reply) {
5450+
5451+ if (!reply->Reply.ErrorCode) {
5452+ retCode = reply->CacheFlag;
5453+ }
5454+
5455+ kfree(reply);
5456+ }
5457+ kfree(cmd);
5458+ }
5459+ }
5460+
5461+ DbgPrint("Novfs_Get_File_Cache_Flag: return %d\n", retCode);
5462+ return (retCode);
5463+}
5464+
5465+/*
5466+ * Arguments:
5467+ * SessionId, file handle, type of lock (read/write or unlock),
5468+ * start of lock area, length of lock area
5469+ *
5470+ * Returns:
5471+ * 0 on success
5472+ * negative value on error
5473+ *
5474+ * Abstract:
5475+ *
5476+ * Notes: lock type - fcntl
5477+ */
5478+int Novfs_Set_File_Lock(session_t SessionId, HANDLE Handle,
5479+ unsigned char fl_type, loff_t fl_start, loff_t fl_len)
5480+{
5481+ PSET_FILE_LOCK_REQUEST cmd;
5482+ PSET_FILE_LOCK_REPLY reply = NULL;
5483+ unsigned long replylen = 0;
5484+ int retCode;
5485+
5486+ retCode = -1;
5487+
5488+ DbgPrint("Novfs_Set_File_Lock:\n"
5489+ " SessionId: 0x%llx\n", SessionId);
5490+
5491+ cmd =
5492+ (PSET_FILE_LOCK_REQUEST) Novfs_Malloc(sizeof(SET_FILE_LOCK_REQUEST),
5493+ GFP_KERNEL);
5494+
5495+ if (cmd) {
5496+ DbgPrint("Novfs_Set_File_Lock 2\n");
5497+
5498+ cmd->Command.CommandType = VFS_COMMAND_SET_FILE_LOCK;
5499+ cmd->Command.SequenceNumber = 0;
5500+ cmd->Command.SessionId = SessionId;
5501+
5502+ cmd->handle = Handle;
5503+ if (F_RDLCK == fl_type) {
5504+ fl_type = 1; // LockRegionExclusive
5505+ } else if (F_WRLCK == fl_type) {
5506+ fl_type = 0; // LockRegionShared
5507+ }
5508+
5509+ cmd->fl_type = fl_type;
5510+ cmd->fl_start = fl_start;
5511+ cmd->fl_len = fl_len;
5512+
5513+ DbgPrint("Novfs_Set_File_Lock 3\n");
5514+
5515+ DbgPrint("Novfs_Set_File_Lock: BEGIN dump arguments\n");
5516+ DbgPrint("Novfs_Set_File_Lock: Queue_Daemon_Command %d\n",
5517+ cmd->Command.CommandType);
5518+ DbgPrint("Novfs_Set_File_Lock: cmd->handle = 0x%p\n",
5519+ cmd->handle);
5520+ DbgPrint("Novfs_Set_File_Lock: cmd->fl_type = %u\n",
5521+ cmd->fl_type);
5522+ DbgPrint("Novfs_Set_File_Lock: cmd->fl_start = 0x%X\n",
5523+ cmd->fl_start);
5524+ DbgPrint("Novfs_Set_File_Lock: cmd->fl_len = 0x%X\n",
5525+ cmd->fl_len);
5526+ DbgPrint
5527+ ("Novfs_Set_File_Lock: sizeof(SET_FILE_LOCK_REQUEST) = %u\n",
5528+ sizeof(SET_FILE_LOCK_REQUEST));
5529+ DbgPrint("Novfs_Set_File_Lock: END dump arguments\n");
5530+
5531+ retCode =
5532+ Queue_Daemon_Command(cmd, sizeof(SET_FILE_LOCK_REQUEST),
5533+ NULL, 0, (void *)&reply, &replylen,
5534+ INTERRUPTIBLE);
5535+ DbgPrint("Novfs_Set_File_Lock 4\n");
5536+
5537+ if (reply) {
5538+ DbgPrint("Novfs_Set_File_Lock 5, ErrorCode = %X\n",
5539+ reply->Reply.ErrorCode);
5540+
5541+ if (reply->Reply.ErrorCode) {
5542+ retCode = reply->Reply.ErrorCode;
5543+ }
5544+ kfree(reply);
5545+ }
5546+
5547+ kfree(cmd);
5548+ }
5549+
5550+ DbgPrint("Novfs_Set_File_Lock 6\n");
5551+
5552+ return (retCode);
5553+}
5554--- /dev/null
5555+++ b/fs/novfs/inode.c
5556@@ -0,0 +1,5563 @@
5557+/*
5558+ * Novell NCP Redirector for Linux
5559+ * Author: James Turner
5560+ *
5561+ * This file contains functions used to control access to the Linux file
5562+ * system.
5563+ *
5564+ * Copyright (C) 2005 Novell, Inc.
5565+ *
5566+ * This program is free software; you can redistribute it and/or
5567+ * modify it under the terms of the GNU General Public License
5568+ * as published by the Free Software Foundation; either version 2
5569+ * of the License, or (at your option) any later version.
5570+ */
5571+
5572+#include <linux/module.h>
5573+#include <linux/autoconf.h>
5574+#include <linux/init.h>
5575+#include <linux/fs.h>
5576+#include <linux/dcache.h>
5577+#include <linux/mount.h>
5578+#include <linux/pagemap.h>
5579+#include <linux/string.h>
5580+#include <linux/smp_lock.h>
5581+#include <linux/slab.h>
5582+#include <linux/unistd.h>
5583+#include <asm/statfs.h>
5584+#include <asm/uaccess.h>
5585+#include <linux/ctype.h>
5586+#include <linux/statfs.h>
5587+#include <linux/pagevec.h>
5588+#include <linux/writeback.h>
5589+#include <linux/backing-dev.h>
5590+#include <linux/mm.h>
5591+#include <linux/file.h>
5592+
5593+/*===[ Include files specific to this module ]============================*/
5594+#include "vfs.h"
5595+
5596+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
5597+#define FSPRIVATE u.generic_ip
5598+#else
5599+#define FSPRIVATE i_private
5600+#endif
5601+
5602+
5603+#define FILE_UPDATE_TIMEOUT 2
5604+
5605+struct inode_data {
5606+ void *Scope;
5607+ unsigned long Flags;
5608+ struct list_head IList;
5609+ struct inode *Inode;
5610+ unsigned long cntDC;
5611+ struct list_head DirCache;
5612+ struct semaphore DirCacheLock;
5613+ HANDLE FileHandle;
5614+ int CacheFlag;
5615+ char Name[1]; /* Needs to be last entry */
5616+};
5617+
5618+// FIXME these are wrong, but fake the compiler out for now until the proper people can be flogged...
5619+extern void *Scope_Get_ScopefromName(struct qstr *Name);
5620+extern void *Scope_Get_ScopefromPath(struct dentry *Dentry);
5621+
5622+/*===[ Function prototypes ]==============================================*/
5623+int Novfs_Remove_from_Root(char *RemoveName);
5624+int Novfs_Add_to_Root(char *);
5625+char *Novfs_dget_path(struct dentry *d, char *path, unsigned int pathlen);
5626+int verify_dentry(struct dentry *dentry, int Flags);
5627+int invalidate_dentry(struct dentry *parent);
5628+struct dentry *Novfs_d_lookup(struct dentry *Parent, struct qstr *Name);
5629+int Novfs_d_add(struct dentry *p, struct dentry *d, struct inode *i, int add);
5630+int Novfs_d_strcmp(struct qstr *s1, struct qstr *s2);
5631+unsigned long Novfs_internal_hash(struct qstr *name);
5632+
5633+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
5634+int Novfs_get_sb(struct file_system_type *Fstype, int Flags,
5635+ const char *Dev_name, void *Data, struct vfsmount *Mnt);
5636+#else
5637+struct super_block *Novfs_get_sb(struct file_system_type *Fstype, int Flags,
5638+ const char *Dev_name, void *Data);
5639+#endif
5640+
5641+int Novfs_fill_super(struct super_block *SB, void *Data, int Silent);
5642+
5643+/*
5644+ * Declared dentry_operations
5645+ */
5646+int Novfs_d_revalidate(struct dentry *, struct nameidata *);
5647+int Novfs_d_hash(struct dentry *, struct qstr *);
5648+int Novfs_d_compare(struct dentry *, struct qstr *, struct qstr *);
5649+int Novfs_d_delete(struct dentry *dentry);
5650+void Novfs_d_release(struct dentry *dentry);
5651+void Novfs_d_iput(struct dentry *dentry, struct inode *inode);
5652+
5653+/*
5654+ * Declared directory operations
5655+ */
5656+int Novfs_dir_open(struct inode *inode, struct file *file);
5657+int Novfs_dir_release(struct inode *inode, struct file *file);
5658+loff_t Novfs_dir_lseek(struct file *file, loff_t offset, int origin);
5659+ssize_t Novfs_dir_read(struct file *file, char *buf, size_t len, loff_t * off);
5660+void addtodentry(struct dentry *Parent, unsigned char *List, int Level);
5661+int Novfs_filldir(void *data, const char *name, int namelen, loff_t off,
5662+ ino_t ino, unsigned ftype);
5663+int Novfs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir);
5664+int Novfs_dir_fsync(struct file *file, struct dentry *dentry, int datasync);
5665+
5666+/*
5667+ * Declared address space operations
5668+ */
5669+int Novfs_a_writepage(struct page *page, struct writeback_control *wbc);
5670+int Novfs_a_writepages(struct address_space *mapping,
5671+ struct writeback_control *wbc);
5672+int Novfs_a_prepare_write(struct file *file, struct page *page, unsigned from,
5673+ unsigned to);
5674+int Novfs_a_commit_write(struct file *file, struct page *page, unsigned offset,
5675+ unsigned to);
5676+int Novfs_a_readpage(struct file *file, struct page *page);
5677+int Novfs_a_readpages(struct file *file, struct address_space *mapping,
5678+ struct list_head *page_lst, unsigned nr_pages);
5679+ssize_t Novfs_a_direct_IO(int rw, struct kiocb *kiocb, const struct iovec *iov,
5680+ loff_t offset, unsigned long nr_segs);
5681+
5682+/*
5683+ * Declared file_operations
5684+ */
5685+ssize_t Novfs_f_read(struct file *, char *, size_t, loff_t *);
5686+ssize_t Novfs_f_write(struct file *, const char *, size_t, loff_t *);
5687+int Novfs_f_readdir(struct file *, void *, filldir_t);
5688+int Novfs_f_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
5689+int Novfs_f_mmap(struct file *file, struct vm_area_struct *vma);
5690+int Novfs_f_open(struct inode *, struct file *);
5691+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
5692+int Novfs_f_flush(struct file *);
5693+#else
5694+int Novfs_f_flush(struct file *, fl_owner_t);
5695+#endif
5696+int Novfs_f_release(struct inode *, struct file *);
5697+int Novfs_f_fsync(struct file *, struct dentry *, int datasync);
5698+int Novfs_f_lock(struct file *, int, struct file_lock *);
5699+
5700+/*
5701+ * Declared inode_operations
5702+ */
5703+int Novfs_i_create(struct inode *, struct dentry *, int, struct nameidata *);
5704+struct dentry *Novfs_i_lookup(struct inode *, struct dentry *,
5705+ struct nameidata *);
5706+int Novfs_i_mkdir(struct inode *, struct dentry *, int);
5707+int Novfs_i_unlink(struct inode *dir, struct dentry *dentry);
5708+int Novfs_i_rmdir(struct inode *, struct dentry *);
5709+int Novfs_i_mknod(struct inode *, struct dentry *, int, dev_t);
5710+int Novfs_i_rename(struct inode *, struct dentry *, struct inode *,
5711+ struct dentry *);
5712+int Novfs_i_permission(struct inode *inode, int mask);
5713+int Novfs_i_setattr(struct dentry *, struct iattr *);
5714+int Novfs_i_getattr(struct vfsmount *mnt, struct dentry *, struct kstat *);
5715+int Novfs_i_revalidate(struct dentry *dentry);
5716+
5717+/*
5718+ * Extended attributes operations
5719+ */
5720+
5721+int Novfs_i_getxattr(struct dentry *dentry, const char *name, void *buffer,
5722+ size_t size);
5723+int Novfs_i_setxattr(struct dentry *dentry, const char *name, const void *value,
5724+ size_t value_size, int flags);
5725+int Novfs_i_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
5726+
5727+void update_inode(struct inode *Inode, struct entry_info *Info);
5728+
5729+/*
5730+ * Declared super_operations
5731+ */
5732+void Novfs_read_inode(struct inode *inode);
5733+void Novfs_write_inode(struct inode *inode);
5734+int Novfs_notify_change(struct dentry *dentry, struct iattr *attr);
5735+void Novfs_clear_inode(struct inode *inode);
5736+int Novfs_show_options(struct seq_file *s, struct vfsmount *m);
5737+
5738+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
5739+int Novfs_statfs(struct dentry *de, struct kstatfs *buf);
5740+#else
5741+int Novfs_statfs(struct super_block *sb, struct kstatfs *buf);
5742+#endif
5743+
5744+/*
5745+ * Declared control interface functions
5746+ */
5747+ssize_t
5748+Novfs_Control_read(struct file *file, char *buf, size_t nbytes, loff_t * ppos);
5749+
5750+ssize_t
5751+Novfs_Control_write(struct file *file, const char *buf, size_t nbytes,
5752+ loff_t * ppos);
5753+
5754+int Novfs_Control_ioctl(struct inode *inode, struct file *file,
5755+ unsigned int cmd, unsigned long arg);
5756+
5757+int __init init_novfs(void);
5758+void __exit exit_novfs(void);
5759+
5760+int Novfs_lock_inode_cache(struct inode *i);
5761+void Novfs_unlock_inode_cache(struct inode *i);
5762+int Novfs_enumerate_inode_cache(struct inode *i, struct list_head **iteration,
5763+ ino_t * ino, struct entry_info *info);
5764+int Novfs_get_entry(struct inode *i, struct qstr *name, ino_t * ino,
5765+ struct entry_info *info);
5766+int Novfs_get_entry_by_pos(struct inode *i, loff_t pos, ino_t * ino,
5767+ struct entry_info *info);
5768+int Novfs_get_entry_time(struct inode *i, struct qstr *name, ino_t * ino,
5769+ struct entry_info *info, u64 * EntryTime);
5770+int Novfs_get_remove_entry(struct inode *i, ino_t * ino, struct entry_info *info);
5771+void Novfs_invalidate_inode_cache(struct inode *i);
5772+static struct dir_cache *Novfs_lookup_inode_cache(struct inode *i, struct qstr *name, ino_t ino);
5773+int Novfs_lookup_validate(struct inode *i, struct qstr *name, ino_t ino);
5774+int Novfs_add_inode_entry(struct inode *i, struct qstr *name, ino_t ino,
5775+ struct entry_info *info);
5776+int Novfs_update_entry(struct inode *i, struct qstr *name, ino_t ino,
5777+ struct entry_info *info);
5778+void Novfs_remove_inode_entry(struct inode *i, struct qstr *name, ino_t ino);
5779+void Novfs_free_invalid_entries(struct inode *i);
5780+void Novfs_free_inode_cache(struct inode *i);
5781+
5782+/*===[ Global variables ]=================================================*/
5783+struct dentry_operations Novfs_dentry_operations = {
5784+ .d_revalidate = Novfs_d_revalidate,
5785+ .d_hash = Novfs_d_hash,
5786+ .d_compare = Novfs_d_compare,
5787+ //.d_delete = Novfs_d_delete,
5788+ .d_release = Novfs_d_release,
5789+ .d_iput = Novfs_d_iput,
5790+};
5791+
5792+struct file_operations Novfs_dir_operations = {
5793+ .owner = THIS_MODULE,
5794+ .open = Novfs_dir_open,
5795+ .release = Novfs_dir_release,
5796+ .llseek = Novfs_dir_lseek,
5797+ .read = Novfs_dir_read,
5798+ .readdir = Novfs_dir_readdir,
5799+ .fsync = Novfs_dir_fsync,
5800+};
5801+
5802+static struct file_operations Novfs_file_operations = {
5803+ .owner = THIS_MODULE,
5804+ .read = Novfs_f_read,
5805+ .write = Novfs_f_write,
5806+ .readdir = Novfs_f_readdir,
5807+ .ioctl = Novfs_f_ioctl,
5808+ .mmap = Novfs_f_mmap,
5809+ .open = Novfs_f_open,
5810+ .flush = Novfs_f_flush,
5811+ .release = Novfs_f_release,
5812+ .fsync = Novfs_f_fsync,
5813+ .llseek = generic_file_llseek,
5814+ .lock = Novfs_f_lock,
5815+};
5816+
5817+static struct address_space_operations Novfs_nocache_aops = {
5818+ .readpage = Novfs_a_readpage,
5819+};
5820+
5821+struct backing_dev_info Novfs_backing_dev_info = {
5822+ .ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
5823+ .state = 0,
5824+ .capabilities = BDI_CAP_NO_WRITEBACK | BDI_CAP_MAP_COPY,
5825+ .unplug_io_fn = default_unplug_io_fn,
5826+};
5827+
5828+static struct address_space_operations Novfs_aops = {
5829+ .readpage = Novfs_a_readpage,
5830+ .readpages = Novfs_a_readpages,
5831+ .writepage = Novfs_a_writepage,
5832+ .writepages = Novfs_a_writepages,
5833+ .prepare_write = Novfs_a_prepare_write,
5834+ .commit_write = Novfs_a_commit_write,
5835+ .set_page_dirty = __set_page_dirty_nobuffers,
5836+ .direct_IO = Novfs_a_direct_IO,
5837+};
5838+
5839+static struct inode_operations Novfs_inode_operations = {
5840+ .create = Novfs_i_create,
5841+ .lookup = Novfs_i_lookup,
5842+ .unlink = Novfs_i_unlink,
5843+ .mkdir = Novfs_i_mkdir,
5844+ .rmdir = Novfs_i_rmdir,
5845+ .mknod = Novfs_i_mknod,
5846+ .rename = Novfs_i_rename,
5847+ .setattr = Novfs_i_setattr,
5848+ .getattr = Novfs_i_getattr,
5849+/*
5850+ .getxattr = Novfs_i_getxattr,
5851+ .setxattr = Novfs_i_setxattr,
5852+ .listxattr = Novfs_i_listxattr,
5853+*/
5854+};
5855+
5856+static struct inode_operations Novfs_file_inode_operations = {
5857+ .setattr = Novfs_i_setattr,
5858+ .getattr = Novfs_i_getattr,
5859+/*
5860+ .getxattr = Novfs_i_getxattr,
5861+ .setxattr = Novfs_i_setxattr,
5862+ .listxattr = Novfs_i_listxattr,
5863+*/
5864+};
5865+
5866+static struct super_operations Novfs_ops = {
5867+ .statfs = Novfs_statfs,
5868+ .clear_inode = Novfs_clear_inode,
5869+ .drop_inode = generic_delete_inode,
5870+ .show_options = Novfs_show_options,
5871+
5872+};
5873+
5874+/* Not currently used
5875+static struct file_operations Novfs_Control_operations = {
5876+ .read = Novfs_Control_read,
5877+ .write = Novfs_Control_write,
5878+ .ioctl = Novfs_Control_ioctl,
5879+};
5880+*/
5881+
5882+static atomic_t Novfs_Inode_Number = ATOMIC_INIT(0);
5883+
5884+struct dentry *Novfs_root = NULL;
5885+
5886+int Novfs_Version_Major = NOVFS_VFS_MAJOR;
5887+int Novfs_Version_Minor = NOVFS_VFS_MINOR;
5888+int Novfs_Version_Sub = NOVFS_VFS_SUB;
5889+int Novfs_Version_Release = NOVFS_VFS_RELEASE;
5890+
5891+char *Novfs_CurrentMount = NULL;
5892+
5893+DECLARE_MUTEX(InodeList_lock);
5894+
5895+LIST_HEAD(InodeList);
5896+
5897+DECLARE_MUTEX(TimeDir_Lock);
5898+uint64_t lastTime;
5899+char lastDir[PATH_MAX];
5900+
5901+uint64_t inHAXTime;
5902+int inHAX;
5903+
5904+unsigned long InodeCount = 0, DCCount = 0;
5905+unsigned long File_update_timeout = FILE_UPDATE_TIMEOUT;
5906+int PageCache = 0;
5907+
5908+typedef struct _Novfs_List2 {
5909+ struct list_head list;
5910+ void *data;
5911+} Novfs_List2;
5912+
5913+typedef struct _File_Private2 {
5914+ int listedall;
5915+ HANDLE enumHandle;
5916+} FilePrivate2;
5917+
5918+static void PRINT_DENTRY(const char *s, struct dentry *d)
5919+{
5920+ DbgPrint("%s: 0x%p\n", s, d);
5921+ DbgPrint(" d_count: 0x%x\n", d->d_count);
5922+ DbgPrint(" d_lock: 0x%x\n", d->d_lock);
5923+ DbgPrint(" d_inode: 0x%x\n", d->d_inode);
5924+ DbgPrint(" d_lru: 0x%p\n"
5925+ " next: 0x%p\n"
5926+ " prev: 0x%p\n", &d->d_lru, d->d_lru.next,
5927+ d->d_lru.prev);
5928+ DbgPrint(" d_child: 0x%p\n" " next: 0x%p\n"
5929+ " prev: 0x%p\n", &d->D_CHILD, d->D_CHILD.next,
5930+ d->D_CHILD.prev);
5931+ DbgPrint(" d_subdirs: 0x%p\n" " next: 0x%p\n"
5932+ " prev: 0x%p\n", &d->d_subdirs, d->d_subdirs.next,
5933+ d->d_subdirs.prev);
5934+ DbgPrint(" d_alias: 0x%p\n" " next: 0x%p\n"
5935+ " prev: 0x%p\n", &d->d_alias, d->d_alias.next,
5936+ d->d_alias.prev);
5937+ DbgPrint(" d_time: 0x%x\n", d->d_time);
5938+ DbgPrint(" d_op: 0x%p\n", d->d_op);
5939+ DbgPrint(" d_sb: 0x%p\n", d->d_sb);
5940+ DbgPrint(" d_flags: 0x%x\n", d->d_flags);
5941+ DbgPrint(" d_mounted: 0x%x\n", d->d_mounted);
5942+ DbgPrint(" d_fsdata: 0x%p\n", d->d_fsdata);
5943+/* DbgPrint(" d_cookie: 0x%x\n", d->d_cookie); */
5944+ DbgPrint(" d_parent: 0x%p\n", d->d_parent);
5945+ DbgPrint(" d_name: 0x%p %.*s\n", &d->d_name, d->d_name.len,
5946+ d->d_name.name);
5947+ DbgPrint(" name: 0x%p\n" " len: %d\n"
5948+ " hash: 0x%x\n", d->d_name.name, d->d_name.len,
5949+ d->d_name.hash);
5950+ DbgPrint(" d_hash: 0x%x\n" " next: 0x%x\n"
5951+ " pprev: 0x%x\n", d->d_hash, d->d_hash.next,
5952+ d->d_hash.pprev);
5953+}
5954+
5955+/*++======================================================================*/
5956+int Novfs_Remove_from_Root(char *RemoveName)
5957+/*
5958+ * Arguments:
5959+ *
5960+ * Returns:
5961+ *
5962+ * Abstract:
5963+ *
5964+ * Notes:
5965+ *
5966+ * Environment:
5967+ *
5968+ *========================================================================*/
5969+{
5970+ struct qstr name;
5971+ struct dentry *dentry;
5972+ struct inode *dir;
5973+
5974+ DbgPrint("Novfs_Remove_from_Root: %s\n", RemoveName);
5975+ name.len = strlen(RemoveName);
5976+ name.name = RemoveName;
5977+ Novfs_d_hash(Novfs_root, &name);
5978+
5979+ dentry = d_lookup(Novfs_root, &name);
5980+ if (dentry) {
5981+ if (dentry->d_inode && dentry->d_inode->FSPRIVATE) {
5982+ ((struct inode_data *)(dentry->d_inode->FSPRIVATE))->Scope =
5983+ NULL;
5984+ }
5985+ dput(dentry);
5986+ }
5987+
5988+ dir = Novfs_root->d_inode;
5989+
5990+ Novfs_lock_inode_cache(dir);
5991+ Novfs_remove_inode_entry(dir, &name, 0);
5992+ Novfs_unlock_inode_cache(dir);
5993+
5994+ return (0);
5995+}
5996+
5997+/*++======================================================================*/
5998+int Novfs_Add_to_Root(char *AddName)
5999+/*
6000+ * Arguments:
6001+ *
6002+ * Returns:
6003+ *
6004+ * Abstract:
6005+ *
6006+ * Notes:
6007+ *
6008+ * Environment:
6009+ *
6010+ *========================================================================*/
6011+{
6012+ struct qstr name;
6013+ struct inode *dir;
6014+ struct entry_info info;
6015+ ino_t ino;
6016+
6017+ DbgPrint("Novfs_Add_to_Root: %s\n", AddName);
6018+ name.len = strlen(AddName);
6019+ name.name = AddName;
6020+ Novfs_d_hash(Novfs_root, &name);
6021+
6022+ dir = Novfs_root->d_inode;
6023+
6024+ Novfs_lock_inode_cache(dir);
6025+
6026+ ino = 0;
6027+
6028+ if (!Novfs_lookup_inode_cache(dir, &name, 0)) {
6029+ info.mode = S_IFDIR | 0700;
6030+ info.size = 0;
6031+ info.atime = info.ctime = info.mtime = CURRENT_TIME;
6032+
6033+ ino = (ino_t)atomic_inc_return(&Novfs_Inode_Number);
6034+ Novfs_add_inode_entry(dir, &name, ino, &info);
6035+ }
6036+
6037+ Novfs_unlock_inode_cache(dir);
6038+
6039+ return (0);
6040+}
6041+
6042+/*++======================================================================*/
6043+int Novfs_Add_to_Root2(char *AddName)
6044+/*
6045+ * Arguments:
6046+ *
6047+ * Returns:
6048+ *
6049+ * Abstract:
6050+ *
6051+ * Notes:
6052+ *
6053+ * Environment:
6054+ *
6055+ *========================================================================*/
6056+{
6057+ struct dentry *entry;
6058+ struct qstr name;
6059+ struct inode *inode;
6060+ void *scope;
6061+
6062+ DbgPrint("Novfs_Add_to_Root: %s\n", AddName);
6063+ name.len = strlen(AddName);
6064+ name.name = AddName;
6065+
6066+ Novfs_d_hash(Novfs_root, &name);
6067+
6068+ entry = Novfs_d_lookup(Novfs_root, &name);
6069+ DbgPrint("Novfs_Add_to_Root: Novfs_d_lookup 0x%p\n", entry);
6070+ if (NULL == entry) {
6071+ scope = Scope_Lookup();
6072+
6073+ entry = d_alloc(Novfs_root, &name);
6074+ DbgPrint("Novfs_Add_to_Root: d_alloc 0x%p\n", entry);
6075+ if (entry) {
6076+ entry->d_op = &Novfs_dentry_operations;
6077+ entry->d_time = jiffies + (File_update_timeout * HZ);
6078+ /*
6079+ * done in Novfs_d_add now... entry->d_fsdata = (void *)Novfs_internal_hash( &name );
6080+ */
6081+ inode =
6082+ Novfs_get_inode(Novfs_root->d_sb, S_IFDIR | 0700, 0, Scope_Get_Uid(scope), 0, &name);
6083+ DbgPrint("Novfs_Add_to_Root: Inode=0x%p\n", inode);
6084+ if (inode) {
6085+ inode->i_atime =
6086+ inode->i_ctime =
6087+ inode->i_mtime = CURRENT_TIME;
6088+ if (!Novfs_d_add(Novfs_root, entry, inode, 1)) {
6089+ if (inode->FSPRIVATE) {
6090+ ((struct inode_data *) inode->
6091+ FSPRIVATE)->Flags = USER_INODE;
6092+ }
6093+ PRINT_DENTRY("After Novfs_d_add",
6094+ entry);
6095+ } else {
6096+ dput(entry);
6097+ iput(inode);
6098+ }
6099+ }
6100+ }
6101+ } else {
6102+ dput(entry);
6103+ PRINT_DENTRY("Novfs_Add_to_Root: After dput Dentry", entry);
6104+ }
6105+ return (0);
6106+}
6107+
6108+/*++======================================================================*/
6109+char *Novfs_dget_path(struct dentry *Dentry, char *Buf, unsigned int Buflen)
6110+/*
6111+ * Arguments: struct dentry *Dentry - starting entry
6112+ * char *Buf - pointer to memory buffer
6113+ * unsigned int Buflen - size of memory buffer
6114+ *
6115+ * Returns: pointer to path.
6116+ *
6117+ * Abstract: Walks the dentry chain building a path.
6118+ *
6119+ * Notes:
6120+ *
6121+ * Environment:
6122+ *
6123+ *========================================================================*/
6124+{
6125+ char *retval = &Buf[Buflen];
6126+ struct dentry *p = Dentry;
6127+
6128+ *(--retval) = '\0';
6129+ Buflen--;
6130+
6131+ if (!IS_ROOT(p) && !IS_ROOT(p->d_parent)) {
6132+ while (Buflen && !IS_ROOT(p) && !IS_ROOT(p->d_parent)) {
6133+ if (Buflen > p->d_name.len) {
6134+ retval -= p->d_name.len;
6135+ Buflen -= p->d_name.len;
6136+ memcpy(retval, p->d_name.name, p->d_name.len);
6137+ *(--retval) = '\\';
6138+ Buflen--;
6139+ p = p->d_parent;
6140+ } else {
6141+ retval = NULL;
6142+ break;
6143+ }
6144+ }
6145+ } else {
6146+ *(--retval) = '\\';
6147+ }
6148+
6149+ if (retval)
6150+ DbgPrint("Novfs_dget_path: %s\n", retval);
6151+ return (retval);
6152+}
6153+
6154+/*++======================================================================*/
6155+int verify_dentry(struct dentry *dentry, int Flags)
6156+/*
6157+ * Arguments: struct dentry *dentry - entry to verify
6158+ *
6159+ * Returns: zero - Inode cache has been updated. If not in the cache
6160+ * then file doesn't exist.
6161+ * !zero - Error
6162+ *
6163+ * Abstract: This routine will verify if the file that dentry is pointing
6164+ * at exist and if it does it will put it in the inode cache of
6165+ * the parent.
6166+ *
6167+ * Notes:
6168+ *
6169+ * Environment:
6170+ *
6171+ *========================================================================*/
6172+{
6173+ int retVal = -ENOENT;
6174+ struct inode *dir;
6175+ struct entry_info *info = NULL;
6176+ struct inode_data *id;
6177+ session_t session;
6178+ char *path, *list = NULL, *cp;
6179+ ino_t ino = 0;
6180+ struct qstr name;
6181+ int iLock = 0;
6182+ struct dentry *parent = NULL;
6183+ u64 ctime;
6184+ struct inode *inode;
6185+
6186+ if (IS_ROOT(dentry)) {
6187+ DbgPrint("verify_dentry: Root entry\n");
6188+ return (0);
6189+ }
6190+
6191+ if (dentry && dentry->d_parent &&
6192+ (dir = dentry->d_parent->d_inode) && (id = dir->FSPRIVATE)) {
6193+ parent = dget_parent(dentry);
6194+
6195+ info = Novfs_Malloc(sizeof(struct entry_info) + PATH_LENGTH_BUFFER, GFP_KERNEL);
6196+
6197+ if (info) {
6198+ if (Novfs_lock_inode_cache(dir)) {
6199+ name.len = dentry->d_name.len;
6200+ name.name = dentry->d_name.name;
6201+ name.hash = Novfs_internal_hash(&name);
6202+ if (!Novfs_get_entry_time(dir, &name, &ino, info, &ctime)) {
6203+ inode = dentry->d_inode;
6204+ if (inode && inode->FSPRIVATE &&
6205+ ((inode->i_size != info->size) ||
6206+ (inode->i_mtime.tv_sec !=
6207+ info->mtime.tv_sec)
6208+ || (inode->i_mtime.tv_nsec !=
6209+ info->mtime.tv_nsec))) {
6210+ /*
6211+ * Values don't match so update.
6212+ */
6213+ ((struct inode_data *) inode->FSPRIVATE)->Flags |= UPDATE_INODE;
6214+ }
6215+
6216+ ctime = get_jiffies_64() - ctime;
6217+ if (Flags || ctime < (u64) (File_update_timeout * HZ)) {
6218+ retVal = 0;
6219+ Novfs_unlock_inode_cache(dir);
6220+ dput(parent);
6221+ kfree(info);
6222+ return (0);
6223+ }
6224+ }
6225+ Novfs_unlock_inode_cache(dir);
6226+ }
6227+
6228+ if (IS_ROOT(dentry->d_parent)) {
6229+ session = Scope_Get_SessionId(Scope_Get_ScopefromName(&dentry->d_name));
6230+ } else {
6231+ session = Scope_Get_SessionId(id->Scope);
6232+ }
6233+
6234+ if (!SC_PRESENT(session)) {
6235+ id->Scope = Scope_Get_ScopefromPath(dentry);
6236+ session = Scope_Get_SessionId(id->Scope);
6237+ }
6238+
6239+ ino = 0;
6240+ retVal = 0;
6241+
6242+ if (IS_ROOT(dentry->d_parent)) {
6243+ DbgPrint("verify_dentry: parent is Root directory\n");
6244+ list = Scope_Get_ScopeUsers();
6245+
6246+ iLock = Novfs_lock_inode_cache(dir);
6247+ Novfs_invalidate_inode_cache(dir);
6248+
6249+ if (list) {
6250+ cp = list;
6251+ while (*cp) {
6252+ name.name = cp;
6253+ name.len = strlen(cp);
6254+ name.hash = Novfs_internal_hash(&name);
6255+ cp += (name.len + 1);
6256+ ino = 0;
6257+ if (Novfs_get_entry(dir, &name, &ino, info)) {
6258+ info->mode = S_IFDIR | 0700;
6259+ info->size = 0;
6260+ info->atime = info->ctime = info->mtime = CURRENT_TIME;
6261+ ino = (ino_t)atomic_inc_return(&Novfs_Inode_Number);
6262+ Novfs_add_inode_entry(dir, &name, ino, info);
6263+ }
6264+ }
6265+ }
6266+ Novfs_free_invalid_entries(dir);
6267+ } else {
6268+
6269+ path =
6270+ Novfs_dget_path(dentry, info->name,
6271+ PATH_LENGTH_BUFFER);
6272+ if (path) {
6273+ if (dentry->d_name.len <=
6274+ NW_MAX_PATH_LENGTH) {
6275+ name.hash =
6276+ Novfs_internal_hash
6277+ (&dentry->d_name);
6278+ name.len = dentry->d_name.len;
6279+ name.name = dentry->d_name.name;
6280+
6281+ retVal = Novfs_Get_File_Info(path, info, &session);
6282+ if (0 == retVal) {
6283+ dentry->d_time =
6284+ jiffies +
6285+ (File_update_timeout
6286+ * HZ);
6287+ iLock =
6288+ Novfs_lock_inode_cache
6289+ (dir);
6290+ if (Novfs_update_entry
6291+ (dir, &name, 0,
6292+ info)) {
6293+ if (dentry->
6294+ d_inode) {
6295+ ino = dentry->d_inode->i_ino;
6296+ } else {
6297+ ino = (ino_t)atomic_inc_return(&Novfs_Inode_Number);
6298+ }
6299+ Novfs_add_inode_entry
6300+ (dir, &name,
6301+ ino, info);
6302+ }
6303+ if (dentry->d_inode) {
6304+ update_inode
6305+ (dentry->
6306+ d_inode,
6307+ info);
6308+ id->Flags &=
6309+ ~UPDATE_INODE;
6310+
6311+ dentry->
6312+ d_inode->
6313+ i_flags &=
6314+ ~S_DEAD;
6315+ if (dentry->
6316+ d_inode->
6317+ FSPRIVATE) {
6318+ ((struct inode_data *) dentry->d_inode->FSPRIVATE)->Scope = id->Scope;
6319+ }
6320+ }
6321+ } else if (-EINTR != retVal) {
6322+ retVal = 0;
6323+ iLock = Novfs_lock_inode_cache(dir);
6324+ Novfs_remove_inode_entry(dir, &name, 0);
6325+ if (dentry->d_inode
6326+ && !(dentry->d_inode->i_flags & S_DEAD)) {
6327+ dentry->d_inode->i_flags |= S_DEAD;
6328+ dentry->d_inode-> i_size = 0;
6329+ dentry->d_inode->i_atime.tv_sec =
6330+ dentry->d_inode->i_atime.tv_nsec =
6331+ dentry->d_inode->i_ctime.tv_sec =
6332+ dentry->d_inode->i_ctime.tv_nsec =
6333+ dentry->d_inode->i_mtime.tv_sec =
6334+ dentry->d_inode->i_mtime.tv_nsec = 0;
6335+ dentry->d_inode->i_blocks = 0;
6336+ d_delete(dentry); /* Remove from cache */
6337+ }
6338+ }
6339+ } else {
6340+ retVal = -ENAMETOOLONG;
6341+ }
6342+ }
6343+ }
6344+ } else {
6345+ retVal = -ENOMEM;
6346+ }
6347+ if (iLock) {
6348+ Novfs_unlock_inode_cache(dir);
6349+ }
6350+ dput(parent);
6351+ }
6352+
6353+ if (list)
6354+ kfree(list);
6355+ if (info)
6356+ kfree(info);
6357+
6358+ DbgPrint("verify_dentry: return=0x%x\n", retVal);
6359+
6360+ return (retVal);
6361+}
6362+
6363+/*++======================================================================*/
6364+struct dentry *Novfs_d_lookup(struct dentry *Parent, struct qstr *Name)
6365+/*
6366+ * Arguments:
6367+ *
6368+ * Returns:
6369+ *
6370+ * Abstract:
6371+ *
6372+ * Notes:
6373+ *
6374+ * Environment:
6375+ *
6376+ *========================================================================*/
6377+{
6378+ return (d_lookup(Parent, Name));
6379+}
6380+
6381+/*++======================================================================*/
6382+int Novfs_d_add(struct dentry *Parent, struct dentry *d, struct inode *i, int a)
6383+/*
6384+ * Arguments:
6385+ *
6386+ * Returns:
6387+ *
6388+ * Abstract:
6389+ *
6390+ * Notes:
6391+ *
6392+ * Environment:
6393+ *
6394+ *========================================================================*/
6395+{
6396+ void *scope;
6397+ struct inode_data *id = NULL;
6398+
6399+ char *path, *buf;
6400+
6401+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
6402+ if (buf) {
6403+ path = Novfs_dget_path(d, buf, PATH_LENGTH_BUFFER);
6404+ if (path) {
6405+ DbgPrint("Novfs_d_add: inode=0x%p ino=%d path %s\n", i,
6406+ i->i_ino, path);
6407+ }
6408+ kfree(buf);
6409+ }
6410+
6411+ if (Parent && Parent->d_inode && Parent->d_inode->FSPRIVATE) {
6412+ id = (struct inode_data *) Parent->d_inode->FSPRIVATE;
6413+ }
6414+
6415+ if (id && id->Scope) {
6416+ scope = id->Scope;
6417+ } else {
6418+ scope = Scope_Get_ScopefromPath(d);
6419+ }
6420+
6421+ ((struct inode_data *) i->FSPRIVATE)->Scope = scope;
6422+
6423+ d->d_time = jiffies + (File_update_timeout * HZ);
6424+ if (a) {
6425+ d_add(d, i);
6426+ } else {
6427+ d_instantiate(d, i);
6428+ }
6429+
6430+ return (0);
6431+}
6432+
6433+/*++======================================================================*/
6434+int Novfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
6435+/*
6436+ * Arguments: struct dentry *dentry - pointer to dentry to revalidate.
6437+ * struct nameidata *nd - pointer to nameidata.
6438+ *
6439+ * Returns: zero - dentry is not valid.
6440+ * !zero - valid entry
6441+ *
6442+ * Abstract:
6443+ *
6444+ * Notes:
6445+ *
6446+ * Environment:
6447+ *
6448+ *========================================================================*/
6449+{
6450+ int retCode = 0;
6451+ struct inode *dir;
6452+ struct inode_data *id;
6453+ struct qstr name;
6454+
6455+ DbgPrint("Novfs_d_revalidate: 0x%p %.*s\n"
6456+ " d_count: %d\n"
6457+ " d_inode: 0x%p\n",
6458+ dentry, dentry->d_name.len, dentry->d_name.name,
6459+ dentry->d_count, dentry->d_inode);
6460+
6461+ if (IS_ROOT(dentry)) {
6462+ retCode = 1;
6463+ } else {
6464+ if (dentry->d_inode &&
6465+ dentry->d_parent &&
6466+ (dir = dentry->d_parent->d_inode) &&
6467+ (id = dir->FSPRIVATE)) {
6468+ /*
6469+ * Check timer to see if in valid time limit
6470+ */
6471+ if (jiffies > dentry->d_time) {
6472+ /*
6473+ * Revalidate entry
6474+ */
6475+ name.len = dentry->d_name.len;
6476+ name.name = dentry->d_name.name;
6477+ name.hash =
6478+ Novfs_internal_hash(&dentry->d_name);
6479+ dentry->d_time = 0;
6480+
6481+ if (0 == verify_dentry(dentry, 0)) {
6482+ if (Novfs_lock_inode_cache(dir)) {
6483+ if (Novfs_lookup_inode_cache
6484+ (dir, &name, 0)) {
6485+ dentry->d_time =
6486+ jiffies +
6487+ (File_update_timeout
6488+ * HZ);
6489+ retCode = 1;
6490+ }
6491+ Novfs_unlock_inode_cache(dir);
6492+ }
6493+ }
6494+ } else {
6495+ retCode = 1;
6496+ }
6497+ }
6498+ }
6499+
6500+ if ((0 == retCode) && dentry->d_inode) {
6501+ /*
6502+ * Entry has become invalid
6503+ */
6504+/* dput(dentry);
6505+*/
6506+ }
6507+
6508+ DbgPrint("Novfs_d_revalidate: return 0x%x %.*s\n", retCode,
6509+ dentry->d_name.len, dentry->d_name.name);
6510+
6511+ return (retCode);
6512+}
6513+
6514+/*++======================================================================*/
6515+unsigned long Novfs_internal_hash(struct qstr *name)
6516+/*
6517+ * Arguments:
6518+ *
6519+ * Returns:
6520+ *
6521+ * Abstract:
6522+ *
6523+ * Notes:
6524+ *
6525+ * Environment:
6526+ *
6527+ *========================================================================*/
6528+{
6529+ unsigned long hash = 0;
6530+ unsigned int len = name->len;
6531+ unsigned char *c = (unsigned char *)name->name;
6532+
6533+ while (len--) {
6534+ /*
6535+ * Lower case values for the hash.
6536+ */
6537+ hash = partial_name_hash(tolower(*c++), hash);
6538+ }
6539+
6540+ return (hash);
6541+}
6542+
6543+/*++======================================================================*/
6544+int Novfs_d_hash(struct dentry *dentry, struct qstr *name)
6545+/*
6546+ * Arguments:
6547+ *
6548+ * Returns:
6549+ *
6550+ * Abstract:
6551+ *
6552+ * Notes:
6553+ *
6554+ * Environment:
6555+ *
6556+ *========================================================================*/
6557+{
6558+ DbgPrint("Novfs_d_hash: %.*s\n", name->len, name->name);
6559+
6560+ name->hash = Novfs_internal_hash(name);
6561+
6562+ return (0);
6563+}
6564+
6565+/*++======================================================================*/
6566+int Novfs_d_strcmp(struct qstr *s1, struct qstr *s2)
6567+/*
6568+ * Arguments:
6569+ *
6570+ * Returns:
6571+ *
6572+ * Abstract:
6573+ *
6574+ * Notes:
6575+ *
6576+ * Environment:
6577+ *
6578+ *========================================================================*/
6579+{
6580+ int retCode = 1;
6581+ unsigned char *str1, *str2;
6582+ unsigned int len;
6583+
6584+ DbgPrint("Novfs_d_strcmp: s1=%.*s s2=%.*s\n", s1->len, s1->name,
6585+ s2->len, s2->name);
6586+
6587+ if (s1->len && (s1->len == s2->len) && (s1->hash == s2->hash)) {
6588+ len = s1->len;
6589+ str1 = (unsigned char *)s1->name;
6590+ str2 = (unsigned char *)s2->name;
6591+ for (retCode = 0; len--; str1++, str2++) {
6592+ if (*str1 != *str2) {
6593+ if (tolower(*str1) != tolower(*str2)) {
6594+ retCode = 1;
6595+ break;
6596+ }
6597+ }
6598+ }
6599+ }
6600+
6601+ DbgPrint("Novfs_d_strcmp: retCode=0x%x\n", retCode);
6602+ return (retCode);
6603+}
6604+
6605+/*++======================================================================*/
6606+int Novfs_d_compare(struct dentry *parent, struct qstr *s1, struct qstr *s2)
6607+/*
6608+ * Arguments:
6609+ *
6610+ * Returns:
6611+ *
6612+ * Abstract:
6613+ *
6614+ * Notes:
6615+ *
6616+ * Environment:
6617+ *
6618+ *========================================================================*/
6619+{
6620+ int retCode;
6621+
6622+ retCode = Novfs_d_strcmp(s1, s2);
6623+
6624+ DbgPrint("Novfs_d_compare: retCode=0x%x\n", retCode);
6625+ return (retCode);
6626+}
6627+
6628+/*++======================================================================*/
6629+int Novfs_d_delete(struct dentry *dentry)
6630+/*
6631+ * Arguments:
6632+ *
6633+ * Returns:
6634+ *
6635+ * Abstract:
6636+ *
6637+ * Notes:
6638+ *
6639+ * Environment:
6640+ *
6641+ *========================================================================*/
6642+{
6643+ int retVal = 0;
6644+
6645+ DbgPrint("Novfs_d_delete: 0x%p %.*s\n"
6646+ " d_count: %d\n"
6647+ " d_inode: 0x%p\n",
6648+ dentry, dentry->d_name.len, dentry->d_name.name,
6649+ dentry->d_count, dentry->d_inode);
6650+
6651+ if (dentry->d_inode && (dentry->d_inode->i_flags & S_DEAD)) {
6652+ retVal = 1;
6653+ }
6654+
6655+ dentry->d_time = 0;
6656+
6657+ return (retVal);
6658+}
6659+
6660+/*++======================================================================*/
6661+void Novfs_d_release(struct dentry *dentry)
6662+/*
6663+ * Arguments:
6664+ *
6665+ * Returns:
6666+ *
6667+ * Abstract:
6668+ *
6669+ * Notes:
6670+ *
6671+ * Environment:
6672+ *
6673+ *========================================================================*/
6674+{
6675+ DbgPrint("Novfs_d_release: 0x%p %.*s\n", dentry, dentry->d_name.len,
6676+ dentry->d_name.name);
6677+}
6678+
6679+/*++======================================================================*/
6680+void Novfs_d_iput(struct dentry *dentry, struct inode *inode)
6681+/*
6682+ * Arguments:
6683+ *
6684+ * Returns:
6685+ *
6686+ * Abstract:
6687+ *
6688+ * Notes:
6689+ *
6690+ * Environment:
6691+ *
6692+ *========================================================================*/
6693+{
6694+ DbgPrint
6695+ ("Novfs_d_iput: Inode=0x%p Ino=%d Dentry=0x%p i_state=%d Name=%.*s\n",
6696+ inode, inode->i_ino, dentry, inode->i_state, dentry->d_name.len,
6697+ dentry->d_name.name);
6698+
6699+ iput(inode);
6700+
6701+}
6702+
6703+/*++======================================================================*/
6704+int Novfs_dir_open(struct inode *dir, struct file *file)
6705+/*
6706+ * Arguments:
6707+ *
6708+ * Returns:
6709+ *
6710+ * Abstract:
6711+ *
6712+ * Notes:
6713+ *
6714+ * Environment:
6715+ *
6716+ *========================================================================*/
6717+{
6718+ char *path, *buf;
6719+ FilePrivate2 *file_private = NULL;
6720+
6721+ DbgPrint("Novfs_dir_open: Inode 0x%p %d Name %.*s\n", dir, dir->i_ino,
6722+ file->f_dentry->d_name.len, file->f_dentry->d_name.name);
6723+
6724+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
6725+ if (buf) {
6726+ path = Novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER);
6727+ if (path) {
6728+ DbgPrint("Novfs_dir_open: path %s\n", path);
6729+ }
6730+ kfree(buf);
6731+ }
6732+
6733+ file_private = Novfs_Malloc(sizeof(FilePrivate2), GFP_KERNEL);
6734+ file_private->listedall = 0;
6735+ file_private->enumHandle = NULL;
6736+
6737+ file->private_data = file_private;
6738+
6739+ return (0);
6740+}
6741+
6742+/*++======================================================================*/
6743+int Novfs_dir_release(struct inode *dir, struct file *file)
6744+/*
6745+ * Arguments:
6746+ *
6747+ * Returns:
6748+ *
6749+ * Abstract:
6750+ *
6751+ * Notes:
6752+ *
6753+ * Environment:
6754+ *
6755+ *========================================================================*/
6756+{
6757+ FilePrivate2 *file_private;
6758+ file_private = (FilePrivate2 *) file->private_data;
6759+
6760+ DbgPrint("Novfs_dir_release: Inode 0x%p %d Name %.*s\n", dir,
6761+ dir->i_ino, file->f_dentry->d_name.len,
6762+ file->f_dentry->d_name.name);
6763+
6764+ if (file_private) {
6765+ kfree(file_private);
6766+ file->private_data = NULL;
6767+ }
6768+
6769+ return (0);
6770+}
6771+
6772+/*++======================================================================*/
6773+loff_t Novfs_dir_lseek(struct file * file, loff_t offset, int origin)
6774+/*
6775+ * Arguments:
6776+ *
6777+ * Returns:
6778+ *
6779+ * Abstract:
6780+ *
6781+ * Notes:
6782+ *
6783+ * Environment:
6784+ *
6785+ *========================================================================*/
6786+{
6787+ FilePrivate2 *file_private = NULL;
6788+
6789+ DbgPrint("Novfs_dir_lseek: offset %lld %d Name %.*s\n", offset, origin,
6790+ file->f_dentry->d_name.len, file->f_dentry->d_name.name);
6791+ //printk("<1> seekdir file = %.*s offset = %i\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, (int)offset);
6792+
6793+ if (0 != offset) {
6794+ return -ESPIPE;
6795+ }
6796+
6797+ file->f_pos = 0;
6798+
6799+ file_private = (FilePrivate2 *) file->private_data;
6800+ file_private->listedall = 0;
6801+ file_private->enumHandle = NULL;
6802+
6803+ return 0;
6804+ //return(default_llseek(file, offset, origin));
6805+}
6806+
6807+/*++======================================================================*/
6808+ssize_t Novfs_dir_read(struct file * file, char *buf, size_t len, loff_t * off)
6809+/*
6810+ * Arguments:
6811+ *
6812+ * Returns:
6813+ *
6814+ * Abstract:
6815+ *
6816+ * Notes:
6817+ *
6818+ * Environment:
6819+ *
6820+ *========================================================================*/
6821+{
6822+/*
6823+ int rlen = 0;
6824+
6825+ DbgPrint("Novfs_dir_readdir: dentry path %.*s buf=0x%p len=%d off=%lld\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, buf, len, *off);
6826+
6827+ if (0 == *off)
6828+ {
6829+ rlen = 8;
6830+ rlen -= copy_to_user(buf, "Testing\n", 8);
6831+ *off += rlen;
6832+ }
6833+ return(rlen);
6834+*/
6835+ DbgPrint("Novfs_dir_read: %lld %d Name %.*s\n", *off, len,
6836+ file->f_dentry->d_name.len, file->f_dentry->d_name.name);
6837+ return (generic_read_dir(file, buf, len, off));
6838+}
6839+
6840+static void Novfs_Dump_Info(struct entry_info *info)
6841+{
6842+ char atime_buf[32], mtime_buf[32], ctime_buf[32];
6843+ char namebuf[512];
6844+ int len = 0;
6845+
6846+ if (info == NULL) {
6847+ DbgPrint("Novfs_dir_readdir : Dump_Info info == NULL\n");
6848+ return;
6849+ }
6850+
6851+ if (info->namelength >= 512) {
6852+ len = 511;
6853+ } else {
6854+ len = info->namelength;
6855+ }
6856+
6857+ memcpy(namebuf, info->name, len);
6858+ namebuf[len] = '\0';
6859+
6860+ ctime_r(&info->atime.tv_sec, atime_buf);
6861+ ctime_r(&info->mtime.tv_sec, mtime_buf);
6862+ ctime_r(&info->ctime.tv_sec, ctime_buf);
6863+ DbgPrint("Novfs_dir_readdir : type = %i\n", info->type);
6864+ DbgPrint("Novfs_dir_readdir : mode = %x\n", info->mode);
6865+ DbgPrint("Novfs_dir_readdir : uid = %d\n", info->uid);
6866+ DbgPrint("Novfs_dir_readdir : gid = %d\n", info->gid);
6867+ DbgPrint("Novfs_dir_readdir : size = %i\n", info->size);
6868+ DbgPrint("Novfs_dir_readdir : atime = %s\n", atime_buf);
6869+ DbgPrint("Novfs_dir_readdir : mtime = %s\n", mtime_buf);
6870+ DbgPrint("Novfs_dir_readdir : ctime = %s\n", ctime_buf);
6871+ DbgPrint("Novfs_dir_readdir : namelength = %i\n", info->namelength);
6872+ DbgPrint("Novfs_dir_readdir : name = %s\n", namebuf);
6873+}
6874+
6875+/*++======================================================================*/
6876+void processList(struct file *file, void *dirent, filldir_t filldir, char *list,
6877+ int type, session_t SessionId)
6878+/*
6879+ * Arguments:
6880+ *
6881+ * Returns:
6882+ *
6883+ * Abstract:
6884+ *
6885+ * Notes:
6886+ *
6887+ * Environment:
6888+ *
6889+ *========================================================================*/
6890+{
6891+ unsigned char *path, *buf = NULL, *cp;
6892+ struct qstr name;
6893+ struct entry_info *pinfo = NULL;
6894+
6895+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
6896+ path = buf;
6897+ if (buf) {
6898+ path = Novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER);
6899+ if (path) {
6900+ strcpy(buf, path);
6901+ }
6902+ path = buf + strlen(buf);
6903+ *path++ = '\\';
6904+ }
6905+
6906+ if (list) {
6907+ cp = list;
6908+ while (*cp) {
6909+ name.name = cp;
6910+ DbgPrint("Novfs_dir_readdir : name.name = %s\n",
6911+ name.name);
6912+ name.len = strlen(cp);
6913+ name.hash = Novfs_internal_hash(&name);
6914+ cp += (name.len + 1);
6915+
6916+ pinfo =
6917+ Novfs_Malloc(sizeof(struct entry_info) +
6918+ PATH_LENGTH_BUFFER, GFP_KERNEL);
6919+ pinfo->mode = S_IFDIR | 0700;
6920+ pinfo->size = 0;
6921+ pinfo->atime = pinfo->ctime = pinfo->mtime =
6922+ CURRENT_TIME;
6923+ strcpy(pinfo->name, name.name);
6924+ pinfo->namelength = name.len;
6925+
6926+ Novfs_Dump_Info(pinfo);
6927+
6928+ filldir(dirent, pinfo->name, pinfo->namelength,
6929+ file->f_pos, file->f_pos, pinfo->mode >> 12);
6930+ file->f_pos += 1;
6931+
6932+ kfree(pinfo);
6933+ }
6934+ }
6935+
6936+ if (buf) {
6937+ kfree(buf);
6938+ }
6939+}
6940+
6941+int processEntries(struct file *file, void *dirent, filldir_t filldir,
6942+ HANDLE * enumHandle, session_t sessionId)
6943+{
6944+ unsigned char *path = NULL, *buf = NULL;
6945+ int count = 0, status = 0;
6946+ struct entry_info *pinfo = NULL;
6947+ struct entry_info *pInfoMem = NULL;
6948+
6949+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
6950+ if (!buf) {
6951+ return -ENOMEM;
6952+ }
6953+
6954+ path = Novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER);
6955+ if (!path) {
6956+ kfree(buf);
6957+ return -ENOMEM;
6958+ }
6959+ //NWSearchfiles
6960+ count = 0;
6961+ status = Novfs_Get_Directory_ListEx(path, enumHandle, &count, &pinfo, &sessionId);
6962+ pInfoMem = pinfo;
6963+
6964+ if ((count == -1) || (count == 0) || (status != 0)) {
6965+ kfree(pInfoMem);
6966+ kfree(buf);
6967+ return -1;
6968+ }
6969+ // parse resultset
6970+ while (pinfo && count--) {
6971+ filldir(dirent, pinfo->name, pinfo->namelength, file->f_pos,
6972+ file->f_pos, pinfo->mode >> 12);
6973+ file->f_pos += 1;
6974+
6975+ pinfo = (struct entry_info *)(pinfo->name + pinfo->namelength);
6976+ }
6977+
6978+ kfree(pInfoMem);
6979+ kfree(buf);
6980+ return 0;
6981+}
6982+
6983+/*++======================================================================*/
6984+int Novfs_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
6985+/*
6986+ * Arguments:
6987+ *
6988+ * Returns:
6989+ *
6990+ * Abstract:
6991+ *
6992+ * Notes:
6993+ *
6994+ * Environment:
6995+ *
6996+ *========================================================================*/
6997+{
6998+ unsigned char *list = NULL;
6999+ int status = 0; //-ENOMEM;
7000+ struct inode *inode = file->f_dentry->d_inode;
7001+ session_t sessionId;
7002+ uid_t uid;
7003+ int type = 0;
7004+ FilePrivate2 *file_private = NULL;
7005+ int lComm;
7006+
7007+ file_private = (FilePrivate2 *) file->private_data;
7008+ DbgPrint("Novfs_dir_readdir: Name %.*s\n", file->f_dentry->d_name.len,
7009+ file->f_dentry->d_name.name);
7010+
7011+ //printk("<1> file = %.*s\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name);
7012+
7013+// Use this hack by default
7014+#ifndef SKIP_CROSSOVER_HACK
7015+ // Hack for crossover - begin
7016+ down(&TimeDir_Lock);
7017+ if ((file->f_dentry->d_name.len == 7) &&
7018+ ((0 == strncmp(file->f_dentry->d_name.name, " !xover", 7)) ||
7019+ (0 == strncmp(file->f_dentry->d_name.name, "z!xover", 7)))) {
7020+ //printk("<1> xoverhack: we are in xoverHack\n");
7021+
7022+ inHAX = 1;
7023+ inHAXTime = get_nanosecond_time();
7024+ //up( &TimeDir_Lock );
7025+ //return 0;
7026+ file_private->listedall = 1;
7027+ } else {
7028+ if (inHAX) {
7029+ if (get_nanosecond_time() - inHAXTime >
7030+ 100 * 1000 * 1000) {
7031+ //printk("<1> xoverhack: it was long, long, long ago...\n");
7032+ inHAX = 0;
7033+ } else {
7034+ //printk("<1> xoverhack: word gotcha in xoverHack...\n");
7035+ inHAXTime = get_nanosecond_time();
7036+ //up( &TimeDir_Lock );
7037+ //return 0;
7038+ file_private->listedall = 1;
7039+ }
7040+ }
7041+ }
7042+
7043+ up(&TimeDir_Lock);
7044+ // Hack for crossover - end
7045+#endif
7046+
7047+ if (file->f_pos == 0) {
7048+ if (filldir(dirent, ".", 1, file->f_pos, inode->i_ino, DT_DIR) <
7049+ 0)
7050+ return 1;
7051+ file->f_pos++;
7052+ return 1;
7053+ }
7054+
7055+ if (file->f_pos == 1) {
7056+ if (filldir
7057+ (dirent, "..", 2, file->f_pos,
7058+ file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
7059+ return 1;
7060+ file->f_pos++;
7061+ return 1;
7062+ }
7063+
7064+ if (file_private->listedall != 0) {
7065+ return 0;
7066+ }
7067+
7068+ inode = file->f_dentry->d_inode;
7069+ if (inode && inode->FSPRIVATE) {
7070+ sessionId =
7071+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)-> Scope);
7072+ if (0 == SC_PRESENT(sessionId)) {
7073+ ((struct inode_data *)inode->FSPRIVATE)->Scope =
7074+ Scope_Get_ScopefromPath(file->f_dentry);
7075+ sessionId =
7076+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
7077+ }
7078+ uid = Scope_Get_Uid(((struct inode_data *)inode->FSPRIVATE)->Scope);
7079+ } else {
7080+ SC_INITIALIZE(sessionId);
7081+ uid = current->euid;
7082+ }
7083+
7084+ if (IS_ROOT(file->f_dentry) || // Root
7085+ IS_ROOT(file->f_dentry->d_parent) || // User
7086+ IS_ROOT(file->f_dentry->d_parent->d_parent)) // Server
7087+ {
7088+ if (IS_ROOT(file->f_dentry)) {
7089+ DbgPrint("Novfs_dir_readdir: Root directory\n");
7090+ list = Scope_Get_ScopeUsers();
7091+ type = USER_LIST;
7092+ } else if (IS_ROOT(file->f_dentry->d_parent)) {
7093+ DbgPrint
7094+ ("Novfs_dir_readdir: Parent is Root directory\n");
7095+ Novfs_Get_Connected_Server_List(&list, &sessionId);
7096+ type = SERVER_LIST;
7097+ } else {
7098+ DbgPrint
7099+ ("Novfs_dir_readdir: Parent-Parent is Root directory\n");
7100+ Novfs_Get_Server_Volume_List(&file->f_dentry->d_name,
7101+ &list, &sessionId);
7102+ type = VOLUME_LIST;
7103+ }
7104+
7105+ processList(file, dirent, filldir, list, type, sessionId);
7106+ file_private->listedall = 1;
7107+ } else {
7108+ status =
7109+ processEntries(file, dirent, filldir,
7110+ &file_private->enumHandle, sessionId);
7111+
7112+ if (status != 0) {
7113+ file_private->listedall = 1;
7114+#ifndef SKIP_CROSSOVER_HACK
7115+ // Hack for crossover part 2 - begin
7116+ lComm = strlen(current->comm);
7117+ if ((lComm > 4)
7118+ && (0 ==
7119+ strcmp(current->comm + lComm - 4, ".EXE"))) {
7120+ if (filldir
7121+ (dirent, " !xover", 7, file->f_pos,
7122+ inode->i_ino, DT_DIR) < 0)
7123+ return 1;
7124+ if (filldir
7125+ (dirent, "z!xover", 7, file->f_pos,
7126+ inode->i_ino, DT_DIR) < 0)
7127+ return 1;
7128+ file->f_pos += 2;
7129+ }
7130+ // Hack for crossover part2 - end
7131+#endif
7132+ }
7133+ }
7134+
7135+ file->private_data = file_private;
7136+ return 1;
7137+}
7138+
7139+/*++======================================================================*/
7140+int Novfs_dir_fsync(struct file *file, struct dentry *dentry, int datasync)
7141+/*
7142+ * Arguments:
7143+ *
7144+ * Returns:
7145+ *
7146+ * Abstract:
7147+ *
7148+ * Notes:
7149+ *
7150+ * Environment:
7151+ *
7152+ *========================================================================*/
7153+{
7154+ DbgPrint("Novfs_dir_fsync: Name %.*s\n", file->f_dentry->d_name.len,
7155+ file->f_dentry->d_name.name);
7156+ return (simple_sync_file(file, dentry, datasync));
7157+}
7158+
7159+/*++======================================================================*/
7160+ssize_t Novfs_f_read(struct file * file, char *buf, size_t len, loff_t * off)
7161+/*
7162+ * Arguments:
7163+ *
7164+ * Returns:
7165+ *
7166+ * Abstract:
7167+ *
7168+ * Notes:
7169+ *
7170+ * Environment:
7171+ *
7172+ *========================================================================*/
7173+{
7174+ size_t thisread, totalread = 0;
7175+ loff_t offset = *off;
7176+ struct inode *inode;
7177+ session_t session;
7178+ struct inode_data *id;
7179+
7180+ if (file->f_dentry &&
7181+ (inode = file->f_dentry->d_inode) &&
7182+ (id = (struct inode_data *)inode->FSPRIVATE)) {
7183+
7184+ DbgPrint("Novfs_f_read(0x%p 0x%p %d %lld %.*s)\n",
7185+ file->private_data,
7186+ buf, len, offset,
7187+ file->f_dentry->d_name.len,
7188+ file->f_dentry->d_name.name);
7189+
7190+ if (PageCache && !(file->f_flags & O_DIRECT) && id->CacheFlag) {
7191+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
7192+ totalread = generic_file_read(file, buf, len, off);
7193+#else
7194+ totalread = do_sync_read(file, buf, len, off);
7195+#endif
7196+ } else {
7197+ session = Scope_Get_SessionId(id->Scope);
7198+ if (0 == SC_PRESENT(session)) {
7199+ id->Scope =
7200+ Scope_Get_ScopefromPath(file->f_dentry);
7201+ session = Scope_Get_SessionId(id->Scope);
7202+ }
7203+
7204+ while (len > 0 && (offset < i_size_read(inode))) {
7205+ int retval;
7206+ thisread = len;
7207+ retval =
7208+ Novfs_Read_File(file->private_data, buf,
7209+ &thisread, &offset,
7210+ session);
7211+ if (retval || !thisread) {
7212+ if (retval) {
7213+ totalread = retval;
7214+ }
7215+ break;
7216+ }
7217+ DbgPrint("Novfs_f_read thisread = 0x%x\n",
7218+ thisread);
7219+ len -= thisread;
7220+ buf += thisread;
7221+ offset += thisread;
7222+ totalread += thisread;
7223+ }
7224+ *off = offset;
7225+ }
7226+ }
7227+ DbgPrint("Novfs_f_read return = %d\n", totalread);
7228+
7229+ return (totalread);
7230+}
7231+
7232+/*++======================================================================*/
7233+ssize_t Novfs_f_write(struct file * file, const char *buf, size_t len,
7234+ loff_t * off)
7235+/*
7236+ * Arguments:
7237+ *
7238+ * Returns:
7239+ *
7240+ * Abstract:
7241+ *
7242+ * Notes:
7243+ *
7244+ * Environment:
7245+ *
7246+ *========================================================================*/
7247+{
7248+ ssize_t thiswrite, totalwrite = 0;
7249+ loff_t offset = *off;
7250+ session_t session;
7251+ struct inode *inode;
7252+ int status;
7253+ struct inode_data *id;
7254+
7255+ if (file->f_dentry &&
7256+ (inode = file->f_dentry->d_inode) &&
7257+ (id = file->f_dentry->d_inode->FSPRIVATE)) {
7258+ DbgPrint("Novfs_f_write(0x%p 0x%p 0x%p %d %lld %.*s)\n",
7259+ file->private_data, inode, id->FileHandle, len, offset,
7260+ file->f_dentry->d_name.len,
7261+ file->f_dentry->d_name.name);
7262+
7263+ if (PageCache &&
7264+ !(file->f_flags & O_DIRECT) &&
7265+ id->CacheFlag && !(file->f_flags & O_WRONLY)) {
7266+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
7267+ totalwrite = generic_file_write(file, buf, len, off);
7268+#else
7269+ totalwrite = do_sync_write(file, buf, len, off);
7270+#endif
7271+ } else {
7272+ if (file->f_flags & O_APPEND) {
7273+ offset = i_size_read(inode);
7274+ DbgPrint
7275+ ("Novfs_f_write appending to end %lld %.*s\n",
7276+ offset, file->f_dentry->d_name.len,
7277+ file->f_dentry->d_name.name);
7278+ }
7279+
7280+ session = Scope_Get_SessionId(id->Scope);
7281+ if (0 == SC_PRESENT(session)) {
7282+ id->Scope =
7283+ Scope_Get_ScopefromPath(file->f_dentry);
7284+ session = Scope_Get_SessionId(id->Scope);
7285+ }
7286+
7287+ while (len > 0) {
7288+ thiswrite = len;
7289+ if ((status =
7290+ Novfs_Write_File(file->private_data,
7291+ (unsigned char *)buf,
7292+ &thiswrite, &offset,
7293+ session)) || !thiswrite) {
7294+ totalwrite = status;
7295+ break;
7296+ }
7297+ DbgPrint("Novfs_f_write thiswrite = 0x%x\n",
7298+ thiswrite);
7299+ len -= thiswrite;
7300+ buf += thiswrite;
7301+ offset += thiswrite;
7302+ totalwrite += thiswrite;
7303+ if (offset > i_size_read(inode)) {
7304+ i_size_write(inode, offset);
7305+ inode->i_blocks =
7306+ (offset + inode->i_sb->s_blocksize -
7307+ 1) >> inode->i_blkbits;
7308+ }
7309+ inode->i_mtime = inode->i_atime = CURRENT_TIME;
7310+ id->Flags |= UPDATE_INODE;
7311+
7312+ }
7313+ *off = offset;
7314+ }
7315+ }
7316+ DbgPrint("Novfs_f_write return = 0x%x\n", totalwrite);
7317+
7318+ return (totalwrite);
7319+}
7320+
7321+int Novfs_f_readdir(struct file *file, void *data, filldir_t fill)
7322+{
7323+ return -EISDIR;
7324+}
7325+
7326+int Novfs_f_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
7327+ unsigned long arg)
7328+{
7329+ DbgPrint("Novfs_f_ioctl: file=0x%p cmd=0x%x arg=0x%p\n", file, cmd,
7330+ arg);
7331+
7332+ return -ENOSYS;
7333+}
7334+
7335+/*++======================================================================*/
7336+int Novfs_f_mmap(struct file *file, struct vm_area_struct *vma)
7337+/*
7338+ * Arguments:
7339+ *
7340+ * Returns:
7341+ *
7342+ * Abstract:
7343+ *
7344+ * Notes:
7345+ *
7346+ * Environment:
7347+ *
7348+ *========================================================================*/
7349+{
7350+ int retCode = -EINVAL;
7351+
7352+ DbgPrint("Novfs_f_mmap: file=0x%p %.*s\n", file,
7353+ file->f_dentry->d_name.len, file->f_dentry->d_name.name);
7354+
7355+ retCode = generic_file_mmap(file, vma);
7356+
7357+ DbgPrint("Novfs_f_mmap: retCode=0x%x\n", retCode);
7358+ return (retCode);
7359+}
7360+
7361+/*++======================================================================*/
7362+int Novfs_f_open(struct inode *inode, struct file *file)
7363+/*
7364+ * Arguments:
7365+ *
7366+ * Returns:
7367+ *
7368+ * Abstract:
7369+ *
7370+ * Notes:
7371+ *
7372+ * Environment:
7373+ *
7374+ *========================================================================*/
7375+{
7376+ struct entry_info *info = NULL;
7377+ int retCode = -ENOENT;
7378+ session_t session;
7379+ char *path;
7380+ struct dentry *parent;
7381+ ino_t ino;
7382+ struct inode_data *id;
7383+ int errInfo;
7384+
7385+ DbgPrint
7386+ ("Novfs_f_open: inode=0x%p file=0x%p dentry=0x%p dentry->d_inode=0x%p %.*s\n",
7387+ inode, file, file->f_dentry, file->f_dentry->d_inode,
7388+ file->f_dentry->d_name.len, file->f_dentry->d_name.name);
7389+ if (file->f_dentry) {
7390+ DbgPrint
7391+ ("Novfs_f_open: %.*s f_flags=0%o f_mode=0%o i_mode=0%o\n",
7392+ file->f_dentry->d_name.len, file->f_dentry->d_name.name,
7393+ file->f_flags, file->f_mode, inode->i_mode);
7394+ }
7395+
7396+ if (inode && inode->FSPRIVATE) {
7397+ id = (struct inode_data *) file->f_dentry->d_inode->FSPRIVATE;
7398+ session = Scope_Get_SessionId(id->Scope);
7399+ if (0 == SC_PRESENT(session)) {
7400+ id->Scope = Scope_Get_ScopefromPath(file->f_dentry);
7401+ session = Scope_Get_SessionId(id->Scope);
7402+ }
7403+
7404+ info = Novfs_Malloc(sizeof(struct entry_info) + PATH_LENGTH_BUFFER, GFP_KERNEL);
7405+ if (info) {
7406+ path =
7407+ Novfs_dget_path(file->f_dentry, info->name,
7408+ PATH_LENGTH_BUFFER);
7409+ if (path) {
7410+ if (file->f_flags & O_TRUNC) {
7411+ errInfo = Novfs_Get_File_Info(path, info, &session);
7412+
7413+ if (errInfo || info->size == 0) {
7414+ // clear O_TRUNC flag, bug #275366
7415+ file->f_flags =
7416+ file->f_flags & (~O_TRUNC);
7417+ }
7418+ }
7419+
7420+ DbgPrint("Novfs_f_open: %s\n", path);
7421+ retCode = Novfs_Open_File(path,
7422+ file->
7423+ f_flags & ~O_EXCL,
7424+ info,
7425+ &file->private_data,
7426+ session);
7427+
7428+ DbgPrint("Novfs_f_open: 0x%x 0x%p\n", retCode,
7429+ file->private_data);
7430+ if (!retCode) {
7431+ /*
7432+ *update_inode(inode, &info);
7433+ */
7434+ //id->FileHandle = file->private_data;
7435+ id->CacheFlag =
7436+ Novfs_Get_File_Cache_Flag(path,
7437+ session);
7438+
7439+ if (!Novfs_Get_File_Info(path, info, &session))
7440+ update_inode(inode, info);
7441+
7442+ parent = dget_parent(file->f_dentry);
7443+
7444+ if (parent && parent->d_inode) {
7445+ struct inode *dir =
7446+ parent->d_inode;
7447+ Novfs_lock_inode_cache(dir);
7448+ ino = 0;
7449+ if (Novfs_get_entry
7450+ (dir,
7451+ &file->f_dentry->d_name,
7452+ &ino, info)) {
7453+ ((struct inode_data *)inode->FSPRIVATE)->Flags |=
7454+ UPDATE_INODE;
7455+ }
7456+
7457+ Novfs_unlock_inode_cache(dir);
7458+ }
7459+ dput(parent);
7460+ }
7461+ }
7462+ kfree(info);
7463+ }
7464+ }
7465+ DbgPrint("Novfs_f_open: retCode=0x%x\n", retCode);
7466+ return (retCode);
7467+}
7468+
7469+/*++======================================================================*/
7470+int Novfs_flush_mapping(HANDLE Handle, struct address_space *mapping,
7471+ session_t Session)
7472+/*
7473+ * Arguments:
7474+ *
7475+ * Returns:
7476+ *
7477+ * Abstract:
7478+ *
7479+ * Notes:
7480+ *
7481+ * Environment:
7482+ *
7483+ *========================================================================*/
7484+{
7485+ struct pagevec pagevec;
7486+ unsigned nrpages;
7487+ pgoff_t index = 0;
7488+ int done, rc = 0;
7489+
7490+ pagevec_init(&pagevec, 0);
7491+
7492+ do {
7493+ done = 1;
7494+ nrpages = pagevec_lookup_tag(&pagevec,
7495+ mapping,
7496+ &index,
7497+ PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE);
7498+
7499+ if (nrpages) {
7500+ struct page *page;
7501+ int i;
7502+
7503+ DbgPrint("Novfs_flush_mapping: %u\n", nrpages);
7504+
7505+ done = 0;
7506+ for (i = 0; !rc && (i < nrpages); i++) {
7507+ page = pagevec.pages[i];
7508+
7509+ DbgPrint("Novfs_flush_mapping: page 0x%p %lu\n",
7510+ page, page->index);
7511+
7512+ lock_page(page);
7513+ page_cache_get(page);
7514+ if (page->mapping == mapping) {
7515+ if (clear_page_dirty_for_io(page)) {
7516+ rc = Novfs_Write_Page(Handle,
7517+ page,
7518+ Session);
7519+ if (!rc) {
7520+ //ClearPageDirty(page);
7521+ radix_tree_tag_clear
7522+ (&mapping->
7523+ page_tree,
7524+ page_index(page),
7525+ PAGECACHE_TAG_DIRTY);
7526+ }
7527+ }
7528+ }
7529+
7530+ page_cache_release(page);
7531+ unlock_page(page);
7532+ }
7533+ pagevec_release(&pagevec);
7534+ }
7535+ } while (!rc && !done);
7536+
7537+ DbgPrint("Novfs_flush_mapping: return %d\n", rc);
7538+
7539+ return (rc);
7540+}
7541+
7542+/*++======================================================================*/
7543+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
7544+int Novfs_f_flush(struct file *file)
7545+#else
7546+int Novfs_f_flush(struct file *file, fl_owner_t ownid)
7547+#endif
7548+/*
7549+ * Arguments:
7550+ *
7551+ * Returns:
7552+ *
7553+ * Abstract:
7554+ *
7555+ * Notes:
7556+ *
7557+ * Environment:
7558+ *
7559+ *========================================================================*/
7560+{
7561+
7562+ int rc = 0;
7563+#ifdef FLUSH
7564+ struct inode *inode;
7565+ session_t session;
7566+ struct inode_data *id;
7567+
7568+ DbgPrint("Novfs_f_flush: Called from 0x%p\n",
7569+ __builtin_return_address(0));
7570+ if (file->f_dentry && (inode = file->f_dentry->d_inode)
7571+ && (id = file->f_dentry->d_inode->FSPRIVATE)) {
7572+
7573+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
7574+ inode = file->f_dentry->d_inode;
7575+ DbgPrint
7576+ ("Novfs_f_flush: %.*s f_flags=0%o f_mode=0%o i_mode=0%o\n",
7577+ file->f_dentry->d_name.len,
7578+ file->f_dentry->d_name.name, file->f_flags,
7579+ file->f_mode, inode->i_mode);
7580+
7581+ session = Scope_Get_SessionId(id->Scope);
7582+ if (0 == SC_PRESENT(session)) {
7583+ id->Scope =
7584+ Scope_Get_ScopefromPath(file->f_dentry);
7585+ session = Scope_Get_SessionId(id->Scope);
7586+ }
7587+
7588+ if (inode &&
7589+ inode->i_mapping && inode->i_mapping->nrpages) {
7590+
7591+ DbgPrint("Novfs_f_flush: %.*s pages=%lu\n",
7592+ file->f_dentry->d_name.len,
7593+ file->f_dentry->d_name.name,
7594+ inode->i_mapping->nrpages);
7595+
7596+ if (file->f_dentry &&
7597+ file->f_dentry->d_inode &&
7598+ file->f_dentry->d_inode->i_mapping &&
7599+ file->f_dentry->d_inode->i_mapping->a_ops &&
7600+ file->f_dentry->d_inode->i_mapping->a_ops->
7601+ writepage) {
7602+ rc = filemap_fdatawrite(file->f_dentry->
7603+ d_inode->
7604+ i_mapping);
7605+ } else {
7606+ rc = Novfs_flush_mapping(file->
7607+ private_data,
7608+ file->
7609+ f_dentry->
7610+ d_inode->
7611+ i_mapping,
7612+ session);
7613+ }
7614+ }
7615+ }
7616+ }
7617+#endif
7618+ return (rc);
7619+}
7620+
7621+/*++======================================================================*/
7622+int Novfs_f_release(struct inode *inode, struct file *file)
7623+/*
7624+ * Arguments:
7625+ *
7626+ * Returns:
7627+ *
7628+ * Abstract:
7629+ *
7630+ * Notes:
7631+ *
7632+ * Environment:
7633+ *
7634+ *========================================================================*/
7635+{
7636+ int retCode = -EACCES;
7637+ session_t session;
7638+ struct inode_data *id;
7639+
7640+ DbgPrint("Novfs_f_release: path=%.*s handle=%p\n",
7641+ file->f_dentry->d_name.len,
7642+ file->f_dentry->d_name.name, file->private_data);
7643+
7644+ if (inode && (id = inode->FSPRIVATE)) {
7645+ session = Scope_Get_SessionId(id->Scope);
7646+ if (0 == SC_PRESENT(session)) {
7647+ id->Scope = Scope_Get_ScopefromPath(file->f_dentry);
7648+ session = Scope_Get_SessionId(id->Scope);
7649+ }
7650+
7651+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
7652+ DbgPrint
7653+ ("Novfs_f_release: %.*s f_flags=0%o f_mode=0%o i_mode=0%o\n",
7654+ file->f_dentry->d_name.len,
7655+ file->f_dentry->d_name.name, file->f_flags,
7656+ file->f_mode, inode->i_mode);
7657+
7658+ if (inode->i_mapping && inode->i_mapping->nrpages) {
7659+
7660+ DbgPrint("Novfs_f_release: %.*s pages=%lu\n",
7661+ file->f_dentry->d_name.len,
7662+ file->f_dentry->d_name.name,
7663+ inode->i_mapping->nrpages);
7664+
7665+ if (inode->i_mapping->a_ops &&
7666+ inode->i_mapping->a_ops->writepage) {
7667+ filemap_fdatawrite(file->f_dentry->
7668+ d_inode->i_mapping);
7669+ } else {
7670+ Novfs_flush_mapping(file->private_data,
7671+ file->f_dentry->
7672+ d_inode->i_mapping,
7673+ session);
7674+ }
7675+ }
7676+ }
7677+
7678+ if (file->f_dentry && file->f_dentry->d_inode) {
7679+ invalidate_remote_inode(file->f_dentry->d_inode);
7680+ }
7681+
7682+ retCode = Novfs_Close_File(file->private_data, session);
7683+ //id->FileHandle = 0;
7684+ }
7685+ return (retCode);
7686+}
7687+
7688+int Novfs_f_fsync(struct file *file, struct dentry *dentry, int datasync)
7689+{
7690+ return 0;
7691+}
7692+
7693+/*++======================================================================*/
7694+int Novfs_f_llseek(struct file *file, loff_t offset, int origin)
7695+/*
7696+ * Arguments:
7697+ *
7698+ * Returns:
7699+ *
7700+ * Abstract:
7701+ *
7702+ * Notes:
7703+ *
7704+ * Environment:
7705+ *
7706+ *========================================================================*/
7707+{
7708+ DbgPrint("Novfs_f_llseek: File=0x%p Name=%.*s offset=%lld origin=%d\n",
7709+ file, file->f_dentry->d_name.len, file->f_dentry->d_name.name,
7710+ offset, origin);
7711+ return (generic_file_llseek(file, offset, origin));
7712+}
7713+
7714+/*++======================================================================*/
7715+int Novfs_f_lock(struct file *file, int cmd, struct file_lock *lock)
7716+/*
7717+ * Arguments:
7718+ * "file" - pointer to file structure - contains file handle in "file->private_data"
7719+ *
7720+ * "cmd" could be F_SETLK, F_SETLKW, F_GETLK
7721+ * F_SETLK/F_SETLKW are for setting/unsetting file lock
7722+ * F_GETLK is for getting infomation about region - is it locked, or not
7723+ *
7724+ * "lock" structure - contains "start" and "end" of locking region
7725+ *
7726+ * Returns:
7727+ * 0 on success
7728+ * -ENOSYS on F_GETLK cmd. It's not implemented.
7729+ * -EINVAL if (lock->fl_start > lock->fl_end)
7730+ * -EAGAIN on all other errors
7731+ * Abstract:
7732+ *
7733+ * Notes:
7734+ * "lock->fl_start" and "lock->fl_end" are of type "long long",
7735+ * but xtier functions in novfsd "NCFsdLockFile" and "NCFsdUnlockFile"
7736+ * receive arguments in u64 type.
7737+ *
7738+ * Environment:
7739+ *
7740+ *========================================================================*/
7741+{
7742+ int err_code;
7743+
7744+ struct inode *inode;
7745+ session_t session;
7746+ struct inode_data *id;
7747+ loff_t len;
7748+
7749+ DbgPrint("Novfs_f_lock(0x%p): begin in Novfs_f_lock 0x%p\n",
7750+ __builtin_return_address(0), file->private_data);
7751+ DbgPrint
7752+ ("Novfs_f_lock: cmd = %d, F_GETLK = %d, F_SETLK = %d, F_SETLKW = %d\n",
7753+ cmd, F_GETLK, F_SETLK, F_SETLKW);
7754+ DbgPrint
7755+ ("Novfs_f_lock: lock->fl_start = 0x%llX, lock->fl_end = 0x%llX\n",
7756+ lock->fl_start, lock->fl_end);
7757+
7758+ err_code = -1;
7759+ if (lock->fl_start <= lock->fl_end) {
7760+ /* Get len from "start" and "end" */
7761+ len = lock->fl_end - lock->fl_start + 1;
7762+ if ((0 == lock->fl_start) && (OFFSET_MAX == lock->fl_end)) {
7763+ len = 0;
7764+ }
7765+
7766+ if (file->f_dentry &&
7767+ (inode = file->f_dentry->d_inode) &&
7768+ (id = (struct inode_data *)inode->FSPRIVATE)) {
7769+ DbgPrint("Novfs_f_lock: (0x%p 0x%p %.*s)\n",
7770+ file->private_data, inode,
7771+ file->f_dentry->d_name.len,
7772+ file->f_dentry->d_name.name);
7773+
7774+ session = Scope_Get_SessionId(id->Scope);
7775+ if (0 == SC_PRESENT(session)) {
7776+ id->Scope =
7777+ Scope_Get_ScopefromPath(file->f_dentry);
7778+ session = Scope_Get_SessionId(id->Scope);
7779+ }
7780+
7781+ /* fl_type = F_RDLCK, F_WRLCK, F_UNLCK */
7782+ switch (cmd) {
7783+ case F_SETLK:
7784+#ifdef F_GETLK64
7785+ case F_SETLK64:
7786+#endif
7787+
7788+ err_code =
7789+ Novfs_Set_File_Lock(session,
7790+ file->private_data,
7791+ lock->fl_type,
7792+ lock->fl_start, len);
7793+ break;
7794+
7795+ case F_SETLKW:
7796+#ifdef F_GETLK64
7797+ case F_SETLKW64:
7798+#endif
7799+ err_code =
7800+ Novfs_Set_File_Lock(session,
7801+ file->private_data,
7802+ lock->fl_type,
7803+ lock->fl_start, len);
7804+ break;
7805+
7806+ case F_GETLK:
7807+#ifdef F_GETLK64
7808+ case F_GETLK64:
7809+#endif
7810+ err_code = -ENOSYS;
7811+ /*
7812+ * Not implemented. We doesn't have appropriate xtier function.
7813+ * */
7814+ break;
7815+
7816+ default:
7817+ printk
7818+ ("<1> novfs in Novfs_f_lock, not implemented cmd = %d\n",
7819+ cmd);
7820+ DbgPrint
7821+ ("Novfs_f_lock: novfs in Novfs_f_lock, not implemented cmd = %d\n",
7822+ cmd);
7823+ break;
7824+ }
7825+ }
7826+
7827+ DbgPrint("Novfs_f_lock: lock->fl_type = %u, err_code 0x%X\n",
7828+ lock->fl_type, err_code);
7829+
7830+ if ((err_code != 0) && (err_code != -1)
7831+ && (err_code != -ENOSYS)) {
7832+ err_code = -EAGAIN;
7833+ }
7834+ } else {
7835+ err_code = -EINVAL;
7836+ }
7837+
7838+ return (err_code);
7839+}
7840+
7841+/*++======================================================================*/
7842+static void Novfs_copy_cache_pages(struct address_space *mapping,
7843+ struct list_head *pages, int bytes_read,
7844+ char *data, struct pagevec *plru_pvec)
7845+/*
7846+ * Arguments:
7847+ *
7848+ * Returns:
7849+ *
7850+ * Abstract:
7851+ *
7852+ * Notes:
7853+ *
7854+ * Environment:
7855+ *
7856+ *========================================================================*/
7857+{
7858+ struct page *page;
7859+ char *target;
7860+
7861+ while (bytes_read > 0) {
7862+ if (list_empty(pages))
7863+ break;
7864+
7865+ page = list_entry(pages->prev, struct page, lru);
7866+ list_del(&page->lru);
7867+
7868+ if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
7869+ page_cache_release(page);
7870+ data += PAGE_CACHE_SIZE;
7871+ bytes_read -= PAGE_CACHE_SIZE;
7872+ continue;
7873+ }
7874+
7875+ target = kmap_atomic(page, KM_USER0);
7876+
7877+ if (PAGE_CACHE_SIZE > bytes_read) {
7878+ memcpy(target, data, bytes_read);
7879+ /* zero the tail end of this partial page */
7880+ memset(target + bytes_read, 0,
7881+ PAGE_CACHE_SIZE - bytes_read);
7882+ bytes_read = 0;
7883+ } else {
7884+ memcpy(target, data, PAGE_CACHE_SIZE);
7885+ bytes_read -= PAGE_CACHE_SIZE;
7886+ }
7887+ kunmap_atomic(target, KM_USER0);
7888+
7889+ flush_dcache_page(page);
7890+ SetPageUptodate(page);
7891+ unlock_page(page);
7892+ if (!pagevec_add(plru_pvec, page))
7893+ __pagevec_lru_add(plru_pvec);
7894+ data += PAGE_CACHE_SIZE;
7895+ }
7896+ return;
7897+}
7898+
7899+/*++======================================================================*/
7900+int Novfs_a_writepage(struct page *page, struct writeback_control *wbc)
7901+/*
7902+ * Arguments:
7903+ *
7904+ * Returns:
7905+ *
7906+ * Abstract:
7907+ *
7908+ * Notes:
7909+ *
7910+ * Environment:
7911+ *
7912+ *========================================================================*/
7913+{
7914+ int retCode = -EFAULT;
7915+ struct inode *inode = page->mapping->host;
7916+ struct inode_data *id = inode->FSPRIVATE;
7917+ loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT);
7918+ session_t session;
7919+ struct data_list dlst[2];
7920+ size_t len = PAGE_CACHE_SIZE;
7921+
7922+ session = Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
7923+
7924+ page_cache_get(page);
7925+
7926+ pos = ((loff_t) page->index << PAGE_CACHE_SHIFT);
7927+
7928+ /*
7929+ * Leave first dlst entry for reply header.
7930+ */
7931+ dlst[1].page = page;
7932+ dlst[1].offset = NULL;
7933+ dlst[1].len = len;
7934+ dlst[1].rwflag = DLREAD;
7935+
7936+ /*
7937+ * Check size so we don't write pass end of file.
7938+ */
7939+ if ((pos + (loff_t) len) > i_size_read(inode)) {
7940+ len = (size_t) (i_size_read(inode) - pos);
7941+ }
7942+
7943+ retCode = Novfs_Write_Pages(id->FileHandle, dlst, 2, len, pos, session);
7944+ if (!retCode) {
7945+ SetPageUptodate(page);
7946+ }
7947+
7948+ unlock_page(page);
7949+ page_cache_release(page);
7950+
7951+ return (retCode);
7952+}
7953+
7954+/*++======================================================================*/
7955+int Novfs_a_writepages(struct address_space *mapping,
7956+ struct writeback_control *wbc)
7957+/*
7958+ * Arguments:
7959+ *
7960+ * Returns:
7961+ *
7962+ * Abstract:
7963+ *
7964+ * Notes:
7965+ *
7966+ * Environment:
7967+ *
7968+ *========================================================================*/
7969+{
7970+ int retCode = 0;
7971+ struct inode *inode = mapping->host;
7972+ session_t session;
7973+ HANDLE fh = 0;
7974+ struct inode_data *id = NULL;
7975+
7976+ int max_page_lookup = MaxIoSize / PAGE_CACHE_SIZE;
7977+
7978+ struct data_list *dlist;
7979+ struct data_list *dlptr;
7980+ struct page **pages;
7981+
7982+ int dlist_idx, i = 0;
7983+ pgoff_t index, next_index = 0;
7984+ loff_t pos = 0;
7985+ size_t tsize;
7986+
7987+ SC_INITIALIZE(session);
7988+ DbgPrint
7989+ ("Novfs_a_writepages: inode=0x%p mapping=0x%p wbc=0x%p nr_to_write=%d\n",
7990+ inode, mapping, wbc, wbc->nr_to_write);
7991+
7992+ if (inode) {
7993+ DbgPrint(" Inode=0x%p Ino=%d Id=0x%p\n", inode, inode->i_ino,
7994+ inode->FSPRIVATE);
7995+
7996+ if (NULL != (id = inode->FSPRIVATE)) {
7997+ session =
7998+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
7999+ fh = ((struct inode_data *)inode->FSPRIVATE)->FileHandle;
8000+ }
8001+ }
8002+
8003+ dlist = Novfs_Malloc(sizeof(struct data_list) * max_page_lookup, GFP_KERNEL);
8004+ pages =
8005+ Novfs_Malloc(sizeof(struct page *) * max_page_lookup, GFP_KERNEL);
8006+
8007+ if (id)
8008+ DbgPrint
8009+ ("Novfs_a_writepages: inode=0x%p fh=0x%p dlist=0x%p pages=0x%p %s\n",
8010+ inode, fh, dlist, pages, id->Name);
8011+ else
8012+ DbgPrint
8013+ ("Novfs_a_writepages: inode=0x%p fh=0x%p dlist=0x%p pages=0x%p\n",
8014+ inode, fh, dlist, pages);
8015+
8016+ if (dlist && pages) {
8017+ struct backing_dev_info *bdi = mapping->backing_dev_info;
8018+ int done = 0;
8019+ int nr_pages = 0;
8020+ int scanned = 0;
8021+
8022+ if (wbc->nonblocking && bdi_write_congested(bdi)) {
8023+ wbc->encountered_congestion = 1;
8024+ return 0;
8025+ }
8026+
8027+ if (wbc->sync_mode == WB_SYNC_NONE) {
8028+ index = mapping->writeback_index; /* Start from prev offset */
8029+ } else {
8030+ index = 0; /* whole-file sweep */
8031+ scanned = 1;
8032+ }
8033+
8034+ next_index = index;
8035+
8036+ while (!done && (wbc->nr_to_write > 0)) {
8037+ dlist_idx = 0;
8038+ dlptr = &dlist[1];
8039+
8040+ DbgPrint("Novfs_a_writepages1: nr_pages=%d\n",
8041+ nr_pages);
8042+ if (!nr_pages) {
8043+ memset(pages, 0,
8044+ sizeof(struct page *) * max_page_lookup);
8045+
8046+ AS_TREE_LOCK(&mapping->tree_lock);
8047+
8048+ /*
8049+ * Need to ask for one less then max_page_lookup or we
8050+ * will overflow the request buffer. This also frees
8051+ * the first entry for the reply buffer.
8052+ */
8053+ nr_pages =
8054+ radix_tree_gang_lookup_tag(&mapping->
8055+ page_tree,
8056+ (void **)pages,
8057+ index,
8058+ max_page_lookup -
8059+ 1,
8060+ PAGECACHE_TAG_DIRTY);
8061+
8062+ DbgPrint("Novfs_a_writepages2: nr_pages=%d\n",
8063+ nr_pages);
8064+ /*
8065+ * Check to see if there are dirty pages and there is a valid
8066+ * file handle.
8067+ */
8068+ if (nr_pages && !fh) {
8069+ set_bit(AS_EIO, &mapping->flags);
8070+ done = 1;
8071+ DbgPrint
8072+ ("Novfs_a_writepage: set_bit AS_EIO\n");
8073+ break;
8074+ }
8075+
8076+ for (i = 0; i < nr_pages; i++) {
8077+ page_cache_get(pages[i]);
8078+ }
8079+
8080+ AS_TREE_UNLOCK(&mapping->tree_lock);
8081+
8082+ if (nr_pages) {
8083+ index = pages[nr_pages - 1]->index + 1;
8084+ pos =
8085+ (loff_t) pages[0]->
8086+ index << PAGE_CACHE_SHIFT;
8087+ }
8088+
8089+ if (!nr_pages) {
8090+ if (scanned) {
8091+ index = 0;
8092+ scanned = 0;
8093+ continue;
8094+ }
8095+ done = 1;
8096+ } else {
8097+ next_index = pages[0]->index;
8098+ i = 0;
8099+ }
8100+ } else {
8101+ if (pages[i]) {
8102+ pos =
8103+ (loff_t) pages[i]->
8104+ index << PAGE_CACHE_SHIFT;
8105+ }
8106+ }
8107+
8108+ for (; i < nr_pages; i++) {
8109+ struct page *page = pages[i];
8110+
8111+ /*
8112+ * At this point we hold neither mapping->tree_lock nor
8113+ * lock on the page itself: the page may be truncated or
8114+ * invalidated (changing page->mapping to NULL), or even
8115+ * swizzled back from swapper_space to tmpfs file
8116+ * mapping
8117+ */
8118+
8119+ DbgPrint
8120+ ("Novfs_a_writepages: pos=0x%llx index=%d page->index=%d next_index=%d\n",
8121+ pos, index, page->index, next_index);
8122+
8123+ if (page->index != next_index) {
8124+ next_index = page->index;
8125+ break;
8126+ }
8127+ next_index = page->index + 1;
8128+
8129+ lock_page(page);
8130+
8131+ if (wbc->sync_mode != WB_SYNC_NONE)
8132+ wait_on_page_writeback(page);
8133+
8134+ if (page->mapping != mapping
8135+ || PageWriteback(page)
8136+ || !clear_page_dirty_for_io(page)) {
8137+ unlock_page(page);
8138+ continue;
8139+ }
8140+
8141+ dlptr[dlist_idx].page = page;
8142+ dlptr[dlist_idx].offset = NULL;
8143+ dlptr[dlist_idx].len = PAGE_CACHE_SIZE;
8144+ dlptr[dlist_idx].rwflag = DLREAD;
8145+ dlist_idx++;
8146+ DbgPrint
8147+ ("Novfs_a_writepages: Add page=0x%p index=0x%lx\n",
8148+ page, page->index);
8149+ }
8150+
8151+ DbgPrint("Novfs_a_writepages: dlist_idx=%d\n",
8152+ dlist_idx);
8153+ if (dlist_idx) {
8154+ tsize = dlist_idx * PAGE_CACHE_SIZE;
8155+ /*
8156+ * Check size so we don't write pass end of file.
8157+ */
8158+ if ((pos + tsize) > i_size_read(inode)) {
8159+ tsize =
8160+ (size_t) (i_size_read(inode) - pos);
8161+ }
8162+
8163+ retCode =
8164+ Novfs_Write_Pages(fh, dlist, dlist_idx + 1,
8165+ tsize, pos, session);
8166+ switch (retCode) {
8167+ case 0:
8168+ wbc->nr_to_write -= dlist_idx;
8169+ break;
8170+
8171+ case -ENOSPC:
8172+ set_bit(AS_ENOSPC, &mapping->flags);
8173+ done = 1;
8174+ break;
8175+
8176+ default:
8177+ set_bit(AS_EIO, &mapping->flags);
8178+ done = 1;
8179+ break;
8180+ }
8181+
8182+ do {
8183+ unlock_page((struct page *)
8184+ dlptr[dlist_idx - 1].page);
8185+ page_cache_release((struct page *)
8186+ dlptr[dlist_idx -
8187+ 1].page);
8188+ DbgPrint
8189+ ("Novfs_a_writepages: release page=0x%p index=0x%lx\n",
8190+ dlptr[dlist_idx - 1].page,
8191+ ((struct page *)
8192+ dlptr[dlist_idx -
8193+ 1].page)->index);
8194+ if (!retCode) {
8195+ wbc->nr_to_write--;
8196+ }
8197+ } while (--dlist_idx);
8198+ }
8199+
8200+ if (i >= nr_pages) {
8201+ nr_pages = 0;
8202+ }
8203+ }
8204+
8205+ mapping->writeback_index = index;
8206+
8207+ } else {
8208+ DbgPrint("Novfs_a_writepage: set_bit AS_EIO\n");
8209+ set_bit(AS_EIO, &mapping->flags);
8210+ }
8211+ if (dlist)
8212+ kfree(dlist);
8213+ if (pages)
8214+ kfree(pages);
8215+
8216+ DbgPrint("Novfs_a_writepage: retCode=%d\n", retCode);
8217+ return (0);
8218+
8219+}
8220+
8221+/*++======================================================================*/
8222+int Novfs_a_readpage(struct file *file, struct page *page)
8223+/*
8224+ * Arguments:
8225+ *
8226+ * Returns:
8227+ *
8228+ * Abstract:
8229+ *
8230+ * Notes:
8231+ *
8232+ * Environment:
8233+ *
8234+ *========================================================================*/
8235+{
8236+ int retCode = 0;
8237+ void *pbuf;
8238+ struct inode *inode = NULL;
8239+ struct dentry *dentry = NULL;
8240+ loff_t offset;
8241+ size_t len;
8242+ session_t session;
8243+
8244+ SC_INITIALIZE(session);
8245+ DbgPrint("Novfs_a_readpage: File=0x%p Name=%.*s Page=0x%p", file,
8246+ file->f_dentry->d_name.len, file->f_dentry->d_name.name, page);
8247+
8248+ dentry = file->f_dentry;
8249+
8250+ if (dentry) {
8251+ DbgPrint(" Dentry=0x%p Name=%.*s", dentry, dentry->d_name.len,
8252+ dentry->d_name.name);
8253+ if (dentry->d_inode) {
8254+ inode = dentry->d_inode;
8255+ }
8256+ }
8257+
8258+ if (inode) {
8259+ DbgPrint(" Inode=0x%p Ino=%d", inode, inode->i_ino);
8260+
8261+ if (inode->FSPRIVATE) {
8262+ session =
8263+ Scope_Get_SessionId(((struct inode_data *)inode->
8264+ FSPRIVATE)->Scope);
8265+ if (0 == SC_PRESENT(session)) {
8266+ ((struct inode_data *)inode->FSPRIVATE)->Scope =
8267+ Scope_Get_ScopefromPath(file->f_dentry);
8268+ session = Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
8269+ }
8270+ }
8271+ }
8272+
8273+ DbgPrint("\n");
8274+
8275+ if (!PageUptodate(page)) {
8276+ struct data_list dlst[2];
8277+
8278+ offset = page->index << PAGE_CACHE_SHIFT;
8279+ len = PAGE_CACHE_SIZE;
8280+
8281+ /*
8282+ * Save the first entry for the reply header.
8283+ */
8284+ dlst[1].page = page;
8285+ dlst[1].offset = NULL;
8286+ dlst[1].len = PAGE_CACHE_SIZE;
8287+ dlst[1].rwflag = DLWRITE;
8288+
8289+ DbgPrint("Novfs_a_readpage: calling= Novfs_Read_Pages %lld\n",
8290+ offset);
8291+ retCode =
8292+ Novfs_Read_Pages(file->private_data, dlst, 2, &len, &offset,
8293+ session);
8294+ if (len && (len < PAGE_CACHE_SIZE)) {
8295+ pbuf = kmap_atomic(page, KM_USER0);
8296+ memset(&((char *)pbuf)[len], 0, PAGE_CACHE_SIZE - len);
8297+ kunmap_atomic(pbuf, KM_USER0);
8298+ }
8299+
8300+ flush_dcache_page(page);
8301+ SetPageUptodate(page);
8302+ }
8303+ unlock_page(page);
8304+
8305+ DbgPrint("Novfs_a_readpage: retCode=%d\n", retCode);
8306+ return (retCode);
8307+
8308+}
8309+
8310+/*++======================================================================*/
8311+int Novfs_a_readpages(struct file *file, struct address_space *mapping,
8312+ struct list_head *page_lst, unsigned nr_pages)
8313+/*
8314+ * Arguments:
8315+ *
8316+ * Returns:
8317+ *
8318+ * Abstract:
8319+ *
8320+ * Notes:
8321+ *
8322+ * Environment:
8323+ *
8324+ *========================================================================*/
8325+{
8326+ int retCode = 0;
8327+ struct inode *inode = NULL;
8328+ struct dentry *dentry = NULL;
8329+ session_t session;
8330+ loff_t offset;
8331+ size_t len;
8332+
8333+ unsigned page_idx;
8334+ struct pagevec lru_pvec;
8335+ pgoff_t next_index;
8336+
8337+ char *rbuf, done = 0;
8338+ SC_INITIALIZE(session);
8339+
8340+ DbgPrint("Novfs_a_readpages: File=0x%p Name=%.*s Pages=%d\n", file,
8341+ file->f_dentry->d_name.len, file->f_dentry->d_name.name,
8342+ nr_pages);
8343+
8344+ dentry = file->f_dentry;
8345+
8346+ if (dentry) {
8347+ DbgPrint(" Dentry=0x%p Name=%.*s\n", dentry, dentry->d_name.len,
8348+ dentry->d_name.name);
8349+ if (dentry->d_inode) {
8350+ inode = dentry->d_inode;
8351+ }
8352+ }
8353+
8354+ if (inode) {
8355+ DbgPrint(" Inode=0x%p Ino=%d\n", inode, inode->i_ino);
8356+
8357+ if (inode->FSPRIVATE) {
8358+ session =
8359+ Scope_Get_SessionId(((struct inode_data *)inode->
8360+ FSPRIVATE)->Scope);
8361+ if (0 == SC_PRESENT(session)) {
8362+ ((struct inode_data *) inode->FSPRIVATE)->Scope =
8363+ Scope_Get_ScopefromPath(file->f_dentry);
8364+ session =
8365+ Scope_Get_SessionId(((struct inode_data *) inode->
8366+ FSPRIVATE)->Scope);
8367+ }
8368+ }
8369+ }
8370+
8371+ rbuf = (char *)Novfs_Malloc(MaxIoSize, GFP_KERNEL);
8372+ if (rbuf) {
8373+ pagevec_init(&lru_pvec, 0);
8374+ for (page_idx = 0; page_idx < nr_pages && !done;) {
8375+ struct page *page, *tpage;
8376+
8377+ if (list_empty(page_lst))
8378+ break;
8379+
8380+ page = list_entry(page_lst->prev, struct page, lru);
8381+
8382+ next_index = page->index;
8383+ offset = (loff_t) page->index << PAGE_CACHE_SHIFT;
8384+ len = 0;
8385+
8386+ /*
8387+ * Count number of contiguous pages.
8388+ */
8389+ list_for_each_entry_reverse(tpage, page_lst, lru) {
8390+ if ((next_index != tpage->index) ||
8391+ (len >= MaxIoSize - PAGE_SIZE)) {
8392+ break;
8393+ }
8394+ len += PAGE_SIZE;
8395+ next_index++;
8396+ }
8397+
8398+ if (len && !done) {
8399+ struct data_list dllst[2];
8400+
8401+ dllst[1].page = NULL;
8402+ dllst[1].offset = rbuf;
8403+ dllst[1].len = len;
8404+ dllst[1].rwflag = DLWRITE;
8405+
8406+ DbgPrint
8407+ ("Novfs_a_readpages: calling Novfs_Read_Pages %lld\n",
8408+ offset);
8409+ if (!Novfs_Read_Pages
8410+ (file->private_data, dllst, 2, &len,
8411+ &offset, session)) {
8412+ Novfs_copy_cache_pages(mapping,
8413+ page_lst, len,
8414+ rbuf, &lru_pvec);
8415+ page_idx += len >> PAGE_CACHE_SHIFT;
8416+ if ((int)(len & PAGE_CACHE_MASK) != len) {
8417+ page_idx++;
8418+ }
8419+ if (len == 0) {
8420+ done = 1;
8421+ }
8422+ } else {
8423+ done = 1;
8424+ }
8425+ }
8426+ }
8427+
8428+ /*
8429+ * Free any remaining pages.
8430+ */
8431+ while (!list_empty(page_lst)) {
8432+ struct page *page =
8433+ list_entry(page_lst->prev, struct page, lru);
8434+
8435+ list_del(&page->lru);
8436+ page_cache_release(page);
8437+ }
8438+
8439+ pagevec_lru_add(&lru_pvec);
8440+ kfree(rbuf);
8441+ } else {
8442+ retCode = -ENOMEM;
8443+ }
8444+
8445+ DbgPrint("Novfs_a_readpages: retCode=%d\n", retCode);
8446+ return (retCode);
8447+
8448+}
8449+
8450+/*++======================================================================*/
8451+int Novfs_a_prepare_write(struct file *file, struct page *page, unsigned from,
8452+ unsigned to)
8453+/*
8454+ * Arguments:
8455+ *
8456+ * Returns:
8457+ *
8458+ * Abstract:
8459+ *
8460+ * Notes:
8461+ *
8462+ * Environment:
8463+ *
8464+ *========================================================================*/
8465+{
8466+ int retVal = 0;
8467+ loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT;
8468+ size_t len = PAGE_CACHE_SIZE;
8469+ session_t session;
8470+ struct data_list dllst[2];
8471+ struct inode *inode = file->f_dentry->d_inode;
8472+ SC_INITIALIZE(session);
8473+
8474+ DbgPrint
8475+ ("Novfs_a_prepare_write: File=0x%p Page=0x%p offset=0x%llx From=%u To=%u filesize=%lld\n",
8476+ file, page, offset, from, to,
8477+ i_size_read(file->f_dentry->d_inode));
8478+ if (!PageUptodate(page)) {
8479+ /*
8480+ * Check to see if whole page
8481+ */
8482+ if ((to == PAGE_CACHE_SIZE) && (from == 0)) {
8483+ SetPageUptodate(page);
8484+ }
8485+
8486+ /*
8487+ * Check to see if we can read page.
8488+ */
8489+ else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
8490+ /*
8491+ * Get session.
8492+ */
8493+ if (file->f_dentry && file->f_dentry->d_inode) {
8494+ if (file->f_dentry->d_inode->FSPRIVATE) {
8495+ session =
8496+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
8497+ if (0 == SC_PRESENT(session)) {
8498+ ((struct inode_data *)inode->FSPRIVATE)->Scope = Scope_Get_ScopefromPath(file->f_dentry);
8499+ session = Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
8500+ }
8501+ }
8502+ }
8503+
8504+ page_cache_get(page);
8505+
8506+ len = i_size_read(inode) - offset;
8507+ if (len > PAGE_CACHE_SIZE) {
8508+ len = PAGE_CACHE_SIZE;
8509+ }
8510+
8511+ if (len) {
8512+ /*
8513+ * Read page from server.
8514+ */
8515+
8516+ dllst[1].page = page;
8517+ dllst[1].offset = 0;
8518+ dllst[1].len = len;
8519+ dllst[1].rwflag = DLWRITE;
8520+
8521+ DbgPrint
8522+ ("Novfs_a_prepare_write: calling Novfs_Read_Pages %lld\n",
8523+ offset);
8524+ Novfs_Read_Pages(file->private_data, dllst, 2,
8525+ &len, &offset, session);
8526+
8527+ /*
8528+ * Zero unnsed page.
8529+ */
8530+ }
8531+
8532+ if (len < PAGE_CACHE_SIZE) {
8533+ char *adr = kmap_atomic(page, KM_USER0);
8534+ memset(adr + len, 0, PAGE_CACHE_SIZE - len);
8535+ kunmap_atomic(adr, KM_USER0);
8536+ }
8537+ } else {
8538+ /*
8539+ * Zero section of memory that not going to be used.
8540+ */
8541+ char *adr = kmap_atomic(page, KM_USER0);
8542+ memset(adr, 0, from);
8543+ memset(adr + to, 0, PAGE_CACHE_SIZE - to);
8544+ kunmap_atomic(adr, KM_USER0);
8545+
8546+ DbgPrint("Novfs_a_prepare_write: memset 0x%p\n", adr);
8547+ }
8548+ flush_dcache_page(page);
8549+ SetPageUptodate(page);
8550+ }
8551+// DbgPrint("Novfs_a_prepare_write: return %d\n", retVal);
8552+ return (retVal);
8553+}
8554+
8555+/*++======================================================================*/
8556+int Novfs_a_commit_write(struct file *file, struct page *page, unsigned offset,
8557+ unsigned to)
8558+/*
8559+ * Arguments:
8560+ *
8561+ * Returns:
8562+ *
8563+ * Abstract:
8564+ *
8565+ * Notes:
8566+ *
8567+ * Environment:
8568+ *
8569+ *========================================================================*/
8570+{
8571+ int retCode = 0;
8572+ struct inode *inode = page->mapping->host;
8573+ loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to;
8574+ session_t session;
8575+ struct inode_data *id;
8576+ struct data_list dlst[1];
8577+ size_t len = to - offset;
8578+
8579+ SC_INITIALIZE(session);
8580+
8581+ DbgPrint
8582+ ("Novfs_a_commit_write: File=0x%p Page=0x%p offset=0x%x To=%u filesize=%lld\n",
8583+ file, page, offset, to, i_size_read(file->f_dentry->d_inode));
8584+ if (file->f_dentry->d_inode
8585+ && (id = file->f_dentry->d_inode->FSPRIVATE)) {
8586+ session = Scope_Get_SessionId(id->Scope);
8587+ if (0 == SC_PRESENT(session)) {
8588+ id->Scope = Scope_Get_ScopefromPath(file->f_dentry);
8589+ session = Scope_Get_SessionId(id->Scope);
8590+ }
8591+
8592+ /*
8593+ * Setup file handle
8594+ */
8595+ id->FileHandle = file->private_data;
8596+
8597+ if (pos > inode->i_size) {
8598+ i_size_write(inode, pos);
8599+ }
8600+
8601+ if (!PageUptodate(page)) {
8602+ pos =
8603+ ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset;
8604+
8605+ if (to < offset) {
8606+ return (retCode);
8607+ }
8608+ dlst[0].page = page;
8609+ dlst[0].offset = (void *)(unsigned long) offset;
8610+ dlst[0].len = len;
8611+ dlst[0].rwflag = DLREAD;
8612+
8613+ retCode =
8614+ Novfs_Write_Pages(id->FileHandle, dlst, 1, len, pos,
8615+ session);
8616+
8617+ } else {
8618+ set_page_dirty(page);
8619+ }
8620+ }
8621+
8622+ return (retCode);
8623+}
8624+
8625+/*++======================================================================*/
8626+ssize_t Novfs_a_direct_IO(int rw, struct kiocb * kiocb,
8627+ const struct iovec * iov,
8628+ loff_t offset, unsigned long nr_segs)
8629+/*
8630+ * Arguments:
8631+ *
8632+ * Returns:
8633+ *
8634+ * Abstract:
8635+ *
8636+ * Notes: This is a dummy function so that we can allow a file
8637+ * to get the direct IO flag set. Novfs_f_read and
8638+ * Novfs_f_write will do the work. Maybe not the best
8639+ * way to do but it was the easiest to implement.
8640+ *
8641+ * Environment:
8642+ *
8643+ *========================================================================*/
8644+{
8645+ return (-EIO);
8646+}
8647+
8648+/*++======================================================================*/
8649+int Novfs_i_create(struct inode *dir, struct dentry *dentry, int mode,
8650+ struct nameidata *nd)
8651+/*
8652+ * Arguments:
8653+ *
8654+ * Returns:
8655+ *
8656+ * Abstract:
8657+ *
8658+ * Notes:
8659+ *
8660+ * Environment:
8661+ *
8662+ *========================================================================*/
8663+{
8664+ char *path, *buf;
8665+ struct entry_info info;
8666+ HANDLE handle;
8667+ session_t session;
8668+ int retCode = -EACCES;
8669+
8670+ DbgPrint("Novfs_i_create: mode=0%o flags=0%o %.*s\n", mode,
8671+ nd->NDOPENFLAGS, dentry->d_name.len, dentry->d_name.name);
8672+
8673+ if (IS_ROOT(dentry) || /* Root */
8674+ IS_ROOT(dentry->d_parent) || /* User */
8675+ IS_ROOT(dentry->d_parent->d_parent) || /* Server */
8676+ IS_ROOT(dentry->d_parent->d_parent->d_parent)) { /* Volume */
8677+ return (-EACCES);
8678+ }
8679+
8680+ if (mode | S_IFREG) {
8681+ if (dir->FSPRIVATE) {
8682+ session =
8683+ Scope_Get_SessionId(((struct inode_data *)dir->FSPRIVATE)->
8684+ Scope);
8685+ if (0 == SC_PRESENT(session)) {
8686+ ((struct inode_data *) dir->FSPRIVATE)->Scope =
8687+ Scope_Get_ScopefromPath(dentry);
8688+ session = Scope_Get_SessionId(((struct inode_data *)dir->FSPRIVATE)->Scope);
8689+ }
8690+
8691+ buf =
8692+ (char *)Novfs_Malloc(PATH_LENGTH_BUFFER,
8693+ GFP_KERNEL);
8694+ if (buf) {
8695+ path =
8696+ Novfs_dget_path(dentry, buf,
8697+ PATH_LENGTH_BUFFER);
8698+ if (path) {
8699+ retCode =
8700+ Novfs_Open_File(path,
8701+ nd->
8702+ NDOPENFLAGS |
8703+ O_RDWR, &info,
8704+ &handle, session);
8705+ if (!retCode && handle) {
8706+ Novfs_Close_File(handle,
8707+ session);
8708+ if (!Novfs_i_mknod
8709+ (dir, dentry,
8710+ mode | S_IFREG, 0)) {
8711+ if (dentry->d_inode) {
8712+ ((struct inode_data *)dentry->d_inode->FSPRIVATE)->Flags |= UPDATE_INODE;
8713+ }
8714+ }
8715+ }
8716+ }
8717+ kfree(buf);
8718+ }
8719+ }
8720+ }
8721+ return (retCode);
8722+}
8723+
8724+/*++======================================================================*/
8725+void update_inode(struct inode *Inode, struct entry_info *Info)
8726+/*
8727+ * Arguments:
8728+ *
8729+ * Returns:
8730+ *
8731+ * Abstract:
8732+ *
8733+ * Notes:
8734+ *
8735+ * Environment:
8736+ *
8737+ *========================================================================*/
8738+{
8739+ static char dbuf[128];
8740+
8741+ DbgPrint("update_inode: Inode=0x%p I_ino=%d\n", Inode, Inode->i_ino);
8742+
8743+ DbgPrint("update_inode: atime=%s\n",
8744+ ctime_r(&Info->atime.tv_sec, dbuf));
8745+ DbgPrint("update_inode: ctime=%s\n",
8746+ ctime_r(&Info->ctime.tv_sec, dbuf));
8747+ DbgPrint("update_inode: mtime=%s %d\n",
8748+ ctime_r(&Info->mtime.tv_sec, dbuf), Info->mtime.tv_nsec);
8749+ DbgPrint("update_inode: size=%lld\n", Info->size);
8750+ DbgPrint("update_inode: mode=0%o\n", Info->mode);
8751+
8752+ if (Inode &&
8753+ ((Inode->i_size != Info->size) ||
8754+ (Inode->i_mtime.tv_sec != Info->mtime.tv_sec) ||
8755+ (Inode->i_mtime.tv_nsec != Info->mtime.tv_nsec))) {
8756+ DbgPrint
8757+ ("update_inode: calling invalidate_remote_inode sz %d %d\n",
8758+ Inode->i_size, Info->size);
8759+ DbgPrint
8760+ ("update_inode: calling invalidate_remote_inode sec %d %d\n",
8761+ Inode->i_mtime.tv_sec, Info->mtime.tv_sec);
8762+ DbgPrint
8763+ ("update_inode: calling invalidate_remote_inode ns %d %d\n",
8764+ Inode->i_mtime.tv_nsec, Info->mtime.tv_nsec);
8765+
8766+ if (Inode && Inode->i_mapping) {
8767+ invalidate_remote_inode(Inode);
8768+ }
8769+ }
8770+
8771+ Inode->i_mode = Info->mode;
8772+ Inode->i_size = Info->size;
8773+ Inode->i_atime = Info->atime;
8774+ Inode->i_ctime = Info->ctime;
8775+ Inode->i_mtime = Info->mtime;
8776+
8777+ if (Inode->i_size && Inode->i_sb->s_blocksize) {
8778+ Inode->i_blocks = (unsigned long) (Info->size >> (loff_t) Inode->i_blkbits);
8779+ Inode->i_bytes = Info->size & (Inode->i_sb->s_blocksize - 1);
8780+
8781+ DbgPrint("update_inode: i_sb->s_blocksize=%d\n", Inode->i_sb->s_blocksize);
8782+ DbgPrint("update_inode: i_blkbits=%d\n", Inode->i_blkbits);
8783+ DbgPrint("update_inode: i_blocks=%d\n", Inode->i_blocks);
8784+ DbgPrint("update_inode: i_bytes=%d\n", Inode->i_bytes);
8785+ }
8786+}
8787+
8788+/*++======================================================================*/
8789+struct dentry *Novfs_i_lookup(struct inode *dir, struct dentry *dentry,
8790+ struct nameidata *nd)
8791+/*
8792+ * Arguments:
8793+ *
8794+ * Returns:
8795+ *
8796+ * Abstract:
8797+ *
8798+ * Notes:
8799+ *
8800+ * Environment:
8801+ *
8802+ *========================================================================*/
8803+{
8804+ struct dentry *retVal = ERR_PTR(-ENOENT);
8805+ struct dentry *parent;
8806+ struct entry_info *info = NULL;
8807+ struct inode_data *id;
8808+ struct inode *inode = NULL;
8809+ uid_t uid = current->euid;
8810+ ino_t ino = 0;
8811+ struct qstr name;
8812+ char *buf;
8813+
8814+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
8815+ if (buf) {
8816+ char *path;
8817+ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
8818+ if (path) {
8819+ DbgPrint
8820+ ("Novfs_i_lookup: dir 0x%p %d hash %d inode 0x%0p %s\n",
8821+ dir, dir->i_ino, dentry->d_name.hash,
8822+ dentry->d_inode, path);
8823+ }
8824+ kfree(buf);
8825+ } else {
8826+ DbgPrint
8827+ ("Novfs_i_lookup: dir 0x%p %d name %.*s hash %d inode 0x%0p\n",
8828+ dir, dir->i_ino, dentry->d_name.len, dentry->d_name.name,
8829+ dentry->d_name.hash, dentry->d_inode);
8830+ }
8831+
8832+ if ((dentry->d_name.len == 7)
8833+ && (0 == strncmp(dentry->d_name.name, " !xover", 7))) {
8834+ dentry->d_op = &Novfs_dentry_operations;
8835+ igrab(dir);
8836+ d_add(dentry, dir);
8837+ return NULL;
8838+ }
8839+ if ((dentry->d_name.len == 7)
8840+ && (0 == strncmp(dentry->d_name.name, "z!xover", 7))) {
8841+ dentry->d_op = &Novfs_dentry_operations;
8842+ igrab(dir);
8843+ d_add(dentry, dir);
8844+ return NULL;
8845+ }
8846+
8847+ if (dir && (id = dir->FSPRIVATE)) {
8848+ retVal = 0;
8849+ if (IS_ROOT(dentry)) {
8850+ DbgPrint("Novfs_i_lookup: Root entry=0x%p\n",
8851+ Novfs_root);
8852+ inode = Novfs_root->d_inode;
8853+ return (0);
8854+ } else {
8855+ info =
8856+ Novfs_Malloc(sizeof(struct entry_info) +
8857+ PATH_LENGTH_BUFFER, GFP_KERNEL);
8858+ if (info) {
8859+ if (NULL ==
8860+ (retVal =
8861+ ERR_PTR(verify_dentry(dentry, 1)))) {
8862+ name.name = dentry->d_name.name;
8863+ name.len = dentry->d_name.len;
8864+ name.hash = Novfs_internal_hash(&name);
8865+
8866+ if (Novfs_lock_inode_cache(dir)) {
8867+ if (!Novfs_get_entry
8868+ (dir, &name, &ino, info)) {
8869+ inode =
8870+ ilookup(dentry->
8871+ d_sb, ino);
8872+ if (inode) {
8873+ update_inode
8874+ (inode,
8875+ info);
8876+ }
8877+ }
8878+ Novfs_unlock_inode_cache(dir);
8879+ }
8880+
8881+ if (!inode && ino) {
8882+ uid = Scope_Get_Uid(id->Scope);
8883+ if (Novfs_lock_inode_cache(dir)) {
8884+ inode = Novfs_get_inode (dentry->d_sb, info->mode, 0, uid, ino, &name);
8885+ if (inode) {
8886+ if (!Novfs_get_entry(dir, &dentry->d_name, &ino, info)) {
8887+ update_inode
8888+ (inode,
8889+ info);
8890+ }
8891+ }
8892+ Novfs_unlock_inode_cache
8893+ (dir);
8894+ }
8895+ }
8896+ }
8897+ }
8898+ }
8899+ }
8900+
8901+ if (!retVal) {
8902+ dentry->d_op = &Novfs_dentry_operations;
8903+ if (inode) {
8904+ parent = dget_parent(dentry);
8905+ Novfs_d_add(dentry->d_parent, dentry, inode, 1);
8906+ dput(parent);
8907+ } else {
8908+ d_add(dentry, inode);
8909+ }
8910+ }
8911+
8912+ if (info)
8913+ kfree(info);
8914+
8915+ DbgPrint
8916+ ("Novfs_i_lookup: inode=0x%p dentry->d_inode=0x%p return=0x%p\n",
8917+ dir, dentry->d_inode, retVal);
8918+
8919+ return (retVal);
8920+}
8921+
8922+/*++======================================================================*/
8923+int Novfs_i_unlink(struct inode *dir, struct dentry *dentry)
8924+/*
8925+ * Arguments:
8926+ *
8927+ * Returns:
8928+ *
8929+ * Abstract:
8930+ *
8931+ * Notes:
8932+ *
8933+ * Environment:
8934+ *
8935+ *========================================================================*/
8936+{
8937+ int retCode = -ENOENT;
8938+ struct inode *inode;
8939+ session_t session;
8940+ char *path, *buf;
8941+ uint64_t t64;
8942+
8943+ DbgPrint("Novfs_i_unlink: dir=0x%p dir->i_ino=%d %.*s\n", dir,
8944+ dir->i_ino, dentry->d_name.len, dentry->d_name.name);
8945+ DbgPrint("Novfs_i_unlink: IS_ROOT(dentry)=%d\n", IS_ROOT(dentry));
8946+ DbgPrint("Novfs_i_unlink: IS_ROOT(dentry->d_parent)=%d\n",
8947+ IS_ROOT(dentry->d_parent));
8948+ DbgPrint("Novfs_i_unlink: IS_ROOT(dentry->d_parent->d_parent)=%d\n",
8949+ IS_ROOT(dentry->d_parent->d_parent));
8950+ DbgPrint
8951+ ("Novfs_i_unlink: IS_ROOT(dentry->d_parent->d_parent->d_parent)=%d\n",
8952+ IS_ROOT(dentry->d_parent->d_parent->d_parent));
8953+
8954+ if (IS_ROOT(dentry) || /* Root */
8955+ IS_ROOT(dentry->d_parent) || /* User */
8956+ (!IS_ROOT(dentry->d_parent->d_parent) && /* Server */
8957+ IS_ROOT(dentry->d_parent->d_parent->d_parent))) { /* Volume */
8958+ return (-EACCES);
8959+ }
8960+
8961+ inode = dentry->d_inode;
8962+ if (inode) {
8963+ DbgPrint
8964+ ("Novfs_i_unlink: dir=0x%p dir->i_ino=%d inode=0x%p ino=%d\n",
8965+ dir, dir->i_ino, inode, inode->i_ino);
8966+ if (inode->FSPRIVATE) {
8967+ session =
8968+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
8969+ if (0 == SC_PRESENT(session)) {
8970+ ((struct inode_data *)inode->FSPRIVATE)->Scope = Scope_Get_ScopefromPath(dentry);
8971+ session = Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
8972+ }
8973+
8974+ buf =
8975+ (char *)Novfs_Malloc(PATH_LENGTH_BUFFER,
8976+ GFP_KERNEL);
8977+ if (buf) {
8978+ path =
8979+ Novfs_dget_path(dentry, buf,
8980+ PATH_LENGTH_BUFFER);
8981+ if (path) {
8982+ DbgPrint
8983+ ("Novfs_i_unlink: path %s mode 0%o\n",
8984+ path, inode->i_mode);
8985+ if (IS_ROOT(dentry->d_parent->d_parent)) {
8986+ retCode = do_logout(&dentry->d_name, &session);
8987+ } else {
8988+ retCode =
8989+ Novfs_Delete(path,
8990+ S_ISDIR(inode->
8991+ i_mode),
8992+ session);
8993+ }
8994+ if (!retCode || IS_DEADDIR(inode)) {
8995+ Novfs_remove_inode_entry(dir,
8996+ &dentry->
8997+ d_name,
8998+ 0);
8999+ dentry->d_time = 0;
9000+ t64 = 0;
9001+ Scope_Set_UserSpace(&t64, &t64,
9002+ &t64, &t64);
9003+ retCode = 0;
9004+ }
9005+ }
9006+ kfree(buf);
9007+ }
9008+ }
9009+ }
9010+
9011+ DbgPrint("Novfs_i_unlink: retCode 0x%x\n", retCode);
9012+ return (retCode);
9013+}
9014+
9015+/*++======================================================================*/
9016+int Novfs_i_mkdir(struct inode *dir, struct dentry *dentry, int mode)
9017+/*
9018+ * Arguments:
9019+ *
9020+ * Returns:
9021+ *
9022+ * Abstract:
9023+ *
9024+ * Notes:
9025+ *
9026+ * Environment:
9027+ *
9028+ *========================================================================*/
9029+{
9030+ char *path, *buf;
9031+ session_t session;
9032+ int retCode = 0;
9033+ struct inode *inode;
9034+ struct entry_info info;
9035+ uid_t uid;
9036+
9037+ DbgPrint("Novfs_i_mkdir: dir=0x%p ino=%d dentry=0x%p %.*s mode=0%lo\n",
9038+ dir, dir->i_ino, dentry, dentry->d_name.len,
9039+ dentry->d_name.name, mode);
9040+
9041+ if (IS_ROOT(dentry) || /* Root */
9042+ IS_ROOT(dentry->d_parent) || /* User */
9043+ IS_ROOT(dentry->d_parent->d_parent) || /* Server */
9044+ IS_ROOT(dentry->d_parent->d_parent->d_parent)) { /* Volume */
9045+ return (-EACCES);
9046+ }
9047+
9048+ mode |= S_IFDIR;
9049+ mode &= (S_IFMT | S_IRWXU);
9050+ if (dir->FSPRIVATE) {
9051+ session =
9052+ Scope_Get_SessionId(((struct inode_data *)dir->FSPRIVATE)->Scope);
9053+ if (0 == SC_PRESENT(session)) {
9054+ ((struct inode_data *)dir->FSPRIVATE)->Scope =
9055+ Scope_Get_ScopefromPath(dentry);
9056+ session =
9057+ Scope_Get_SessionId(((struct inode_data *)dir->FSPRIVATE)->Scope);
9058+ }
9059+
9060+ uid = Scope_Get_Uid(((struct inode_data *)dir->FSPRIVATE)->Scope);
9061+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
9062+ if (buf) {
9063+ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
9064+ if (path) {
9065+ DbgPrint("Novfs_i_mkdir: path %s\n", path);
9066+ retCode =
9067+ Novfs_Create(path, S_ISDIR(mode), session);
9068+ if (!retCode) {
9069+ retCode = Novfs_Get_File_Info(path, &info, &session);
9070+ if (!retCode) {
9071+ retCode = Novfs_i_mknod(dir, dentry, mode, 0);
9072+ inode = dentry->d_inode;
9073+ if (inode) {
9074+ update_inode(inode,
9075+ &info);
9076+ ((struct inode_data *)inode->FSPRIVATE)->Flags &= ~UPDATE_INODE;
9077+
9078+ dentry->d_time =
9079+ jiffies +
9080+ (File_update_timeout
9081+ * HZ);
9082+
9083+ Novfs_lock_inode_cache
9084+ (dir);
9085+ if (Novfs_update_entry
9086+ (dir,
9087+ &dentry->d_name, 0,
9088+ &info)) {
9089+ Novfs_add_inode_entry
9090+ (dir,
9091+ &dentry->
9092+ d_name,
9093+ inode->
9094+ i_ino,
9095+ &info);
9096+ }
9097+ Novfs_unlock_inode_cache
9098+ (dir);
9099+ }
9100+
9101+ }
9102+ }
9103+ }
9104+ kfree(buf);
9105+ }
9106+ }
9107+
9108+ return (retCode);
9109+}
9110+
9111+/*++======================================================================*/
9112+int Novfs_i_rmdir(struct inode *inode, struct dentry *dentry)
9113+/*
9114+ * Arguments:
9115+ *
9116+ * Returns:
9117+ *
9118+ * Abstract:
9119+ *
9120+ * Notes:
9121+ *
9122+ * Environment:
9123+ *
9124+ *========================================================================*/
9125+{
9126+ return (Novfs_i_unlink(inode, dentry));
9127+}
9128+
9129+/*++======================================================================*/
9130+int Novfs_i_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
9131+/*
9132+ * Arguments:
9133+ *
9134+ * Returns:
9135+ *
9136+ * Abstract:
9137+ *
9138+ * Notes:
9139+ *
9140+ * Environment:
9141+ *
9142+ *========================================================================*/
9143+{
9144+ struct inode *inode = NULL;
9145+ int retCode = -EACCES;
9146+ uid_t uid;
9147+ struct dentry *parent;
9148+
9149+ if (IS_ROOT(dentry) || /* Root */
9150+ IS_ROOT(dentry->d_parent) || /* User */
9151+ IS_ROOT(dentry->d_parent->d_parent) || /* Server */
9152+ IS_ROOT(dentry->d_parent->d_parent->d_parent)) { /* Volume */
9153+ return (-EACCES);
9154+ }
9155+
9156+ if (((struct inode_data *)dir->FSPRIVATE)) {
9157+ uid = Scope_Get_Uid(((struct inode_data *)dir->FSPRIVATE)->Scope);
9158+ if (mode & (S_IFREG | S_IFDIR)) {
9159+ inode =
9160+ Novfs_get_inode(dir->i_sb, mode, dev, uid, 0, &dentry->d_name);
9161+ }
9162+ }
9163+ if (inode) {
9164+ struct entry_info info;
9165+
9166+ dentry->d_op = &Novfs_dentry_operations;
9167+ parent = dget_parent(dentry);
9168+ Novfs_d_add(parent, dentry, inode, 0);
9169+ memset(&info, 0, sizeof(info));
9170+ info.mode = inode->i_mode;
9171+ Novfs_lock_inode_cache(dir);
9172+ Novfs_add_inode_entry(dir, &dentry->d_name, inode->i_ino,
9173+ &info);
9174+ Novfs_unlock_inode_cache(dir);
9175+
9176+ dput(parent);
9177+
9178+ retCode = 0;
9179+ }
9180+ DbgPrint("Novfs_i_mknod: return 0x%x\n", retCode);
9181+ return retCode;
9182+}
9183+
9184+int Novfs_i_rename(struct inode *odir, struct dentry *od, struct inode *ndir,
9185+ struct dentry *nd)
9186+{
9187+ int retCode = -ENOTEMPTY;
9188+ char *newpath, *newbuf, *newcon;
9189+ char *oldpath, *oldbuf, *oldcon;
9190+ struct qstr newname, oldname;
9191+ struct entry_info *info = NULL;
9192+ int oldlen, newlen;
9193+ session_t session;
9194+ ino_t ino;
9195+
9196+ if (IS_ROOT(od) || /* Root */
9197+ IS_ROOT(od->d_parent) || /* User */
9198+ IS_ROOT(od->d_parent->d_parent) || /* Server */
9199+ IS_ROOT(od->d_parent->d_parent->d_parent)) { /* Volume */
9200+ return (-EACCES);
9201+ }
9202+
9203+ DbgPrint("Novfs_i_rename: odir=0x%p ino=%d ndir=0x%p ino=%d\n", odir,
9204+ odir->i_ino, ndir, ndir->i_ino);
9205+
9206+ oldbuf = Novfs_Malloc(PATH_LENGTH_BUFFER * 2, GFP_KERNEL);
9207+ newbuf = oldbuf + PATH_LENGTH_BUFFER;
9208+ if (oldbuf && newbuf) {
9209+ oldpath = Novfs_dget_path(od, oldbuf, PATH_LENGTH_BUFFER);
9210+ newpath = Novfs_dget_path(nd, newbuf, PATH_LENGTH_BUFFER);
9211+ if (oldpath && newpath) {
9212+ oldlen = PATH_LENGTH_BUFFER - (int)(oldpath - oldbuf);
9213+ newlen = PATH_LENGTH_BUFFER - (int)(newpath - newbuf);
9214+
9215+ DbgPrint
9216+ ("Novfs_i_rename: od=0x%p od->inode=0x%p od->inode->i_ino=%d %s\n",
9217+ od, od->d_inode, od->d_inode->i_ino, oldpath);
9218+ if (nd->d_inode) {
9219+ DbgPrint
9220+ ("Novfs_i_rename: nd=0x%p nd->inode=0x%p nd->inode->i_ino=%d %s\n",
9221+ nd, nd->d_inode, nd->d_inode->i_ino,
9222+ newpath);
9223+ } else {
9224+ DbgPrint
9225+ ("Novfs_i_rename: nd=0x%p nd->inode=0x%p %s\n",
9226+ nd, nd->d_inode, newpath);
9227+ }
9228+
9229+ /*
9230+ * Check to see if two different servers or different volumes
9231+ */
9232+ newcon = strchr(newpath + 1, '\\');
9233+ oldcon = strchr(oldpath + 1, '\\');
9234+ DbgPrint("Novfs_i_rename: newcon=0x%p newpath=0x%p\n",
9235+ newcon, newpath);
9236+ DbgPrint("Novfs_i_rename: oldcon=0x%p oldpath=0x%p\n",
9237+ oldcon, oldpath);
9238+ retCode = -EXDEV;
9239+ if (newcon && oldcon
9240+ && ((int)(newcon - newpath) ==
9241+ (int)(oldcon - oldpath))) {
9242+ newcon = strchr(newcon + 1, '\\');
9243+ oldcon = strchr(oldcon + 1, '\\');
9244+ DbgPrint("Novfs_i_rename2: newcon=0x%p newpath=0x%p\n", newcon, newpath);
9245+ DbgPrint("Novfs_i_rename2: oldcon=0x%p oldpath=0x%p\n", oldcon, oldpath);
9246+ if (newcon && oldcon &&
9247+ ((int)(newcon - newpath) == (int)(oldcon - oldpath))) {
9248+ newname.name = newpath;
9249+ newname.len = (int)(newcon - newpath);
9250+ newname.hash = 0;
9251+
9252+ oldname.name = oldpath;
9253+ oldname.len = (int)(oldcon - oldpath);
9254+ oldname.hash = 0;
9255+ if (!Novfs_d_strcmp(&newname, &oldname)) {
9256+
9257+ if (od->d_inode
9258+ && od->d_inode->FSPRIVATE) {
9259+
9260+ if ((nd->d_inode) &&
9261+ (nd->d_inode->FSPRIVATE)) {
9262+ session = Scope_Get_SessionId(((struct inode_data *)ndir->FSPRIVATE)->Scope);
9263+ if (0 == SC_PRESENT(session)) {
9264+ ((struct inode_data *)ndir->FSPRIVATE)->Scope = Scope_Get_ScopefromPath(nd);
9265+ session = Scope_Get_SessionId(((struct inode_data *)ndir->FSPRIVATE)->Scope);
9266+ }
9267+
9268+ retCode = Novfs_Delete(newpath, S_ISDIR(nd->d_inode->i_mode), session);
9269+ }
9270+
9271+ session = Scope_Get_SessionId(((struct inode_data *) ndir->FSPRIVATE)->Scope);
9272+ if (0 == SC_PRESENT(session)) {
9273+ ((struct inode_data *)ndir->FSPRIVATE)->Scope = Scope_Get_ScopefromPath(nd);
9274+ session = Scope_Get_SessionId(((struct inode_data *) ndir->FSPRIVATE)->Scope);
9275+ }
9276+ retCode = Novfs_Rename_File(S_ISDIR(od->d_inode->i_mode), oldpath, oldlen - 1, newpath, newlen - 1, session);
9277+
9278+ if (!retCode) {
9279+ info = (struct entry_info *) oldbuf;
9280+ od->d_time = 0;
9281+ Novfs_remove_inode_entry(odir, &od->d_name, 0);
9282+ Novfs_remove_inode_entry(ndir, &nd->d_name, 0);
9283+ Novfs_Get_File_Info(newpath, info, &session);
9284+ nd->d_time = jiffies + (File_update_timeout * HZ);
9285+
9286+ if (od->d_inode && od->d_inode->i_ino) {
9287+ ino = od->d_inode-> i_ino;
9288+ } else {
9289+ ino = (ino_t)atomic_inc_return(&Novfs_Inode_Number);
9290+ }
9291+ Novfs_add_inode_entry(ndir, &nd->d_name, ino, info);
9292+ }
9293+ }
9294+ }
9295+ }
9296+ }
9297+ }
9298+ }
9299+
9300+ if (oldbuf)
9301+ kfree(oldbuf);
9302+
9303+ DbgPrint("Novfs_i_rename: return %d\n", retCode);
9304+ return (retCode);
9305+}
9306+
9307+/*++======================================================================*/
9308+int Novfs_i_permission(struct inode *inode, int mask)
9309+/*
9310+ * Arguments:
9311+ *
9312+ * Returns:
9313+ *
9314+ * Abstract:
9315+ *
9316+ * Notes:
9317+ *
9318+ * Environment:
9319+ *
9320+ *========================================================================*/
9321+{
9322+ int retCode = 0;
9323+
9324+ return (retCode);
9325+}
9326+
9327+/*++======================================================================*/
9328+int Novfs_i_setattr(struct dentry *dentry, struct iattr *attr)
9329+/*
9330+ * Arguments:
9331+ *
9332+ * Returns:
9333+ *
9334+ * Abstract:
9335+ *
9336+ * Notes:
9337+ *
9338+ * Environment:
9339+ *
9340+ *========================================================================*/
9341+{
9342+ char *path, *buf;
9343+ struct inode *inode = dentry->d_inode;
9344+ char atime_buf[32];
9345+ char mtime_buf[32];
9346+ char ctime_buf[32];
9347+ unsigned int ia_valid = attr->ia_valid;
9348+ session_t session;
9349+ int retVal = 0;
9350+ struct iattr mattr;
9351+
9352+ if (IS_ROOT(dentry) || /* Root */
9353+ IS_ROOT(dentry->d_parent) || /* User */
9354+ IS_ROOT(dentry->d_parent->d_parent) || /* Server */
9355+ IS_ROOT(dentry->d_parent->d_parent->d_parent)) { /* Volume */
9356+ return (-EACCES);
9357+ }
9358+
9359+ if (inode && inode->FSPRIVATE) {
9360+ session =
9361+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
9362+ if (0 == SC_PRESENT(session)) {
9363+ ((struct inode_data *)inode->FSPRIVATE)->Scope =
9364+ Scope_Get_ScopefromPath(dentry);
9365+ session =
9366+ Scope_Get_SessionId(((struct inode_data *) inode->
9367+ FSPRIVATE)->Scope);
9368+ }
9369+
9370+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
9371+ if (buf) {
9372+ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
9373+ if (path) {
9374+ strcpy(atime_buf, "Unspecified");
9375+ strcpy(mtime_buf, "Unspecified");
9376+ strcpy(ctime_buf, "Unspecified");
9377+ if (attr->ia_valid & ATTR_ATIME) {
9378+ ctime_r(&attr->ia_atime.tv_sec,
9379+ atime_buf);
9380+ }
9381+ if (attr->ia_valid & ATTR_MTIME) {
9382+ ctime_r(&attr->ia_mtime.tv_sec,
9383+ mtime_buf);
9384+ }
9385+ if (attr->ia_valid & ATTR_CTIME) {
9386+ ctime_r(&attr->ia_ctime.tv_sec,
9387+ ctime_buf);
9388+ }
9389+ /* Removed for Bug 132374. jlt */
9390+ DbgPrint("Novfs_i_setattr: %s\n"
9391+ " ia_valid: 0x%x\n"
9392+ " ia_mode: 0%o\n"
9393+ " ia_uid: %d\n"
9394+ " ia_gid: %d\n"
9395+ " ia_size: %lld\n"
9396+ " ia_atime: %s\n"
9397+ " ia_mtime: %s\n"
9398+ " ia_ctime: %s\n",
9399+ path,
9400+ attr->ia_valid,
9401+ attr->ia_mode,
9402+ attr->ia_uid,
9403+ attr->ia_gid,
9404+ attr->ia_size,
9405+ atime_buf, mtime_buf, ctime_buf);
9406+
9407+ if ((attr->ia_valid & ATTR_FILE)
9408+ && (attr->ia_valid & ATTR_SIZE)) {
9409+ memcpy(&mattr, attr, sizeof(mattr));
9410+ mattr.ia_valid &=
9411+ ~(ATTR_FILE | ATTR_SIZE);
9412+ attr = &mattr;
9413+ ia_valid = attr->ia_valid;
9414+#if 0 // thanks to vfs changes in our tree...
9415+ retVal = Novfs_Truncate_File_Ex(attr->ia_file->private_data, attr->ia_size, session);
9416+ if (!retVal) {
9417+ inode->i_size = attr->ia_size;
9418+ ((struct inode_data *)inode->FSPRIVATE)->Flags |= UPDATE_INODE;
9419+ }
9420+#endif
9421+ }
9422+
9423+ if (ia_valid
9424+ && !(retVal =
9425+ Novfs_Set_Attr(path, attr, session))) {
9426+ ((struct inode_data *)inode->FSPRIVATE)->Flags |= UPDATE_INODE;
9427+
9428+ if (ia_valid & ATTR_ATIME)
9429+ inode->i_atime = attr->ia_atime;
9430+ if (ia_valid & ATTR_MTIME)
9431+ inode->i_mtime = attr->ia_mtime;
9432+ if (ia_valid & ATTR_CTIME)
9433+ inode->i_ctime = attr->ia_ctime;
9434+ if (ia_valid & ATTR_MODE) {
9435+ inode->i_mode =
9436+ attr->
9437+ ia_mode & (S_IFMT |
9438+ S_IRWXU);
9439+ }
9440+ }
9441+ }
9442+ }
9443+ kfree(buf);
9444+ }
9445+ DbgPrint("Novfs_i_setattr: return 0x%x\n", retVal);
9446+
9447+ return (retVal);
9448+}
9449+
9450+/*++======================================================================*/
9451+int Novfs_i_getattr(struct vfsmount *mnt, struct dentry *dentry,
9452+ struct kstat *kstat)
9453+/*
9454+ * Arguments:
9455+ *
9456+ * Returns:
9457+ *
9458+ * Abstract:
9459+ *
9460+ * Notes:
9461+ *
9462+ * Environment:
9463+ *
9464+ *========================================================================*/
9465+{
9466+ int retCode = 0;
9467+ char atime_buf[32];
9468+ char mtime_buf[32];
9469+ char ctime_buf[32];
9470+ struct inode *inode = dentry->d_inode;
9471+
9472+ struct entry_info info;
9473+ char *path, *buf;
9474+ session_t session;
9475+ struct inode_data *id;
9476+
9477+ if (!IS_ROOT(dentry) && !IS_ROOT(dentry->d_parent)) {
9478+ SC_INITIALIZE(session);
9479+ id = dentry->d_inode->FSPRIVATE;
9480+
9481+ if (id && (id->Flags & UPDATE_INODE)) {
9482+ session = Scope_Get_SessionId(id->Scope);
9483+
9484+ if (0 == SC_PRESENT(session)) {
9485+ id->Scope = Scope_Get_ScopefromPath(dentry);
9486+ session = Scope_Get_SessionId(id->Scope);
9487+ }
9488+
9489+ buf =
9490+ (char *)Novfs_Malloc(PATH_LENGTH_BUFFER,
9491+ GFP_KERNEL);
9492+ if (buf) {
9493+ path =
9494+ Novfs_dget_path(dentry, buf,
9495+ PATH_LENGTH_BUFFER);
9496+ if (path) {
9497+ retCode = Novfs_Get_File_Info(path, &info, &session);
9498+ if (!retCode) {
9499+ update_inode(inode, &info);
9500+ id->Flags &= ~UPDATE_INODE;
9501+ }
9502+ }
9503+ kfree(buf);
9504+ }
9505+ }
9506+ }
9507+
9508+ kstat->ino = inode->i_ino;
9509+ kstat->dev = inode->i_sb->s_dev;
9510+ kstat->mode = inode->i_mode;
9511+ kstat->nlink = inode->i_nlink;
9512+ kstat->uid = inode->i_uid;
9513+ kstat->gid = inode->i_gid;
9514+ kstat->rdev = inode->i_rdev;
9515+ kstat->size = i_size_read(inode);
9516+ kstat->atime = inode->i_atime;
9517+ kstat->mtime = inode->i_mtime;
9518+ kstat->ctime = inode->i_ctime;
9519+ kstat->blksize = inode->i_sb->s_blocksize;
9520+ kstat->blocks = inode->i_blocks;
9521+ if (inode->i_bytes) {
9522+ kstat->blocks++;
9523+ }
9524+ ctime_r(&kstat->atime.tv_sec, atime_buf);
9525+ ctime_r(&kstat->mtime.tv_sec, mtime_buf);
9526+ ctime_r(&kstat->ctime.tv_sec, ctime_buf);
9527+
9528+ DbgPrint("Novfs_i_getattr: 0x%x 0x%p <%.*s>\n"
9529+ " ino: %d\n"
9530+ " dev: 0x%x\n"
9531+ " mode: 0%o\n"
9532+ " nlink: 0x%x\n"
9533+ " uid: 0x%x\n"
9534+ " gid: 0x%x\n"
9535+ " rdev: 0x%x\n"
9536+ " size: 0x%llx\n"
9537+ " atime: %s\n"
9538+ " mtime: %s\n"
9539+ " ctime: %s\n"
9540+ " blksize: 0x%x\n"
9541+ " blocks: 0x%x\n",
9542+ retCode, dentry, dentry->d_name.len, dentry->d_name.name,
9543+ kstat->ino,
9544+ kstat->dev,
9545+ kstat->mode,
9546+ kstat->nlink,
9547+ kstat->uid,
9548+ kstat->gid,
9549+ kstat->rdev,
9550+ kstat->size,
9551+ atime_buf,
9552+ mtime_buf, ctime_buf, kstat->blksize, kstat->blocks);
9553+ return (retCode);
9554+}
9555+
9556+/*++======================================================================*/
9557+int Novfs_i_getxattr(struct dentry *dentry, const char *name, void *buffer,
9558+ size_t buffer_size)
9559+/*
9560+ * Arguments:
9561+ *
9562+ * Returns:
9563+ *
9564+ * Abstract:
9565+ *
9566+ * Notes:
9567+ *
9568+ * Environment:
9569+ *
9570+ *========================================================================*/
9571+{
9572+ struct inode *inode = dentry->d_inode;
9573+ session_t sessionId;
9574+ char *path, *buf, *bufRead;
9575+ ssize_t dataLen;
9576+
9577+ int retxcode = 0;
9578+
9579+ SC_INITIALIZE(sessionId);
9580+
9581+ DbgPrint("Novfs_i_getxattr: Ian\n"); /*%.*s\n", dentry->d_name.len, dentry->d_name.name); */
9582+ DbgPrint
9583+ ("Novfs_i_getxattr: dentry->d_name.len %u, dentry->d_name.name %s\n",
9584+ dentry->d_name.len, dentry->d_name.name);
9585+ DbgPrint("Novfs_i_getxattr: name %s\n", name);
9586+ DbgPrint("Novfs_i_getxattr: size %u\n", buffer_size);
9587+
9588+ if (inode && inode->FSPRIVATE) {
9589+ sessionId =
9590+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
9591+ DbgPrint("Novfs_i_getxattr: SessionId = %u\n", sessionId);
9592+ //if (0 == sessionId)
9593+ if (0 == SC_PRESENT(sessionId)) {
9594+ ((struct inode_data *) inode->FSPRIVATE)->Scope = Scope_Get_ScopefromPath(dentry);
9595+ sessionId = Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
9596+ DbgPrint("Novfs_i_getxattr: SessionId = %u\n",
9597+ sessionId);
9598+ }
9599+ }
9600+
9601+ dataLen = 0;
9602+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
9603+ if (buf) {
9604+ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
9605+ if (path) {
9606+ bufRead = (char *)Novfs_Malloc(XA_BUFFER, GFP_KERNEL);
9607+ if (bufRead) {
9608+ retxcode = Novfs_GetX_File_Info(path, name, bufRead, XA_BUFFER, &dataLen, &sessionId);
9609+ DbgPrint("Novfs_i_getxattr: after Novfs_GetX_File_Info retxcode = %d\n", retxcode);
9610+ if (!retxcode) {
9611+ mydump(64, bufRead);
9612+ if (buffer_size != 0) {
9613+ if (buffer_size >= dataLen) {
9614+ memcpy(buffer, bufRead,
9615+ dataLen);
9616+ } else {
9617+ DbgPrint
9618+ ("Novfs_i_getxattr: (!!!) not enough buffer_size. buffer_size = %d, dataLen = %d\n",
9619+ buffer_size,
9620+ dataLen);
9621+ retxcode = -ERANGE;
9622+ }
9623+ }
9624+
9625+ if (bufRead) {
9626+ kfree(bufRead);
9627+ }
9628+ }
9629+ }
9630+ }
9631+ kfree(buf);
9632+ }
9633+
9634+ if (retxcode) {
9635+ dataLen = retxcode;
9636+ } else {
9637+ if ((buffer_size > 0) && (buffer_size < dataLen)) {
9638+ dataLen = -ERANGE;
9639+ }
9640+ }
9641+
9642+ return (dataLen);
9643+}
9644+
9645+/*++======================================================================*/
9646+int Novfs_i_setxattr(struct dentry *dentry, const char *name, const void *value,
9647+ size_t value_size, int flags)
9648+/*
9649+ * Arguments:
9650+ *
9651+ * Returns:
9652+ *
9653+ * Abstract:
9654+ *
9655+ * Notes:
9656+ *
9657+ * Environment:
9658+ *
9659+ *========================================================================*/
9660+{
9661+
9662+ struct inode *inode = dentry->d_inode;
9663+ session_t sessionId;
9664+ char *path, *buf;
9665+ unsigned long bytesWritten = 0;
9666+ int retError = 0;
9667+ int retxcode = 0;
9668+
9669+ SC_INITIALIZE(sessionId);
9670+
9671+ DbgPrint("Novfs_i_setxattr: Ian\n"); /*%.*s\n", dentry->d_name.len, dentry->d_name.name); */
9672+ DbgPrint
9673+ ("Novfs_i_setxattr: dentry->d_name.len %u, dentry->d_name.name %s\n",
9674+ dentry->d_name.len, dentry->d_name.name);
9675+ DbgPrint("Novfs_i_setxattr: name %s\n", name);
9676+ DbgPrint("Novfs_i_setxattr: value_size %u\n", value_size);
9677+ DbgPrint("Novfs_i_setxattr: flags %d\n", flags);
9678+
9679+ if (inode && inode->FSPRIVATE) {
9680+ sessionId =
9681+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->
9682+ Scope);
9683+ DbgPrint("Novfs_i_setxattr: SessionId = %u\n", sessionId);
9684+ //if (0 == sessionId)
9685+ if (0 == SC_PRESENT(sessionId)) {
9686+ ((struct inode_data *)inode->FSPRIVATE)->Scope =
9687+ Scope_Get_ScopefromPath(dentry);
9688+ sessionId =
9689+ Scope_Get_SessionId(((struct inode_data *)inode->
9690+ FSPRIVATE)->Scope);
9691+ DbgPrint("Novfs_i_setxattr: SessionId = %u\n",
9692+ sessionId);
9693+ }
9694+ }
9695+
9696+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
9697+ if (buf) {
9698+ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
9699+ if (path) {
9700+ retxcode =
9701+ Novfs_SetX_File_Info(path, name, value, value_size,
9702+ &bytesWritten, flags,
9703+ &sessionId);
9704+ if (!retxcode) {
9705+ DbgPrint
9706+ ("Novfs_i_setxattr: bytesWritten = %u\n",
9707+ bytesWritten);
9708+ }
9709+ }
9710+ kfree(buf);
9711+ }
9712+
9713+ if (retxcode) {
9714+ retError = retxcode;
9715+ }
9716+
9717+ if (bytesWritten < value_size) {
9718+ retError = retxcode;
9719+ }
9720+ return (retError);
9721+}
9722+
9723+int Novfs_i_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
9724+{
9725+ struct inode *inode = dentry->d_inode;
9726+ session_t sessionId;
9727+ char *path, *buf, *bufList;
9728+ ssize_t dataLen;
9729+
9730+ int retxcode = 0;
9731+
9732+ SC_INITIALIZE(sessionId);
9733+
9734+ DbgPrint("Novfs_i_listxattr: Ian\n"); //%.*s\n", dentry->d_name.len, dentry->d_name.name);
9735+ DbgPrint
9736+ ("Novfs_i_listxattr: dentry->d_name.len %u, dentry->d_name.name %s\n",
9737+ dentry->d_name.len, dentry->d_name.name);
9738+ DbgPrint("Novfs_i_listxattr: size %u\n", buffer_size);
9739+
9740+ if (inode && inode->FSPRIVATE) {
9741+ sessionId =
9742+ Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)-> Scope);
9743+ DbgPrint("Novfs_i_listxattr: SessionId = %u\n", sessionId);
9744+ //if (0 == sessionId)
9745+ if (0 == SC_PRESENT(sessionId)) {
9746+ ((struct inode_data *)inode->FSPRIVATE)->Scope = Scope_Get_ScopefromPath(dentry);
9747+ sessionId = Scope_Get_SessionId(((struct inode_data *)inode->FSPRIVATE)->Scope);
9748+ DbgPrint("Novfs_i_listxattr: SessionId = %u\n",
9749+ sessionId);
9750+ }
9751+ }
9752+
9753+ dataLen = 0;
9754+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
9755+ if (buf) {
9756+ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
9757+ if (path) {
9758+ bufList = (char *)Novfs_Malloc(XA_BUFFER, GFP_KERNEL);
9759+ if (bufList) {
9760+ retxcode = Novfs_ListX_File_Info(path, bufList, XA_BUFFER, &dataLen, &sessionId);
9761+
9762+ mydump(64, bufList);
9763+ if (buffer_size != 0) {
9764+ if (buffer_size >= dataLen) {
9765+ memcpy(buffer, bufList,
9766+ dataLen);
9767+ } else {
9768+ DbgPrint
9769+ ("Novfs_i_listxattr: (!!!) not enough buffer_size. buffer_size = %d, dataLen = %d\n",
9770+ buffer_size, dataLen);
9771+ retxcode = -1;
9772+ }
9773+ }
9774+
9775+ if (bufList) {
9776+ kfree(bufList);
9777+ }
9778+ }
9779+
9780+ }
9781+ kfree(buf);
9782+ }
9783+
9784+ if (retxcode) {
9785+ dataLen = -1;
9786+ } else {
9787+
9788+ if ((buffer_size > 0) && (buffer_size < dataLen)) {
9789+ dataLen = -ERANGE;
9790+ }
9791+ }
9792+ return (dataLen);
9793+}
9794+
9795+int Novfs_i_revalidate(struct dentry *dentry)
9796+{
9797+
9798+ DbgPrint("Novfs_i_revalidate: name %.*s\n", dentry->d_name.len,
9799+ dentry->d_name.name);
9800+
9801+ return (0);
9802+}
9803+
9804+void Novfs_read_inode(struct inode *inode)
9805+{
9806+ DbgPrint("Novfs_read_inode: 0x%p %d\n", inode, inode->i_ino);
9807+}
9808+
9809+void Novfs_write_inode(struct inode *inode)
9810+{
9811+ DbgPrint("Novfs_write_inode: Inode=0x%p Ino=%d\n", inode, inode->i_ino);
9812+}
9813+
9814+int Novfs_notify_change(struct dentry *dentry, struct iattr *attr)
9815+{
9816+ struct inode *inode = dentry->d_inode;
9817+
9818+ DbgPrint
9819+ ("Novfs_notify_change: Dentry=0x%p Name=%.*s Inode=0x%p Ino=%d ia_valid=0x%x\n",
9820+ dentry, dentry->d_name.len, dentry->d_name.name, inode,
9821+ inode->i_ino, attr->ia_valid);
9822+ return (0);
9823+}
9824+
9825+/*++======================================================================*/
9826+void Novfs_clear_inode(struct inode *inode)
9827+/*
9828+ * Arguments: sb - pointer to the super_block
9829+ * buf - pointer to the statfs buffer
9830+ *
9831+ * Returns: 0
9832+ *
9833+ * Abstract: Called when statfs(2) system called.
9834+ *
9835+ * Notes:
9836+ *
9837+ * Environment: Superblock operation
9838+ *
9839+ *========================================================================*/
9840+{
9841+ InodeCount--;
9842+
9843+ if (inode->FSPRIVATE) {
9844+ struct inode_data *id = inode->FSPRIVATE;
9845+
9846+ DbgPrint
9847+ ("Novfs_clear_inode: inode=0x%p ino=%d Scope=0x%p Name=%s\n",
9848+ inode, inode->i_ino, id->Scope, id->Name);
9849+
9850+ Novfs_free_inode_cache(inode);
9851+
9852+ down(&InodeList_lock);
9853+ list_del(&id->IList);
9854+ up(&InodeList_lock);
9855+
9856+ kfree(inode->FSPRIVATE);
9857+ inode->FSPRIVATE = NULL;
9858+
9859+ remove_inode_hash(inode);
9860+
9861+ } else {
9862+ DbgPrint("Novfs_clear_inode: inode=0x%p ino=%d\n", inode,
9863+ inode->i_ino);
9864+ }
9865+}
9866+
9867+/*++======================================================================*/
9868+int Novfs_show_options(struct seq_file *s, struct vfsmount *m)
9869+/*
9870+ * Arguments:
9871+ *
9872+ * Returns: 0
9873+ *
9874+ * Abstract: Called when /proc/mounts is read
9875+ *
9876+ * Notes:
9877+ *
9878+ * Environment:
9879+ *
9880+ *========================================================================*/
9881+{
9882+ char *buf, *path, *tmp;
9883+
9884+ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
9885+ if (buf) {
9886+ struct path my_path;
9887+ my_path.mnt = m;
9888+ my_path.dentry = m->mnt_root;
9889+ path = d_path(&my_path, buf, PATH_LENGTH_BUFFER);
9890+ if (path) {
9891+ if (!Novfs_CurrentMount
9892+ || (Novfs_CurrentMount
9893+ && strcmp(Novfs_CurrentMount, path))) {
9894+ DbgPrint("Novfs_show_options: %.*s %.*s %s\n",
9895+ m->mnt_root->d_name.len,
9896+ m->mnt_root->d_name.name,
9897+ m->mnt_mountpoint->d_name.len,
9898+ m->mnt_mountpoint->d_name.name, path);
9899+ tmp =
9900+ (char *)Novfs_Malloc(PATH_LENGTH_BUFFER -
9901+ (int)(path - buf),
9902+ GFP_KERNEL);
9903+ if (tmp) {
9904+ strcpy(tmp, path);
9905+ path = Novfs_CurrentMount;
9906+ Novfs_CurrentMount = tmp;
9907+ Daemon_SetMountPoint
9908+ (Novfs_CurrentMount);
9909+
9910+ if (path) {
9911+ kfree(path);
9912+ }
9913+ }
9914+ }
9915+ }
9916+ kfree(buf);
9917+ }
9918+ return (0);
9919+}
9920+
9921+/*++======================================================================*/
9922+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
9923+int Novfs_statfs(struct dentry *de, struct kstatfs *buf)
9924+#else
9925+int Novfs_statfs(struct super_block *sb, struct kstatfs *buf)
9926+#endif
9927+/*
9928+ * Arguments: sb - pointer to the super_block
9929+ * buf - pointer to the statfs buffer
9930+ *
9931+ * Returns: 0
9932+ *
9933+ * Abstract: Called when statfs(2) system called.
9934+ *
9935+ * Notes:
9936+ *
9937+ * Environment: Superblock operation
9938+ *
9939+ *========================================================================*/
9940+{
9941+ uint64_t td, fd, te, fe;
9942+
9943+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
9944+ struct super_block *sb = de->d_sb;
9945+#endif
9946+
9947+ DbgPrint("Novfs_statfs:\n");
9948+
9949+ td = fd = te = fe = 0;
9950+
9951+ Scope_Get_UserSpace(&td, &fd, &te, &fe);
9952+
9953+ DbgPrint("td=%llu\n", td);
9954+ DbgPrint("fd=%llu\n", fd);
9955+ DbgPrint("te=%llu\n", te);
9956+ DbgPrint("fe=%llu\n", fd);
9957+
9958+ buf->f_type = sb->s_magic;
9959+ buf->f_bsize = sb->s_blocksize;
9960+ buf->f_namelen = NW_MAX_PATH_LENGTH;
9961+ buf->f_blocks =
9962+ (sector_t) (td +
9963+ (uint64_t) (sb->s_blocksize -
9964+ 1)) >> (uint64_t) sb->s_blocksize_bits;
9965+ buf->f_bfree = (sector_t) fd >> (uint64_t) sb->s_blocksize_bits;
9966+ buf->f_bavail = (sector_t) buf->f_bfree;
9967+ buf->f_files = (sector_t) te;
9968+ buf->f_ffree = (sector_t) fe;
9969+ buf->f_frsize = sb->s_blocksize;
9970+ if (te > 0xffffffff)
9971+ buf->f_files = 0xffffffff;
9972+
9973+ if (fe > 0xffffffff)
9974+ buf->f_ffree = 0xffffffff;
9975+
9976+ DbgPrint("f_type: 0x%x\n", buf->f_type);
9977+ DbgPrint("f_bsize: %u\n", buf->f_bsize);
9978+ DbgPrint("f_namelen: %d\n", buf->f_namelen);
9979+ DbgPrint("f_blocks: %llu\n", buf->f_blocks);
9980+ DbgPrint("f_bfree: %llu\n", buf->f_bfree);
9981+ DbgPrint("f_bavail: %llu\n", buf->f_bavail);
9982+ DbgPrint("f_files: %llu\n", buf->f_files);
9983+ DbgPrint("f_ffree: %llu\n", buf->f_ffree);
9984+ DbgPrint("f_frsize: %u\n", buf->f_frsize);
9985+
9986+ return 0;
9987+}
9988+
9989+struct inode *Novfs_get_inode(struct super_block *sb, int mode, int dev,
9990+ uid_t Uid, ino_t ino, struct qstr *name)
9991+{
9992+ struct inode *inode = new_inode(sb);
9993+
9994+ if (inode) {
9995+ InodeCount++;
9996+ inode->i_mode = mode;
9997+ inode->i_uid = Uid;
9998+ inode->i_gid = 0;
9999+ /* bug # 340510 tells us to comment this out... */
10000+//#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
10001+// inode->i_blksize = sb->s_blocksize;
10002+//#else
10003+// inode->i_sb->s_blocksize = sb->s_blocksize;
10004+//#endif
10005+ inode->i_blkbits = sb->s_blocksize_bits;
10006+ inode->i_blocks = 0;
10007+ inode->i_rdev = 0;
10008+ inode->i_ino = (ino) ? ino : (ino_t)atomic_inc_return(&Novfs_Inode_Number);
10009+ if (PageCache) {
10010+ inode->i_mapping->a_ops = &Novfs_aops;
10011+ } else {
10012+ inode->i_mapping->a_ops = &Novfs_nocache_aops;
10013+ }
10014+ inode->i_mapping->backing_dev_info = &Novfs_backing_dev_info;
10015+ inode->i_atime.tv_sec = 0;
10016+ inode->i_atime.tv_nsec = 0;
10017+ inode->i_mtime = inode->i_ctime = inode->i_atime;
10018+
10019+ DbgPrint("Novfs_get_inode: Inode=0x%p I_ino=%d len=%d\n", inode,
10020+ inode->i_ino, name->len);
10021+
10022+ if (NULL !=
10023+ (inode->FSPRIVATE =
10024+ Novfs_Malloc(sizeof(struct inode_data) + name->len,
10025+ GFP_KERNEL))) {
10026+ struct inode_data *id;
10027+ id = inode->FSPRIVATE;
10028+
10029+ DbgPrint("Novfs_get_inode: FSPRIVATE 0x%p\n", id);
10030+
10031+ id->Scope = NULL;
10032+ id->Flags = 0;
10033+ id->Inode = inode;
10034+
10035+ id->cntDC = 1;
10036+
10037+ INIT_LIST_HEAD(&id->DirCache);
10038+ init_MUTEX(&id->DirCacheLock);
10039+
10040+ id->FileHandle = 0;
10041+ id->CacheFlag = 0;
10042+
10043+ down(&InodeList_lock);
10044+
10045+ list_add_tail(&id->IList, &InodeList);
10046+ up(&InodeList_lock);
10047+
10048+ id->Name[0] = '\0';
10049+
10050+ memcpy(id->Name, name->name, name->len);
10051+ id->Name[name->len] = '\0';
10052+
10053+ DbgPrint("Novfs_get_inode: name %s\n", id->Name);
10054+ }
10055+
10056+ insert_inode_hash(inode);
10057+
10058+ switch (mode & S_IFMT) {
10059+
10060+ case S_IFREG:
10061+ inode->i_op = &Novfs_file_inode_operations;
10062+ inode->i_fop = &Novfs_file_operations;
10063+ break;
10064+
10065+ case S_IFDIR:
10066+ inode->i_op = &Novfs_inode_operations;
10067+ inode->i_fop = &Novfs_dir_operations;
10068+// Again bug #340510
10069+//#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
10070+// inode->i_blksize = 0;
10071+//#else
10072+// inode->i_sb->s_blocksize = 0;
10073+//#endif
10074+ inode->i_blkbits = 0;
10075+ break;
10076+
10077+ default:
10078+ init_special_inode(inode, mode, dev);
10079+ break;
10080+ }
10081+
10082+ DbgPrint("Novfs_get_inode: size=%lld\n", inode->i_size);
10083+ DbgPrint("Novfs_get_inode: mode=0%o\n", inode->i_mode);
10084+ DbgPrint("Novfs_get_inode: i_sb->s_blocksize=%d\n",
10085+ inode->i_sb->s_blocksize);
10086+ DbgPrint("Novfs_get_inode: i_blkbits=%d\n", inode->i_blkbits);
10087+ DbgPrint("Novfs_get_inode: i_blocks=%d\n", inode->i_blocks);
10088+ DbgPrint("Novfs_get_inode: i_bytes=%d\n", inode->i_bytes);
10089+ }
10090+
10091+ DbgPrint("Novfs_get_inode: 0x%p %d\n", inode, inode->i_ino);
10092+ return (inode);
10093+}
10094+
10095+int Novfs_fill_super(struct super_block *SB, void *Data, int Silent)
10096+{
10097+ struct inode *inode;
10098+ struct dentry *server, *tree;
10099+ struct qstr name;
10100+ struct entry_info info;
10101+
10102+ SB->s_blocksize = PAGE_CACHE_SIZE;
10103+ SB->s_blocksize_bits = PAGE_CACHE_SHIFT;
10104+ SB->s_maxbytes = 0xFFFFFFFFFFFFFFFFULL; /* Max file size */
10105+ SB->s_op = &Novfs_ops;
10106+ SB->s_flags |= (MS_NODIRATIME | MS_NODEV | MS_POSIXACL);
10107+ SB->s_magic = NOVFS_MAGIC;
10108+
10109+ name.len = 1;
10110+ name.name = "/";
10111+
10112+ inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name);
10113+ if (!inode) {
10114+ return (-ENOMEM);
10115+ }
10116+
10117+ Novfs_root = d_alloc_root(inode);
10118+
10119+ if (!Novfs_root) {
10120+ iput(inode);
10121+ return (-ENOMEM);
10122+ }
10123+ Novfs_root->d_time = jiffies + (File_update_timeout * HZ);
10124+
10125+ inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
10126+
10127+ SB->s_root = Novfs_root;
10128+
10129+ DbgPrint("Novfs_fill_super: root 0x%p\n", Novfs_root);
10130+
10131+ if (Novfs_root) {
10132+ Novfs_root->d_op = &Novfs_dentry_operations;
10133+
10134+ name.name = SERVER_DIRECTORY_NAME;
10135+ name.len = strlen(SERVER_DIRECTORY_NAME);
10136+ name.hash = Novfs_internal_hash(&name);
10137+
10138+ inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name);
10139+ if (inode) {
10140+ info.mode = inode->i_mode;
10141+ info.namelength = 0;
10142+ inode->i_size = info.size = 0;
10143+ inode->i_uid = info.uid = 0;
10144+ inode->i_gid = info.gid = 0;
10145+ inode->i_atime = info.atime =
10146+ inode->i_ctime = info.ctime =
10147+ inode->i_mtime = info.mtime = CURRENT_TIME;
10148+
10149+ server = d_alloc(Novfs_root, &name);
10150+ if (server) {
10151+ server->d_op = &Novfs_dentry_operations;
10152+ server->d_time = 0xffffffff;
10153+ d_add(server, inode);
10154+ DbgPrint("Novfs_fill_super: d_add %s 0x%p\n",
10155+ SERVER_DIRECTORY_NAME, server);
10156+ Novfs_add_inode_entry(Novfs_root->d_inode,
10157+ &name, inode->i_ino,
10158+ &info);
10159+ }
10160+ }
10161+
10162+ name.name = TREE_DIRECTORY_NAME;
10163+ name.len = strlen(TREE_DIRECTORY_NAME);
10164+ name.hash = Novfs_internal_hash(&name);
10165+
10166+ inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name);
10167+ if (inode) {
10168+ info.mode = inode->i_mode;
10169+ info.namelength = 0;
10170+ inode->i_size = info.size = 0;
10171+ inode->i_uid = info.uid = 0;
10172+ inode->i_gid = info.gid = 0;
10173+ inode->i_atime = info.atime =
10174+ inode->i_ctime = info.ctime =
10175+ inode->i_mtime = info.mtime = CURRENT_TIME;
10176+ tree = d_alloc(Novfs_root, &name);
10177+ if (tree) {
10178+ tree->d_op = &Novfs_dentry_operations;
10179+ tree->d_time = 0xffffffff;
10180+
10181+ d_add(tree, inode);
10182+ DbgPrint("Novfs_fill_super: d_add %s 0x%p\n",
10183+ TREE_DIRECTORY_NAME, tree);
10184+ Novfs_add_inode_entry(Novfs_root->d_inode,
10185+ &name, inode->i_ino,
10186+ &info);
10187+ }
10188+ }
10189+ }
10190+
10191+ return (0);
10192+}
10193+
10194+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
10195+int Novfs_get_sb(struct file_system_type *Fstype, int Flags,
10196+ const char *Dev_name, void *Data, struct vfsmount *Mnt)
10197+#else
10198+struct super_block *Novfs_get_sb(struct file_system_type *Fstype, int Flags,
10199+ const char *Dev_name, void *Data)
10200+#endif
10201+{
10202+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
10203+ int sb;
10204+#else
10205+ struct super_block *sb;
10206+#endif
10207+
10208+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
10209+ sb = get_sb_nodev(Fstype, Flags, Data, Novfs_fill_super, Mnt);
10210+#else
10211+ sb = get_sb_nodev(Fstype, Flags, Data, Novfs_fill_super);
10212+#endif
10213+
10214+ DbgPrint("Novfs_get_sb: sb=0x%p Fstype=0x%x Dev_name=%s\n", sb, Fstype,
10215+ Dev_name);
10216+
10217+ return (sb);
10218+}
10219+
10220+static void novfs_kill_sb(struct super_block *super)
10221+{
10222+ /* calling shrink_dcache_sb() fixes novell bugzilla #345179, but I'm
10223+ * not so sure about it... */
10224+ shrink_dcache_sb(super);
10225+ kill_litter_super(super);
10226+}
10227+
10228+ssize_t Novfs_Control_read(struct file *file, char *buf, size_t nbytes,
10229+ loff_t * ppos)
10230+{
10231+ ssize_t retval = 0;
10232+
10233+ DbgPrint("Novfs_Control_read: kernel_locked 0x%x\n", kernel_locked());
10234+
10235+ return retval;
10236+}
10237+
10238+ssize_t Novfs_Control_write(struct file * file, const char *buf, size_t nbytes,
10239+ loff_t * ppos)
10240+{
10241+ ssize_t retval = 0;
10242+
10243+ DbgPrint("Novfs_Control_write: kernel_locked 0x%x\n", kernel_locked());
10244+ if (buf && nbytes) {
10245+ }
10246+
10247+ return (retval);
10248+}
10249+
10250+int Novfs_Control_ioctl(struct inode *inode, struct file *file,
10251+ unsigned int cmd, unsigned long arg)
10252+{
10253+ int retval = 0;
10254+
10255+ DbgPrint("Novfs_Control_ioctl: kernel_locked 0x%x\n", kernel_locked());
10256+
10257+ return (retval);
10258+}
10259+
10260+static struct file_system_type Novfs_fs_type = {
10261+ .name = "novfs",
10262+ .get_sb = Novfs_get_sb,
10263+ .kill_sb = novfs_kill_sb,
10264+ .owner = THIS_MODULE,
10265+};
10266+
10267+int __init init_novfs(void)
10268+{
10269+ int retCode;
10270+
10271+ lastDir[0] = 0;
10272+ lastTime = get_nanosecond_time();
10273+
10274+ inHAX = 0;
10275+ inHAXTime = get_nanosecond_time();
10276+
10277+ retCode = Init_Procfs_Interface();
10278+
10279+ init_profile();
10280+
10281+ if (!retCode) {
10282+ DbgPrint("init_novfs: %s %s %s\n", __DATE__, __TIME__,
10283+ NOVFS_VERSION_STRING);
10284+ Init_Daemon_Queue();
10285+ Scope_Init();
10286+ retCode = register_filesystem(&Novfs_fs_type);
10287+ if (retCode) {
10288+ Uninit_Procfs_Interface();
10289+ Uninit_Daemon_Queue();
10290+ Scope_Uninit();
10291+ }
10292+ }
10293+ return (retCode);
10294+}
10295+
10296+void __exit exit_novfs(void)
10297+{
10298+ printk(KERN_INFO "exit_novfs\n");
10299+
10300+ Scope_Uninit();
10301+ printk(KERN_INFO "exit_novfs after Scope_Uninit\n");
10302+
10303+ Uninit_Daemon_Queue();
10304+ printk(KERN_INFO "exit_novfs after Uninit_Daemon_Queue\n");
10305+
10306+ uninit_profile();
10307+ printk(KERN_INFO "exit_novfs after uninit_profile\n");
10308+
10309+ Uninit_Procfs_Interface();
10310+ printk(KERN_INFO "exit_novfs Uninit_Procfs_Interface\n");
10311+
10312+ unregister_filesystem(&Novfs_fs_type);
10313+ printk(KERN_INFO "exit_novfs: Exit\n");
10314+
10315+ if (Novfs_CurrentMount) {
10316+ kfree(Novfs_CurrentMount);
10317+ Novfs_CurrentMount = NULL;
10318+ }
10319+}
10320+
10321+int Novfs_lock_inode_cache(struct inode *i)
10322+/*
10323+ *
10324+ * Arguments: struct inode *i - pointer to directory inode
10325+ *
10326+ * Returns: 0 - locked
10327+ * -1 - not locked
10328+ *
10329+ * Abstract: Locks the inode cache.
10330+ *
10331+ * Notes:
10332+ *
10333+ * Environment:
10334+ *
10335+ *========================================================================*/
10336+{
10337+ struct inode_data *id;
10338+ int retVal = 0;
10339+
10340+ DbgPrint("Novfs_lock_inode_cache: 0x%p\n", i);
10341+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10342+ down(&id->DirCacheLock);
10343+ retVal = 1;
10344+ }
10345+ DbgPrint("Novfs_lock_inode_cache: return %d\n", retVal);
10346+ return (retVal);
10347+}
10348+
10349+/*++======================================================================*/
10350+void Novfs_unlock_inode_cache(struct inode *i)
10351+/*
10352+ * Arguments: struct inode *i - pointer to directory inode
10353+ *
10354+ * Returns: nothing
10355+ *
10356+ * Abstract: Unlocks inode cache.
10357+ *
10358+ * Notes:
10359+ *
10360+ * Environment:
10361+ *
10362+ *========================================================================*/
10363+{
10364+ struct inode_data *id;
10365+
10366+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10367+ up(&id->DirCacheLock);
10368+ }
10369+}
10370+
10371+/*++======================================================================*/
10372+int Novfs_enumerate_inode_cache(struct inode *i, struct list_head **iteration,
10373+ ino_t * ino, struct entry_info *info)
10374+/*
10375+ * Arguments: struct inode *i - pointer to directory inode
10376+ *
10377+ * Returns: 0 - item found
10378+ * -1 - done
10379+ *
10380+ * Abstract: Unlocks inode cache.
10381+ *
10382+ * Notes: DirCacheLock should be held before calling this routine.
10383+ *
10384+ * Environment:
10385+ *
10386+ *========================================================================*/
10387+{
10388+ struct inode_data *id;
10389+ struct dir_cache *dc;
10390+ struct list_head *l = NULL;
10391+ int retVal = -1;
10392+
10393+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10394+ if ((NULL == iteration) || (NULL == *iteration)) {
10395+ l = id->DirCache.next;
10396+ } else {
10397+ l = *iteration;
10398+ }
10399+
10400+ if (l == &id->DirCache) {
10401+ l = NULL;
10402+ } else {
10403+ dc = list_entry(l, struct dir_cache, list);
10404+
10405+ *ino = dc->ino;
10406+ info->type = 0;
10407+ info->mode = dc->mode;
10408+ info->size = dc->size;
10409+ info->atime = dc->atime;
10410+ info->mtime = dc->mtime;
10411+ info->ctime = dc->ctime;
10412+ info->namelength = dc->nameLen;
10413+ memcpy(info->name, dc->name, dc->nameLen);
10414+ info->name[dc->nameLen] = '\0';
10415+ retVal = 0;
10416+
10417+ l = l->next;
10418+ }
10419+ }
10420+ *iteration = l;
10421+ return (retVal);
10422+}
10423+
10424+/*++======================================================================*/
10425+int Novfs_get_entry(struct inode *i, struct qstr *name, ino_t * ino,
10426+ struct entry_info *info)
10427+/*
10428+ * Arguments:
10429+ *
10430+ * Returns:
10431+ *
10432+ * Abstract:
10433+ *
10434+ * Notes: DirCacheLock should be held before calling this routine.
10435+ *
10436+ * Environment:
10437+ *
10438+ *========================================================================*/
10439+{
10440+ struct inode_data *id;
10441+ struct dir_cache *dc;
10442+ int retVal = -1;
10443+ char *n = "<NULL>";
10444+ int nl = 6;
10445+
10446+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10447+ if (name && name->len) {
10448+ n = (char *)name->name;
10449+ nl = name->len;
10450+ }
10451+
10452+ dc = Novfs_lookup_inode_cache(i, name, *ino);
10453+ if (dc) {
10454+ dc->flags |= ENTRY_VALID;
10455+ retVal = 0;
10456+ *ino = dc->ino;
10457+ info->type = 0;
10458+ info->mode = dc->mode;
10459+ info->size = dc->size;
10460+ info->atime = dc->atime;
10461+ info->mtime = dc->mtime;
10462+ info->ctime = dc->ctime;
10463+ info->namelength = dc->nameLen;
10464+ memcpy(info->name, dc->name, dc->nameLen);
10465+ info->name[dc->nameLen] = '\0';
10466+ retVal = 0;
10467+ }
10468+
10469+ DbgPrint("Novfs_get_entry:\n"
10470+ " inode: 0x%p\n"
10471+ " name: %.*s\n" " ino: %d\n", i, nl, n, *ino);
10472+ }
10473+ DbgPrint("Novfs_get_entry: return %d\n", retVal);
10474+ return (retVal);
10475+}
10476+
10477+int Novfs_get_entry_by_pos(struct inode *i, loff_t pos, ino_t * ino,
10478+ struct entry_info *info)
10479+/*
10480+ * Arguments:
10481+ *
10482+ * Returns:
10483+ *
10484+ * Abstract:
10485+ *
10486+ * Notes: DirCacheLock should be held before calling this routine.
10487+ *
10488+ * Environment:
10489+ *
10490+ *========================================================================*/
10491+{
10492+ int retVal = -1;
10493+ loff_t count = 0;
10494+ loff_t i_pos = pos - 2;
10495+ struct list_head *inter = NULL;
10496+ while (!Novfs_enumerate_inode_cache(i, &inter, ino, info)) {
10497+ DbgPrint
10498+ ("Novfs_dir_readdir : Novfs_get_entry_by_pos : info->name = %s\n",
10499+ info->name);
10500+ if (count == i_pos) {
10501+ retVal = 0;
10502+ break;
10503+ } else
10504+ count++;
10505+ }
10506+
10507+ return retVal;
10508+}
10509+
10510+/*++======================================================================*/
10511+int Novfs_get_entry_time(struct inode *i, struct qstr *name, ino_t * ino,
10512+ struct entry_info *info, u64 * EntryTime)
10513+/*
10514+ * Arguments:
10515+ *
10516+ * Returns:
10517+ *
10518+ * Abstract:
10519+ *
10520+ * Notes: DirCacheLock should be held before calling this routine.
10521+ *
10522+ * Environment:
10523+ *
10524+ *========================================================================*/
10525+{
10526+ struct inode_data *id;
10527+ struct dir_cache *dc;
10528+ int retVal = -1;
10529+ char *n = "<NULL>";
10530+ int nl = 6;
10531+
10532+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10533+ if (name && name->len) {
10534+ n = (char *)name->name;
10535+ nl = name->len;
10536+ }
10537+ DbgPrint("Novfs_get_entry_time:\n"
10538+ " inode: 0x%p\n"
10539+ " name: %.*s\n" " ino: %d\n", i, nl, n, *ino);
10540+
10541+ dc = Novfs_lookup_inode_cache(i, name, *ino);
10542+ if (dc) {
10543+ retVal = 0;
10544+ *ino = dc->ino;
10545+ info->type = 0;
10546+ info->mode = dc->mode;
10547+ info->size = dc->size;
10548+ info->atime = dc->atime;
10549+ info->mtime = dc->mtime;
10550+ info->ctime = dc->ctime;
10551+ info->namelength = dc->nameLen;
10552+ memcpy(info->name, dc->name, dc->nameLen);
10553+ info->name[dc->nameLen] = '\0';
10554+ if (EntryTime) {
10555+ *EntryTime = dc->jiffies;
10556+ }
10557+ retVal = 0;
10558+ }
10559+ }
10560+ DbgPrint("Novfs_get_entry_time: return %d\n", retVal);
10561+ return (retVal);
10562+}
10563+
10564+/*++======================================================================*/
10565+int Novfs_get_remove_entry(struct inode *i, ino_t * ino, struct entry_info *info)
10566+/*
10567+ * Arguments:
10568+ *
10569+ * Returns:
10570+ *
10571+ * Abstract: This routine will return the first entry on the list
10572+ * and then remove it.
10573+ *
10574+ * Notes: DirCacheLock should be held before calling this routine.
10575+ *
10576+ * Environment:
10577+ *
10578+ *========================================================================*/
10579+{
10580+ struct inode_data *id;
10581+ struct dir_cache *dc;
10582+ struct list_head *l = NULL;
10583+ int retVal = -1;
10584+
10585+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10586+ l = id->DirCache.next;
10587+
10588+ if (l != &id->DirCache) {
10589+ dc = list_entry(l, struct dir_cache, list);
10590+
10591+ *ino = dc->ino;
10592+ info->type = 0;
10593+ info->mode = dc->mode;
10594+ info->size = dc->size;
10595+ info->atime = dc->atime;
10596+ info->mtime = dc->mtime;
10597+ info->ctime = dc->ctime;
10598+ info->namelength = dc->nameLen;
10599+ memcpy(info->name, dc->name, dc->nameLen);
10600+ info->name[dc->nameLen] = '\0';
10601+ retVal = 0;
10602+
10603+ list_del(&dc->list);
10604+ kfree(dc);
10605+ DCCount--;
10606+
10607+ id->cntDC--;
10608+ }
10609+ }
10610+ return (retVal);
10611+}
10612+
10613+/*++======================================================================*/
10614+void Novfs_invalidate_inode_cache(struct inode *i)
10615+/*
10616+ * Arguments: struct inode *i - pointer to directory inode
10617+ *
10618+ * Returns: nothing
10619+ *
10620+ * Abstract: Marks all entries in the directory cache as invalid.
10621+ *
10622+ * Notes: DirCacheLock should be held before calling this routine.
10623+ *
10624+ * Environment:
10625+ *
10626+ *========================================================================*/
10627+{
10628+ struct inode_data *id;
10629+ struct dir_cache *dc;
10630+ struct list_head *l;
10631+
10632+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10633+ list_for_each(l, &id->DirCache) {
10634+ dc = list_entry(l, struct dir_cache, list);
10635+ dc->flags &= ~ENTRY_VALID;
10636+ }
10637+ }
10638+}
10639+
10640+/*++======================================================================*/
10641+static struct dir_cache *Novfs_lookup_inode_cache(struct inode *i, struct qstr *name, ino_t ino)
10642+/*
10643+ * Arguments: struct inode *i - pointer to directory inode
10644+ * struct qstr *name - pointer to name
10645+ * ino_t - inode number
10646+ *
10647+ * Returns: struct dir_cache entry if match
10648+ * NULL - if there is no match.
10649+ *
10650+ * Abstract: Checks a inode directory to see if there are any enties
10651+ * matching name or ino. If name is specified then ino is
10652+ * not used. ino is use if name is not specified.
10653+ *
10654+ * Notes: DirCacheLock should be held before calling this routine.
10655+ *
10656+ * Environment:
10657+ *
10658+ *========================================================================*/
10659+{
10660+ struct inode_data *id;
10661+ struct dir_cache *dc;
10662+ struct dir_cache *retVal = NULL;
10663+ struct list_head *l;
10664+ char *n = "<NULL>";
10665+ int nl = 6;
10666+ int hash = 0;
10667+
10668+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10669+ if (name && name->name) {
10670+ nl = name->len;
10671+ n = (char *)name->name;
10672+ hash = name->hash;
10673+ }
10674+ DbgPrint("Novfs_lookup_inode_cache:\n"
10675+ " inode: 0x%p\n"
10676+ " name: %.*s\n"
10677+ " hash: 0x%x\n"
10678+ " len: %d\n"
10679+ " ino: %d\n", i, nl, n, hash, nl, ino);
10680+
10681+ list_for_each(l, &id->DirCache) {
10682+ dc = list_entry(l, struct dir_cache, list);
10683+ if (name) {
10684+
10685+/* DbgPrint("Novfs_lookup_inode_cache: 0x%p\n" \
10686+ " ino: %d\n" \
10687+ " hash: 0x%x\n" \
10688+ " len: %d\n" \
10689+ " name: %.*s\n",
10690+ dc, dc->ino, dc->hash, dc->nameLen, dc->nameLen, dc->name);
10691+*/
10692+ if ((name->hash == dc->hash) &&
10693+ (name->len == dc->nameLen) &&
10694+ (0 ==
10695+ memcmp(name->name, dc->name, name->len))) {
10696+ retVal = dc;
10697+ break;
10698+ }
10699+ } else {
10700+ if (ino == dc->ino) {
10701+ retVal = dc;
10702+ break;
10703+ }
10704+ }
10705+ }
10706+ }
10707+
10708+ DbgPrint("Novfs_lookup_inode_cache: return 0x%p\n", retVal);
10709+ return (retVal);
10710+}
10711+
10712+/*++======================================================================*/
10713+int Novfs_lookup_validate(struct inode *i, struct qstr *name, ino_t ino)
10714+/*
10715+ * Arguments: struct inode *i - pointer to directory inode
10716+ * struct qstr *name - pointer to name
10717+ * ino_t - inode number
10718+ *
10719+ * Returns: 0 if found
10720+ * !0 if not found
10721+ *
10722+ * Abstract: Checks a inode directory to see if there are any enties
10723+ * matching name or ino. If entry is found the valid bit
10724+ * is set.
10725+ *
10726+ * Notes: DirCacheLock should be held before calling this routine.
10727+ *
10728+ * Environment:
10729+ *
10730+ *========================================================================*/
10731+{
10732+ struct inode_data *id;
10733+ struct dir_cache *dc;
10734+ int retVal = -1;
10735+ char *n = "<NULL>";
10736+ int nl = 6;
10737+
10738+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10739+ if (name && name->len) {
10740+ n = (char *)name->name;
10741+ nl = name->len;
10742+ }
10743+ DbgPrint("Novfs_update_entry:\n"
10744+ " inode: 0x%p\n"
10745+ " name: %.*s\n" " ino: %d\n", i, nl, n, ino);
10746+
10747+ dc = Novfs_lookup_inode_cache(i, name, ino);
10748+ if (dc) {
10749+ dc->flags |= ENTRY_VALID;
10750+ retVal = 0;
10751+ }
10752+ }
10753+ return (retVal);
10754+}
10755+
10756+/*++======================================================================*/
10757+int Novfs_add_inode_entry(struct inode *i,
10758+ struct qstr *name, ino_t ino, struct entry_info *info)
10759+/*
10760+ * Arguments:
10761+ *
10762+ * Returns: -ENOMEM - alloc error.
10763+ * 0 - success.
10764+ *
10765+ * Abstract: Added entry to directory cache.
10766+ *
10767+ * Notes: DirCacheLock should be held before calling this routine.
10768+ *
10769+ * Environment:
10770+ *
10771+ *========================================================================*/
10772+{
10773+ struct inode_data *id;
10774+ struct dir_cache *new;
10775+ int retVal = -ENOMEM;
10776+ struct dir_cache *todel;
10777+ struct list_head *todeltmp;
10778+
10779+ //SClark
10780+ DbgPrint("Novfs_add_inode_entry:\n" " i: %u\n", i);
10781+ if ((id = i->FSPRIVATE)) {
10782+ DbgPrint(" i->FSPRIVATE: %p\n", id);
10783+ if (id->DirCache.next)
10784+ DbgPrint(" id->DirCache.next: %p\n",
10785+ id->DirCache.next);
10786+ }
10787+ //SClark
10788+
10789+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10790+ new = Novfs_Malloc(sizeof(struct dir_cache) + name->len, GFP_KERNEL);
10791+ if (new) {
10792+ id->cntDC++;
10793+
10794+ DCCount++;
10795+ DbgPrint("Novfs_add_inode_entry:\n"
10796+ " inode: 0x%p\n"
10797+ " id: 0x%p\n"
10798+ " DC: 0x%p\n"
10799+ " new: 0x%p\n"
10800+ " name: %.*s\n"
10801+ " ino: %d\n"
10802+ " size: %lld\n"
10803+ " mode: 0x%x\n",
10804+ i, id, &id->DirCache, new, name->len,
10805+ name->name, ino, info->size, info->mode);
10806+
10807+ retVal = 0;
10808+ new->flags = ENTRY_VALID;
10809+ new->jiffies = get_jiffies_64();
10810+ new->size = info->size;
10811+ new->mode = info->mode;
10812+ new->atime = info->atime;
10813+ new->mtime = info->mtime;
10814+ new->ctime = info->ctime;
10815+ new->ino = ino;
10816+ new->hash = name->hash;
10817+ new->nameLen = name->len;
10818+ memcpy(new->name, name->name, name->len);
10819+ new->name[new->nameLen] = '\0';
10820+ list_add(&new->list, &id->DirCache);
10821+
10822+ if (id->cntDC > 20) {
10823+ todeltmp = id->DirCache.prev;
10824+ todel = list_entry(todeltmp, struct dir_cache, list);
10825+
10826+ list_del(&todel->list);
10827+
10828+ kfree(todel);
10829+
10830+ DCCount--;
10831+ id->cntDC--;
10832+ }
10833+ }
10834+ }
10835+ return (retVal);
10836+}
10837+
10838+/*++======================================================================*/
10839+int Novfs_update_entry(struct inode *i, struct qstr *name, ino_t ino,
10840+ struct entry_info *info)
10841+/*
10842+ * Arguments:
10843+ *
10844+ * Returns:
10845+ *
10846+ * Abstract:
10847+ *
10848+ * Notes: DirCacheLock should be held before calling this routine.
10849+ *
10850+ * Environment:
10851+ *
10852+ *========================================================================*/
10853+{
10854+ struct inode_data *id;
10855+ struct dir_cache *dc;
10856+ int retVal = -1;
10857+ char *n = "<NULL>";
10858+ int nl = 6;
10859+ char atime_buf[32];
10860+ char mtime_buf[32];
10861+ char ctime_buf[32];
10862+
10863+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10864+
10865+ if (name && name->len) {
10866+ n = (char *)name->name;
10867+ nl = name->len;
10868+ }
10869+ ctime_r(&info->atime.tv_sec, atime_buf);
10870+ ctime_r(&info->mtime.tv_sec, mtime_buf);
10871+ ctime_r(&info->ctime.tv_sec, ctime_buf);
10872+ DbgPrint("Novfs_update_entry:\n"
10873+ " inode: 0x%p\n"
10874+ " name: %.*s\n"
10875+ " ino: %d\n"
10876+ " size: %lld\n"
10877+ " atime: %s\n"
10878+ " mtime: %s\n"
10879+ " ctime: %s\n",
10880+ i, nl, n, ino, info->size, atime_buf, mtime_buf,
10881+ ctime_buf);
10882+
10883+ dc = Novfs_lookup_inode_cache(i, name, ino);
10884+ if (dc) {
10885+ retVal = 0;
10886+ dc->flags = ENTRY_VALID;
10887+ dc->jiffies = get_jiffies_64();
10888+ dc->size = info->size;
10889+ dc->mode = info->mode;
10890+ dc->atime = info->atime;
10891+ dc->mtime = info->mtime;
10892+ dc->ctime = info->ctime;
10893+
10894+ ctime_r(&dc->atime.tv_sec, atime_buf);
10895+ ctime_r(&dc->mtime.tv_sec, mtime_buf);
10896+ ctime_r(&dc->ctime.tv_sec, ctime_buf);
10897+ DbgPrint("Novfs_update_entry entry: 0x%p\n"
10898+ " flags: 0x%x\n"
10899+ " jiffies: %lld\n"
10900+ " ino: %d\n"
10901+ " size: %lld\n"
10902+ " mode: 0%o\n"
10903+ " atime: %s\n"
10904+ " mtime: %s %d\n"
10905+ " ctime: %s\n"
10906+ " hash: 0x%x\n"
10907+ " nameLen: %d\n"
10908+ " name: %s\n",
10909+ dc, dc->flags, dc->jiffies, dc->ino, dc->size,
10910+ dc->mode, atime_buf, mtime_buf,
10911+ dc->mtime.tv_nsec, ctime_buf, dc->hash,
10912+ dc->nameLen, dc->name);
10913+ }
10914+ }
10915+ DbgPrint("Novfs_update_entry: return %d\n", retVal);
10916+ return (retVal);
10917+}
10918+
10919+/*++======================================================================*/
10920+void Novfs_remove_inode_entry(struct inode *i, struct qstr *name, ino_t ino)
10921+/*
10922+ * Arguments:
10923+ *
10924+ * Returns: nothing
10925+ *
10926+ * Abstract: Removes entry from directory cache. You can specify a name
10927+ * or an inode number.
10928+ *
10929+ * Notes: DirCacheLock should be held before calling this routine.
10930+ *
10931+ * Environment:
10932+ *
10933+ *========================================================================*/
10934+{
10935+ struct inode_data *id;
10936+ struct dir_cache *dc;
10937+ char *n = "<NULL>";
10938+ int nl = 6;
10939+
10940+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10941+ dc = Novfs_lookup_inode_cache(i, name, ino);
10942+ if (dc) {
10943+ if (name && name->name) {
10944+ nl = name->len;
10945+ n = (char *)name->name;
10946+ }
10947+ DbgPrint("Novfs_remove_inode_entry:\n"
10948+ " inode: 0x%p\n"
10949+ " id: 0x%p\n"
10950+ " DC: 0x%p\n"
10951+ " name: %.*s\n"
10952+ " ino: %d\n"
10953+ " entry: 0x%p\n"
10954+ " name: %.*s\n"
10955+ " ino: %d\n"
10956+ " next: 0x%p\n"
10957+ " prev: 0x%p\n",
10958+ i, id, &id->DirCache, nl, n, ino, dc,
10959+ dc->nameLen, dc->name, dc->ino, dc->list.next,
10960+ dc->list.prev);
10961+ list_del(&dc->list);
10962+ kfree(dc);
10963+ DCCount--;
10964+
10965+ id->cntDC--;
10966+ }
10967+ }
10968+}
10969+
10970+/*++======================================================================*/
10971+void Novfs_free_invalid_entries(struct inode *i)
10972+/*
10973+ * Arguments: struct inode *i - pointer to directory inode.
10974+ *
10975+ * Returns: nothing
10976+ *
10977+ * Abstract: Frees all invalid entries in the directory cache.
10978+ *
10979+ * Notes: DirCacheLock should be held before calling this routine.
10980+ *
10981+ * Environment:
10982+ *
10983+ *========================================================================*/
10984+{
10985+ struct inode_data *id;
10986+ struct dir_cache *dc;
10987+ struct list_head *l;
10988+
10989+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
10990+ list_for_each(l, &id->DirCache) {
10991+ dc = list_entry(l, struct dir_cache, list);
10992+ if (0 == (dc->flags & ENTRY_VALID)) {
10993+ DbgPrint("Novfs_free_invalid_entries:\n"
10994+ " inode: 0x%p\n"
10995+ " id: 0x%p\n"
10996+ " entry: 0x%p\n"
10997+ " name: %.*s\n"
10998+ " ino: %d\n",
10999+ i, id, dc, dc->nameLen, dc->name,
11000+ dc->ino);
11001+ l = l->prev;
11002+ list_del(&dc->list);
11003+ kfree(dc);
11004+ DCCount--;
11005+
11006+ id->cntDC--;
11007+ }
11008+ }
11009+ }
11010+}
11011+
11012+/*++======================================================================*/
11013+void Novfs_free_inode_cache(struct inode *i)
11014+/*
11015+ * Arguments: struct inode *i - pointer to directory inode.
11016+ *
11017+ * Returns: nothing
11018+ *
11019+ * Abstract: Frees all entries in the inode cache.
11020+ *
11021+ * Notes: DirCacheLock should be held before calling this routine.
11022+ *
11023+ * Environment:
11024+ *
11025+ *========================================================================*/
11026+{
11027+ struct inode_data *id;
11028+ struct dir_cache *dc;
11029+ struct list_head *l;
11030+
11031+ if (i && (id = i->FSPRIVATE) && id->DirCache.next) {
11032+ list_for_each(l, &id->DirCache) {
11033+ dc = list_entry(l, struct dir_cache, list);
11034+ l = l->prev;
11035+ list_del(&dc->list);
11036+ kfree(dc);
11037+ DCCount--;
11038+
11039+ id->cntDC--;
11040+ }
11041+ }
11042+}
11043+
11044+void Novfs_dump_inode(void *pf)
11045+{
11046+ struct inode *inode;
11047+ void (*pfunc) (char *Fmt, ...) = pf;
11048+ struct inode_data *id;
11049+ struct dir_cache *dc;
11050+ struct list_head *il, *l;
11051+ char atime_buf[32];
11052+ char mtime_buf[32];
11053+ char ctime_buf[32];
11054+ unsigned long icnt = 0, dccnt = 0;
11055+
11056+ down(&InodeList_lock);
11057+ list_for_each(il, &InodeList) {
11058+ id = list_entry(il, struct inode_data, IList);
11059+ inode = id->Inode;
11060+ if (inode) {
11061+ icnt++;
11062+
11063+ pfunc("Inode=0x%p I_ino=%d\n", inode, inode->i_ino);
11064+
11065+ pfunc(" atime=%s\n",
11066+ ctime_r(&inode->i_atime.tv_sec, atime_buf));
11067+ pfunc(" ctime=%s\n",
11068+ ctime_r(&inode->i_mtime.tv_sec, atime_buf));
11069+ pfunc(" mtime=%s\n",
11070+ ctime_r(&inode->i_ctime.tv_sec, atime_buf));
11071+ pfunc(" size=%lld\n", inode->i_size);
11072+ pfunc(" mode=0%o\n", inode->i_mode);
11073+ pfunc(" count=0%o\n", atomic_read(&inode->i_count));
11074+ }
11075+
11076+ pfunc(" inode_data: 0x%p Name=%s Scope=0x%p\n", id, id->Name,
11077+ id->Scope);
11078+
11079+ if (id->DirCache.next) {
11080+ list_for_each(l, &id->DirCache) {
11081+ dccnt++;
11082+ dc = list_entry(l, struct dir_cache, list);
11083+ ctime_r(&dc->atime.tv_sec, atime_buf);
11084+ ctime_r(&dc->mtime.tv_sec, mtime_buf);
11085+ ctime_r(&dc->ctime.tv_sec, ctime_buf);
11086+
11087+ pfunc(" Cache Entry: 0x%p\n"
11088+ " flags: 0x%x\n"
11089+ " jiffies: %llu\n"
11090+ " ino: %u\n"
11091+ " size: %llu\n"
11092+ " mode: 0%o\n"
11093+ " atime: %s\n"
11094+ " mtime: %s\n"
11095+ " ctime: %s\n"
11096+ " hash: 0x%x\n"
11097+ " len: %d\n"
11098+ " name: %s\n",
11099+ dc, dc->flags, dc->jiffies,
11100+ dc->ino, dc->size, dc->mode,
11101+ atime_buf, mtime_buf, ctime_buf,
11102+ dc->hash, dc->nameLen, dc->name);
11103+ }
11104+ }
11105+ }
11106+ up(&InodeList_lock);
11107+
11108+ pfunc("Inodes: %d(%d) DirCache: %d(%d)\n", InodeCount, icnt, DCCount,
11109+ dccnt);
11110+
11111+}
11112+
11113+module_init(init_novfs);
11114+module_exit(exit_novfs);
11115+
11116+MODULE_LICENSE("GPL");
11117+MODULE_AUTHOR("Novell Inc.");
11118+MODULE_DESCRIPTION("Novell NetWare Client for Linux");
11119+MODULE_VERSION(NOVFS_VERSION_STRING);
11120--- /dev/null
11121+++ b/fs/novfs/nwcapi.c
11122@@ -0,0 +1,2537 @@
11123+/*
11124+ * Novell NCP Redirector for Linux
11125+ * Author: James Turner/Richard Williams
11126+ *
11127+ * This file contains functions used to interface to the library interface of
11128+ * the daemon.
11129+ *
11130+ * Copyright (C) 2005 Novell, Inc.
11131+ *
11132+ * This program is free software; you can redistribute it and/or
11133+ * modify it under the terms of the GNU General Public License
11134+ * as published by the Free Software Foundation; either version 2
11135+ * of the License, or (at your option) any later version.
11136+ */
11137+
11138+#include <linux/module.h>
11139+#include <linux/fs.h>
11140+#include <linux/slab.h>
11141+#include <linux/list.h>
11142+#include <linux/timer.h>
11143+#include <linux/poll.h>
11144+#include <linux/semaphore.h>
11145+#include <asm/uaccess.h>
11146+
11147+#include "nwcapi.h"
11148+#include "nwerror.h"
11149+#include "vfs.h"
11150+#include "commands.h"
11151+
11152+static void GetUserData(NwcScanConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply);
11153+static void GetConnData(NwcGetConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply);
11154+
11155+
11156+int NwOpenConnByName(PXPLAT pdata, HANDLE * Handle, session_t Session)
11157+{
11158+ PXPLAT_CALL_REQUEST cmd;
11159+ PXPLAT_CALL_REPLY reply;
11160+ PNwdCOpenConnByName openConn, connReply;
11161+ NwcOpenConnByName ocbn;
11162+ int retCode = 0;
11163+ unsigned long cmdlen, datalen, replylen, cpylen;
11164+ char *data;
11165+
11166+ cpylen = copy_from_user(&ocbn, pdata->reqData, sizeof(ocbn));
11167+ datalen = sizeof(*openConn) + strlen_user(ocbn.pName->pString) + strlen_user(ocbn.pServiceType);
11168+ cmdlen = datalen + sizeof(*cmd);
11169+ cmd = kmalloc(cmdlen, GFP_KERNEL);
11170+ if (!cmd)
11171+ return -ENOMEM;
11172+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11173+ cmd->Command.SequenceNumber = 0;
11174+ cmd->Command.SessionId = Session;
11175+ cmd->NwcCommand = NWC_OPEN_CONN_BY_NAME;
11176+
11177+ cmd->dataLen = datalen;
11178+ openConn = (PNwdCOpenConnByName) cmd->data;
11179+
11180+ openConn->nameLen = strlen_user(ocbn.pName->pString);
11181+ openConn->serviceLen = strlen_user(ocbn.pServiceType);
11182+ openConn->uConnFlags = ocbn.uConnFlags;
11183+ openConn->ConnHandle = Uint32toHandle(ocbn.ConnHandle);
11184+ data = (char *)openConn;
11185+ data += sizeof(*openConn);
11186+ openConn->oName = sizeof(*openConn);
11187+
11188+ openConn->oServiceType = openConn->oName + openConn->nameLen;
11189+ cpylen = copy_from_user(data, ocbn.pName->pString, openConn->nameLen);
11190+ data += openConn->nameLen;
11191+ cpylen = copy_from_user(data, ocbn.pServiceType, openConn->serviceLen);
11192+
11193+ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11194+ (void **)&reply, &replylen,
11195+ INTERRUPTIBLE);
11196+ if (reply) {
11197+ /*
11198+ * we got reply data from the daemon
11199+ */
11200+ connReply = (PNwdCOpenConnByName) reply->data;
11201+ retCode = reply->Reply.ErrorCode;
11202+ if (!retCode) {
11203+ /*
11204+ * we got valid data.
11205+ */
11206+ connReply = (PNwdCOpenConnByName) reply->data;
11207+ ocbn.RetConnHandle = HandletoUint32(connReply->newConnHandle);
11208+ *Handle = connReply->newConnHandle;
11209+
11210+ cpylen = copy_to_user(pdata->reqData, &ocbn, sizeof(ocbn));
11211+ DbgPrint("New Conn Handle = %X\n", connReply->newConnHandle);
11212+ }
11213+ kfree(reply);
11214+ }
11215+
11216+ kfree(cmd);
11217+
11218+ return retCode;
11219+
11220+}
11221+
11222+int NwOpenConnByAddr(PXPLAT pdata, HANDLE * Handle, session_t Session)
11223+{
11224+ PXPLAT_CALL_REQUEST cmd;
11225+ PXPLAT_CALL_REPLY reply;
11226+ PNwdCOpenConnByAddr openConn, connReply;
11227+ NwcOpenConnByAddr ocba;
11228+ NwcTranAddr tranAddr;
11229+ int retCode = 0;
11230+ unsigned long cmdlen, datalen, replylen, cpylen;
11231+ char addr[MAX_ADDRESS_LENGTH];
11232+
11233+ cpylen = copy_from_user(&ocba, pdata->reqData, sizeof(ocba));
11234+ datalen = sizeof(*openConn);
11235+ cmdlen = datalen + sizeof(*cmd);
11236+ cmd = kmalloc(cmdlen, GFP_KERNEL);
11237+ if (!cmd)
11238+ return -ENOMEM;
11239+
11240+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11241+ cmd->Command.SequenceNumber = 0;
11242+ cmd->Command.SessionId = Session;
11243+ cmd->NwcCommand = NWC_OPEN_CONN_BY_ADDRESS;
11244+ cmd->dataLen = datalen;
11245+ openConn = (PNwdCOpenConnByAddr) cmd->data;
11246+
11247+ cpylen = copy_from_user(&tranAddr, ocba.pTranAddr, sizeof(tranAddr));
11248+
11249+ DbgPrint("NwOpenConnByAddr: tranAddr\n");
11250+ mydump(sizeof(tranAddr), &tranAddr);
11251+
11252+ openConn->TranAddr.uTransportType = tranAddr.uTransportType;
11253+ openConn->TranAddr.uAddressLength = tranAddr.uAddressLength;
11254+ memset(addr, 0xcc, sizeof(addr) - 1);
11255+
11256+ cpylen = copy_from_user(addr, tranAddr.puAddress, tranAddr.uAddressLength);
11257+
11258+ DbgPrint("NwOpenConnByAddr: addr\n");
11259+ mydump(sizeof(addr), addr);
11260+
11261+ openConn->TranAddr.oAddress = *(unsigned int*) (&addr[2]);
11262+
11263+ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11264+ (void **)&reply, &replylen,
11265+ INTERRUPTIBLE);
11266+ if (reply) {
11267+ /*
11268+ * we got reply data from the daemon
11269+ */
11270+ connReply = (PNwdCOpenConnByAddr) reply->data;
11271+ retCode = reply->Reply.ErrorCode;
11272+ if (!retCode) {
11273+ /*
11274+ * we got valid data.
11275+ */
11276+ connReply = (PNwdCOpenConnByAddr) reply->data;
11277+ ocba.ConnHandle = HandletoUint32(connReply->ConnHandle);
11278+ *Handle = connReply->ConnHandle;
11279+ cpylen = copy_to_user(pdata->reqData, &ocba, sizeof(ocba));
11280+ DbgPrint("New Conn Handle = %X\n", connReply->ConnHandle);
11281+ }
11282+ kfree(reply);
11283+ }
11284+
11285+ kfree(cmd);
11286+ return retCode;
11287+}
11288+
11289+/*++======================================================================*/
11290+int NwOpenConnByRef(PXPLAT pdata, HANDLE * Handle, session_t Session)
11291+/*
11292+ * Arguments:
11293+ *
11294+ * Returns:
11295+ *
11296+ * Abstract:
11297+ *
11298+ * Notes:
11299+ *
11300+ * Environment:
11301+ *
11302+ *========================================================================*/
11303+{
11304+ PXPLAT_CALL_REQUEST cmd;
11305+ PXPLAT_CALL_REPLY reply;
11306+ PNwdCOpenConnByRef openConn;
11307+ NwcOpenConnByReference ocbr;
11308+ int retCode = -ENOMEM;
11309+ unsigned long cmdlen, datalen, replylen, cpylen;
11310+
11311+ cpylen = copy_from_user(&ocbr, pdata->reqData, sizeof(ocbr));
11312+ datalen = sizeof(*openConn);
11313+ cmdlen = datalen + sizeof(*cmd);
11314+ cmd = kmalloc(cmdlen, GFP_KERNEL);
11315+ if (!cmd)
11316+ return -ENOMEM;
11317+
11318+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11319+ cmd->Command.SequenceNumber = 0;
11320+ cmd->Command.SessionId = Session;
11321+ cmd->NwcCommand = NWC_OPEN_CONN_BY_REFERENCE;
11322+ cmd->dataLen = datalen;
11323+ openConn = (PNwdCOpenConnByRef) cmd->data;
11324+
11325+ openConn->uConnReference = (HANDLE) (unsigned long) ocbr.uConnReference;
11326+ openConn->uConnFlags = ocbr.uConnFlags;
11327+
11328+ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11329+ (void **)&reply, &replylen,
11330+ INTERRUPTIBLE);
11331+ if (reply) {
11332+ /*
11333+ * we got reply data from the daemon
11334+ */
11335+ openConn = (PNwdCOpenConnByRef) reply->data;
11336+ retCode = reply->Reply.ErrorCode;
11337+ if (!retCode) {
11338+ /*
11339+ * we got valid data.
11340+ */
11341+ ocbr.ConnHandle = HandletoUint32(openConn->ConnHandle);
11342+ *Handle = openConn->ConnHandle;
11343+
11344+ cpylen = copy_to_user(pdata->reqData, &ocbr, sizeof(ocbr));
11345+ DbgPrint("New Conn Handle = %X\n", openConn->ConnHandle);
11346+ }
11347+ kfree(reply);
11348+ }
11349+
11350+ kfree(cmd);
11351+ return (retCode);
11352+
11353+}
11354+
11355+int NwRawSend(PXPLAT pdata, session_t Session)
11356+{
11357+ NwcRequest xRequest;
11358+ PNwcFrag frag = NULL;
11359+ PNwcFrag cFrag = NULL;
11360+ PNwcFrag reqFrag = NULL;
11361+ PXPLAT_CALL_REQUEST cmd;
11362+ PXPLAT_CALL_REPLY reply;
11363+ int retCode = -ENOMEM;
11364+ unsigned long cmdlen, datalen, replylen, cpylen, totalLen;
11365+ unsigned int x;
11366+ PNwdCNCPReq ncpData;
11367+ PNwdCNCPRep ncpReply;
11368+ unsigned char *reqData;
11369+ unsigned long actualReplyLength = 0;
11370+
11371+ DbgPrint("[XPLAT] Process Raw NCP Send\n");
11372+ cpylen = copy_from_user(&xRequest, pdata->reqData, sizeof(xRequest));
11373+
11374+ /*
11375+ * Figure out the length of the request
11376+ */
11377+ frag = kmalloc(xRequest.uNumReplyFrags * sizeof(NwcFrag), GFP_KERNEL);
11378+ DbgPrint("[XPLAT RawNCP] - Reply Frag Count 0x%X\n", xRequest.uNumReplyFrags);
11379+
11380+ if (!frag)
11381+ goto exit;
11382+
11383+ cpylen = copy_from_user(frag, xRequest.pReplyFrags, xRequest.uNumReplyFrags * sizeof(NwcFrag));
11384+ totalLen = 0;
11385+
11386+ cFrag = frag;
11387+ for (x = 0; x < xRequest.uNumReplyFrags; x++) {
11388+ DbgPrint("[XPLAT - RawNCP] - Frag Len = %d\n", cFrag->uLength);
11389+ totalLen += cFrag->uLength;
11390+ cFrag++;
11391+ }
11392+
11393+ DbgPrint("[XPLAT - RawNCP] - totalLen = %d\n", totalLen);
11394+ datalen = 0;
11395+ reqFrag = kmalloc(xRequest.uNumRequestFrags * sizeof(NwcFrag), GFP_KERNEL);
11396+ if (!reqFrag)
11397+ goto exit;
11398+
11399+ cpylen = copy_from_user(reqFrag, xRequest.pRequestFrags, xRequest.uNumRequestFrags * sizeof(NwcFrag));
11400+ cFrag = reqFrag;
11401+ for (x = 0; x < xRequest.uNumRequestFrags; x++) {
11402+ datalen += cFrag->uLength;
11403+ cFrag++;
11404+ }
11405+
11406+ /*
11407+ * Allocate the cmd Request
11408+ */
11409+ cmdlen = datalen + sizeof(*cmd) + sizeof(*ncpData);
11410+ DbgPrint("[XPLAT RawNCP] - Frag Count 0x%X\n", xRequest.uNumRequestFrags);
11411+ DbgPrint("[XPLAT RawNCP] - Total Command Data Len = %x\n", cmdlen);
11412+
11413+ cmd = kmalloc(cmdlen, GFP_KERNEL);
11414+ if (!cmd)
11415+ goto exit;
11416+
11417+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11418+ cmd->Command.SequenceNumber = 0;
11419+ cmd->Command.SessionId = Session;
11420+ cmd->NwcCommand = NWC_RAW_NCP_REQUEST;
11421+
11422+ /*
11423+ * build the NCP Request
11424+ */
11425+ cmd->dataLen = cmdlen - sizeof(*cmd);
11426+ ncpData = (PNwdCNCPReq) cmd->data;
11427+ ncpData->replyLen = totalLen;
11428+ ncpData->requestLen = datalen;
11429+ ncpData->ConnHandle = (HANDLE) (unsigned long) xRequest.ConnHandle;
11430+ ncpData->function = xRequest.uFunction;
11431+
11432+ reqData = ncpData->data;
11433+ cFrag = reqFrag;
11434+
11435+ for (x = 0; x < xRequest.uNumRequestFrags; x++) {
11436+ cpylen =
11437+ copy_from_user(reqData, cFrag->pData,
11438+ cFrag->uLength);
11439+ reqData += cFrag->uLength;
11440+ cFrag++;
11441+ }
11442+
11443+ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11444+ (void **)&reply, &replylen,
11445+ INTERRUPTIBLE);
11446+ DbgPrint("RawNCP - reply = %x\n", reply);
11447+ DbgPrint("RawNCP - retCode = %x\n", retCode);
11448+
11449+ if (reply) {
11450+ /*
11451+ * we got reply data from the daemon
11452+ */
11453+ ncpReply = (PNwdCNCPRep) reply->data;
11454+ retCode = reply->Reply.ErrorCode;
11455+
11456+ DbgPrint("RawNCP - Reply Frag Count 0x%X\n",
11457+ xRequest.uNumReplyFrags);
11458+
11459+ /*
11460+ * We need to copy the reply frags to the packet.
11461+ */
11462+ reqData = ncpReply->data;
11463+ cFrag = frag;
11464+
11465+ totalLen = ncpReply->replyLen;
11466+ for (x = 0; x < xRequest.uNumReplyFrags; x++) {
11467+
11468+ DbgPrint("RawNCP - Copy Frag %d: 0x%X\n", x,
11469+ cFrag->uLength);
11470+
11471+ datalen = min((unsigned long)cFrag->uLength, totalLen);
11472+
11473+ cpylen = copy_to_user(cFrag->pData, reqData, datalen);
11474+ totalLen -= datalen;
11475+ reqData += datalen;
11476+ actualReplyLength += datalen;
11477+
11478+ cFrag++;
11479+ }
11480+
11481+ kfree(reply);
11482+ } else {
11483+ retCode = -EIO;
11484+ }
11485+
11486+ kfree(cmd);
11487+
11488+ xRequest.uActualReplyLength = actualReplyLength;
11489+ cpylen = copy_to_user(pdata->reqData, &xRequest, sizeof(xRequest));
11490+
11491+exit:
11492+ kfree(reqFrag);
11493+ kfree(frag);
11494+ return retCode;
11495+}
11496+
11497+int NwConnClose(PXPLAT pdata, HANDLE * Handle, session_t Session)
11498+{
11499+ PXPLAT_CALL_REQUEST cmd;
11500+ PXPLAT_CALL_REPLY reply;
11501+ NwcCloseConn cc;
11502+ PNwdCCloseConn nwdClose;
11503+ int retCode = 0;
11504+ unsigned long cmdlen, datalen, replylen, cpylen;
11505+
11506+ cpylen = copy_from_user(&cc, pdata->reqData, sizeof(cc));
11507+
11508+ datalen = sizeof(*nwdClose);
11509+ cmdlen = datalen + sizeof(*cmd);
11510+ cmd = kmalloc(cmdlen, GFP_KERNEL);
11511+ if (!cmd)
11512+ return -ENOMEM;
11513+
11514+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11515+ cmd->Command.SequenceNumber = 0;
11516+ cmd->Command.SessionId = Session;
11517+ cmd->NwcCommand = NWC_CLOSE_CONN;
11518+
11519+ nwdClose = (PNwdCCloseConn) cmd->data;
11520+ cmd->dataLen = sizeof(*nwdClose);
11521+ *Handle = nwdClose->ConnHandle = Uint32toHandle(cc.ConnHandle);
11522+
11523+ /*
11524+ * send the request
11525+ */
11526+ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11527+ (void **)&reply, &replylen, 0);
11528+ if (reply) {
11529+ retCode = reply->Reply.ErrorCode;
11530+ kfree(reply);
11531+ }
11532+ kfree(cmd);
11533+ return retCode;
11534+}
11535+
11536+int NwSysConnClose(PXPLAT pdata, unsigned long *Handle, session_t Session)
11537+{
11538+ PXPLAT_CALL_REQUEST cmd;
11539+ PXPLAT_CALL_REPLY reply;
11540+ NwcCloseConn cc;
11541+ PNwdCCloseConn nwdClose;
11542+ unsigned int retCode = 0;
11543+ unsigned long cmdlen, datalen, replylen, cpylen;
11544+
11545+ cpylen = copy_from_user(&cc, pdata->reqData, sizeof(cc));
11546+
11547+ datalen = sizeof(*nwdClose);
11548+ cmdlen = datalen + sizeof(*cmd);
11549+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
11550+ if (cmd) {
11551+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11552+ cmd->Command.SequenceNumber = 0;
11553+ cmd->Command.SessionId = Session;
11554+ cmd->NwcCommand = NWC_SYS_CLOSE_CONN;
11555+
11556+ nwdClose = (PNwdCCloseConn) cmd->data;
11557+ cmd->dataLen = sizeof(*nwdClose);
11558+ nwdClose->ConnHandle = (HANDLE) (unsigned long) cc.ConnHandle;
11559+ *Handle = (unsigned long) cc.ConnHandle;
11560+
11561+ /*
11562+ * send the request
11563+ */
11564+ retCode =
11565+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11566+ (void **)&reply, &replylen, 0);
11567+ if (reply) {
11568+ retCode = reply->Reply.ErrorCode;
11569+ kfree(reply);
11570+ }
11571+ kfree(cmd);
11572+
11573+ }
11574+
11575+ return (retCode);
11576+
11577+}
11578+
11579+/*++======================================================================*/
11580+int NwLoginIdentity(PXPLAT pdata, struct schandle *Session)
11581+/*
11582+ * Arguments:
11583+ *
11584+ * Returns:
11585+ *
11586+ * Abstract:
11587+ *
11588+ * Notes:
11589+ *
11590+ * Environment:
11591+ *
11592+ *========================================================================*/
11593+{
11594+ NwcLoginIdentity lgn, *plgn;
11595+ int retCode = -ENOMEM;
11596+ NclString server;
11597+ NclString username;
11598+ NclString password;
11599+ unsigned long cpylen;
11600+ NwcString nwcStr;
11601+
11602+ cpylen = copy_from_user(&lgn, pdata->reqData, sizeof(lgn));
11603+
11604+ DbgPrint("NwLoginIdentity:\n");
11605+ mydump(sizeof(lgn), &lgn);
11606+
11607+ cpylen = copy_from_user(&nwcStr, lgn.pDomainName, sizeof(nwcStr));
11608+ DbgPrint("NwLoginIdentity: DomainName\n");
11609+ mydump(sizeof(nwcStr), &nwcStr);
11610+
11611+ if ((server.buffer = Novfs_Malloc(nwcStr.DataLen, GFP_KERNEL))) {
11612+ server.type = nwcStr.DataType;
11613+ server.len = nwcStr.DataLen;
11614+ if (!copy_from_user
11615+ ((void *)server.buffer, nwcStr.pBuffer, server.len)) {
11616+ DbgPrint("NwLoginIdentity: Server\n");
11617+ mydump(server.len, server.buffer);
11618+
11619+ cpylen =
11620+ copy_from_user(&nwcStr, lgn.pObjectName,
11621+ sizeof(nwcStr));
11622+ DbgPrint("NwLoginIdentity: ObjectName\n");
11623+ mydump(sizeof(nwcStr), &nwcStr);
11624+
11625+ if ((username.buffer =
11626+ Novfs_Malloc(nwcStr.DataLen, GFP_KERNEL))) {
11627+ username.type = nwcStr.DataType;
11628+ username.len = nwcStr.DataLen;
11629+ if (!copy_from_user
11630+ ((void *)username.buffer, nwcStr.pBuffer,
11631+ username.len)) {
11632+ DbgPrint("NwLoginIdentity: User\n");
11633+ mydump(username.len, username.buffer);
11634+
11635+ cpylen =
11636+ copy_from_user(&nwcStr,
11637+ lgn.pPassword,
11638+ sizeof(nwcStr));
11639+ DbgPrint("NwLoginIdentity: Password\n");
11640+ mydump(sizeof(nwcStr), &nwcStr);
11641+
11642+ if ((password.buffer =
11643+ Novfs_Malloc(nwcStr.DataLen,
11644+ GFP_KERNEL))) {
11645+ password.type = nwcStr.DataType;
11646+ password.len = nwcStr.DataLen;
11647+ if (!copy_from_user
11648+ ((void *)password.buffer,
11649+ nwcStr.pBuffer,
11650+ password.len)) {
11651+ retCode =
11652+ do_login(&server,
11653+ &username,
11654+ &password,
11655+ (HANDLE *)&lgn.AuthenticationId,
11656+ Session);
11657+ if (retCode) {
11658+ lgn.AuthenticationId = 0;
11659+ }
11660+
11661+ plgn =
11662+ (NwcLoginIdentity *)
11663+ pdata->reqData;
11664+ cpylen =
11665+ copy_to_user(&plgn->
11666+ AuthenticationId,
11667+ &lgn.
11668+ AuthenticationId,
11669+ sizeof
11670+ (plgn->
11671+ AuthenticationId));
11672+
11673+ }
11674+ memset(password.buffer, 0,
11675+ password.len);
11676+ kfree(password.buffer);
11677+ }
11678+ }
11679+ memset(username.buffer, 0, username.len);
11680+ kfree(username.buffer);
11681+ }
11682+ }
11683+ kfree(server.buffer);
11684+ }
11685+ return (retCode);
11686+}
11687+
11688+/*++======================================================================*/
11689+int NwAuthConnWithId(PXPLAT pdata, session_t Session)
11690+/*
11691+ * Arguments:
11692+ *
11693+ * Returns:
11694+ *
11695+ * Abstract:
11696+ *
11697+ * Notes:
11698+ *
11699+ * Environment:
11700+ *
11701+ *========================================================================*/
11702+{
11703+ NwcAuthenticateWithId pauth;
11704+ PNwdCAuthenticateWithId pDauth;
11705+ PXPLAT_CALL_REQUEST cmd;
11706+ PXPLAT_CALL_REPLY reply;
11707+ int retCode = -ENOMEM;
11708+ unsigned long cmdlen, datalen, replylen, cpylen;
11709+
11710+ datalen = sizeof(*pDauth);
11711+ cmdlen = datalen + sizeof(*cmd);
11712+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
11713+
11714+ if (cmd) {
11715+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11716+ cmd->Command.SequenceNumber = 0;
11717+ cmd->Command.SessionId = Session;
11718+ cmd->NwcCommand = NWC_AUTHENTICATE_CONN_WITH_ID;
11719+
11720+ cpylen = copy_from_user(&pauth, pdata->reqData, sizeof(pauth));
11721+
11722+ pDauth = (PNwdCAuthenticateWithId) cmd->data;
11723+ cmd->dataLen = datalen;
11724+ pDauth->AuthenticationId = pauth.AuthenticationId;
11725+ pDauth->ConnHandle = (HANDLE) (unsigned long) pauth.ConnHandle;
11726+
11727+ retCode =
11728+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11729+ (void **)&reply, &replylen,
11730+ INTERRUPTIBLE);
11731+ if (reply) {
11732+ retCode = reply->Reply.ErrorCode;
11733+ kfree(reply);
11734+ }
11735+ kfree(cmd);
11736+ }
11737+ return (retCode);
11738+}
11739+
11740+/*++======================================================================*/
11741+int NwLicenseConn(PXPLAT pdata, session_t Session)
11742+/*
11743+ * Arguments:
11744+ *
11745+ * Returns:
11746+ *
11747+ * Abstract:
11748+ *
11749+ * Notes:
11750+ *
11751+ * Environment:
11752+ *
11753+ *========================================================================*/
11754+{
11755+ PXPLAT_CALL_REQUEST cmd;
11756+ PXPLAT_CALL_REPLY reply;
11757+ NwcLicenseConn lisc;
11758+ PNwdCLicenseConn pDLisc;
11759+ int retCode = -ENOMEM;
11760+ unsigned long cmdlen, datalen, replylen, cpylen;
11761+
11762+ datalen = sizeof(*pDLisc);
11763+ cmdlen = datalen + sizeof(*cmd);
11764+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
11765+
11766+ if (cmd) {
11767+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11768+ cmd->Command.SequenceNumber = 0;
11769+ cmd->Command.SessionId = Session;
11770+ cmd->NwcCommand = NWC_LICENSE_CONN;
11771+
11772+ cpylen = copy_from_user(&lisc, pdata->reqData, sizeof(lisc));
11773+
11774+ pDLisc = (PNwdCLicenseConn) cmd->data;
11775+ cmd->dataLen = datalen;
11776+ pDLisc->ConnHandle = (HANDLE) (unsigned long) lisc.ConnHandle;
11777+
11778+ retCode =
11779+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11780+ (void **)&reply, &replylen,
11781+ INTERRUPTIBLE);
11782+ if (reply) {
11783+ retCode = reply->Reply.ErrorCode;
11784+ kfree(reply);
11785+ }
11786+ kfree(cmd);
11787+ }
11788+ return (retCode);
11789+}
11790+
11791+/*++======================================================================*/
11792+int NwLogoutIdentity(PXPLAT pdata, session_t Session)
11793+/*
11794+ * Arguments:
11795+ *
11796+ * Returns:
11797+ *
11798+ * Abstract:
11799+ *
11800+ * Notes:
11801+ *
11802+ * Environment:
11803+ *
11804+ *========================================================================*/
11805+{
11806+ PXPLAT_CALL_REQUEST cmd;
11807+ PXPLAT_CALL_REPLY reply;
11808+ NwcLogoutIdentity logout;
11809+ PNwdCLogoutIdentity pDLogout;
11810+ int retCode = -ENOMEM;
11811+ unsigned long cmdlen, datalen, replylen, cpylen;
11812+
11813+ datalen = sizeof(*pDLogout);
11814+ cmdlen = datalen + sizeof(*cmd);
11815+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
11816+
11817+ if (cmd) {
11818+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11819+ cmd->Command.SequenceNumber = 0;
11820+ cmd->Command.SessionId = Session;
11821+ cmd->NwcCommand = NWC_LOGOUT_IDENTITY;
11822+
11823+ cpylen =
11824+ copy_from_user(&logout, pdata->reqData, sizeof(logout));
11825+
11826+ pDLogout = (PNwdCLogoutIdentity) cmd->data;
11827+ cmd->dataLen = datalen;
11828+ pDLogout->AuthenticationId = logout.AuthenticationId;
11829+
11830+ retCode =
11831+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11832+ (void **)&reply, &replylen,
11833+ INTERRUPTIBLE);
11834+ if (reply) {
11835+ retCode = reply->Reply.ErrorCode;
11836+ kfree(reply);
11837+ }
11838+ kfree(cmd);
11839+ }
11840+ return (retCode);
11841+}
11842+
11843+/*++======================================================================*/
11844+int NwUnlicenseConn(PXPLAT pdata, session_t Session)
11845+/*
11846+ * Arguments:
11847+ *
11848+ * Returns:
11849+ *
11850+ * Abstract:
11851+ *
11852+ * Notes:
11853+ *
11854+ * Environment:
11855+ *
11856+ *========================================================================*/
11857+{
11858+ PXPLAT_CALL_REQUEST cmd;
11859+ PXPLAT_CALL_REPLY reply;
11860+ PNwdCUnlicenseConn pUconn;
11861+ NwcUnlicenseConn ulc;
11862+ int retCode = -ENOMEM;
11863+ unsigned long cmdlen, datalen, replylen, cpylen;
11864+
11865+ cpylen = copy_from_user(&ulc, pdata->reqData, sizeof(ulc));
11866+ datalen = sizeof(*pUconn);
11867+ cmdlen = datalen + sizeof(*cmd);
11868+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
11869+ if (cmd) {
11870+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11871+ cmd->Command.SequenceNumber = 0;
11872+ cmd->Command.SessionId = Session;
11873+ cmd->NwcCommand = NWC_UNLICENSE_CONN;
11874+ cmd->dataLen = datalen;
11875+ pUconn = (PNwdCUnlicenseConn) cmd->data;
11876+
11877+ pUconn->ConnHandle = (HANDLE) (unsigned long) ulc.ConnHandle;
11878+ retCode =
11879+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11880+ (void **)&reply, &replylen,
11881+ INTERRUPTIBLE);
11882+ if (reply) {
11883+ /*
11884+ * we got reply data from the daemon
11885+ */
11886+ retCode = reply->Reply.ErrorCode;
11887+ kfree(reply);
11888+ }
11889+
11890+ kfree(cmd);
11891+ }
11892+ return (retCode);
11893+
11894+}
11895+
11896+/*++======================================================================*/
11897+int NwUnAuthenticate(PXPLAT pdata, session_t Session)
11898+/*
11899+ * Arguments:
11900+ *
11901+ * Returns:
11902+ *
11903+ * Abstract:
11904+ *
11905+ * Notes:
11906+ *
11907+ * Environment:
11908+ *
11909+ *========================================================================*/
11910+{
11911+ PXPLAT_CALL_REQUEST cmd;
11912+ PXPLAT_CALL_REPLY reply;
11913+ NwcUnauthenticate auth;
11914+ PNwdCUnauthenticate pDAuth;
11915+ int retCode = -ENOMEM;
11916+ unsigned long cmdlen, datalen, replylen, cpylen;
11917+
11918+ datalen = sizeof(*pDAuth);
11919+ cmdlen = datalen + sizeof(*cmd);
11920+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
11921+
11922+ if (cmd) {
11923+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11924+ cmd->Command.SequenceNumber = 0;
11925+ cmd->Command.SessionId = Session;
11926+ cmd->NwcCommand = NWC_UNAUTHENTICATE_CONN;
11927+
11928+ cpylen = copy_from_user(&auth, pdata->reqData, sizeof(auth));
11929+
11930+ pDAuth = (PNwdCUnauthenticate) cmd->data;
11931+ cmd->dataLen = datalen;
11932+ pDAuth->AuthenticationId = auth.AuthenticationId;
11933+ pDAuth->ConnHandle = (HANDLE) (unsigned long) auth.ConnHandle;
11934+
11935+ retCode =
11936+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11937+ (void **)&reply, &replylen,
11938+ INTERRUPTIBLE);
11939+ if (reply) {
11940+ retCode = reply->Reply.ErrorCode;
11941+ kfree(reply);
11942+ }
11943+ kfree(cmd);
11944+ }
11945+ return (retCode);
11946+
11947+}
11948+
11949+/*++======================================================================*/
11950+int NwGetConnInfo(PXPLAT pdata, session_t Session)
11951+/*
11952+ * Arguments:
11953+ *
11954+ * Returns:
11955+ *
11956+ * Abstract:
11957+ *
11958+ * Notes:
11959+ *
11960+ * Environment:
11961+ *
11962+ *========================================================================*/
11963+{
11964+ PXPLAT_CALL_REQUEST cmd;
11965+ PXPLAT_CALL_REPLY reply;
11966+ NwcGetConnInfo connInfo;
11967+ PNwdCGetConnInfo pDConnInfo;
11968+ int retCode = -ENOMEM;
11969+ unsigned long cmdlen, replylen, cpylen;
11970+
11971+ cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo);
11972+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
11973+ cpylen =
11974+ copy_from_user(&connInfo, pdata->reqData, sizeof(NwcGetConnInfo));
11975+
11976+ if (cmd) {
11977+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
11978+ cmd->Command.SequenceNumber = 0;
11979+ cmd->Command.SessionId = Session;
11980+ cmd->NwcCommand = NWC_GET_CONN_INFO;
11981+
11982+ pDConnInfo = (PNwdCGetConnInfo) cmd->data;
11983+
11984+ pDConnInfo->ConnHandle = (HANDLE) (unsigned long) connInfo.ConnHandle;
11985+ pDConnInfo->uInfoLevel = connInfo.uInfoLevel;
11986+ pDConnInfo->uInfoLength = connInfo.uInfoLength;
11987+ cmd->dataLen = sizeof(*pDConnInfo);
11988+
11989+ retCode =
11990+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
11991+ (void **)&reply, &replylen,
11992+ INTERRUPTIBLE);
11993+ if (reply) {
11994+ retCode = reply->Reply.ErrorCode;
11995+ if (!retCode) {
11996+ GetConnData(&connInfo, cmd, reply);
11997+ }
11998+
11999+ kfree(reply);
12000+ }
12001+ kfree(cmd);
12002+
12003+ }
12004+
12005+ return (retCode);
12006+
12007+}
12008+
12009+/*++======================================================================*/
12010+int NwSetConnInfo(PXPLAT pdata, session_t Session)
12011+/*
12012+ * Arguments:
12013+ *
12014+ * Returns:
12015+ *
12016+ * Abstract:
12017+ *
12018+ * Notes:
12019+ *
12020+ * Environment:
12021+ *
12022+ *========================================================================*/
12023+{
12024+ PXPLAT_CALL_REQUEST cmd;
12025+ PXPLAT_CALL_REPLY reply;
12026+ NwcSetConnInfo connInfo;
12027+ PNwdCSetConnInfo pDConnInfo;
12028+ int retCode = -ENOMEM;
12029+ unsigned long cmdlen, replylen, cpylen;
12030+
12031+ cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo);
12032+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12033+ cpylen =
12034+ copy_from_user(&connInfo, pdata->reqData, sizeof(NwcSetConnInfo));
12035+
12036+ if (cmd) {
12037+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12038+ cmd->Command.SequenceNumber = 0;
12039+ cmd->Command.SessionId = Session;
12040+ cmd->NwcCommand = NWC_SET_CONN_INFO;
12041+
12042+ pDConnInfo = (PNwdCSetConnInfo) cmd->data;
12043+
12044+ pDConnInfo->ConnHandle = (HANDLE) (unsigned long) connInfo.ConnHandle;
12045+ pDConnInfo->uInfoLevel = connInfo.uInfoLevel;
12046+ pDConnInfo->uInfoLength = connInfo.uInfoLength;
12047+ cmd->dataLen = sizeof(*pDConnInfo);
12048+
12049+ retCode =
12050+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12051+ (void **)&reply, &replylen,
12052+ INTERRUPTIBLE);
12053+ if (reply) {
12054+ retCode = reply->Reply.ErrorCode;
12055+ kfree(reply);
12056+ }
12057+ kfree(cmd);
12058+
12059+ }
12060+
12061+ return (retCode);
12062+
12063+}
12064+
12065+/*++======================================================================*/
12066+int NwGetIdentityInfo(PXPLAT pdata, session_t Session)
12067+/*
12068+ * Arguments:
12069+ *
12070+ * Returns:
12071+ *
12072+ * Abstract:
12073+ *
12074+ * Notes:
12075+ *
12076+ * Environment:
12077+ *
12078+ *========================================================================*/
12079+{
12080+ PXPLAT_CALL_REQUEST cmd;
12081+ PXPLAT_CALL_REPLY reply;
12082+ NwcGetIdentityInfo qidInfo, *gId;
12083+ PNwdCGetIdentityInfo idInfo;
12084+ NwcString xferStr;
12085+ char *str;
12086+ int retCode = -ENOMEM;
12087+ unsigned long cmdlen, replylen, cpylen;
12088+
12089+ cmdlen = sizeof(*cmd) + sizeof(*idInfo);
12090+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12091+ cpylen = copy_from_user(&qidInfo, pdata->reqData, sizeof(qidInfo));
12092+
12093+ if (cmd) {
12094+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12095+ cmd->Command.SequenceNumber = 0;
12096+ cmd->Command.SessionId = Session;
12097+ cmd->NwcCommand = NWC_GET_IDENTITY_INFO;
12098+
12099+ idInfo = (PNwdCGetIdentityInfo) cmd->data;
12100+
12101+ idInfo->AuthenticationId = qidInfo.AuthenticationId;
12102+ cmd->dataLen = sizeof(*idInfo);
12103+
12104+ retCode =
12105+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12106+ (void **)&reply, &replylen,
12107+ INTERRUPTIBLE);
12108+ if (reply) {
12109+ retCode = reply->Reply.ErrorCode;
12110+
12111+ if (!reply->Reply.ErrorCode) {
12112+ /*
12113+ * Save the return info to the user structure.
12114+ */
12115+ gId = pdata->reqData;
12116+ idInfo = (PNwdCGetIdentityInfo) reply->data;
12117+ cpylen =
12118+ copy_to_user(&gId->AuthenticationId,
12119+ &idInfo->AuthenticationId,
12120+ sizeof(idInfo->
12121+ AuthenticationId));
12122+ cpylen =
12123+ copy_to_user(&gId->AuthType,
12124+ &idInfo->AuthType,
12125+ sizeof(idInfo->AuthType));
12126+ cpylen =
12127+ copy_to_user(&gId->IdentityFlags,
12128+ &idInfo->IdentityFlags,
12129+ sizeof(idInfo->IdentityFlags));
12130+ cpylen =
12131+ copy_to_user(&gId->NameType,
12132+ &idInfo->NameType,
12133+ sizeof(idInfo->NameType));
12134+ cpylen =
12135+ copy_to_user(&gId->ObjectType,
12136+ &idInfo->ObjectType,
12137+ sizeof(idInfo->ObjectType));
12138+
12139+ cpylen =
12140+ copy_from_user(&xferStr, gId->pDomainName,
12141+ sizeof(NwcString));
12142+ str =
12143+ (char *)((char *)reply->data +
12144+ idInfo->pDomainNameOffset);
12145+ cpylen =
12146+ copy_to_user(xferStr.pBuffer, str,
12147+ idInfo->domainLen);
12148+ xferStr.DataType = NWC_STRING_TYPE_ASCII;
12149+ xferStr.DataLen = idInfo->domainLen;
12150+ cpylen =
12151+ copy_to_user(gId->pDomainName, &xferStr,
12152+ sizeof(NwcString));
12153+
12154+ cpylen =
12155+ copy_from_user(&xferStr, gId->pObjectName,
12156+ sizeof(NwcString));
12157+ str =
12158+ (char *)((char *)reply->data +
12159+ idInfo->pObjectNameOffset);
12160+ cpylen =
12161+ copy_to_user(xferStr.pBuffer, str,
12162+ idInfo->objectLen);
12163+ xferStr.DataLen = idInfo->objectLen - 1;
12164+ xferStr.DataType = NWC_STRING_TYPE_ASCII;
12165+ cpylen =
12166+ copy_to_user(gId->pObjectName, &xferStr,
12167+ sizeof(NwcString));
12168+ }
12169+
12170+ kfree(reply);
12171+ }
12172+ kfree(cmd);
12173+
12174+ }
12175+
12176+ return (retCode);
12177+}
12178+
12179+/*++======================================================================*/
12180+int NwScanConnInfo(PXPLAT pdata, session_t Session)
12181+/*
12182+ * Arguments:
12183+ *
12184+ * Returns:
12185+ *
12186+ * Abstract:
12187+ *
12188+ * Notes:
12189+ *
12190+ * Environment:
12191+ *
12192+ *========================================================================*/
12193+{
12194+ PXPLAT_CALL_REQUEST cmd;
12195+ PXPLAT_CALL_REPLY reply;
12196+ NwcScanConnInfo connInfo, *rInfo;
12197+ PNwdCScanConnInfo pDConnInfo;
12198+ int retCode = -ENOMEM;
12199+ unsigned long cmdlen, replylen, cpylen;
12200+ unsigned char *localData;
12201+
12202+ cpylen =
12203+ copy_from_user(&connInfo, pdata->reqData, sizeof(NwcScanConnInfo));
12204+
12205+ cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo) + connInfo.uScanInfoLen;
12206+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12207+
12208+ if (cmd) {
12209+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12210+ cmd->Command.SequenceNumber = 0;
12211+ cmd->Command.SessionId = Session;
12212+ cmd->NwcCommand = NWC_SCAN_CONN_INFO;
12213+
12214+ pDConnInfo = (PNwdCScanConnInfo) cmd->data;
12215+
12216+ DbgPrint("NwScanConnInfo: Input Data\n");
12217+ DbgPrint("connInfo.uScanIndex = 0x%X\n", connInfo.uScanIndex);
12218+ DbgPrint("connInfo.uConnectionReference = 0x%X\n",
12219+ connInfo.uConnectionReference);
12220+ DbgPrint("connInfo.uScanInfoLevel = 0x%X\n",
12221+ connInfo.uScanInfoLevel);
12222+ DbgPrint("connInfo.uScanInfoLen = 0x%X\n",
12223+ connInfo.uScanInfoLen);
12224+ DbgPrint("connInfo.uReturnInfoLength = 0x%X\n",
12225+ connInfo.uReturnInfoLength);
12226+ DbgPrint("connInfo.uReturnInfoLevel = 0x%X\n",
12227+ connInfo.uReturnInfoLevel);
12228+ DbgPrint("connInfo.uScanFlags = 0x%X\n", connInfo.uScanFlags);
12229+
12230+ pDConnInfo->uScanIndex = connInfo.uScanIndex;
12231+ pDConnInfo->uConnectionReference =
12232+ connInfo.uConnectionReference;
12233+ pDConnInfo->uScanInfoLevel = connInfo.uScanInfoLevel;
12234+ pDConnInfo->uScanInfoLen = connInfo.uScanInfoLen;
12235+ pDConnInfo->uReturnInfoLength = connInfo.uReturnInfoLength;
12236+ pDConnInfo->uReturnInfoLevel = connInfo.uReturnInfoLevel;
12237+ pDConnInfo->uScanFlags = connInfo.uScanFlags;
12238+
12239+ if (pDConnInfo->uScanInfoLen) {
12240+ localData = (unsigned char *) pDConnInfo;
12241+ pDConnInfo->uScanConnInfoOffset = sizeof(*pDConnInfo);
12242+ localData += pDConnInfo->uScanConnInfoOffset;
12243+ cpylen =
12244+ copy_from_user(localData, connInfo.pScanConnInfo,
12245+ connInfo.uScanInfoLen);
12246+ } else {
12247+ pDConnInfo->uScanConnInfoOffset = 0;
12248+ }
12249+
12250+ cmd->dataLen = sizeof(*pDConnInfo);
12251+
12252+ retCode =
12253+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12254+ (void **)&reply, &replylen,
12255+ INTERRUPTIBLE);
12256+ if (reply) {
12257+ DbgPrint("NwScanConnInfo: Reply recieved\n");
12258+ DbgPrint(" NextIndex = %x\n", connInfo.uScanIndex);
12259+ DbgPrint(" ErrorCode = %x\n", reply->Reply.ErrorCode);
12260+ DbgPrint(" data = %x\n", reply->data);
12261+
12262+ pDConnInfo = (PNwdCScanConnInfo) reply->data;
12263+ retCode = (unsigned long) reply->Reply.ErrorCode;
12264+ if (!retCode) {
12265+ GetUserData(&connInfo, cmd, reply);
12266+ rInfo = (NwcScanConnInfo *) pdata->repData;
12267+ cpylen =
12268+ copy_to_user(pdata->repData,
12269+ &pDConnInfo->uScanIndex,
12270+ sizeof(pDConnInfo->
12271+ uScanIndex));
12272+ cpylen =
12273+ copy_to_user(&rInfo->uConnectionReference,
12274+ &pDConnInfo->
12275+ uConnectionReference,
12276+ sizeof(pDConnInfo->
12277+ uConnectionReference));
12278+ } else {
12279+ unsigned long x;
12280+
12281+ x = 0;
12282+ rInfo = (NwcScanConnInfo *) pdata->reqData;
12283+ cpylen =
12284+ copy_to_user(&rInfo->uConnectionReference,
12285+ &x,
12286+ sizeof(rInfo->
12287+ uConnectionReference));
12288+ }
12289+
12290+ kfree(reply);
12291+ } else {
12292+ retCode = -EIO;
12293+ }
12294+ kfree(cmd);
12295+
12296+ }
12297+
12298+ return (retCode);
12299+}
12300+
12301+/*++======================================================================*/
12302+static void GetUserData(NwcScanConnInfo * connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply)
12303+/*
12304+ * Abstract: Copies the user data out of the scan conn info call.
12305+ *
12306+ *========================================================================*/
12307+{
12308+ unsigned long uLevel;
12309+ PNwdCScanConnInfo pDConnInfo;
12310+
12311+ unsigned char *srcData = NULL;
12312+ unsigned long dataLen = 0, cpylen;
12313+
12314+ pDConnInfo = (PNwdCScanConnInfo) reply->data;
12315+ uLevel = pDConnInfo->uReturnInfoLevel;
12316+ DbgPrint
12317+ ("[GetUserData] uLevel = %d, reply = 0x%p, reply->data = 0x%X\n",
12318+ uLevel, reply, reply->data);
12319+
12320+ switch (uLevel) {
12321+ case NWC_CONN_INFO_RETURN_ALL:
12322+ case NWC_CONN_INFO_NDS_STATE:
12323+ case NWC_CONN_INFO_MAX_PACKET_SIZE:
12324+ case NWC_CONN_INFO_LICENSE_STATE:
12325+ case NWC_CONN_INFO_PUBLIC_STATE:
12326+ case NWC_CONN_INFO_SERVICE_TYPE:
12327+ case NWC_CONN_INFO_DISTANCE:
12328+ case NWC_CONN_INFO_SERVER_VERSION:
12329+ case NWC_CONN_INFO_AUTH_ID:
12330+ case NWC_CONN_INFO_SUSPENDED:
12331+ case NWC_CONN_INFO_WORKGROUP_ID:
12332+ case NWC_CONN_INFO_SECURITY_STATE:
12333+ case NWC_CONN_INFO_CONN_NUMBER:
12334+ case NWC_CONN_INFO_USER_ID:
12335+ case NWC_CONN_INFO_BCAST_STATE:
12336+ case NWC_CONN_INFO_CONN_REF:
12337+ case NWC_CONN_INFO_AUTH_STATE:
12338+ case NWC_CONN_INFO_TREE_NAME:
12339+ case NWC_CONN_INFO_SERVER_NAME:
12340+ case NWC_CONN_INFO_VERSION:
12341+ srcData = (unsigned char *) pDConnInfo;
12342+ srcData += pDConnInfo->uReturnConnInfoOffset;
12343+ dataLen = pDConnInfo->uReturnInfoLength;
12344+ break;
12345+
12346+ case NWC_CONN_INFO_TRAN_ADDR:
12347+ {
12348+ unsigned char *dstData = connInfo->pReturnConnInfo;
12349+ NwcTranAddr tranAddr;
12350+
12351+ srcData = (unsigned char *) reply->data;
12352+ dataLen = reply->dataLen;
12353+
12354+ DbgPrint
12355+ ("GetUserData NWC_CONN_INFO_TRAN_ADDR 0x%p -> 0x%p :: 0x%X\n",
12356+ srcData, connInfo->pReturnConnInfo, dataLen);
12357+
12358+ cpylen =
12359+ copy_from_user(&tranAddr, dstData,
12360+ sizeof(tranAddr));
12361+
12362+ srcData +=
12363+ ((PNwdCScanConnInfo) srcData)->
12364+ uReturnConnInfoOffset;
12365+
12366+ tranAddr.uTransportType =
12367+ ((PNwdTranAddr) srcData)->uTransportType;
12368+ tranAddr.uAddressLength =
12369+ ((PNwdTranAddr) srcData)->uAddressLength;
12370+
12371+ cpylen =
12372+ copy_to_user(dstData, &tranAddr, sizeof(tranAddr));
12373+ cpylen =
12374+ copy_to_user(tranAddr.puAddress,
12375+ ((PNwdTranAddr) srcData)->Buffer,
12376+ ((PNwdTranAddr) srcData)->
12377+ uAddressLength);
12378+ dataLen = 0;
12379+ break;
12380+ }
12381+ case NWC_CONN_INFO_RETURN_NONE:
12382+ case NWC_CONN_INFO_TREE_NAME_UNICODE:
12383+ case NWC_CONN_INFO_SERVER_NAME_UNICODE:
12384+ case NWC_CONN_INFO_LOCAL_TRAN_ADDR:
12385+ case NWC_CONN_INFO_ALTERNATE_ADDR:
12386+ case NWC_CONN_INFO_SERVER_GUID:
12387+ default:
12388+ break;
12389+ }
12390+
12391+ if (srcData && dataLen) {
12392+ DbgPrint("Copy Data in GetUserData 0x%p -> 0x%p :: 0x%X\n",
12393+ srcData, connInfo->pReturnConnInfo, dataLen);
12394+ cpylen =
12395+ copy_to_user(connInfo->pReturnConnInfo, srcData, dataLen);
12396+ }
12397+
12398+ return;
12399+}
12400+
12401+/*++======================================================================*/
12402+static void GetConnData(NwcGetConnInfo * connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply)
12403+/*
12404+ * Abstract: Copies the user data out of the scan conn info call.
12405+ *
12406+ *========================================================================*/
12407+{
12408+ unsigned long uLevel;
12409+ PNwdCGetConnInfo pDConnInfo;
12410+
12411+ unsigned char *srcData = NULL;
12412+ unsigned long dataLen = 0, cpylen;
12413+
12414+ pDConnInfo = (PNwdCGetConnInfo) cmd->data;
12415+ uLevel = pDConnInfo->uInfoLevel;
12416+
12417+ switch (uLevel) {
12418+ case NWC_CONN_INFO_RETURN_ALL:
12419+ srcData = (unsigned char *) reply->data;
12420+ dataLen = reply->dataLen;
12421+ break;
12422+
12423+ case NWC_CONN_INFO_RETURN_NONE:
12424+ dataLen = 0;
12425+ break;
12426+
12427+ case NWC_CONN_INFO_TRAN_ADDR:
12428+ {
12429+ unsigned char *dstData = connInfo->pConnInfo;
12430+ NwcTranAddr tranAddr;
12431+
12432+ srcData = (unsigned char *) reply->data;
12433+
12434+ cpylen =
12435+ copy_from_user(&tranAddr, dstData,
12436+ sizeof(tranAddr));
12437+ tranAddr.uTransportType =
12438+ ((PNwdTranAddr) srcData)->uTransportType;
12439+ tranAddr.uAddressLength =
12440+ ((PNwdTranAddr) srcData)->uAddressLength;
12441+
12442+ cpylen =
12443+ copy_to_user(dstData, &tranAddr, sizeof(tranAddr));
12444+ cpylen =
12445+ copy_to_user(tranAddr.puAddress,
12446+ ((PNwdTranAddr) srcData)->Buffer,
12447+ ((PNwdTranAddr) srcData)->
12448+ uAddressLength);
12449+ dataLen = 0;
12450+ break;
12451+ }
12452+ case NWC_CONN_INFO_NDS_STATE:
12453+ case NWC_CONN_INFO_MAX_PACKET_SIZE:
12454+ case NWC_CONN_INFO_LICENSE_STATE:
12455+ case NWC_CONN_INFO_PUBLIC_STATE:
12456+ case NWC_CONN_INFO_SERVICE_TYPE:
12457+ case NWC_CONN_INFO_DISTANCE:
12458+ case NWC_CONN_INFO_SERVER_VERSION:
12459+ case NWC_CONN_INFO_AUTH_ID:
12460+ case NWC_CONN_INFO_SUSPENDED:
12461+ case NWC_CONN_INFO_WORKGROUP_ID:
12462+ case NWC_CONN_INFO_SECURITY_STATE:
12463+ case NWC_CONN_INFO_CONN_NUMBER:
12464+ case NWC_CONN_INFO_USER_ID:
12465+ case NWC_CONN_INFO_BCAST_STATE:
12466+ case NWC_CONN_INFO_CONN_REF:
12467+ case NWC_CONN_INFO_AUTH_STATE:
12468+ case NWC_CONN_INFO_VERSION:
12469+ case NWC_CONN_INFO_SERVER_NAME:
12470+ case NWC_CONN_INFO_TREE_NAME:
12471+ srcData = (unsigned char *) reply->data;
12472+ dataLen = reply->dataLen;
12473+ break;
12474+
12475+ case NWC_CONN_INFO_TREE_NAME_UNICODE:
12476+ case NWC_CONN_INFO_SERVER_NAME_UNICODE:
12477+ break;
12478+
12479+ case NWC_CONN_INFO_LOCAL_TRAN_ADDR:
12480+ break;
12481+
12482+ case NWC_CONN_INFO_ALTERNATE_ADDR:
12483+ break;
12484+
12485+ case NWC_CONN_INFO_SERVER_GUID:
12486+ break;
12487+
12488+ default:
12489+ break;
12490+ }
12491+
12492+ if (srcData && dataLen) {
12493+ cpylen =
12494+ copy_to_user(connInfo->pConnInfo, srcData,
12495+ connInfo->uInfoLength);
12496+ }
12497+
12498+ return;
12499+}
12500+
12501+/*++======================================================================*/
12502+int NwGetDaemonVersion(PXPLAT pdata, session_t Session)
12503+/*
12504+ * Arguments:
12505+ *
12506+ * Returns:
12507+ *
12508+ * Abstract:
12509+ *
12510+ * Notes:
12511+ *
12512+ * Environment:
12513+ *
12514+ *========================================================================*/
12515+{
12516+ PXPLAT_CALL_REQUEST cmd;
12517+ PXPLAT_CALL_REPLY reply;
12518+ PNwdCGetRequesterVersion pDVersion;
12519+ int retCode = -ENOMEM;
12520+ unsigned long cmdlen, datalen, replylen, cpylen;
12521+
12522+ datalen = sizeof(*pDVersion);
12523+ cmdlen = datalen + sizeof(*cmd);
12524+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12525+
12526+ if (cmd) {
12527+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12528+ cmd->Command.SequenceNumber = 0;
12529+ cmd->Command.SessionId = Session;
12530+ cmd->NwcCommand = NWC_GET_REQUESTER_VERSION;
12531+ cmdlen = sizeof(*cmd);
12532+ retCode =
12533+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12534+ (void **)&reply, &replylen,
12535+ INTERRUPTIBLE);
12536+ if (reply) {
12537+ retCode = reply->Reply.ErrorCode;
12538+ pDVersion = (PNwdCGetRequesterVersion) reply->data;
12539+ cpylen =
12540+ copy_to_user(pDVersion, pdata->reqData,
12541+ sizeof(*pDVersion));
12542+ kfree(reply);
12543+ }
12544+ kfree(cmd);
12545+ }
12546+ return (retCode);
12547+
12548+}
12549+
12550+/*++======================================================================*/
12551+int NwcGetPreferredDSTree(PXPLAT pdata, session_t Session)
12552+/*
12553+ * Arguments:
12554+ *
12555+ * Returns:
12556+ *
12557+ * Abstract:
12558+ *
12559+ * Notes:
12560+ *
12561+ * Environment:
12562+ *
12563+ *========================================================================*/
12564+{
12565+ PXPLAT_CALL_REQUEST cmd;
12566+ PXPLAT_CALL_REPLY reply;
12567+ PNwdCGetPreferredDsTree pDGetTree;
12568+ NwcGetPreferredDsTree xplatCall, *p;
12569+ int retCode = -ENOMEM;
12570+ unsigned long cmdlen, datalen, replylen, cpylen;
12571+ unsigned char *dPtr;
12572+
12573+ cpylen =
12574+ copy_from_user(&xplatCall, pdata->reqData,
12575+ sizeof(NwcGetPreferredDsTree));
12576+ datalen = sizeof(*pDGetTree) + xplatCall.uTreeLength;
12577+ cmdlen = datalen + sizeof(*cmd);
12578+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12579+
12580+ if (cmd) {
12581+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12582+ cmd->Command.SequenceNumber = 0;
12583+ cmd->Command.SessionId = Session;
12584+ cmd->NwcCommand = NWC_GET_PREFERRED_DS_TREE;
12585+ cmdlen = sizeof(*cmd);
12586+
12587+ retCode =
12588+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12589+ (void **)&reply, &replylen,
12590+ INTERRUPTIBLE);
12591+ if (reply) {
12592+ retCode = reply->Reply.ErrorCode;
12593+ if (!retCode) {
12594+ pDGetTree =
12595+ (PNwdCGetPreferredDsTree) reply->data;
12596+ dPtr =
12597+ reply->data + pDGetTree->DsTreeNameOffset;
12598+ p = (NwcGetPreferredDsTree *) pdata->reqData;
12599+
12600+ DbgPrint
12601+ ("NwcGetPreferredDSTree: Reply recieved\n");
12602+ DbgPrint(" TreeLen = %x\n",
12603+ pDGetTree->uTreeLength);
12604+ DbgPrint(" TreeName = %s\n", dPtr);
12605+
12606+ cpylen =
12607+ copy_to_user(p, &pDGetTree->uTreeLength, 4);
12608+ cpylen =
12609+ copy_to_user(xplatCall.pDsTreeName, dPtr,
12610+ pDGetTree->uTreeLength);
12611+ }
12612+ kfree(reply);
12613+ }
12614+ kfree(cmd);
12615+ }
12616+ return (retCode);
12617+
12618+}
12619+
12620+/*++======================================================================*/
12621+int NwcSetPreferredDSTree(PXPLAT pdata, session_t Session)
12622+/*
12623+ * Arguments:
12624+ *
12625+ * Returns:
12626+ *
12627+ * Abstract:
12628+ *
12629+ * Notes:
12630+ *
12631+ * Environment:
12632+ *
12633+ *========================================================================*/
12634+{
12635+ PXPLAT_CALL_REQUEST cmd;
12636+ PXPLAT_CALL_REPLY reply;
12637+ PNwdCSetPreferredDsTree pDSetTree;
12638+ NwcSetPreferredDsTree xplatCall;
12639+ int retCode = -ENOMEM;
12640+ unsigned long cmdlen, datalen, replylen, cpylen;
12641+ unsigned char *dPtr;
12642+
12643+ cpylen =
12644+ copy_from_user(&xplatCall, pdata->reqData,
12645+ sizeof(NwcSetPreferredDsTree));
12646+ datalen = sizeof(*pDSetTree) + xplatCall.uTreeLength;
12647+ cmdlen = datalen + sizeof(*cmd);
12648+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12649+
12650+ if (cmd) {
12651+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12652+ cmd->Command.SequenceNumber = 0;
12653+ cmd->Command.SessionId = Session;
12654+ cmd->NwcCommand = NWC_SET_PREFERRED_DS_TREE;
12655+
12656+ pDSetTree = (PNwdCSetPreferredDsTree) cmd->data;
12657+ pDSetTree->DsTreeNameOffset = sizeof(*pDSetTree);
12658+ pDSetTree->uTreeLength = xplatCall.uTreeLength;
12659+
12660+ dPtr = cmd->data + sizeof(*pDSetTree);
12661+ cpylen =
12662+ copy_from_user(dPtr, xplatCall.pDsTreeName,
12663+ xplatCall.uTreeLength);
12664+
12665+ retCode =
12666+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12667+ (void **)&reply, &replylen,
12668+ INTERRUPTIBLE);
12669+ if (reply) {
12670+ retCode = reply->Reply.ErrorCode;
12671+ kfree(reply);
12672+ }
12673+ kfree(cmd);
12674+ }
12675+ return (retCode);
12676+
12677+}
12678+
12679+/*++======================================================================*/
12680+int NwcSetDefaultNameCtx(PXPLAT pdata, session_t Session)
12681+/*
12682+ * Arguments:
12683+ *
12684+ * Returns:
12685+ *
12686+ * Abstract:
12687+ *
12688+ * Notes:
12689+ *
12690+ * Environment:
12691+ *
12692+ *========================================================================*/
12693+{
12694+ PXPLAT_CALL_REQUEST cmd;
12695+ PXPLAT_CALL_REPLY reply;
12696+ NwcSetDefaultNameContext xplatCall;
12697+ PNwdCSetDefaultNameContext pDSet;
12698+ int retCode = -ENOMEM;
12699+ unsigned long cmdlen, datalen, replylen, cpylen;
12700+ unsigned char *dPtr;
12701+
12702+ cpylen =
12703+ copy_from_user(&xplatCall, pdata->reqData,
12704+ sizeof(NwcSetDefaultNameContext));
12705+ datalen =
12706+ sizeof(*pDSet) + xplatCall.uTreeLength + xplatCall.uNameLength;
12707+ cmdlen = datalen + sizeof(*cmd);
12708+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12709+
12710+ if (cmd) {
12711+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12712+ cmd->Command.SequenceNumber = 0;
12713+ cmd->Command.SessionId = Session;
12714+ cmd->NwcCommand = NWC_SET_DEFAULT_NAME_CONTEXT;
12715+ cmd->dataLen =
12716+ sizeof(NwdCSetDefaultNameContext) + xplatCall.uTreeLength +
12717+ xplatCall.uNameLength;
12718+
12719+ pDSet = (PNwdCSetDefaultNameContext) cmd->data;
12720+ dPtr = cmd->data;
12721+
12722+ pDSet->TreeOffset = sizeof(NwdCSetDefaultNameContext);
12723+ pDSet->uTreeLength = xplatCall.uTreeLength;
12724+ pDSet->NameContextOffset =
12725+ pDSet->TreeOffset + xplatCall.uTreeLength;
12726+ pDSet->uNameLength = xplatCall.uNameLength;
12727+
12728+//sgled cpylen = copy_from_user(dPtr+pDSet->TreeOffset, xplatCall.pTreeName, xplatCall.uTreeLength);
12729+ cpylen = copy_from_user(dPtr + pDSet->TreeOffset, xplatCall.pDsTreeName, xplatCall.uTreeLength); //sgled
12730+ cpylen =
12731+ copy_from_user(dPtr + pDSet->NameContextOffset,
12732+ xplatCall.pNameContext,
12733+ xplatCall.uNameLength);
12734+
12735+ retCode =
12736+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12737+ (void **)&reply, &replylen,
12738+ INTERRUPTIBLE);
12739+ if (reply) {
12740+ retCode = reply->Reply.ErrorCode;
12741+ kfree(reply);
12742+ }
12743+ kfree(cmd);
12744+ }
12745+ return (retCode);
12746+
12747+}
12748+
12749+/*++======================================================================*/
12750+int NwcGetDefaultNameCtx(PXPLAT pdata, session_t Session)
12751+/*
12752+ * Arguments:
12753+ *
12754+ * Returns:
12755+ *
12756+ * Abstract:
12757+ *
12758+ * Notes:
12759+ *
12760+ * Environment:
12761+ *
12762+ *========================================================================*/
12763+{
12764+ PXPLAT_CALL_REQUEST cmd;
12765+ PXPLAT_CALL_REPLY reply;
12766+ NwcGetDefaultNameContext xplatCall;
12767+ PNwdCGetDefaultNameContext pGet;
12768+ char *dPtr;
12769+ int retCode = -ENOMEM;
12770+ unsigned long cmdlen, replylen, cpylen;
12771+
12772+ cpylen =
12773+ copy_from_user(&xplatCall, pdata->reqData,
12774+ sizeof(NwcGetDefaultNameContext));
12775+ cmdlen =
12776+ sizeof(*cmd) + sizeof(NwdCGetDefaultNameContext) +
12777+ xplatCall.uTreeLength;
12778+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12779+
12780+ if (cmd) {
12781+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12782+ cmd->Command.SequenceNumber = 0;
12783+ cmd->Command.SessionId = Session;
12784+ cmd->NwcCommand = NWC_GET_DEFAULT_NAME_CONTEXT;
12785+ cmd->dataLen =
12786+ sizeof(NwdCGetDefaultNameContext) + xplatCall.uTreeLength;
12787+
12788+ pGet = (PNwdCGetDefaultNameContext) cmd->data;
12789+ dPtr = cmd->data;
12790+
12791+ pGet->TreeOffset = sizeof(NwdCGetDefaultNameContext);
12792+ pGet->uTreeLength = xplatCall.uTreeLength;
12793+
12794+//sgled cpylen = copy_from_user( dPtr + pGet->TreeOffset, xplatCall.pTreeName, xplatCall.uTreeLength);
12795+ cpylen = copy_from_user(dPtr + pGet->TreeOffset, xplatCall.pDsTreeName, xplatCall.uTreeLength); //sgled
12796+ dPtr[pGet->TreeOffset + pGet->uTreeLength] = 0;
12797+
12798+ retCode =
12799+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12800+ (void **)&reply, &replylen,
12801+ INTERRUPTIBLE);
12802+ if (reply) {
12803+ retCode = reply->Reply.ErrorCode;
12804+ if (!retCode) {
12805+ pGet = (PNwdCGetDefaultNameContext) reply->data;
12806+
12807+ DbgPrint
12808+ ("NwcGetDefaultNameCtx: retCode=0x%x uNameLength1=%d uNameLength2=%d\n",
12809+ retCode, pGet->uNameLength,
12810+ xplatCall.uNameLength);
12811+ if (xplatCall.uNameLength < pGet->uNameLength) {
12812+ pGet->uNameLength =
12813+ xplatCall.uNameLength;
12814+ retCode = NWE_BUFFER_OVERFLOW;
12815+ }
12816+ dPtr = (char *)pGet + pGet->NameContextOffset;
12817+ cpylen =
12818+ copy_to_user(xplatCall.pNameContext, dPtr,
12819+ pGet->uNameLength);
12820+ }
12821+
12822+ kfree(reply);
12823+ }
12824+ kfree(cmd);
12825+ }
12826+ return (retCode);
12827+
12828+}
12829+
12830+int NwQueryFeature(PXPLAT pdata, session_t Session)
12831+{
12832+ NwcQueryFeature xpCall;
12833+ int status = 0;
12834+ unsigned long cpylen;
12835+
12836+ cpylen =
12837+ copy_from_user(&xpCall, pdata->reqData, sizeof(NwcQueryFeature));
12838+ switch (xpCall.Feature) {
12839+ case NWC_FEAT_NDS:
12840+ case NWC_FEAT_NDS_MTREE:
12841+ case NWC_FEAT_PRN_CAPTURE:
12842+ case NWC_FEAT_NDS_RESOLVE:
12843+
12844+ status = NWE_REQUESTER_FAILURE;
12845+
12846+ }
12847+ return (status);
12848+}
12849+
12850+/*++======================================================================*/
12851+int NwcGetTreeMonitoredConn(PXPLAT pdata, session_t Session)
12852+/*
12853+ * Arguments:
12854+ *
12855+ * Returns:
12856+ *
12857+ * Abstract:
12858+ *
12859+ * Notes:
12860+ *
12861+ * Environment:
12862+ *
12863+ *========================================================================*/
12864+{
12865+ PXPLAT_CALL_REQUEST cmd;
12866+ PXPLAT_CALL_REPLY reply;
12867+ NwcGetTreeMonitoredConnRef xplatCall, *p;
12868+ PNwdCGetTreeMonitoredConnRef pDConnRef;
12869+ char *dPtr;
12870+ unsigned long status = -ENOMEM, cmdlen, datalen, replylen, cpylen;
12871+
12872+ cpylen =
12873+ copy_from_user(&xplatCall, pdata->reqData,
12874+ sizeof(NwcGetTreeMonitoredConnRef));
12875+ datalen = sizeof(*pDConnRef) + xplatCall.pTreeName->DataLen;
12876+ cmdlen = datalen + sizeof(*cmd);
12877+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12878+
12879+ if (cmd) {
12880+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12881+ cmd->Command.SequenceNumber = 0;
12882+ cmd->Command.SessionId = Session;
12883+ cmd->NwcCommand = NWC_GET_TREE_MONITORED_CONN_REF;
12884+
12885+ pDConnRef = (PNwdCGetTreeMonitoredConnRef) cmd->data;
12886+ pDConnRef->TreeName.boffset = sizeof(*pDConnRef);
12887+ pDConnRef->TreeName.len = xplatCall.pTreeName->DataLen;
12888+ pDConnRef->TreeName.type = xplatCall.pTreeName->DataType;
12889+
12890+ dPtr = cmd->data + sizeof(*pDConnRef);
12891+ cpylen =
12892+ copy_from_user(dPtr, xplatCall.pTreeName->pBuffer,
12893+ pDConnRef->TreeName.len);
12894+ status =
12895+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12896+ (void **)&reply, &replylen,
12897+ INTERRUPTIBLE);
12898+ if (reply) {
12899+ pDConnRef = (PNwdCGetTreeMonitoredConnRef) reply->data;
12900+ dPtr = reply->data + pDConnRef->TreeName.boffset;
12901+ p = (NwcGetTreeMonitoredConnRef *) pdata->reqData;
12902+ cpylen =
12903+ copy_to_user(&p->uConnReference,
12904+ &pDConnRef->uConnReference, 4);
12905+
12906+ status = reply->Reply.ErrorCode;
12907+ kfree(reply);
12908+ }
12909+ kfree(cmd);
12910+
12911+ }
12912+
12913+ return (status);
12914+}
12915+
12916+/*++======================================================================*/
12917+int NwcEnumIdentities(PXPLAT pdata, session_t Session)
12918+/*
12919+ * Arguments:
12920+ *
12921+ * Returns:
12922+ *
12923+ * Abstract:
12924+ *
12925+ * Notes:
12926+ *
12927+ * Environment:
12928+ *
12929+ *========================================================================*/
12930+{
12931+ PXPLAT_CALL_REQUEST cmd;
12932+ PXPLAT_CALL_REPLY reply;
12933+ NwcEnumerateIdentities xplatCall, *eId;
12934+ PNwdCEnumerateIdentities pEnum;
12935+ NwcString xferStr;
12936+ char *str;
12937+ unsigned long status = -ENOMEM, cmdlen, datalen, replylen, cpylen;
12938+
12939+ cpylen =
12940+ copy_from_user(&xplatCall, pdata->reqData,
12941+ sizeof(NwcEnumerateIdentities));
12942+ datalen = sizeof(*pEnum);
12943+ cmdlen = datalen + sizeof(*cmd);
12944+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
12945+
12946+ if (cmd) {
12947+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
12948+ cmd->Command.SequenceNumber = 0;
12949+ cmd->Command.SessionId = Session;
12950+ cmd->NwcCommand = NWC_ENUMERATE_IDENTITIES;
12951+
12952+ DbgPrint("NwcEnumIdentities: Send Request\n");
12953+ DbgPrint(" iterator = %x\n", xplatCall.Iterator);
12954+ DbgPrint(" cmdlen = %d\n", cmdlen);
12955+
12956+ pEnum = (PNwdCEnumerateIdentities) cmd->data;
12957+ pEnum->Iterator = xplatCall.Iterator;
12958+ status =
12959+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
12960+ (void **)&reply, &replylen,
12961+ INTERRUPTIBLE);
12962+ if (reply) {
12963+ status = reply->Reply.ErrorCode;
12964+
12965+ eId = pdata->repData;
12966+ pEnum = (PNwdCEnumerateIdentities) reply->data;
12967+ cpylen =
12968+ copy_to_user(&eId->Iterator, &pEnum->Iterator,
12969+ sizeof(pEnum->Iterator));
12970+ DbgPrint("[XPLAT NWCAPI] Found AuthId 0x%X\n",
12971+ pEnum->AuthenticationId);
12972+ cpylen =
12973+ copy_to_user(&eId->AuthenticationId,
12974+ &pEnum->AuthenticationId,
12975+ sizeof(pEnum->AuthenticationId));
12976+ cpylen =
12977+ copy_to_user(&eId->AuthType, &pEnum->AuthType,
12978+ sizeof(pEnum->AuthType));
12979+ cpylen =
12980+ copy_to_user(&eId->IdentityFlags,
12981+ &pEnum->IdentityFlags,
12982+ sizeof(pEnum->IdentityFlags));
12983+ cpylen =
12984+ copy_to_user(&eId->NameType, &pEnum->NameType,
12985+ sizeof(pEnum->NameType));
12986+ cpylen =
12987+ copy_to_user(&eId->ObjectType, &pEnum->ObjectType,
12988+ sizeof(pEnum->ObjectType));
12989+
12990+ if (!status) {
12991+ cpylen =
12992+ copy_from_user(&xferStr, eId->pDomainName,
12993+ sizeof(NwcString));
12994+ str =
12995+ (char *)((char *)reply->data +
12996+ pEnum->domainNameOffset);
12997+ DbgPrint("[XPLAT NWCAPI] Found Domain %s\n",
12998+ str);
12999+ cpylen =
13000+ copy_to_user(xferStr.pBuffer, str,
13001+ pEnum->domainNameLen);
13002+ xferStr.DataType = NWC_STRING_TYPE_ASCII;
13003+ xferStr.DataLen = pEnum->domainNameLen - 1;
13004+ cpylen =
13005+ copy_to_user(eId->pDomainName, &xferStr,
13006+ sizeof(NwcString));
13007+
13008+ cpylen =
13009+ copy_from_user(&xferStr, eId->pObjectName,
13010+ sizeof(NwcString));
13011+ str =
13012+ (char *)((char *)reply->data +
13013+ pEnum->objectNameOffset);
13014+ DbgPrint("[XPLAT NWCAPI] Found User %s\n", str);
13015+ cpylen =
13016+ copy_to_user(xferStr.pBuffer, str,
13017+ pEnum->objectNameLen);
13018+ xferStr.DataType = NWC_STRING_TYPE_ASCII;
13019+ xferStr.DataLen = pEnum->objectNameLen - 1;
13020+ cpylen =
13021+ copy_to_user(eId->pObjectName, &xferStr,
13022+ sizeof(NwcString));
13023+ }
13024+
13025+ kfree(reply);
13026+
13027+ }
13028+ kfree(cmd);
13029+
13030+ }
13031+ return (status);
13032+}
13033+
13034+/*++======================================================================*/
13035+int NwcChangeAuthKey(PXPLAT pdata, session_t Session)
13036+/*
13037+ * Arguments:
13038+ *
13039+ * Returns:
13040+ *
13041+ * Abstract: Change the password on the server
13042+ *
13043+ * Notes:
13044+ *
13045+ * Environment:
13046+ *
13047+ *========================================================================*/
13048+{
13049+ PXPLAT_CALL_REQUEST cmd;
13050+ PXPLAT_CALL_REPLY reply;
13051+ NwcChangeKey xplatCall;
13052+ PNwdCChangeKey pNewKey;
13053+ NwcString xferStr;
13054+ char *str;
13055+ unsigned long status = -ENOMEM, cmdlen, datalen, replylen, cpylen;
13056+
13057+ cpylen =
13058+ copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcChangeKey));
13059+
13060+ datalen =
13061+ sizeof(NwdCChangeKey) + xplatCall.pDomainName->DataLen +
13062+ xplatCall.pObjectName->DataLen + xplatCall.pNewPassword->DataLen +
13063+ xplatCall.pVerifyPassword->DataLen;
13064+
13065+ cmdlen = sizeof(*cmd) + datalen;
13066+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
13067+
13068+ if (cmd) {
13069+ pNewKey = (PNwdCChangeKey) cmd->data;
13070+ cmd->dataLen = datalen;
13071+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13072+ cmd->Command.SequenceNumber = 0;
13073+ cmd->Command.SessionId = Session;
13074+ cmd->NwcCommand = NWC_CHANGE_KEY;
13075+
13076+ pNewKey->NameType = xplatCall.NameType;
13077+ pNewKey->ObjectType = xplatCall.ObjectType;
13078+ pNewKey->AuthType = xplatCall.AuthType;
13079+ str = (char *)pNewKey;
13080+
13081+ /*
13082+ * Get the tree name
13083+ */
13084+ str += sizeof(*pNewKey);
13085+ cpylen =
13086+ copy_from_user(&xferStr, xplatCall.pDomainName,
13087+ sizeof(NwcString));
13088+ pNewKey->domainNameOffset = sizeof(*pNewKey);
13089+ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen);
13090+ pNewKey->domainNameLen = xferStr.DataLen;
13091+
13092+ /*
13093+ * Get the User Name
13094+ */
13095+ str += pNewKey->domainNameLen;
13096+ cpylen =
13097+ copy_from_user(&xferStr, xplatCall.pObjectName,
13098+ sizeof(NwcString));
13099+ pNewKey->objectNameOffset =
13100+ pNewKey->domainNameOffset + pNewKey->domainNameLen;
13101+ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen);
13102+ pNewKey->objectNameLen = xferStr.DataLen;
13103+
13104+ /*
13105+ * Get the New Password
13106+ */
13107+ str += pNewKey->objectNameLen;
13108+ cpylen =
13109+ copy_from_user(&xferStr, xplatCall.pNewPassword,
13110+ sizeof(NwcString));
13111+ pNewKey->newPasswordOffset =
13112+ pNewKey->objectNameOffset + pNewKey->objectNameLen;
13113+ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen);
13114+ pNewKey->newPasswordLen = xferStr.DataLen;
13115+
13116+ /*
13117+ * Get the Verify Password
13118+ */
13119+ str += pNewKey->newPasswordLen;
13120+ cpylen =
13121+ copy_from_user(&xferStr, xplatCall.pVerifyPassword,
13122+ sizeof(NwcString));
13123+ pNewKey->verifyPasswordOffset =
13124+ pNewKey->newPasswordOffset + pNewKey->newPasswordLen;
13125+ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen);
13126+ pNewKey->verifyPasswordLen = xferStr.DataLen;
13127+
13128+ status =
13129+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
13130+ (void **)&reply, &replylen,
13131+ INTERRUPTIBLE);
13132+ if (reply) {
13133+ status = reply->Reply.ErrorCode;
13134+ kfree(reply);
13135+ }
13136+ memset(cmd, 0, cmdlen);
13137+
13138+ kfree(cmd);
13139+ }
13140+
13141+ return (status);
13142+}
13143+
13144+/*++======================================================================*/
13145+int NwcSetPrimaryConn(PXPLAT pdata, session_t Session)
13146+/*
13147+ * Arguments:
13148+ *
13149+ * Returns:
13150+ *
13151+ * Abstract: Set the primary connection Id
13152+ *
13153+ * Notes:
13154+ *
13155+ * Environment:
13156+ *
13157+ *========================================================================*/
13158+{
13159+ PXPLAT_CALL_REQUEST cmd;
13160+ PXPLAT_CALL_REPLY reply;
13161+ NwcSetPrimaryConnection xplatCall;
13162+ PNwdCSetPrimaryConnection pConn;
13163+ unsigned long status = -ENOMEM, cmdlen, datalen, replylen, cpylen;
13164+
13165+ cpylen =
13166+ copy_from_user(&xplatCall, pdata->reqData,
13167+ sizeof(NwcSetPrimaryConnection));
13168+
13169+ datalen = sizeof(NwdCSetPrimaryConnection);
13170+ cmdlen = sizeof(*cmd) + datalen;
13171+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
13172+ if (cmd) {
13173+ pConn = (PNwdCSetPrimaryConnection) cmd->data;
13174+ cmd->dataLen = datalen;
13175+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13176+ cmd->Command.SequenceNumber = 0;
13177+ cmd->Command.SessionId = Session;
13178+ cmd->NwcCommand = NWC_SET_PRIMARY_CONN;
13179+ pConn->ConnHandle = (HANDLE) (unsigned long) xplatCall.ConnHandle;
13180+ status =
13181+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
13182+ (void **)&reply, &replylen,
13183+ INTERRUPTIBLE);
13184+
13185+ if (reply) {
13186+ status = reply->Reply.ErrorCode;
13187+ kfree(reply);
13188+ }
13189+
13190+ kfree(cmd);
13191+ }
13192+
13193+ return (status);
13194+}
13195+
13196+/*++======================================================================*/
13197+int NwcGetPrimaryConn(PXPLAT pdata, session_t Session)
13198+/*
13199+ * Arguments:
13200+ *
13201+ * Returns:
13202+ *
13203+ * Abstract: Get the Primary connection
13204+ *
13205+ * Notes:
13206+ *
13207+ * Environment:
13208+ *
13209+ *========================================================================*/
13210+{
13211+ XPLAT_CALL_REQUEST cmd;
13212+ PXPLAT_CALL_REPLY reply;
13213+ unsigned long status = -ENOMEM, cmdlen, replylen, cpylen;
13214+
13215+ cmdlen = (unsigned long) (&((PXPLAT_CALL_REQUEST) 0)->data);
13216+
13217+ cmd.dataLen = 0;
13218+ cmd.Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13219+ cmd.Command.SequenceNumber = 0;
13220+ cmd.Command.SessionId = Session;
13221+ cmd.NwcCommand = NWC_GET_PRIMARY_CONN;
13222+
13223+ status =
13224+ Queue_Daemon_Command((void *)&cmd, cmdlen, NULL, 0, (void **)&reply,
13225+ &replylen, INTERRUPTIBLE);
13226+
13227+ if (reply) {
13228+ status = reply->Reply.ErrorCode;
13229+ if (!status) {
13230+ cpylen =
13231+ copy_to_user(pdata->repData, reply->data,
13232+ sizeof(unsigned long));
13233+ }
13234+
13235+ kfree(reply);
13236+ }
13237+
13238+ return (status);
13239+}
13240+
13241+/*++======================================================================*/
13242+int NwcSetMapDrive(PXPLAT pdata, session_t Session)
13243+/*
13244+ * Arguments:
13245+ *
13246+ * Returns:
13247+ *
13248+ * Abstract: Get the Primary connection
13249+ *
13250+ * Notes:
13251+ *
13252+ * Environment:
13253+ *
13254+ *========================================================================*/
13255+{
13256+
13257+ PXPLAT_CALL_REQUEST cmd;
13258+ PXPLAT_CALL_REPLY reply;
13259+ unsigned long status = 0, datalen, cmdlen, replylen, cpylen;
13260+ NwcMapDriveEx symInfo;
13261+
13262+ DbgPrint("Call to NwcSetMapDrive\n");
13263+ cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo));
13264+ cmdlen = sizeof(*cmd);
13265+ datalen =
13266+ sizeof(symInfo) + symInfo.dirPathOffsetLength +
13267+ symInfo.linkOffsetLength;
13268+
13269+ DbgPrint(" cmdlen = %d\n", cmdlen);
13270+ DbgPrint(" dataLen = %d\n", datalen);
13271+ DbgPrint(" symInfo.dirPathOffsetLength = %d\n",
13272+ symInfo.dirPathOffsetLength);
13273+ DbgPrint(" symInfo.linkOffsetLength = %d\n", symInfo.linkOffsetLength);
13274+ DbgPrint(" pdata->datalen = %d\n", pdata->reqLen);
13275+
13276+ mydump(sizeof(symInfo), &symInfo);
13277+
13278+ cmdlen += datalen;
13279+
13280+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
13281+ if (cmd) {
13282+ cmd->dataLen = datalen;
13283+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13284+ cmd->Command.SequenceNumber = 0;
13285+ cmd->Command.SessionId = Session;
13286+ cmd->NwcCommand = NWC_MAP_DRIVE;
13287+
13288+ cpylen = copy_from_user(cmd->data, pdata->reqData, datalen);
13289+ status =
13290+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
13291+ (void **)&reply, &replylen,
13292+ INTERRUPTIBLE);
13293+
13294+ if (reply) {
13295+ status = reply->Reply.ErrorCode;
13296+ kfree(reply);
13297+ }
13298+ kfree(cmd);
13299+ }
13300+ return (status);
13301+
13302+}
13303+
13304+/*++======================================================================*/
13305+int NwcUnMapDrive(PXPLAT pdata, session_t Session)
13306+/*
13307+ * Arguments:
13308+ *
13309+ * Returns:
13310+ *
13311+ * Abstract: Get the Primary connection
13312+ *
13313+ * Notes:
13314+ *
13315+ * Environment:
13316+ *
13317+ *========================================================================*/
13318+{
13319+ PXPLAT_CALL_REQUEST cmd;
13320+ PXPLAT_CALL_REPLY reply;
13321+ unsigned long status = 0, datalen, cmdlen, replylen, cpylen;
13322+ NwcUnmapDriveEx symInfo;
13323+
13324+ DbgPrint("Call to NwcUnMapDrive\n");
13325+
13326+ cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo));
13327+ cmdlen = sizeof(*cmd);
13328+ datalen = sizeof(symInfo) + symInfo.linkLen;
13329+
13330+ cmdlen += datalen;
13331+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
13332+ if (cmd) {
13333+ cmd->dataLen = datalen;
13334+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13335+ cmd->Command.SequenceNumber = 0;
13336+ cmd->Command.SessionId = Session;
13337+ cmd->NwcCommand = NWC_UNMAP_DRIVE;
13338+
13339+ cpylen = copy_from_user(cmd->data, pdata->reqData, datalen);
13340+ status =
13341+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
13342+ (void **)&reply, &replylen,
13343+ INTERRUPTIBLE);
13344+
13345+ if (reply) {
13346+ status = reply->Reply.ErrorCode;
13347+ kfree(reply);
13348+ }
13349+ kfree(cmd);
13350+ }
13351+
13352+ return (status);
13353+}
13354+
13355+/*++======================================================================*/
13356+int NwcEnumerateDrives(PXPLAT pdata, session_t Session)
13357+/*
13358+ * Arguments:
13359+ *
13360+ * Returns:
13361+ *
13362+ * Abstract: Get the Primary connection
13363+ *
13364+ * Notes:
13365+ *
13366+ * Environment:
13367+ *
13368+ *========================================================================*/
13369+{
13370+ PXPLAT_CALL_REQUEST cmd;
13371+ PXPLAT_CALL_REPLY reply;
13372+ unsigned long status = 0, cmdlen, replylen, cpylen;
13373+ unsigned long offset;
13374+ char *cp;
13375+
13376+ DbgPrint("Call to NwcEnumerateDrives\n");
13377+
13378+ cmdlen = sizeof(*cmd);
13379+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
13380+ if (cmd) {
13381+ cmd->dataLen = 0;
13382+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13383+ cmd->Command.SequenceNumber = 0;
13384+ cmd->Command.SessionId = Session;
13385+ cmd->NwcCommand = NWC_ENUMERATE_DRIVES;
13386+ status =
13387+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
13388+ (void **)&reply, &replylen,
13389+ INTERRUPTIBLE);
13390+
13391+ if (reply) {
13392+ status = reply->Reply.ErrorCode;
13393+ DbgPrint("Status Code = 0x%X\n", status);
13394+ if (!status) {
13395+ offset =
13396+ sizeof(((PNwcGetMappedDrives) pdata->
13397+ repData)->MapBuffLen);
13398+ cp = reply->data;
13399+ replylen =
13400+ ((PNwcGetMappedDrives) pdata->repData)->
13401+ MapBuffLen;
13402+ cpylen =
13403+ copy_to_user(pdata->repData, cp, offset);
13404+ cp += offset;
13405+ cpylen =
13406+ copy_to_user(((PNwcGetMappedDrives) pdata->
13407+ repData)->MapBuffer, cp,
13408+ min(replylen - offset,
13409+ reply->dataLen - offset));
13410+ }
13411+
13412+ kfree(reply);
13413+ }
13414+ kfree(cmd);
13415+ }
13416+
13417+ return (status);
13418+}
13419+
13420+/*++======================================================================*/
13421+int NwcGetBroadcastMessage(PXPLAT pdata, session_t Session)
13422+/*
13423+ * Arguments:
13424+ *
13425+ * Returns:
13426+ *
13427+ * Abstract: Get the Primary connection
13428+ *
13429+ * Notes:
13430+ *
13431+ * Environment:
13432+ *
13433+ *========================================================================*/
13434+{
13435+ PXPLAT_CALL_REQUEST cmd;
13436+ PXPLAT_CALL_REPLY reply;
13437+ unsigned long cmdlen, replylen;
13438+ int status = 0x8866, cpylen;
13439+ NwcGetBroadcastNotification msg;
13440+ PNwdCGetBroadcastNotification dmsg;
13441+
13442+ cmdlen = sizeof(*cmd) + sizeof(*dmsg);
13443+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
13444+ if (cmd) {
13445+
13446+ cpylen = copy_from_user(&msg, pdata->reqData, sizeof(msg));
13447+ cmd->dataLen = sizeof(*dmsg);
13448+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13449+ cmd->Command.SequenceNumber = 0;
13450+ cmd->Command.SessionId = Session;
13451+
13452+ cmd->NwcCommand = NWC_GET_BROADCAST_MESSAGE;
13453+ dmsg = (PNwdCGetBroadcastNotification) cmd->data;
13454+ dmsg->uConnReference = (HANDLE) (unsigned long) msg.uConnReference;
13455+
13456+ status =
13457+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
13458+ (void **)&reply, &replylen,
13459+ INTERRUPTIBLE);
13460+
13461+ if (reply) {
13462+ status = reply->Reply.ErrorCode;
13463+
13464+ if (!status) {
13465+ char *cp = pdata->repData;
13466+
13467+ dmsg =
13468+ (PNwdCGetBroadcastNotification) reply->data;
13469+ if (pdata->repLen < dmsg->messageLen) {
13470+ dmsg->messageLen = pdata->repLen;
13471+ }
13472+ msg.messageLen = dmsg->messageLen;
13473+ cpylen = offsetof(NwcGetBroadcastNotification, message);
13474+ cp += cpylen;
13475+ cpylen = copy_to_user(pdata->repData, &msg, cpylen);
13476+ cpylen = copy_to_user(cp, dmsg->message, msg.messageLen);
13477+ } else {
13478+ msg.messageLen = 0;
13479+ msg.message[0] = 0;
13480+ cpylen = offsetof(NwcGetBroadcastNotification, message);
13481+ cpylen = copy_to_user(pdata->repData, &msg, sizeof(msg));
13482+ }
13483+
13484+ kfree(reply);
13485+ }
13486+ kfree(cmd);
13487+ }
13488+ return (status);
13489+}
13490+
13491+int NwdSetKeyValue(PXPLAT pdata, session_t Session)
13492+{
13493+ PXPLAT_CALL_REQUEST cmd;
13494+ PXPLAT_CALL_REPLY reply;
13495+ NwcSetKey xplatCall;
13496+ PNwdCSetKey pNewKey;
13497+ NwcString cstrObjectName, cstrPassword;
13498+ char *str;
13499+ unsigned long status = -ENOMEM, cmdlen, datalen, replylen, cpylen;
13500+
13501+ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetKey));
13502+ cpylen =
13503+ copy_from_user(&cstrObjectName, xplatCall.pObjectName,
13504+ sizeof(NwcString));
13505+ cpylen =
13506+ copy_from_user(&cstrPassword, xplatCall.pNewPassword,
13507+ sizeof(NwcString));
13508+
13509+ datalen =
13510+ sizeof(NwdCSetKey) + cstrObjectName.DataLen + cstrPassword.DataLen;
13511+
13512+ cmdlen = sizeof(*cmd) + datalen;
13513+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
13514+
13515+ if (cmd) {
13516+ pNewKey = (PNwdCSetKey) cmd->data;
13517+ cmd->dataLen = datalen;
13518+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13519+ cmd->Command.SequenceNumber = 0;
13520+ cmd->Command.SessionId = Session;
13521+ cmd->NwcCommand = NWC_SET_KEY;
13522+
13523+ pNewKey->ObjectType = xplatCall.ObjectType;
13524+ pNewKey->AuthenticationId = xplatCall.AuthenticationId;
13525+ pNewKey->ConnHandle = (HANDLE) (unsigned long) xplatCall.ConnHandle;
13526+ str = (char *)pNewKey;
13527+
13528+ /*
13529+ * Get the User Name
13530+ */
13531+ str += sizeof(NwdCSetKey);
13532+ cpylen =
13533+ copy_from_user(str, cstrObjectName.pBuffer,
13534+ cstrObjectName.DataLen);
13535+
13536+ str += pNewKey->objectNameLen = cstrObjectName.DataLen;
13537+ pNewKey->objectNameOffset = sizeof(NwdCSetKey);
13538+
13539+ /*
13540+ * Get the Verify Password
13541+ */
13542+ cpylen =
13543+ copy_from_user(str, cstrPassword.pBuffer,
13544+ cstrPassword.DataLen);
13545+
13546+ pNewKey->newPasswordLen = cstrPassword.DataLen;
13547+ pNewKey->newPasswordOffset =
13548+ pNewKey->objectNameOffset + pNewKey->objectNameLen;
13549+
13550+ status =
13551+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
13552+ (void **)&reply, &replylen,
13553+ INTERRUPTIBLE);
13554+ if (reply) {
13555+ status = reply->Reply.ErrorCode;
13556+ kfree(reply);
13557+ }
13558+ memset(cmd, 0, cmdlen);
13559+ kfree(cmd);
13560+ }
13561+
13562+ return (status);
13563+}
13564+
13565+/*++======================================================================*/
13566+int NwdVerifyKeyValue(PXPLAT pdata, session_t Session)
13567+/*
13568+ * Arguments:
13569+ *
13570+ * Returns:
13571+ *
13572+ * Abstract: Change the password on the server
13573+ *
13574+ * Notes:
13575+ *
13576+ * Environment:
13577+ *
13578+ *========================================================================*/
13579+{
13580+ PXPLAT_CALL_REQUEST cmd;
13581+ PXPLAT_CALL_REPLY reply;
13582+ NwcVerifyKey xplatCall;
13583+ PNwdCVerifyKey pNewKey;
13584+ NwcString xferStr;
13585+ char *str;
13586+ unsigned long status = -ENOMEM, cmdlen, datalen, replylen, cpylen;
13587+
13588+ cpylen =
13589+ copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcVerifyKey));
13590+
13591+ datalen =
13592+ sizeof(NwdCVerifyKey) + xplatCall.pDomainName->DataLen +
13593+ xplatCall.pObjectName->DataLen + xplatCall.pVerifyPassword->DataLen;
13594+
13595+ cmdlen = sizeof(*cmd) + datalen;
13596+ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL);
13597+
13598+ if (cmd) {
13599+ pNewKey = (PNwdCVerifyKey) cmd->data;
13600+ cmd->dataLen = datalen;
13601+ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL;
13602+ cmd->Command.SequenceNumber = 0;
13603+ cmd->Command.SessionId = Session;
13604+ cmd->NwcCommand = NWC_VERIFY_KEY;
13605+
13606+ pNewKey->NameType = xplatCall.NameType;
13607+ pNewKey->ObjectType = xplatCall.ObjectType;
13608+ pNewKey->AuthType = xplatCall.AuthType;
13609+ str = (char *)pNewKey;
13610+
13611+ /*
13612+ * Get the tree name
13613+ */
13614+ str += sizeof(*pNewKey);
13615+ cpylen =
13616+ copy_from_user(&xferStr, xplatCall.pDomainName,
13617+ sizeof(NwcString));
13618+ pNewKey->domainNameOffset = sizeof(*pNewKey);
13619+ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen);
13620+ pNewKey->domainNameLen = xferStr.DataLen;
13621+
13622+ /*
13623+ * Get the User Name
13624+ */
13625+ str += pNewKey->domainNameLen;
13626+ cpylen =
13627+ copy_from_user(&xferStr, xplatCall.pObjectName,
13628+ sizeof(NwcString));
13629+ pNewKey->objectNameOffset =
13630+ pNewKey->domainNameOffset + pNewKey->domainNameLen;
13631+ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen);
13632+ pNewKey->objectNameLen = xferStr.DataLen;
13633+
13634+ /*
13635+ * Get the Verify Password
13636+ */
13637+ str += pNewKey->objectNameLen;
13638+ cpylen =
13639+ copy_from_user(&xferStr, xplatCall.pVerifyPassword,
13640+ sizeof(NwcString));
13641+ pNewKey->verifyPasswordOffset =
13642+ pNewKey->objectNameOffset + pNewKey->objectNameLen;
13643+ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen);
13644+ pNewKey->verifyPasswordLen = xferStr.DataLen;
13645+
13646+ status =
13647+ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0,
13648+ (void **)&reply, &replylen,
13649+ INTERRUPTIBLE);
13650+ if (reply) {
13651+ status = reply->Reply.ErrorCode;
13652+ kfree(reply);
13653+ }
13654+ memset(cmd, 0, cmdlen);
13655+ kfree(cmd);
13656+ }
13657+
13658+ return (status);
13659+}
13660--- /dev/null
13661+++ b/fs/novfs/nwcapi.h
13662@@ -0,0 +1,2213 @@
13663+/*
13664+ * NetWare Redirector for Linux
13665+ * Author: Sheffer Clark
13666+ *
13667+ * This file contains all typedefs and constants for the NetWare Client APIs.
13668+ *
13669+ * Copyright (C) 2005 Novell, Inc.
13670+ *
13671+ * This program is free software; you can redistribute it and/or
13672+ * modify it under the terms of the GNU General Public License
13673+ * as published by the Free Software Foundation; either version 2
13674+ * of the License, or (at your option) any later version.
13675+ */
13676+#ifndef __NWCLNX_H__
13677+#define __NWCLNX_H__
13678+
13679+#if 0 //sgled hack
13680+#else //sgled hack (up to endif)
13681+
13682+#define NW_MAX_TREE_NAME_LEN 33
13683+#define NW_MAX_SERVICE_TYPE_LEN 49
13684+/* Transport Type - (nuint32 value) */
13685+#define NWC_TRAN_TYPE_IPX 0x0001
13686+#define NWC_TRAN_TYPE_DDP 0x0003
13687+#define NWC_TRAN_TYPE_ASP 0x0004
13688+#define NWC_TRAN_TYPE_UDP 0x0008
13689+#define NWC_TRAN_TYPE_TCP 0x0009
13690+#define NWC_TRAN_TYPE_UDP6 0x000A
13691+#define NWC_TRAN_TYPE_TCP6 0x000B
13692+#define NWC_TRAN_TYPE_WILD 0x8000
13693+
13694+//
13695+// DeviceIoControl requests for the NetWare Redirector
13696+//
13697+// Macro definition for defining DeviceIoControl function control codes.
13698+// The function codes 0 - 2047 are reserved for Microsoft.
13699+// Function codes 2048 - 4096 are reserved for customers.
13700+// The NetWare Redirector will use codes beginning at 3600.
13701+//
13702+// METHOD_NEITHER User buffers will be passed directly from the application
13703+// to the file system. The redirector is responsible for either probing
13704+// and locking the buffers or using a try - except around access of the
13705+// buffers.
13706+
13707+#define BASE_REQ_NUM 0x4a541000
13708+
13709+// Connection functions
13710+#define NWC_OPEN_CONN_BY_NAME (BASE_REQ_NUM + 0)
13711+#define NWC_OPEN_CONN_BY_ADDRESS (BASE_REQ_NUM + 1)
13712+#define NWC_OPEN_CONN_BY_REFERENCE (BASE_REQ_NUM + 2)
13713+#define NWC_CLOSE_CONN (BASE_REQ_NUM + 3)
13714+#define NWC_SYS_CLOSE_CONN (BASE_REQ_NUM + 4)
13715+#define NWC_GET_CONN_INFO (BASE_REQ_NUM + 5)
13716+#define NWC_SET_CONN_INFO (BASE_REQ_NUM + 6)
13717+#define NWC_SCAN_CONN_INFO (BASE_REQ_NUM + 7)
13718+#define NWC_MAKE_CONN_PERMANENT (BASE_REQ_NUM + 8)
13719+#define NWC_LICENSE_CONN (BASE_REQ_NUM + 9)
13720+#define NWC_UNLICENSE_CONN (BASE_REQ_NUM + 10)
13721+#define NWC_GET_NUM_CONNS (BASE_REQ_NUM + 11)
13722+#define NWC_GET_PREFERRED_SERVER (BASE_REQ_NUM + 12)
13723+#define NWC_SET_PREFERRED_SERVER (BASE_REQ_NUM + 13)
13724+#define NWC_GET_PRIMARY_CONN (BASE_REQ_NUM + 14)
13725+#define NWC_SET_PRIMARY_CONN (BASE_REQ_NUM + 15)
13726+
13727+// Authentication functions
13728+#define NWC_CHANGE_KEY (BASE_REQ_NUM + 20)
13729+#define NWC_ENUMERATE_IDENTITIES (BASE_REQ_NUM + 21)
13730+#define NWC_GET_IDENTITY_INFO (BASE_REQ_NUM + 22)
13731+#define NWC_LOGIN_IDENTITY (BASE_REQ_NUM + 23)
13732+#define NWC_LOGOUT_IDENTITY (BASE_REQ_NUM + 24)
13733+#define NWC_SET_KEY (BASE_REQ_NUM + 25)
13734+#define NWC_VERIFY_KEY (BASE_REQ_NUM + 26)
13735+#define NWC_AUTHENTICATE_CONN_WITH_ID (BASE_REQ_NUM + 27)
13736+#define NWC_UNAUTHENTICATE_CONN (BASE_REQ_NUM + 28)
13737+
13738+// Directory Services functions
13739+#define NWC_GET_DEFAULT_NAME_CONTEXT (BASE_REQ_NUM + 30)
13740+#define NWC_SET_DEFAULT_NAME_CONTEXT (BASE_REQ_NUM + 31)
13741+#define NWC_GET_PREFERRED_DS_TREE (BASE_REQ_NUM + 32)
13742+#define NWC_SET_PREFERRED_DS_TREE (BASE_REQ_NUM + 33)
13743+#define NWC_GET_TREE_MONITORED_CONN_REF (BASE_REQ_NUM + 34)
13744+#define NWC_NDS_RESOLVE_NAME_TO_ID (BASE_REQ_NUM + 35)
13745+
13746+// NCP Request functions
13747+#define NWC_FRAGMENT_REQUEST (BASE_REQ_NUM + 40)
13748+#define NWC_NCP_ORDERED_REQUEST_ALL (BASE_REQ_NUM + 41)
13749+#define NWC_RAW_NCP_REQUEST (BASE_REQ_NUM + 42)
13750+#define NWC_RAW_NCP_REQUEST_ALL (BASE_REQ_NUM + 43)
13751+
13752+// File Handle Conversion functions
13753+#define NWC_CONVERT_LOCAL_HANDLE (BASE_REQ_NUM + 50)
13754+#define NWC_CONVERT_NETWARE_HANDLE (BASE_REQ_NUM + 51)
13755+
13756+// Misc. functions
13757+#define NWC_MAP_DRIVE (BASE_REQ_NUM + 60)
13758+#define NWC_UNMAP_DRIVE (BASE_REQ_NUM + 61)
13759+#define NWC_ENUMERATE_DRIVES (BASE_REQ_NUM + 62)
13760+
13761+#define NWC_GET_REQUESTER_VERSION (BASE_REQ_NUM + 63)
13762+#define NWC_QUERY_FEATURE (BASE_REQ_NUM + 64)
13763+
13764+#define NWC_GET_CONFIGURED_NSPS (BASE_REQ_NUM + 65)
13765+
13766+#define NWC_GET_MOUNT_PATH (BASE_REQ_NUM + 66)
13767+
13768+#define NWC_GET_BROADCAST_MESSAGE (BASE_REQ_NUM + 67)
13769+
13770+#endif //sgled hack -------------------------------
13771+
13772+#define IOC_XPLAT 0x4a540002
13773+
13774+typedef struct _XPLAT_ {
13775+ int xfunction;
13776+ unsigned long reqLen;
13777+ void *reqData;
13778+ unsigned long repLen;
13779+ void *repData;
13780+
13781+} XPLAT, *PXPLAT;
13782+
13783+#if 0
13784+N_EXTERN_LIBRARY(NWRCODE)
13785+ NWCLnxReq
13786+ (nuint32 request, nptr pInBuf, nuint32 inLen, nptr pOutBuf, nuint32 outLen);
13787+#endif
13788+//
13789+// Network Name Format Type
13790+//
13791+
13792+#define NWC_NAME_FORMAT_NDS 0x0001
13793+#define NWC_NAME_FORMAT_BIND 0x0002
13794+#define NWC_NAME_FORMAT_BDP 0x0004
13795+#define NWC_NAME_FORMAT_NDS_TREE 0x0008
13796+#define NWC_NAME_FORMAT_WILD 0x8000
13797+
13798+//
13799+// API String Types
13800+//
13801+
13802+#define NWC_STRING_TYPE_ASCII 0x0001 // multi-byte, not really ascii
13803+#define NWC_STRING_TYPE_UNICODE 0x0002
13804+#define NWC_STRING_TYPE_UTF8 0x0003
13805+
13806+//
13807+// Open Connection Flags
13808+//
13809+
13810+#define NWC_OPEN_LICENSED 0x0001
13811+#define NWC_OPEN_UNLICENSED 0x0002
13812+#define NWC_OPEN_PRIVATE 0x0004
13813+#define NWC_OPEN_PUBLIC 0x0008
13814+#define NWC_OPEN_EXISTING_HANDLE 0x0010
13815+#define NWC_OPEN_NO_HANDLE 0x0020
13816+#define NWC_OPEN_PERMANENT 0x0040
13817+#define NWC_OPEN_DISCONNECTED 0x0080
13818+#define NWC_OPEN_NEAREST 0x0100
13819+#define NWC_OPEN_IGNORE_CACHE 0x0200
13820+
13821+//
13822+// Close Connection Flags
13823+//
13824+
13825+#define NWC_CLOSE_TEMPORARY 0x0000
13826+#define NWC_CLOSE_PERMANENT 0x0001
13827+
13828+//
13829+// Connection Information Levels
13830+//
13831+
13832+#define NWC_CONN_INFO_RETURN_ALL 0xFFFF
13833+#define NWC_CONN_INFO_RETURN_NONE 0x0000
13834+#define NWC_CONN_INFO_VERSION 0x0001
13835+#define NWC_CONN_INFO_AUTH_STATE 0x0002
13836+#define NWC_CONN_INFO_BCAST_STATE 0x0003
13837+#define NWC_CONN_INFO_CONN_REF 0x0004
13838+#define NWC_CONN_INFO_TREE_NAME 0x0005
13839+#define NWC_CONN_INFO_WORKGROUP_ID 0x0006
13840+#define NWC_CONN_INFO_SECURITY_STATE 0x0007
13841+#define NWC_CONN_INFO_CONN_NUMBER 0x0008
13842+#define NWC_CONN_INFO_USER_ID 0x0009
13843+#define NWC_CONN_INFO_SERVER_NAME 0x000A
13844+#define NWC_CONN_INFO_TRAN_ADDR 0x000B
13845+#define NWC_CONN_INFO_NDS_STATE 0x000C
13846+#define NWC_CONN_INFO_MAX_PACKET_SIZE 0x000D
13847+#define NWC_CONN_INFO_LICENSE_STATE 0x000E
13848+#define NWC_CONN_INFO_PUBLIC_STATE 0x000F
13849+#define NWC_CONN_INFO_SERVICE_TYPE 0x0010
13850+#define NWC_CONN_INFO_DISTANCE 0x0011
13851+#define NWC_CONN_INFO_SERVER_VERSION 0x0012
13852+#define NWC_CONN_INFO_AUTH_ID 0x0013
13853+#define NWC_CONN_INFO_SUSPENDED 0x0014
13854+#define NWC_CONN_INFO_TREE_NAME_UNICODE 0x0015
13855+#define NWC_CONN_INFO_SERVER_NAME_UNICODE 0x0016
13856+#define NWC_CONN_INFO_LOCAL_TRAN_ADDR 0x0017
13857+#define NWC_CONN_INFO_ALTERNATE_ADDR 0x0018
13858+#define NWC_CONN_INFO_SERVER_GUID 0x0019
13859+
13860+#define NWC_CONN_INFO_MAX_LEVEL 0x0014
13861+
13862+//
13863+// Information Versions
13864+//
13865+
13866+#define NWC_INFO_VERSION_1 0x0001
13867+#define NWC_INFO_VERSION_2 0x0002
13868+
13869+//
13870+// Authentication State
13871+//
13872+
13873+#define NWC_AUTH_TYPE_NONE 0x0000
13874+#define NWC_AUTH_TYPE_BINDERY 0x0001
13875+#define NWC_AUTH_TYPE_NDS 0x0002
13876+#define NWC_AUTH_TYPE_PNW 0x0003
13877+
13878+#define NWC_AUTH_STATE_NONE 0x0000
13879+#define NWC_AUTH_STATE_BINDERY 0x0001
13880+#define NWC_AUTH_STATE_NDS 0x0002
13881+#define NWC_AUTH_STATE_PNW 0x0003
13882+
13883+//
13884+// Authentication Flags
13885+//
13886+
13887+#define NWC_AUTH_PRIVATE 0x00000004
13888+#define NWC_AUTH_PUBLIC 0x00000008
13889+
13890+//
13891+// Broadcast State
13892+//
13893+
13894+#define NWC_BCAST_PERMIT_ALL 0x0000
13895+#define NWC_BCAST_PERMIT_SYSTEM 0x0001
13896+#define NWC_BCAST_PERMIT_NONE 0x0002
13897+#define NWC_BCAST_PERMIT_SYSTEM_POLLED 0x0003
13898+#define NWC_BCAST_PERMIT_ALL_POLLED 0x0004
13899+
13900+//
13901+// Broadcast State
13902+//
13903+
13904+#define NWC_NDS_NOT_CAPABLE 0x0000
13905+#define NWC_NDS_CAPABLE 0x0001
13906+
13907+//
13908+// License State
13909+//
13910+
13911+#define NWC_NOT_LICENSED 0x0000
13912+#define NWC_CONNECTION_LICENSED 0x0001
13913+#define NWC_HANDLE_LICENSED 0x0002
13914+
13915+//
13916+// Public State
13917+//
13918+
13919+#define NWC_CONN_PUBLIC 0x0000
13920+#define NWC_CONN_PRIVATE 0x0001
13921+
13922+//
13923+// Scan Connection Information Flags used
13924+// for finding connections by specific criteria
13925+//
13926+
13927+#define NWC_MATCH_NOT_EQUALS 0x0000
13928+#define NWC_MATCH_EQUALS 0x0001
13929+#define NWC_RETURN_PUBLIC 0x0002
13930+#define NWC_RETURN_PRIVATE 0x0004
13931+#define NWC_RETURN_LICENSED 0x0008
13932+#define NWC_RETURN_UNLICENSED 0x0010
13933+
13934+//
13935+// Authentication Types
13936+//
13937+
13938+#define NWC_AUTHENT_BIND 0x0001
13939+#define NWC_AUTHENT_NDS 0x0002
13940+#define NWC_AUTHENT_PNW 0x0003
13941+
13942+//
13943+// Disconnected info
13944+//
13945+
13946+#define NWC_SUSPENDED 0x0001
13947+
13948+//
13949+// Maximum object lengths
13950+//
13951+
13952+#define MAX_DEVICE_LENGTH 16
13953+#define MAX_NETWORK_NAME_LENGTH 1024
13954+#define MAX_OBJECT_NAME_LENGTH 48
13955+#define MAX_PASSWORD_LENGTH 128
13956+#define MAX_SERVER_NAME_LENGTH 48
13957+#define MAX_SERVICE_TYPE_LENGTH 48
13958+#define MAX_TREE_NAME_LENGTH 32
13959+#define MAX_ADDRESS_LENGTH 32
13960+#define MAX_NAME_SERVICE_PROVIDERS 10
13961+
13962+//
13963+// Flags for the GetBroadcastMessage API
13964+//
13965+
13966+#define MESSAGE_GET_NEXT_MESSAGE 1
13967+#define MESSAGE_RECEIVED_FOR_CONNECTION 2
13968+
13969+//
13970+// This constant must always be equal to the last device
13971+//
13972+
13973+#define DEVICE_LAST_DEVICE 0x00000003
13974+
13975+//
13976+// Defined feature set provided by requester
13977+//
13978+
13979+#ifndef NWC_FEAT_PRIV_CONN
13980+#define NWC_FEAT_PRIV_CONN 1
13981+#define NWC_FEAT_REQ_AUTH 2
13982+#define NWC_FEAT_SECURITY 3
13983+#define NWC_FEAT_NDS 4
13984+#define NWC_FEAT_NDS_MTREE 5
13985+#define NWC_FEAT_PRN_CAPTURE 6
13986+#define NWC_FEAT_NDS_RESOLVE 7
13987+#endif
13988+
13989+//===[ Type definitions ]==================================================
13990+
13991+//
13992+// Connection Handle returned from all OpenConnByXXXX calls
13993+//
13994+
13995+typedef u32 NW_CONN_HANDLE, *PNW_CONN_HANDLE;
13996+
13997+//
13998+// Authentication Id returned from the NwcCreateAuthenticationId call
13999+//
14000+
14001+typedef u32 AUTHEN_ID, *PAUTHEN_ID;
14002+
14003+//
14004+// Structure for defining what a transport
14005+// address looks like
14006+//
14007+
14008+typedef struct tagNwcTranAddr {
14009+ u32 uTransportType;
14010+ u32 uAddressLength;
14011+ unsigned char *puAddress;
14012+
14013+} NwcTranAddr, *PNwcTranAddr;
14014+
14015+//
14016+// Structure for defining what a new transport
14017+// address looks like
14018+//
14019+
14020+typedef struct tagNwcTranAddrEx {
14021+ u32 uTransportType;
14022+ u32 uAddressLength;
14023+ unsigned char buBuffer[MAX_ADDRESS_LENGTH];
14024+
14025+} NwcTranAddrEx, *PNwcTranAddrEx;
14026+
14027+typedef struct tagNwcReferral {
14028+ u32 uAddrCnt;
14029+ PNwcTranAddrEx pAddrs;
14030+
14031+} NwcReferral, *PNwcReferral;
14032+
14033+typedef struct tagNwcServerVersion {
14034+ u32 uMajorVersion;
14035+ u16 uMinorVersion;
14036+ u16 uRevision;
14037+
14038+} NwcServerVersion, *PNwcServerVersion;
14039+
14040+typedef struct tagNwcConnString {
14041+ char *pString;
14042+ u32 uStringType;
14043+ u32 uNameFormatType;
14044+
14045+} NwcConnString, *PNwcConnString;
14046+
14047+//#if defined(NTYPES_H)
14048+//typedef NWCString NwcString, *PNwcString;
14049+//#else
14050+typedef struct tagNwcString {
14051+ u32 DataType;
14052+ u32 BuffSize;
14053+ u32 DataLen;
14054+ void *pBuffer;
14055+ u32 CodePage;
14056+ u32 CountryCode;
14057+
14058+} NwcString, *PNwcString;
14059+//#endif
14060+
14061+//
14062+// Structure used in NDS Resolve name
14063+//
14064+
14065+#define RESOLVE_INFO_SVC_V1_00 0x00FE0001
14066+
14067+typedef struct tagNwcResolveInfo {
14068+ u32 uResolveInfoVersion;
14069+ u32 luFlags;
14070+ u32 luReqFlags;
14071+ u32 luReqScope;
14072+ u32 luResolveType;
14073+ u32 luRepFlags;
14074+ u32 luResolvedOffset;
14075+ u32 luDerefNameLen;
14076+ u16 *pDerefName;
14077+} NwcResolveInfo, *PNwcResolveInfo;
14078+
14079+//
14080+// Definition of a fragment for the Raw NCP requests
14081+//
14082+
14083+typedef struct tagNwcFrag {
14084+ void *pData;
14085+ u32 uLength;
14086+
14087+} NwcFrag, *PNwcFrag;
14088+
14089+//
14090+// Current connection information available for
14091+// enumeration using GetConnInfo and ScanConnInfo
14092+//
14093+
14094+#define NW_INFO_BUFFER_SIZE NW_MAX_TREE_NAME_LEN + \
14095+ NW_MAX_TREE_NAME_LEN + \
14096+ NW_MAX_SERVICE_TYPE_LEN
14097+
14098+typedef struct tagNwcConnInfo {
14099+ u32 uInfoVersion;
14100+ u32 uAuthenticationState;
14101+ u32 uBroadcastState;
14102+ u32 uConnectionReference;
14103+ u32 TreeNameOffset;
14104+ u32 uSecurityState;
14105+ u32 uConnectionNumber;
14106+ u32 uUserId;
14107+ u32 ServerNameOffset;
14108+ u32 uNdsState;
14109+ u32 uMaxPacketSize;
14110+ u32 uLicenseState;
14111+ u32 uPublicState;
14112+ u32 bcastState;
14113+ u32 ServiceTypeOffset;
14114+ u32 uDistance;
14115+ u32 uAuthId;
14116+ u32 uDisconnected;
14117+ NwcServerVersion serverVersion;
14118+ NwcTranAddrEx tranAddress;
14119+ unsigned char buBuffer[NW_INFO_BUFFER_SIZE];
14120+
14121+} NwcConnInfo, *PNwcConnInfo;
14122+
14123+//
14124+// Get Browse Connection References
14125+//
14126+
14127+typedef struct _GetBrowseConnectionsRec {
14128+
14129+ u32 recordSize;
14130+ u32 numConnectionsReturned;
14131+ u32 numConnectionsAvailable;
14132+ u32 connReferences[1];
14133+
14134+} GetBrowseConnectionRec, *PGetBrowseConnectionRec;
14135+
14136+//++=======================================================================
14137+// API Name: NwcClearBroadcastMessage
14138+//
14139+// Arguments In: NONE
14140+//
14141+// Arguments Out: NONE
14142+//
14143+// Returns: STATUS_SUCCESS
14144+//
14145+// Abstract: This API is clears the broadcast message buffer.
14146+//
14147+// Notes:
14148+//
14149+// Environment: PASSIVE_LEVEL, LINUX
14150+//
14151+//=======================================================================--
14152+
14153+//++=======================================================================
14154+// API Name: NwcCloseConn
14155+//
14156+// Arguments In: ConnHandle - The handle to a connection that is
14157+// no longer needed.
14158+//
14159+// Arguments Out: NONE
14160+//
14161+// Returns: STATUS_SUCCESS
14162+// NWE_ACCESS_VIOLATION
14163+// NWE_CONN_INVALID
14164+// NWE_INVALID_OWNER
14165+// NWE_RESOURCE_LOCK
14166+//
14167+// Abstract: This API is used by an application that opened the
14168+// connection using one of the open connection calls
14169+// is finished using the connection. After it is closed,
14170+// the handle may no longer be used to access the
14171+// connection.
14172+//
14173+// Notes:
14174+//
14175+// Environment: PASSIVE_LEVEL, LINUX
14176+//
14177+//=======================================================================--
14178+
14179+typedef struct tagNwcCloseConn {
14180+ NW_CONN_HANDLE ConnHandle;
14181+
14182+} NwcCloseConn, *PNwcCloseConn;
14183+
14184+//++=======================================================================
14185+// API Name: NwcConvertLocalFileHandle
14186+//
14187+// Arguments In: NONE
14188+//
14189+// Arguments Out: uConnReference - The connection reference associated
14190+// with the returned NetWare file handle.
14191+//
14192+// pNetWareFileHandle - The six byte NetWare file handle
14193+// associated with the given local file handle.
14194+//
14195+// Returns: STATUS_SUCCESS
14196+// NWE_ACCESS_VIOLATION
14197+// NWE_RESOURCE_NOT_OWNED
14198+//
14199+// Abstract: This API is used to return the NetWare handle that
14200+// has been associated to a local file handle.
14201+// In addition to returning the NetWare file handle,
14202+// this API also returns the connection reference to
14203+// the connection that owns the file.
14204+//
14205+// Notes: This API does not create a new NetWare handle, it
14206+// only returns the existing handle associated to the
14207+// local handle.
14208+//
14209+// Environment: PASSIVE_LEVEL, LINUX
14210+//
14211+//=======================================================================--
14212+
14213+typedef struct tagNwcConvertLocalHandle {
14214+ u32 uConnReference;
14215+ unsigned char NetWareHandle[6];
14216+
14217+} NwcConvertLocalHandle, *PNwcConvertLocalHandle;
14218+
14219+//++=======================================================================
14220+// API Name: NwcConvertNetWareHandle
14221+//
14222+// Arguments In: ConnHandle - The connection associated with the
14223+// NetWare file handle to convert.
14224+//
14225+// uAccessMode - The access rights to be used when
14226+// allocating the local file handle.
14227+//
14228+// pNetWareHandle - The NetWare handle that will be
14229+// bound to the new local handle being created.
14230+//
14231+// uFileSize - The current file size of the NetWare
14232+// file associated with the given NetWare file handle.
14233+//
14234+// Arguments Out: NONE
14235+//
14236+// Returns: STATUS_SUCCESS
14237+// NWE_ACCESS_VIOLATION
14238+// NWE_RESOURCE_NOT_OWNED
14239+//
14240+// Abstract: This API is used to convert a NetWare file handle
14241+// to a local file handle.
14242+//
14243+// The local handle must have been created previously
14244+// by doing a local open to \Special\$Special.net.
14245+//
14246+// Then an Ioctl to this function must be issued using the
14247+// handle returned from the special net open.
14248+//
14249+// Notes: After making this call, the NetWare file handle
14250+// should not be closed using the NetWare library
14251+// call, instead it should be closed using the local
14252+// operating system's close call.
14253+//
14254+// Environment: PASSIVE_LEVEL, LINUX
14255+//
14256+//=======================================================================--
14257+typedef struct tagNwcConvertNetWareHandle {
14258+ NW_CONN_HANDLE ConnHandle;
14259+ u32 uAccessMode;
14260+ unsigned char NetWareHandle[6];
14261+ u32 uFileSize;
14262+} NwcConvertNetWareHandle, *PNwcConvertNetWareHandle;
14263+
14264+//++=======================================================================
14265+// API Name: NwcFragmentRequest
14266+//
14267+// Arguments In: ConnHandle
14268+// The connection handle the request is being
14269+// directed to.
14270+//
14271+// uFunction
14272+// The NCP function to be called, should be 104
14273+// for NDS fragger/defragger requests.
14274+//
14275+// uSubFunction
14276+// The NCP subfunction to be called, should be
14277+// 2 for NDS fragger/defragger requests.
14278+//
14279+// uVerb
14280+// The actual operation to be completed on the
14281+// server backend.
14282+//
14283+// flags
14284+// Currently not implemented. Reserved for
14285+// future use.
14286+//
14287+// uNumRequestFrags
14288+// The number of fragments that the request packet
14289+// has been broken into.
14290+//
14291+// pRequestFrags
14292+// List of fragments that make up the request packet.
14293+// Each fragment includes the length of the fragment
14294+// data and a pointer to the data.
14295+//
14296+// uNumReplyFrags
14297+// The number of fragments the reply packet has been
14298+// broken into.
14299+//
14300+// Arguments Out: pReplyFrags
14301+// List of fragments that make up the reply packet.
14302+// Each fragment includes the length of the fragment
14303+// data and a pointer to the data.
14304+//
14305+// uActualReplyLength
14306+// Total size of the reply packet after any header
14307+// and tail information is removed.
14308+//
14309+// Returns: STATUS_SUCCESS
14310+// NWE_ACCESS_VIOLATION
14311+// NWE_CONN_INVALID
14312+//
14313+// Abstract: API for sending large NCP/NDS packets that are
14314+// larger than the max MTU size for the underlying
14315+// network.
14316+//
14317+// Notes:
14318+//
14319+// Environment: PASSIVE_LEVEL, LINUX
14320+//
14321+//=======================================================================--
14322+typedef struct tagNwcFragmentRequest {
14323+ NW_CONN_HANDLE ConnHandle;
14324+ u32 uFunction;
14325+ u32 uSubFunction;
14326+ u32 uVerb;
14327+ u32 flags;
14328+ u32 uNumRequestFrags;
14329+ PNwcFrag pRequestFrags;
14330+ u32 uNumReplyFrags;
14331+ PNwcFrag pReplyFrags;
14332+ u32 uActualReplyLength;
14333+} NwcFragmentRequest, *PNwcFragmentRequest;
14334+
14335+//++=======================================================================
14336+// API Name: NwcGetBroadcastMessage
14337+//
14338+// Arguments In: uMessageFlags - Not currently used.
14339+//
14340+// uConnReference - connection reference for
14341+// pending message.
14342+//
14343+// messageLen - length of message buffer.
14344+//
14345+// message - message buffer
14346+//
14347+// Arguments Out: messageLen - length of the message
14348+//
14349+// Returns: STATUS_SUCCESS
14350+// NWE_ACCESS_VIOLATION
14351+// NWE_NO_MORE_ENTRIES
14352+//
14353+// Abstract: This API is used for notifying a caller of pending
14354+// broadcast messages on the server.
14355+//
14356+// Notes:
14357+//
14358+// Environment: PASSIVE_LEVEL, LINUX
14359+//
14360+//=======================================================================--
14361+
14362+/* jlt
14363+typedef struct tagNwcGetBroadcastMessage
14364+{
14365+ u32 uMessageFlags;
14366+ u32 uConnReference;
14367+ u32 messageLen;
14368+ unsigned char message[255];
14369+
14370+} NwcGetBroadcastMessage, *PNwcGetBroadcastMessage;
14371+*/
14372+
14373+//++=======================================================================
14374+// API Name: NwcGetConnInfo
14375+//
14376+// Arguments In: ConnHandle - Connection handle for the connection to
14377+// get information on.
14378+// uInfoLevel - Specifies what information should be
14379+// returned.
14380+// uInfoLen - Length of the ConnInfo buffer.
14381+//
14382+// Arguments Out: pConnInfo - A pointer to a buffer to return connection
14383+// information in. If the caller is requesting all
14384+// information the pointer will be to a structure of
14385+// type NwcConnInfo. If the caller is requesting just
14386+// a single piece of information, the pointer is the
14387+// type of information being requested.
14388+//
14389+// Returns: STATUS_SUCCESS
14390+// NWE_ACCESS_VIOLATION
14391+// NWE_CONN_INVALID
14392+// NWE_INVALID_OWNER
14393+// NWE_RESOURCE_LOCK
14394+// NWE_STRING_TRANSLATION
14395+//
14396+// Abstract: This API returns connection information for the specified
14397+// connection. The requester can receive one piece of
14398+// information or the whole information structure.
14399+// Some of the entries in the NwcConnInfo structure are
14400+// pointers. The requester is responsible for supplying
14401+// valid pointers for any info specified to be returned.
14402+// If the requester does not want a piece of information
14403+// returned, a NULL pointer should be placed in the field.
14404+//
14405+// Notes:
14406+//
14407+// Environment: PASSIVE_LEVEL, LINUX
14408+//
14409+//=======================================================================--
14410+
14411+typedef struct tagNwcGetConnInfo {
14412+ NW_CONN_HANDLE ConnHandle;
14413+ u32 uInfoLevel;
14414+ u32 uInfoLength;
14415+ void *pConnInfo;
14416+
14417+} NwcGetConnInfo, *PNwcGetConnInfo;
14418+
14419+//++=======================================================================
14420+// API Name: NwcGetDefaultNameContext
14421+//
14422+// Arguments In:: uTreeLength - Length of tree string.
14423+//
14424+// pDsTreeName - Pointer to tree string (multi-byte)
14425+//
14426+// pNameLength - On input, this is the length of the
14427+// name context buffer. On output, this is the actual
14428+// length of the name context string.
14429+//
14430+// Arguments Out: pNameContext - The buffer to copy the default name
14431+// context into (multi-byte).
14432+//
14433+// Returns: STATUS_SUCCESS
14434+// NWE_ACCESS_VIOLATION
14435+// NWE_BUFFER_OVERFLOW
14436+// NWE_OBJECT_NOT_FOUND
14437+// NWE_PARAM_INVALID
14438+// NWE_RESOURCE_LOCK
14439+//
14440+// Abstract: This API returns the default name context that
14441+// was previously set either by configuration or
14442+// by calling NwcSetDefaultNameContext.
14443+//
14444+// Notes:
14445+//
14446+// Environment: PASSIVE_LEVEL, LINUX
14447+//
14448+//=======================================================================--
14449+
14450+typedef struct tagNwcGetDefaultNameContext {
14451+ u32 uTreeLength;
14452+ unsigned char *pDsTreeName;
14453+ u32 uNameLength;
14454+// unsigned short *pNameContext;
14455+ unsigned char *pNameContext;
14456+
14457+} NwcGetDefaultNameContext, *PNwcGetDefaultNameContext;
14458+
14459+//++=======================================================================
14460+// API Name: NwcGetTreeMonitoredConnReference
14461+//
14462+// Arguments In: NONE
14463+//
14464+// Arguments Out: uConnReference - The connection reference associated
14465+// with the monitored connection.
14466+//
14467+// Returns: STATUS_SUCCESS
14468+// NWE_ACCESS_VIOLATION
14469+// NWE_OBJECT_NOT_FOUND
14470+// NWE_RESOURCE_LOCK
14471+//
14472+// Abstract: This call returns a connection reference to a
14473+// connection that is monitored. This connection
14474+// reference may be used to open the connection.
14475+//
14476+// Notes:
14477+//
14478+// Environment: PASSIVE_LEVEL, LINUX
14479+//
14480+//=======================================================================--
14481+
14482+typedef struct tagNwcGetTreeMonitoredConnRef {
14483+ PNwcString pTreeName;
14484+ u32 uConnReference;
14485+
14486+} NwcGetTreeMonitoredConnRef, *PNwcGetTreeMonitoredConnRef;
14487+
14488+//++=======================================================================
14489+// API Name: NwcGetNumberConns
14490+//
14491+// Arguments In: NONE
14492+//
14493+// Arguments Out: uMaxConns - The maximum number of connections
14494+// supported by the redirector. -1 for dynamic.
14495+//
14496+// uPublicConns - The current number of public
14497+// connections.
14498+//
14499+// uTasksPrivateConns - The current number of private
14500+// connections that are owned by the calling process.
14501+//
14502+// uOtherPrivateConns - The current number of private
14503+// connections that are not owned by the calling
14504+// process.
14505+//
14506+// Returns: STATUS_SUCCESS
14507+// NWE_ACCESS_VIOLATION
14508+// NWE_RESOURCE_LOCK
14509+//
14510+// Abstract: This API returns the current number of connections
14511+// as well as the maximum number of supported
14512+// connections. If the requester/redirector supports
14513+// a dynamic connection table, -1 will be returned
14514+// in the uMaxConns field.
14515+//
14516+// Notes:
14517+//
14518+// Environment: PASSIVE_LEVEL, LINUX
14519+//
14520+//=======================================================================--
14521+
14522+typedef struct tagNwcGetNumberConns {
14523+ u32 uMaxConns;
14524+ u32 uPublicConns;
14525+ u32 uTasksPrivateConns;
14526+ u32 uOtherPrivateConns;
14527+
14528+} NwcGetNumberConns, *PNwcGetNumberConns;
14529+
14530+//++=======================================================================
14531+// API Name: NwcGetPreferredServer
14532+//
14533+// Arguments In: uServerNameLength - On input, this is the length
14534+// in bytes of the server buffer. On output, this is
14535+// the actual length of the server name string in bytes.
14536+//
14537+// Arguments Out: pServerName - The buffer to copy the preferred server
14538+// name into.
14539+//
14540+// Returns: STATUS_SUCCESS
14541+// NWE_ACCESS_VIOLATION
14542+// NWE_BUFFER_OVERFLOW
14543+// NWE_OBJECT_NOT_FOUND
14544+// NWE_PARAM_INVALID
14545+// NWE_RESOURCE_LOCK
14546+//
14547+// Abstract: This API returns the configured preferred bindery
14548+// server previously set either by configuration or
14549+// by calling NwcSetPreferredServer.
14550+//
14551+// Notes:
14552+//
14553+// Environment: PASSIVE_LEVEL, LINUX
14554+//
14555+//=======================================================================--
14556+
14557+typedef struct tagNwcGetPreferredServer {
14558+ u32 uServerNameLength;
14559+ char *pServerName;
14560+
14561+} NwcGetPreferredServer, *PNwcGetPreferredServer;
14562+
14563+//++=======================================================================
14564+// API Name: NwcGetPreferredDsTree
14565+//
14566+// Arguments In: uTreeLength - On input, this is the length in bytes
14567+// of the DS tree name buffer. On output, this is the
14568+// actual length of the DS tree name string in bytes.
14569+//
14570+// Arguments Out: pDsTreeName - The buffer to copy the DS tree name into.
14571+//
14572+// Returns: STATUS_SUCCESS
14573+// NWE_ACCESS_VIOLATION
14574+// NWE_BUFFER_OVERFLOW
14575+// NWE_PARAM_INVALID
14576+// NWE_DS_PREFERRED_NOT_FOUND
14577+// NWE_RESOURCE_LOCK
14578+//
14579+// Abstract: This API returns the preferred DS tree name that was
14580+// previously set either by configuration or
14581+// by calling NwcSetPreferredDsTree.
14582+//
14583+// Notes:
14584+//
14585+// Environment: PASSIVE_LEVEL, LINUX
14586+//
14587+//=======================================================================--
14588+typedef struct tagNwcGetPreferredDsTree {
14589+ u32 uTreeLength;
14590+ unsigned char *pDsTreeName;
14591+} NwcGetPreferredDsTree, *PNwcGetPreferredDsTree;
14592+
14593+//++=======================================================================
14594+// API Name: NwcGetPrimaryConnection
14595+//
14596+// Arguments In: NONE
14597+//
14598+// Arguments Out: uConnReference - Reference to the primary connection.
14599+//
14600+// Returns: STATUS_SUCCESS
14601+// NWE_ACCESS_VIOLATION
14602+// NWE_CONN_PRIMARY_NOT_SET
14603+//
14604+// Abstract: This API returns the reference to the current primary
14605+// connection in the redirector.
14606+//
14607+// Notes:
14608+//
14609+// Environment: PASSIVE_LEVEL, LINUX
14610+//
14611+//=======================================================================--
14612+
14613+typedef struct tagNwcGetPrimaryConnection {
14614+ u32 uConnReference;
14615+
14616+} NwcGetPrimaryConnection, *PNwcGetPrimaryConnection;
14617+
14618+//++=======================================================================
14619+// API Name: NwcGetRequesterVersion
14620+//
14621+// Arguments In: NONE
14622+//
14623+// Arguments Out: uMajorVersion
14624+// uMinorVersion
14625+// uRevision
14626+//
14627+// Returns: STATUS_SUCCESS
14628+// NWE_ACCESS_VIOLATION
14629+//
14630+// Abstract: This API returns the major version, minor version and
14631+// revision of the requester/redirector.
14632+//
14633+// Notes:
14634+//
14635+// Environment: PASSIVE_LEVEL, LINUX
14636+//
14637+//=======================================================================--
14638+
14639+typedef struct tagNwcGetRequesterVersion {
14640+ u32 uMajorVersion;
14641+ u32 uMinorVersion;
14642+ u32 uRevision;
14643+
14644+} NwcGetRequesterVersion, *PNwcGetRequesterVersion;
14645+
14646+//++=======================================================================
14647+// API Name: NwcLicenseConn
14648+//
14649+// Arguments In: ConnHandle - An open connection handle that is in
14650+// an unlicensed state.
14651+//
14652+// Arguments Out: NONE
14653+//
14654+// Returns: STATUS_SUCCESS
14655+// NWE_ACCESS_VIOLATION
14656+// NWE_CONN_INVALID
14657+// NWE_HANDLE_ALREADY_LICENSED
14658+//
14659+//
14660+// Abstract: This API changes a connections state to licensed.
14661+// The licensed count will be incremented, and if
14662+// necessary, the license NCP will be sent.
14663+// If this handle is already in a licensed state,
14664+// an error will be returned.
14665+//
14666+// Notes:
14667+//
14668+// Environment: PASSIVE_LEVEL, LINUX
14669+//
14670+//=======================================================================--
14671+
14672+typedef struct tagNwcLicenseConn {
14673+ NW_CONN_HANDLE ConnHandle;
14674+
14675+} NwcLicenseConn, *PNwcLicenseConn;
14676+
14677+//++=======================================================================
14678+// API Name: NwcMakeConnPermanent
14679+//
14680+// Arguments In: ConnHandle - An open connection handle associated
14681+// with the connection to be made permanent.
14682+//
14683+// Arguments Out: NONE
14684+//
14685+// Returns: NWE_ACCESS_VIOLATION
14686+// NWE_CONN_INVALID
14687+// NWE_INVALID_OWNER
14688+//
14689+// Abstract: This API is used to keep the connection from being
14690+// destroyed until a NwcSysCloseConn request is made
14691+// on the connection. This allows the connection to
14692+// remain after all processes that have the
14693+// connection open terminate.
14694+//
14695+// Notes:
14696+//
14697+// Environment: PASSIVE_LEVEL, LINUX
14698+//
14699+//=======================================================================--
14700+
14701+typedef struct tagNwcMakeConnPermanent {
14702+ NW_CONN_HANDLE ConnHandle;
14703+
14704+} NwcMakeConnPermanent, *PNwcMakeConnPermanent;
14705+
14706+//++=======================================================================
14707+// API Name: NwcMapDrive
14708+//
14709+// Arguments In: ConnHandle - The connection handle of the server
14710+// to where the drive is to be mapped.
14711+//
14712+// LocalUID - Local user ID
14713+//
14714+// LocalPathLen - Length of local/link directory path string,
14715+// including nul terminator.
14716+//
14717+// LocalPathOffset - Offset of local directory path that will
14718+// be mapped to NetWare directory path.
14719+//
14720+// NetWarePathLen - Offset of NetWare directory path,
14721+// including nul terminator.
14722+//
14723+// NetWarePathOffset - Offset of NetWare directory path in
14724+// structure.
14725+//
14726+// Arguments Out: NONE
14727+//
14728+// Returns: STATUS_SUCCESS
14729+// NWE_ACCESS_VIOLATION
14730+// NWE_CONN_INVALID
14731+// NWE_INSUFFICIENT_RESOURCES
14732+// NWE_STRING_TRANSLATION
14733+//
14734+// Abstract: This API maps the target drive to the specified
14735+// directory.
14736+//
14737+// Notes:
14738+//
14739+// Environment: PASSIVE_LEVEL, LINUX
14740+//
14741+//=======================================================================--
14742+
14743+typedef struct tagNwcMapDrive {
14744+ NW_CONN_HANDLE ConnHandle;
14745+ u32 LocalUID;
14746+ u32 LinkPathLen;
14747+ u32 LinkPathOffset;
14748+ u32 DestPathLen;
14749+ u32 DestPathOffset;
14750+
14751+} NwcMapDrive, *PNwcMapDrive;
14752+
14753+//++=======================================================================
14754+// API Name: NwcUnmapDrive
14755+//
14756+// Arguments In: LinkPathLen - Length of local/link path string,
14757+// including nul terminator.
14758+//
14759+// LinkPath - Local/link path in structure
14760+// to be unmapped
14761+//
14762+// Arguments Out: NONE
14763+//
14764+// Returns: STATUS_SUCCESS
14765+// NWE_ACCESS_VIOLATION
14766+// NWE_PARAM_INVALID
14767+//
14768+// Abstract: This API deletes a network drive mapping.
14769+//
14770+// Notes:
14771+//
14772+// Environment: PASSIVE_LEVEL, LINUX
14773+//
14774+//=======================================================================--
14775+
14776+typedef struct tagNwcUnmapDrive {
14777+ u32 LinkPathLen;
14778+ unsigned char LinkPath[1];
14779+
14780+} NwcUnmapDrive, *PNwcUnmapDrive;
14781+
14782+//++=======================================================================
14783+// API Name: NWCGetMappedDrives
14784+//
14785+// Arguments In:
14786+// Arguments Out:
14787+//
14788+// Returns: STATUS_SUCCESS
14789+// NWE_ACCESS_VIOLATION
14790+// NWE_BUFFER_OVERFLOW
14791+//
14792+// Abstract: This API returns the NetWare mapped drive info
14793+// per user.
14794+//
14795+// Notes:
14796+//
14797+// Environment: PASSIVE_LEVEL, LINUX
14798+//
14799+//=======================================================================--
14800+
14801+typedef struct tagNwcMapDriveElem {
14802+ u32 ElemLen; // Lenght of drive element
14803+ u32 ConnRefernce; // Connection reference
14804+ u32 LinkPathLen; // Local/link dir path, length includes nul
14805+ unsigned char LinkPath[1]; // LinkPath[LinkPathLen]
14806+// u32 DirPathLen; // NetWare dir path, length includes nul (vol:path)
14807+// unsigned char DirPath[DirPathLen]; // NetWarePath[DirPathLen]
14808+} NwcMapDriveElem, *PNwcMapDriveElem;
14809+
14810+typedef struct tagNwcMapDriveBuff {
14811+ u32 MapCount; // Number of mapped drives
14812+ NwcMapDriveElem MapDriveElem[1]; // MapDriveElem[MapCount]
14813+
14814+} NwcMapDriveBuff, *PNwcMapDriveBuff;
14815+
14816+typedef struct tagNwcGetMappedDrives {
14817+ u32 MapBuffLen; // Buffer length (actual buffer size returned)
14818+ PNwcMapDriveBuff MapBuffer; // Pointer to map buffer
14819+
14820+} NwcGetMappedDrives, *PNwcGetMappedDrives;
14821+
14822+//++=======================================================================
14823+// API Name: NwcGetMountPath
14824+//
14825+// Arguments In: MountPathLen - Length of mount path buffer
14826+// including nul terminator.
14827+//
14828+// Arguments Out: MountPath - Pointer to mount path buffer
14829+//
14830+// Returns: STATUS_SUCCESS
14831+// NWE_ACCESS_VIOLATION
14832+// NWE_BUFFER_OVERFLOW
14833+//
14834+// Abstract: This API returns the mount point of the NOVFS file
14835+// system.
14836+//
14837+// Notes:
14838+//
14839+// Environment: PASSIVE_LEVEL, LINUX
14840+//
14841+//=======================================================================--
14842+
14843+typedef struct tagNwcGetMountPath {
14844+ u32 MountPathLen;
14845+ unsigned char *pMountPath;
14846+
14847+} NwcGetMountPath, *PNwcGetMountPath;
14848+
14849+//++=======================================================================
14850+// API Name: NwcMonitorConn
14851+//
14852+// Arguments In: ConnHandle - The handle associated with the connection
14853+// that is to be marked as the monitored connection.
14854+//
14855+// Arguments Out: NONE
14856+//
14857+// Returns: STATUS_SUCCESS
14858+// NWE_ACCESS_VIOLATION
14859+// NWE_RESOURCE_LOCK
14860+// NWE_CONN_INVALID
14861+//
14862+//
14863+// Abstract: This call marks the connection associated with the
14864+// connection handle as monitored.
14865+//
14866+// Notes:
14867+//
14868+// Environment: PASSIVE_LEVEL, LINUX
14869+//
14870+//=======================================================================--
14871+
14872+typedef struct tagNwcMonitorConn {
14873+ NW_CONN_HANDLE ConnHandle;
14874+
14875+} NwcMonitorConn, *PNwcMonitorConn;
14876+
14877+//++=======================================================================
14878+// API Name: NwcOpenConnByAddr
14879+//
14880+// Arguments In: pServiceType - The type of service required.
14881+//
14882+// uConnFlags - Specifies whether this connection
14883+// should be public or private.
14884+//
14885+// pTranAddress - Specifies the transport address of
14886+// the service to open a connection on.
14887+// a connection to.
14888+//
14889+// Arguments Out: ConnHandle - The new connection handle returned.
14890+// This handle may in turn be used for all requests
14891+// directed to this connection.
14892+//
14893+// Returns: STATUS_SUCCESS
14894+// NWE_ACCESS_VIOLATION
14895+// NWE_INSUFFICIENT_RESOURCES
14896+// NWE_TRAN_INVALID_TYPE
14897+// NWE_RESOURCE_LOCK
14898+// NWE_UNSUPPORTED_TRAN_TYPE
14899+//
14900+// Abstract: This API will create a service connection to
14901+// the service specified by the transport address.
14902+//
14903+// Notes:
14904+//
14905+// Environment: PASSIVE_LEVEL, LINUX
14906+//
14907+//=======================================================================--
14908+
14909+typedef struct tagNwcOpenConnByAddr {
14910+ char *pServiceType;
14911+ u32 uConnFlags;
14912+ PNwcTranAddr pTranAddr;
14913+ NW_CONN_HANDLE ConnHandle;
14914+
14915+} NwcOpenConnByAddr, *PNwcOpenConnByAddr;
14916+
14917+//++=======================================================================
14918+// API Name: NwcOpenConnByName
14919+//
14920+// Arguments In: ConnHandle - The connection to use when resolving
14921+// a name. For instance, if the name is a bindery name
14922+// the requester will scan the bindery of the given
14923+// connection to retrieve the service's address. This
14924+// value can also be NULL if the caller doesn't care
14925+// which connection is used to resolve the address.
14926+//
14927+// pName - A pointer to the name of the service trying
14928+// to be connected to. This string is NULL terminated,
14929+// contains no wild cards, and is a maximum of 512
14930+// characters long.
14931+//
14932+// pServiceType - The type of service required.
14933+//
14934+// uConnFlags - Specifies whether this connection
14935+// should be public or private.
14936+//
14937+// uTranType - Specifies the preferred or required
14938+// transport type to be used.
14939+// NWC_TRAN_TYPE_WILD may be ORed with the other values
14940+// or used alone. When ORed with another value, the
14941+// wild value indicates an unmarked alternative is
14942+// acceptable. When used alone, the current preferred
14943+// transport is used.
14944+//
14945+// Arguments Out: ConnHandle - The new connection handle returned.
14946+// This handle may in turn be used for all requests
14947+// directed to this connection.
14948+//
14949+// Returns: STATUS_SUCCESS
14950+// NWE_ACCESS_VIOLATION
14951+// NWE_BUFFER_OVERFLOW
14952+// NWE_INSUFFICIENT_RESOURCES
14953+// NWE_INVALID_STRING_TYPE
14954+// NWE_RESOURCE_LOCK
14955+// NWE_STRING_TRANSLATION
14956+// NWE_TRAN_INVALID_TYPE
14957+// NWE_UNSUPPORTED_TRAN_TYPE
14958+//
14959+// Abstract: This API will resolve the given name to a network
14960+// address then create a service connection to the
14961+// specified service.
14962+//
14963+// Notes:
14964+//
14965+// Environment: PASSIVE_LEVEL, LINUX
14966+//
14967+//=======================================================================--
14968+
14969+typedef struct tagNwcOpenConnByName {
14970+ NW_CONN_HANDLE ConnHandle;
14971+ PNwcConnString pName;
14972+ char *pServiceType;
14973+ u32 uConnFlags;
14974+ u32 uTranType;
14975+ NW_CONN_HANDLE RetConnHandle;
14976+
14977+} NwcOpenConnByName, *PNwcOpenConnByName;
14978+
14979+//++=======================================================================
14980+// API Name: NwcOpenConnByReference
14981+//
14982+// Arguments In: uConnReference - A reference handle which identifies
14983+// a valid connection that the caller wants to obtain
14984+// a connection handle to. A reference handle can be
14985+// used to get information about the connection without
14986+// actually getting a handle to it. A connection handle
14987+// must be used to make actual requests to that
14988+// connection.
14989+//
14990+// uConnFlags - Currently unused.
14991+//
14992+// Arguments Out: ConnHandle - The new connection handle returned.
14993+// This handle may in turn be used for all requests
14994+// directed to this connection.
14995+//
14996+// Returns: STATUS_SUCCESS
14997+// NWE_ACCESS_VIOLATION
14998+// NWE_CONN_INVALID
14999+//
15000+// Abstract: This API will open the connection associated with
15001+// the given connection reference. The connection
15002+// reference can be obtained by calling the
15003+// NwcScanConnInfo API.
15004+//
15005+// Notes:
15006+//
15007+// Environment: PASSIVE_LEVEL, LINUX
15008+//
15009+//=======================================================================--
15010+
15011+typedef struct tagNwcOpenConnByReference {
15012+ u32 uConnReference;
15013+ u32 uConnFlags;
15014+ NW_CONN_HANDLE ConnHandle;
15015+
15016+} NwcOpenConnByReference, *PNwcOpenConnByReference;
15017+
15018+//++=======================================================================
15019+// API Name: NwcRawRequest
15020+//
15021+// Arguments In: ConnHandle - The connection handle of the connection
15022+// that the request is being directed to.
15023+//
15024+// uFunction - The NCP function that is being called.
15025+//
15026+// uNumRequestFrags - The number of fragments that the
15027+// request packet has been broken into.
15028+//
15029+// pRequestFrags - List of fragments that make up the
15030+// request packet. Each fragment includes the length
15031+// of the fragment data and a pointer to the data.
15032+//
15033+// uNumReplyFrags - The number of fragments the reply
15034+// packet has been broken into.
15035+//
15036+// Arguments Out: pReplyFrags - List of fragments that make up the
15037+// request packet. Each fragment includes the length
15038+// of the fragment data and a pointer to the data.
15039+//
15040+// uActualReplyLength - Total size of the reply packet
15041+// after any header and tail information is removed.
15042+//
15043+// Returns: STATUS_SUCCESS
15044+// NWE_ACCESS_VIOLATION
15045+// NWE_CONN_INVALID
15046+//
15047+// Abstract: API for sending raw NCP packets directly to a server.
15048+//
15049+// Notes:
15050+//
15051+// Environment: PASSIVE_LEVEL, LINUX
15052+//
15053+//=======================================================================--
15054+
15055+typedef struct tagNwcRequest {
15056+ NW_CONN_HANDLE ConnHandle;
15057+ u32 uFunction;
15058+ u32 uNumRequestFrags;
15059+ PNwcFrag pRequestFrags;
15060+ u32 uNumReplyFrags;
15061+ PNwcFrag pReplyFrags;
15062+ u32 uActualReplyLength;
15063+
15064+} NwcRequest, *PNwcRequest;
15065+
15066+//++=======================================================================
15067+// API Name: NwcRawRequestAll
15068+//
15069+// Arguments In: uFunction - The NCP function that is being called.
15070+//
15071+// uNumRequestFrags - The number of fragments that the
15072+// request packet has been broken into.
15073+//
15074+// pRequestFrags - List of fragments that make up the
15075+// request packet. Each fragment includes the length
15076+// of the fragment data and a pointer to the data.
15077+//
15078+// Arguments Out: NONE
15079+//
15080+// Returns: STATUS_SUCCESS
15081+// NWE_ACCESS_VIOLATION
15082+// NWE_CONN_INVALID
15083+//
15084+// Abstract: API for sending the given NCP request to all valid
15085+// connections. If there is a private connection that
15086+// is not owned by the caller of this function, that
15087+// connection will not be included. Also, if the
15088+// caller has both a private and a public connection
15089+// to the same server, only the private connection
15090+// will receive the request.
15091+//
15092+// Notes:
15093+//
15094+// Environment: PASSIVE_LEVEL, LINUX
15095+//
15096+//=======================================================================--
15097+
15098+typedef struct tagNwcRequestAll {
15099+ u32 uFunction;
15100+ u32 uNumRequestFrags;
15101+ PNwcFrag pRequestFrags;
15102+
15103+} NwcRequestAll, *PNwcRequestAll;
15104+
15105+//++=======================================================================
15106+// API Name: NwcScanConnInfo
15107+//
15108+// Arguments In: uScanIndex - The index to be used on the next
15109+// iteration of the scan. This value should be initially
15110+// set to zero. The output of this parameter will be
15111+// used in subsequent calls to this function.
15112+//
15113+// uScanInfoLevel - Describes the composition of the
15114+// pScanConnInfo pointer. If this parameter contains
15115+// NWC_CONN_INFO_RETURN_ALL, information for all
15116+// connections will be returned.
15117+//
15118+// uScanInfoLen - Lenght of pScanConnInfo buffer
15119+//
15120+// pScanConnInfo - This parameter is a pointer to
15121+// data that describes one piece of connection
15122+// information. The type of this data depends on
15123+// which level of information is being scanned for.
15124+// For instance, if the scan is being used to find all
15125+// connections with a particular authentication state,
15126+// pScanConnInfo would be a "pnuint" since
15127+// authentication state is described as nuint in the
15128+// NwcConnInfo structure.
15129+//
15130+// uScanFlag - This parameter tells whether to return
15131+// connection information for connections that match
15132+// the scan criteria or that do not match the scan
15133+// criteria. If the caller wants to find all the
15134+// connections that are not in the "NOVELL_INC" DS
15135+// tree, he would use the call as described below in
15136+// the description except the uScanFlag parameter would
15137+// have the value of NWC_MATCH_NOT_EQUALS. This flag
15138+// is also used to tell the requester whether to
15139+// return private or public, licensed or unlicensed
15140+// connections.
15141+//
15142+// uReturnInfoLevel - Specifies what information
15143+// should be returned.
15144+//
15145+// uReturnInfoLength - The size in bytes of pConnInfo.
15146+//
15147+// Arguments Out: uConnectionReference - Connection reference
15148+// associated with the information that is being
15149+// returned.
15150+//
15151+// pReturnConnInfo - A pointer to the NwcConnInfo
15152+// structure defined above. In some of the
15153+// structures within the union, there are pointers to
15154+// data to be returned. It is the responsibility of
15155+// the caller to provide pointers to valid memory
15156+// to copy this data into.
15157+//
15158+// Returns: STATUS_SUCCESS
15159+// NWE_ACCESS_VIOLATION
15160+// NWE_RESOURCE_LOCK
15161+// NWE_CONN_INVALID
15162+// NWE_INVALID_LEVEL
15163+// NWE_STRING_TRANSLATION
15164+// NWE_INVALID_MATCH_DATA
15165+// NWE_MATCH_FAILED
15166+// NWE_BUFFER_OVERFLOW
15167+// NWE_NO_MORE_ENTRIES
15168+//
15169+// Abstract: This API is used to return connection information
15170+// for multiple connections. It will return one
15171+// piece or the full structure of connection information
15172+// for one connection at a time. This call is designed
15173+// to scan for connections based on any piece of
15174+// connection information as described in the
15175+// NwcConnInfo structure. For instance, if the caller
15176+// wants to scan for all connections in the DS tree
15177+// "NOVELL_INC", the call would be made with the
15178+// following paramters:
15179+//
15180+// uScanLevelInfo = NWC_CONN_INFO_TREE_NAME
15181+// pScanConnInfo = "NOVELL_INC"
15182+// uScanFlag = NWC_MATCH_EQUALS |
15183+// NWC_RETURN_PUBLIC |
15184+// NWC_RETURN_LICENSED
15185+//
15186+// The scan flag is used to tell if the scan is
15187+// supposed to return connections that match or don't
15188+// match. This design doesn't allow any other
15189+// conditions for this flag (such as greater than or
15190+// less than).
15191+//
15192+// If the caller specifies the uReturnInfoLevel =
15193+// NWC_CONN_INFO_RETURN_ALL, the full NwcConnInfo
15194+// structure is returned. The caller must supply
15195+// data for any pointers in the NwcConnInfo structure
15196+// (these include tree name, workgroup id, server name
15197+// and transport address). However if the caller
15198+// doesn't want to get a particular piece of info
15199+// that is expecting a pointer to some data, a NULL
15200+// pointer may be used to indicate to the requester
15201+// that it should not return that piece of information.
15202+//
15203+// Notes:
15204+//
15205+// Environment: PASSIVE_LEVEL, LINUX
15206+//
15207+//=======================================================================--
15208+
15209+typedef struct tagNwcScanConnInfo {
15210+ u32 uScanIndex;
15211+ u32 uScanInfoLevel;
15212+ u32 uScanInfoLen;
15213+ void *pScanConnInfo;
15214+ u32 uScanFlags;
15215+ u32 uReturnInfoLevel;
15216+ u32 uReturnInfoLength;
15217+ u32 uConnectionReference;
15218+ void *pReturnConnInfo;
15219+
15220+} NwcScanConnInfo, *PNwcScanConnInfo;
15221+
15222+//++=======================================================================
15223+// API Name: NwcSetConnInfo
15224+//
15225+// Arguments In: ConnHandle - Connection handle for the connection to
15226+// set information on.
15227+//
15228+// uInfoLevel - Specifies what information should be set.
15229+//
15230+// uInfoLen - Length in bytes of the information being set.
15231+//
15232+// pConnInfo - Connection information to set.
15233+//
15234+// Arguments Out: NONE
15235+//
15236+// Returns: STATUS_SUCCESS
15237+// NWE_ACCESS_VIOLATION
15238+// NWE_RESOURCE_LOCK
15239+// NWE_CONN_INVALID
15240+// NWE_INVALID_LEVEL
15241+//
15242+//
15243+// Abstract: This API sets information in the connection associated
15244+// with the connection handle.
15245+//
15246+// Notes: At this time the only setable information levels are:
15247+// NWC_CONN_INFO_AUTH_STATE
15248+// NWC_CONN_INFO_BCAST_STATE
15249+//
15250+// Environment: PASSIVE_LEVEL, LINUX
15251+//
15252+//=======================================================================--
15253+
15254+typedef struct tagNwcSetConnInfo {
15255+ NW_CONN_HANDLE ConnHandle;
15256+ u32 uInfoLevel;
15257+ u32 uInfoLength;
15258+ void *pConnInfo;
15259+
15260+} NwcSetConnInfo, *PNwcSetConnInfo;
15261+
15262+//++=======================================================================
15263+// API Name: NwcSetDefaultNameContext
15264+//
15265+// Arguments In:: uTreeLength - Length of tree string.
15266+//
15267+// pDsTreeName - The tree string (multi-byte).
15268+//
15269+// uNameLength - The length in bytes of the name
15270+// context string.
15271+//
15272+// pNameContext - The string to be used as the default
15273+// name context (multi-byte).
15274+//
15275+// Arguments Out: NONE
15276+//
15277+// Returns: STATUS_SUCCESS
15278+// NWE_ACCESS_VIOLATION
15279+// NWE_PARAM_INVALID
15280+// NWE_RESOURCE_LOCK
15281+// NWE_STRING_TRANSLATION
15282+//
15283+// Abstract: This API sets the default name context.
15284+//
15285+// Notes:
15286+//
15287+// Environment: PASSIVE_LEVEL, LINUX
15288+//
15289+//=======================================================================--
15290+
15291+typedef struct tagNwcSetDefaultNameContext {
15292+ u32 uTreeLength;
15293+ unsigned char *pDsTreeName;
15294+ u32 uNameLength;
15295+// unsined short *pNameContext;
15296+ unsigned char *pNameContext;
15297+
15298+} NwcSetDefaultNameContext, *PNwcSetDefaultNameContext;
15299+
15300+//++=======================================================================
15301+// API Name: NwcSetPreferredDsTree
15302+//
15303+// Arguments In: uTreeLength - The length in bytes of the DS tree name.
15304+//
15305+// pDsTreeName - The string to be used as the preferred
15306+// DS tree name.
15307+//
15308+// Arguments Out: NONE
15309+//
15310+// Returns: STATUS_SUCCESS
15311+// NWE_ACCESS_VIOLATION
15312+// NWE_INSUFFICIENT_RESOURCES
15313+// NWE_RESOURCE_LOCK
15314+//
15315+// Abstract: This API sets the preferred DS tree name.
15316+//
15317+// Notes:
15318+//
15319+// Environment: PASSIVE_LEVEL, LINUX
15320+//
15321+//=======================================================================--
15322+
15323+typedef struct tagNwcSetPreferredDsTree {
15324+ u32 uTreeLength;
15325+ unsigned char *pDsTreeName;
15326+
15327+} NwcSetPreferredDsTree, *PNwcSetPreferredDsTree;
15328+
15329+//++=======================================================================
15330+// API Name: NwcSetPreferredServer
15331+//
15332+// Arguments In: uServerNameLength - The length in bytes of the
15333+// preferred server string.
15334+//
15335+// pServerName - a pointer to an ASCIIZ string of the
15336+// preferred bindery server.
15337+//
15338+// Arguments Out: NONE
15339+//
15340+// Returns: STATUS_SUCCESS
15341+// NWE_ACCESS_VIOLATION
15342+// NWE_INSUFFICIENT_RESOURCES
15343+// NWE_RESOURCE_LOCK
15344+//
15345+// Abstract: This API sets the preferred server name.
15346+//
15347+// Notes:
15348+//
15349+// Environment: PASSIVE_LEVEL, LINUX
15350+//
15351+//=======================================================================--
15352+
15353+typedef struct tagNwcSetPreferredServer {
15354+ u32 uServerNameLength;
15355+ char *pServerName;
15356+
15357+} NwcSetPreferredServer, *PNwcSetPreferredServer;
15358+
15359+//++=======================================================================
15360+// API Name: NwcSetPrimaryConnection
15361+//
15362+// Arguments In: ConnHandle - Connection handle associated to the
15363+// connection reference which the caller wishes to set
15364+// as primary.
15365+//
15366+// Arguments Out: NONE
15367+//
15368+// Returns: STATUS_SUCCESS
15369+// NWE_ACCESS_VIOLATION
15370+// NWE_CONN_PRIMARY_NOT_SET
15371+//
15372+// Abstract: This API sets the primary connection according to
15373+// the connection handle passed in by the caller.
15374+//
15375+// Notes:
15376+//
15377+// Environment: PASSIVE_LEVEL, LINUX
15378+//
15379+//=======================================================================--
15380+
15381+typedef struct tagNwcSetPrimaryConnection {
15382+ NW_CONN_HANDLE ConnHandle;
15383+
15384+} NwcSetPrimaryConnection, *PNwcSetPrimaryConnection;
15385+
15386+//++=======================================================================
15387+// API Name: NwcSysCloseConn
15388+//
15389+// Arguments In: ConnHandle - The handle to a connection that is
15390+// to be destroyed.
15391+//
15392+// Arguments Out: NONE
15393+//
15394+// Returns: STATUS_SUCCESS
15395+// NWE_ACCESS_VIOLATION
15396+// NWE_CONN_INVALID
15397+//
15398+// Abstract: This API is similiar to the NwcCloseConn API, except
15399+// that it forces all handles to the connection closed
15400+// and destroys the service connection. This is a system
15401+// level request that will cause all processes that are
15402+// accessing this connection to lose access to the
15403+// resources associated to the connection.
15404+//
15405+// Notes:
15406+//
15407+// Environment: PASSIVE_LEVEL, LINUX
15408+//
15409+//=======================================================================--
15410+
15411+typedef struct tagNwcSysCloseConn {
15412+ NW_CONN_HANDLE ConnHandle;
15413+
15414+} NwcSysCloseConn, *PNwcSysCloseConn;
15415+
15416+//++=======================================================================
15417+// API Name: NwcUnlicenseConn
15418+//
15419+// Arguments In: ConnHandle - Open connection handle that will be
15420+// accessing the connection in an unlicensed manner.
15421+//
15422+// Arguments Out: NONE
15423+//
15424+// Returns: STATUS_SUCCESS
15425+// NWE_ACCESS_VIOLATION
15426+// NWE_CONN_INVALID
15427+// NWE_HANDLE_ALREADY_UNLICENSED
15428+//
15429+// Abstract: This API is used to change the state of a connection
15430+// handle from licensed to unlicensed. If all handles
15431+// to the connection have been changed to the unlicensed
15432+// state, the unlicensed NCP is sent to the server.
15433+//
15434+// Notes:
15435+//
15436+// Environment: PASSIVE_LEVEL, LINUX
15437+//
15438+//=======================================================================--
15439+
15440+typedef struct tagNwcUnlicenseConn {
15441+ NW_CONN_HANDLE ConnHandle;
15442+
15443+} NwcUnlicenseConn, *PNwcUnlicenseConn;
15444+
15445+//++=======================================================================
15446+// API Name: NwcQueryFeature
15447+//
15448+// Arguments In: Feature - The number associated with a particular
15449+// feature that the caller wants to know if the requester
15450+// is supporting
15451+//
15452+// Arguments Out:
15453+//
15454+// Returns: STATUS_SUCCESS
15455+// NWE_REQUESTER_FAILURE
15456+// NWE_ACCESS_VIOLATION
15457+//
15458+// Abstract:
15459+//
15460+// Notes:
15461+//
15462+// Environment: PASSIVE_LEVEL, LINUX
15463+//
15464+//=======================================================================--
15465+
15466+typedef struct tagNwcQueryFeature {
15467+ u32 Feature;
15468+
15469+} NwcQueryFeature, *PNwcQueryFeature;
15470+
15471+//++=======================================================================
15472+// API Name: NWCChangePassword
15473+//
15474+// Arguments In:
15475+//
15476+// Arguments Out:
15477+//
15478+// Returns: STATUS_SUCCESS
15479+// NWE_ACCESS_VIOLATION
15480+//
15481+// Abstract:
15482+//
15483+// Notes:
15484+//
15485+// Environment: PASSIVE_LEVEL, LINUX
15486+//
15487+//=======================================================================--
15488+
15489+typedef struct tagNwcChangeKey {
15490+ PNwcString pDomainName;
15491+ u32 AuthType;
15492+ PNwcString pObjectName;
15493+ u32 NameType;
15494+ u16 ObjectType;
15495+ PNwcString pVerifyPassword;
15496+ PNwcString pNewPassword;
15497+
15498+} NwcChangeKey, *PNwcChangeKey;
15499+
15500+//++=======================================================================
15501+// API Name: NWCEnumerateIdentities `
15502+//
15503+// Arguments In:
15504+//
15505+// Arguments Out:
15506+//
15507+// Returns: STATUS_SUCCESS
15508+// NWE_ACCESS_VIOLATION
15509+//
15510+// Abstract:
15511+//
15512+// Notes:
15513+//
15514+// Environment: PASSIVE_LEVEL, LINUX
15515+//
15516+//=======================================================================--
15517+
15518+typedef struct tagNwcEnumerateIdentities {
15519+ u32 Iterator;
15520+ PNwcString pDomainName;
15521+ u32 AuthType;
15522+ PNwcString pObjectName;
15523+ u32 NameType;
15524+ u16 ObjectType;
15525+ u32 IdentityFlags;
15526+ AUTHEN_ID AuthenticationId;
15527+
15528+} NwcEnumerateIdentities, *PNwcEnumerateIdentities;
15529+
15530+//++=======================================================================
15531+// API Name: NWCGetIdentityInfo
15532+//
15533+// Arguments In:
15534+//
15535+// Arguments Out:
15536+//
15537+// Returns: STATUS_SUCCESS
15538+// NWE_ACCESS_VIOLATION
15539+//
15540+// Abstract:
15541+//
15542+// Notes:
15543+//
15544+// Environment: PASSIVE_LEVEL, LINUX
15545+//
15546+//=======================================================================--
15547+
15548+typedef struct tagNwcGetIdentityInfo {
15549+ AUTHEN_ID AuthenticationId;
15550+ PNwcString pDomainName;
15551+ u32 AuthType;
15552+ PNwcString pObjectName;
15553+ u32 NameType;
15554+ u16 ObjectType;
15555+ u32 IdentityFlags;
15556+
15557+} NwcGetIdentityInfo, *PNwcGetIdentityInfo;
15558+
15559+//++=======================================================================
15560+// API Name: NWCLoginIdentity
15561+//
15562+// Arguments In:
15563+//
15564+// Arguments Out:
15565+//
15566+// Returns: STATUS_SUCCESS
15567+// NWE_ACCESS_VIOLATION
15568+//
15569+// Abstract:
15570+//
15571+// Notes:
15572+//
15573+// Environment: PASSIVE_LEVEL, LINUX
15574+//
15575+//=======================================================================--
15576+
15577+typedef struct tagNwcLoginIdentity {
15578+ PNwcString pDomainName;
15579+ u32 AuthType;
15580+ PNwcString pObjectName;
15581+ u32 NameType;
15582+ u16 ObjectType;
15583+ u32 IdentityFlags;
15584+ PNwcString pPassword;
15585+ AUTHEN_ID AuthenticationId;
15586+
15587+} NwcLoginIdentity, *PNwcLoginIdentity;
15588+
15589+//++=======================================================================
15590+// API Name: NWCLogoutIdentity
15591+////
15592+
15593+// Arguments In:
15594+//
15595+// Arguments Out:
15596+//
15597+// Returns: STATUS_SUCCESS
15598+// NWE_ACCESS_VIOLATION
15599+//
15600+// Abstract:
15601+//
15602+// Notes:
15603+//
15604+// Environment: PASSIVE_LEVEL, LINUX
15605+//
15606+//=======================================================================--
15607+
15608+typedef struct tagNwcLogoutIdentity {
15609+ AUTHEN_ID AuthenticationId;
15610+
15611+} NwcLogoutIdentity, *PNwcLogoutIdentity;
15612+
15613+//++=======================================================================
15614+// API Name: NWCSetPassword
15615+//
15616+// Arguments In:
15617+//
15618+// Arguments Out:
15619+//
15620+// Returns: STATUS_SUCCESS
15621+// NWE_ACCESS_VIOLATION
15622+//
15623+// Abstract:
15624+//
15625+// Notes:
15626+//
15627+// Environment: PASSIVE_LEVEL, LINUX
15628+//
15629+//=======================================================================--
15630+
15631+typedef struct tagNwcSetKey {
15632+ NW_CONN_HANDLE ConnHandle;
15633+ AUTHEN_ID AuthenticationId;
15634+ PNwcString pObjectName;
15635+ u16 ObjectType;
15636+ PNwcString pNewPassword;
15637+
15638+} NwcSetKey, *PNwcSetKey;
15639+
15640+//++=======================================================================
15641+// API Name: NWCVerifyPassword
15642+//
15643+// Arguments In:
15644+//
15645+// Arguments Out:
15646+//
15647+// Returns: STATUS_SUCCESS
15648+// NWE_ACCESS_VIOLATION
15649+//
15650+// Abstract:
15651+//
15652+// Notes:
15653+//
15654+// Environment: PASSIVE_LEVEL, LINUX
15655+//
15656+//++=======================================================================
15657+
15658+typedef struct tagNwcVerifyKey {
15659+ PNwcString pDomainName;
15660+ u32 AuthType;
15661+ PNwcString pObjectName;
15662+ u32 NameType;
15663+ u16 ObjectType;
15664+ PNwcString pVerifyPassword;
15665+
15666+} NwcVerifyKey, *PNwcVerifyKey;
15667+
15668+//++=======================================================================
15669+// API Name: NwcAuthenticateWithId
15670+//
15671+// Arguments In: ConnHandle - The connection to be authenticated
15672+//
15673+// AuthenticationId - the authentication Id associated
15674+// to the information necessary to authenticate this
15675+// connection.
15676+//
15677+// Arguments Out: NONE
15678+//
15679+// Returns: STATUS_SUCCESS
15680+// NWE_ACCESS_VIOLATION
15681+//
15682+// Abstract: This API is used to authenticate a connection using
15683+// an authentication ID that has already been created.
15684+//
15685+// Notes:
15686+//
15687+// Environment: PASSIVE_LEVEL, LINUX
15688+//
15689+//=======================================================================--
15690+
15691+typedef struct tagNwcAuthenticateWithId {
15692+ NW_CONN_HANDLE ConnHandle;
15693+ AUTHEN_ID AuthenticationId;
15694+
15695+} NwcAuthenticateWithId, *PNwcAuthenticateWithId;
15696+
15697+//++=======================================================================
15698+// API Name: NwcUnauthenticate
15699+//
15700+// Arguments In: ConnHandle - The connection to unauthenticate.
15701+//
15702+// Arguments Out: NONE
15703+//
15704+// Returns: STATUS_SUCCESS
15705+// NWE_ACCESS_VIOLATION
15706+// NWE_CONN_INVALID
15707+// NWE_INVALID_OWNER
15708+// NWE_RESOURCE_LOCK
15709+//
15710+// Abstract: This API removes the authentication for the specified
15711+// connection.
15712+//
15713+// Notes:
15714+//
15715+// Environment: PASSIVE_LEVEL, LINUX
15716+//
15717+//=======================================================================--
15718+
15719+typedef struct tagNwcUnauthenticate {
15720+ NW_CONN_HANDLE ConnHandle;
15721+ AUTHEN_ID AuthenticationId;
15722+
15723+} NwcUnauthenticate, *PNwcUnauthenticate;
15724+
15725+//++=======================================================================
15726+// API Name: NwcGetCfgNameServiceProviders
15727+//
15728+// Arguments In:
15729+//
15730+// Arguments Out:
15731+//
15732+// Returns: STATUS_SUCCESS
15733+// NWE_ACCESS_VIOLATION
15734+//
15735+// Abstract:
15736+//
15737+// Notes:
15738+//
15739+// Environment: PASSIVE_LEVEL, LINUX
15740+//
15741+//=======================================================================--
15742+
15743+typedef struct {
15744+ u32 providerCount;
15745+ u32 providers[MAX_NAME_SERVICE_PROVIDERS];
15746+
15747+} NwcGetCfgNameServiceProviders, *PNwcGetCfgNameServiceProviders;
15748+
15749+//++=======================================================================
15750+// API Name: NwcNdsResolveNameToId
15751+//
15752+// Arguments In: connHandle
15753+// Specifies connection to use to resolve name with.
15754+//
15755+// pName
15756+// Points to the name of the NDS entry to resolve.
15757+//
15758+// uReqTranType
15759+// Specifies the preferred or required transport to
15760+// be used.
15761+//
15762+// pResolveInfo
15763+// Points to the NwcNdsResolveInfo structure
15764+// containing information on how the entry is to be
15765+// resolved.
15766+//
15767+// Arguments Out: pResolveInfo
15768+// Points to the NwcNdsResolveInfo structure
15769+// containing return information on the resolved
15770+// entry.
15771+//
15772+// pluEntryId
15773+// Points to the resolved name's entry ID.
15774+//
15775+// pReferral
15776+// Points to the NwcReferral structure which describes
15777+// network addresses that can be used to locate other
15778+// NDS partitions that contain the entry name.
15779+//
15780+// Returns: STATUS_SUCCESS
15781+// NWE_CONN_INVALID,
15782+// NWE_BUFFER_OVERFLOW,
15783+// NWE_TRAN_INVALID_TYPE,
15784+// NWE_ACCESS_VIOLATION,
15785+// NWE_UNSUPPORTED_TRAN_TYPE,
15786+// Nds error code
15787+//
15788+// Abstract: This API resolves a NDS entry name.
15789+//
15790+// Notes:
15791+//
15792+// Environment: PASSIVE_LEVEL, LINUX
15793+//
15794+//=======================================================================--
15795+
15796+typedef struct tagNwcNdsResolveNameToId {
15797+ NW_CONN_HANDLE connHandle;
15798+ PNwcString pName;
15799+ u32 uReqTranType;
15800+ PNwcResolveInfo pResolveInfo;
15801+ u32 entryId;
15802+ PNwcReferral pReferral;
15803+
15804+} NwcNdsResolveNameToId, *PNwcNdsResolveNameToId;
15805+
15806+//++=======================================================================
15807+// API Name: NwcOrderedRequest
15808+//
15809+// Arguments In: uFunction - The NCP function that is being called.
15810+//
15811+// uNumRequestFrags - The number of fragments that the
15812+// request packet has been broken into.
15813+//
15814+// pRequestFrags - List of fragments that make up the
15815+// request packet. Each fragment includes the length
15816+// of the fragment data and a pointer to the data.
15817+//
15818+// uInverseReqCode - The NCP function that will be called
15819+// if the request fails.
15820+//
15821+// uNumInverseFrags - The number of fragments the inverse
15822+// request packet has been broken into.
15823+//
15824+// pReplyFrags - List of fragments that make up the
15825+// inverse request packet. Each fragment includes the length
15826+// of the fragment data and a pointer to the data.
15827+//
15828+// Returns: STATUS_SUCCESS
15829+// NWE_ACCESS_VIOLATION
15830+// NWE_CONN_INVALID
15831+//
15832+// Abstract: API for sending raw NCP packets directly to a server.
15833+//
15834+// Notes:
15835+//
15836+// Environment: PASSIVE_LEVEL, LINUX
15837+//
15838+//=======================================================================--
15839+
15840+typedef struct tagNwcOrderedRequest {
15841+ u32 uReqCode;
15842+ u32 uNumRequestFrags;
15843+ PNwcFrag pRequestFrags;
15844+ u32 uInverseReqCode;
15845+ u32 uNumInverseFrags;
15846+ PNwcFrag pInverseFrags;
15847+
15848+} NwcOrderedRequest, *PNwcOrderedRequest;
15849+
15850+#if 1 //sgled
15851+typedef struct tagNwcUnmapDriveEx {
15852+// unsigned long connHdl;
15853+ unsigned int linkLen;
15854+ char linkData[1];
15855+
15856+} NwcUnmapDriveEx, *PNwcUnmapDriveEx;
15857+
15858+typedef struct tagNwcMapDriveEx {
15859+ NW_CONN_HANDLE ConnHandle;
15860+ unsigned int localUid;
15861+ unsigned int linkOffsetLength;
15862+ unsigned int linkOffset;
15863+ unsigned int dirPathOffsetLength;
15864+ unsigned int dirPathOffset;
15865+} NwcMapDriveEx, *PNwcMapDriveEx;
15866+
15867+typedef struct tagNwcGetBroadcastNotification {
15868+ u32 uMessageFlags;
15869+ u32 uConnReference;
15870+ u32 messageLen;
15871+ char message[1];
15872+} NwcGetBroadcastNotification, *PNwcGetBroadcastNotification;
15873+
15874+#endif
15875+#endif /* __NWCLNX_H__ */
15876--- /dev/null
15877+++ b/fs/novfs/nwerror.h
15878@@ -0,0 +1,658 @@
15879+/*
15880+ * NetWare Redirector for Linux
15881+ * Author: Tom Buckley
15882+ *
15883+ * This file contains all return error codes.
15884+ *
15885+ * Copyright (C) 2005 Novell, Inc.
15886+ *
15887+ * This program is free software; you can redistribute it and/or
15888+ * modify it under the terms of the GNU General Public License
15889+ * as published by the Free Software Foundation; either version 2
15890+ * of the License, or (at your option) any later version.
15891+ */
15892+#ifndef __NOVFS_ERROR_H
15893+#define __NOVFS_ERROR_H
15894+
15895+
15896+/*
15897+ * Network errors
15898+ * Decimal values at end of line are 32768 lower than actual
15899+ */
15900+
15901+#define SHELL_ERROR 0x8800
15902+#define VLM_ERROR 0x8800
15903+#define ALREADY_ATTACHED 0x8800 // 0 - Attach attempted to server with valid, existing connection
15904+#define INVALID_CONNECTION 0x8801 // 1 - Request attempted with invalid or non-attached connection handle
15905+#define DRIVE_IN_USE 0x8802 // 2 - OS/2 only (NOT USED)
15906+#define CANT_ADD_CDS 0x8803 // 3 - Map drive attempted but unable to add new current directory structure
15907+#define DRIVE_CANNOT_MAP 0x8803
15908+#define BAD_DRIVE_BASE 0x8804 // 4 - Map drive attempted with invalid path specification
15909+#define NET_READ_ERROR 0x8805 // 5 - Attempt to receive from the selected transport failed
15910+#define NET_RECV_ERROR 0x8805 // 5
15911+#define UNKNOWN_NET_ERROR 0x8806 // 6 - Network send attempted with an un-specific network error
15912+#define SERVER_INVALID_SLOT 0x8807 // 7 - Server request attempted with invalid server connection slot
15913+#define BAD_SERVER_SLOT 0x8807 // 7
15914+#define NO_SERVER_SLOTS 0x8808 // 8 - Attach attempted to server with no connection slots available
15915+#define NET_WRITE_ERROR 0x8809 // 9 - Attempt to send on the selected transport failed
15916+#define CONNECTION_IN_ERROR_STATE 0x8809 // Client-32
15917+#define NET_SEND_ERROR 0x8809 // 9
15918+#define SERVER_NO_ROUTE 0x880A // 10 - Attempted to find route to server where no route exists
15919+#define BAD_LOCAL_TARGET 0x880B // 11 - OS/2 only
15920+#define TOO_MANY_REQ_FRAGS 0x880C // 12 - Attempted request with too many request fragments specified
15921+#define CONNECT_LIST_OVERFLOW 0x880D // 13
15922+#define BUFFER_OVERFLOW 0x880E // 14 - Attempt to receive more data than the reply buffer had room for
15923+#define MORE_DATA_ERROR 0x880E // Client-32
15924+#define NO_CONN_TO_SERVER 0x880F // 15
15925+#define NO_CONNECTION_TO_SERVER 0x880F // 15 - Attempt to get connection for a server not connected
15926+#define NO_ROUTER_FOUND 0x8810 // 16 - OS/2 only
15927+#define BAD_FUNC_ERROR 0x8811 // 17
15928+#define INVALID_SHELL_CALL 0x8811 // 17 - Attempted function call to non- existent or illegal function
15929+#define SCAN_COMPLETE 0x8812
15930+#define LIP_RESIZE_ERROR 0x8812 // Client-32
15931+#define UNSUPPORTED_NAME_FORMAT_TYPE 0x8813
15932+#define INVALID_DIR_HANDLE 0x8813 // Client-32
15933+#define HANDLE_ALREADY_LICENSED 0x8814
15934+#define OUT_OF_CLIENT_MEMORY 0x8814 // Client-32
15935+#define HANDLE_ALREADY_UNLICENSED 0x8815
15936+#define PATH_NOT_OURS 0x8815 // Client-32
15937+#define INVALID_NCP_PACKET_LENGTH 0x8816
15938+#define PATH_IS_PRINT_DEVICE 0x8816 // Client-32
15939+#define SETTING_UP_TIMEOUT 0x8817
15940+#define PATH_IS_EXCLUDED_DEVICE 0x8817 // Client-32
15941+#define SETTING_SIGNALS 0x8818
15942+#define PATH_IS_INVALID 0x8818 // Client-32
15943+#define SERVER_CONNECTION_LOST 0x8819
15944+#define NOT_SAME_DEVICE 0x8819 // Client-32
15945+#define OUT_OF_HEAP_SPACE 0x881A
15946+#define INVALID_SERVICE_REQUEST 0x881B
15947+#define INVALID_SEARCH_HANDLE 0x881B // Client-32
15948+#define INVALID_TASK_NUMBER 0x881C
15949+#define INVALID_DEVICE_HANDLE 0x881C // Client-32
15950+#define INVALID_MESSAGE_LENGTH 0x881D
15951+#define INVALID_SEM_HANDLE 0x881D // Client-32
15952+#define EA_SCAN_DONE 0x881E
15953+#define INVALID_CFG_HANDLE 0x881E // Client-32
15954+#define BAD_CONNECTION_NUMBER 0x881F
15955+#define INVALID_MOD_HANDLE 0x881F // Client-32
15956+#define ASYN_FIRST_PASS 0x8820
15957+#define INVALID_DEVICE_INDEX 0x8821
15958+#define INVALID_CONN_HANDLE 0x8822
15959+#define INVALID_QUEUE_ID 0x8823
15960+#define INVALID_PDEVICE_HANDLE 0x8824
15961+#define INVALID_JOB_HANDLE 0x8825
15962+#define INVALID_ELEMENT_ID 0x8826
15963+#define ALIAS_NOT_FOUND 0x8827
15964+#define RESOURCE_SUSPENDED 0x8828
15965+#define INVALID_QUEUE_SPECIFIED 0x8829
15966+#define DEVICE_ALREADY_OPEN 0x882A
15967+#define JOB_ALREADY_OPEN 0x882B
15968+#define QUEUE_NAME_ID_MISMATCH 0x882C
15969+#define JOB_ALREADY_STARTED 0x882D
15970+#define SPECT_DAA_TYPE_NOT_SUPPORTED 0x882E
15971+#define INVALID_ENVIR_HANDLE 0x882F
15972+#define NOT_SAME_CONNECTION 0x8830 // 48 - Internal server request attempted accross different server connections
15973+#define PRIMARY_CONNECTION_NOT_SET 0x8831 // 49 - Attempt to retrieve default connection with no primary connection set
15974+#define NO_PRIMARY_SET 0x8831 // 49
15975+#define KEYWORD_NOT_FOUND 0x8832 // Client-32
15976+#define PRINT_CAPTURE_NOT_IN_PROGRESS 0x8832 // Client-32
15977+#define NO_CAPTURE_SET 0x8832 // 50
15978+#define NO_CAPTURE_IN_PROGRESS 0x8832 // 50 - Capture information requested on port with no capture in progress
15979+#define BAD_BUFFER_LENGTH 0x8833 // 51
15980+#define INVALID_BUFFER_LENGTH 0x8833 // 51 - Used to indicate length which caller requested on a GetDNC or SetDNC was too large
15981+#define NO_USER_NAME 0x8834 // 52
15982+#define NO_NETWARE_PRINT_SPOOLER 0x8835 // 53 - Capture requested without having the local print spooler installed
15983+#define INVALID_PARAMETER 0x8836 // 54 - Attempted function with an invalid function parameter specified
15984+#define CONFIG_FILE_OPEN_FAILED 0x8837 // 55 - OS/2 only
15985+#define NO_CONFIG_FILE 0x8838 // 56 - OS/2 only
15986+#define CONFIG_FILE_READ_FAILED 0x8839 // 57 - OS/2 only
15987+#define CONFIG_LINE_TOO_LONG 0x883A // 58 - OS/2 only
15988+#define CONFIG_LINES_IGNORED 0x883B // 59 - OS/2 only
15989+#define NOT_MY_RESOURCE 0x883C // 60 - Attempted request made with a parameter using foriegn resource
15990+#define DAEMON_INSTALLED 0x883D // 61 - OS/2 only
15991+#define SPOOLER_INSTALLED 0x883E // 62 - Attempted load of print spooler with print spooler already installed
15992+#define CONN_TABLE_FULL 0x883F // 63
15993+#define CONNECTION_TABLE_FULL 0x883F // 63 - Attempted to allocate a connection handle with no more local connection table entries
15994+#define CONFIG_SECTION_NOT_FOUND 0x8840 // 64 - OS/2 only
15995+#define BAD_TRAN_TYPE 0x8841 // 65
15996+#define INVALID_TRANSPORT_TYPE 0x8841 // 65 - Attempted function on a connection with an invalid transport selected
15997+#define TDS_TAG_IN_USE 0x8842 // 66 - OS/2 only
15998+#define TDS_OUT_OF_MEMORY 0x8843 // 67 - OS/2 only
15999+#define TDS_INVALID_TAG 0x8844 // 68 - Attempted TDS function with invalid tag
16000+#define TDS_WRITE_TRUNCATED 0x8845 // 69 - Attempted TDS write with buffer that exceeded buffer
16001+#define NO_CONNECTION_TO_DS 0x8846 // Client-32
16002+#define NO_DIRECTORY_SERVICE_CONNECTION 0x8846 // 70
16003+#define SERVICE_BUSY 0x8846 // 70 - Attempted request made to partially asynchronous function in busy state
16004+#define NO_SERVER_ERROR 0x8847 // 71 - Attempted connect failed to find any servers responding
16005+#define BAD_VLM_ERROR 0x8848 // 72 - Attempted function call to non-existant or not-loaded overlay
16006+#define NETWORK_DRIVE_IN_USE 0x8849 // 73 - Attempted map to network drive that was already mapped
16007+#define LOCAL_DRIVE_IN_USE 0x884A // 74 - Attempted map to local drive that was in use
16008+#define NO_DRIVES_AVAILABLE 0x884B // 75 - Attempted map to next available drive when none were available
16009+#define DEVICE_NOT_REDIRECTED 0x884C // 76 - The device is not redirected
16010+#define NO_MORE_SFT_ENTRIES 0x884D // 77 - Maximum number of files was reached
16011+#define UNLOAD_ERROR 0x884E // 78 - Attempted unload failed
16012+#define IN_USE_ERROR 0x884F // 79 - Attempted re-use of already in use connection entry
16013+#define TOO_MANY_REP_FRAGS 0x8850 // 80 - Attempted request with too many reply fragments specified
16014+#define TABLE_FULL 0x8851 // 81 - Attempted to add a name into the name table after it was full
16015+#ifndef SOCKET_NOT_OPEN
16016+#define SOCKET_NOT_OPEN 0x8852 // 82 - Listen was posted on unopened socket
16017+#endif
16018+#define MEM_MGR_ERROR 0x8853 // 83 - Attempted enhanced memory operation failed
16019+#define SFT3_ERROR 0x8854 // 84 - An SFT3 switch occured mid-transfer
16020+#define PREFERRED_NOT_FOUND 0x8855 // 85 - the preferred directory server was not established but another directory server was returned
16021+#define DEVICE_NOT_RECOGNIZED 0x8856 // 86 - used to determine if the device is not used by VISE so pass it on to the next redirector, if any.
16022+#define BAD_NET_TYPE 0x8857 // 87 - the network type (Bind/NDS) does not match the server version
16023+#define ERROR_OPENING_FILE 0x8858 // 88 - generic open failure error, invalid path, access denied, etc..
16024+#define NO_PREFERRED_SPECIFIED 0x8859 // 89 - no preferred name specified
16025+#define ERROR_OPENING_SOCKET 0x885A // 90 - error opening a socket
16026+#define REQUESTER_FAILURE 0x885A // Client-32
16027+#define RESOURCE_ACCESS_DENIED 0x885B // Client-32
16028+#define SIGNATURE_LEVEL_CONFLICT 0x8861
16029+#define NO_LOCK_FOUND 0x8862 // OS/2 - process lock on conn handle failed, process ID not recognized
16030+#define LOCK_TABLE_FULL 0x8863 // OS/2 - process lock on conn handle failed, process lock table full
16031+#define INVALID_MATCH_DATA 0x8864
16032+#define MATCH_FAILED 0x8865
16033+#define NO_MORE_ENTRIES 0x8866
16034+#define INSUFFICIENT_RESOURCES 0x8867
16035+#define STRING_TRANSLATION 0x8868
16036+#define STRING_TRANSLATION_NEEDED 0x8868 // Client-32
16037+#define ACCESS_VIOLATION 0x8869
16038+#define NOT_AUTHENTICATED 0x886A
16039+#define INVALID_LEVEL 0x886B
16040+#define RESOURCE_LOCK_ERROR 0x886C
16041+#define INVALID_NAME_FORMAT 0x886D
16042+#define OBJECT_EXISTS 0x886E
16043+#define OBJECT_NOT_FOUND 0x886F
16044+#define UNSUPPORTED_TRAN_TYPE 0x8870
16045+#define INVALID_STRING_TYPE 0x8871
16046+#define INVALID_OWNER 0x8872
16047+#define UNSUPPORTED_AUTHENTICATOR 0x8873
16048+#define IO_PENDING 0x8874
16049+#define INVALID_DRIVE_NUM 0x8875
16050+#define SHELL_FAILURE 0x88FF
16051+#define VLM_FAILURE 0x88FF
16052+
16053+#define SVC_ALREADY_REGISTERED 0x8880 // Client-32
16054+#define SVC_REGISTRY_FULL 0x8881 // Client-32
16055+#define SVC_NOT_REGISTERED 0x8882 // Client-32
16056+#define OUT_OF_RESOURCES 0x8883 // Client-32
16057+#define RESOLVE_SVC_FAILED 0x8884 // Client-32
16058+#define CONNECT_FAILED 0x8885 // Client-32
16059+#define PROTOCOL_NOT_BOUND 0x8886 // Client-32
16060+#define AUTHENTICATION_FAILED 0x8887 // Client-32
16061+#define INVALID_AUTHEN_HANDLE 0x8888 // Client-32
16062+#define AUTHEN_HANDLE_ALREADY_EXISTS 0x8889 // Client-32
16063+
16064+#define DIFF_OBJECT_ALREADY_AUTHEN 0x8890 // Client-32
16065+#define REQUEST_NOT_SERVICEABLE 0x8891 // Client-32
16066+#define AUTO_RECONNECT_SO_REBUILD 0x8892 // Client-32
16067+#define AUTO_RECONNECT_RETRY_REQUEST 0x8893 // Client-32
16068+#define ASYNC_REQUEST_IN_USE 0x8894 // Client-32
16069+#define ASYNC_REQUEST_CANCELED 0x8895 // Client-32
16070+#define SESS_SVC_ALREADY_REGISTERED 0x8896 // Client-32
16071+#define SESS_SVC_NOT_REGISTERED 0x8897 // Client-32
16072+#define PREVIOUSLY_AUTHENTICATED 0x8899 // Client-32
16073+#define RESOLVE_SVC_PARTIAL 0x889A // Client-32
16074+#define NO_DEFAULT_SPECIFIED 0x889B // Client-32
16075+#define HOOK_REQUEST_NOT_HANDLED 0x889C // Client-32
16076+#define HOOK_REQUEST_BUSY 0x889D // Client-32
16077+#define HOOK_REQUEST_QUEUED 0x889D // Client-32
16078+#define AUTO_RECONNECT_SO_IGNORE 0x889E // Client-32
16079+#define ASYNC_REQUEST_NOT_IN_USE 0x889F // Client-32
16080+#define AUTO_RECONNECT_FAILURE 0x88A0 // Client-32
16081+#define NET_ERROR_ABORT_APPLICATION 0x88A1 // Client-32
16082+#define NET_ERROR_SUSPEND_APPLICATION 0x88A2 // Client-32
16083+#define NET_ERROR_ABORTED_PROCESS_GROUP 0x88A3 // Client-32
16084+#define NET_ERROR_PASSWORD_HAS_EXPIRED 0x88A5 // Client-32
16085+#define NET_ERROR_NETWORK_INACTIVE 0x88A6 // Client-32
16086+#define REPLY_TRUNCATED 0x88E6 // 230 NLM
16087+#define UTF8_CONVERSION_FAILED 0x88F0 // NWCALLS
16088+
16089+/*
16090+ * Server Errors
16091+ */
16092+
16093+#define ERR_INSUFFICIENT_SPACE 0x8901 // 001
16094+#define NLM_INVALID_CONNECTION 0x890A // 010
16095+#define ERR_TIMEOUT 0x8910 // 016 - nlm connection timeout
16096+#define ERR_NO_MORE_ENTRY 0x8914 // 020
16097+#define ERR_BUFFER_TOO_SMALL 0x8977 // 119
16098+#define ERR_VOLUME_FLAG_NOT_SET 0x8978 // 120 the service requested, not avail. on the selected vol.
16099+#define ERR_NO_ITEMS_FOUND 0x8979 // 121
16100+#define ERR_CONN_ALREADY_TEMP 0x897A // 122
16101+#define ERR_CONN_ALREADY_LOGGED_IN 0x897B // 123
16102+#define ERR_CONN_NOT_AUTHENTICATED 0x897C // 124
16103+#define ERR_CONN_NOT_LOGGED_IN 0x897D // 125
16104+#define NCP_BOUNDARY_CHECK_FAILED 0x897E // 126
16105+#define ERR_LOCK_WAITING 0x897F // 127
16106+#define ERR_LOCK_FAIL 0x8980 // 128
16107+#define FILE_IN_USE_ERROR 0x8980 // 128
16108+#define NO_MORE_FILE_HANDLES 0x8981 // 129
16109+#define NO_OPEN_PRIVILEGES 0x8982 // 130
16110+#define IO_ERROR_NETWORK_DISK 0x8983 // 131
16111+#define ERR_AUDITING_HARD_IO_ERROR 0x8983 // 131
16112+#define NO_CREATE_PRIVILEGES 0x8984 // 132
16113+#define ERR_AUDITING_NOT_SUPV 0x8984 // 132
16114+#define NO_CREATE_DELETE_PRIVILEGES 0x8985 // 133
16115+#define CREATE_FILE_EXISTS_READ_ONLY 0x8986 // 134
16116+#define WILD_CARDS_IN_CREATE_FILE_NAME 0x8987 // 135
16117+#define CREATE_FILENAME_ERROR 0x8987 // 135
16118+#define INVALID_FILE_HANDLE 0x8988 // 136
16119+#define NO_SEARCH_PRIVILEGES 0x8989 // 137
16120+#define NO_DELETE_PRIVILEGES 0x898A // 138
16121+#define NO_RENAME_PRIVILEGES 0x898B // 139
16122+#define NO_MODIFY_PRIVILEGES 0x898C // 140
16123+#define SOME_FILES_AFFECTED_IN_USE 0x898D // 141
16124+#define NO_FILES_AFFECTED_IN_USE 0x898E // 142
16125+#define SOME_FILES_AFFECTED_READ_ONLY 0x898F // 143
16126+#define NO_FILES_AFFECTED_READ_ONLY 0x8990 // 144
16127+#define SOME_FILES_RENAMED_NAME_EXISTS 0x8991 // 145
16128+#define NO_FILES_RENAMED_NAME_EXISTS 0x8992 // 146
16129+#define NO_READ_PRIVILEGES 0x8993 // 147
16130+#define NO_WRITE_PRIVILEGES_OR_READONLY 0x8994 // 148
16131+#define FILE_DETACHED 0x8995 // 149
16132+#define SERVER_OUT_OF_MEMORY 0x8996 // 150
16133+#define ERR_TARGET_NOT_A_SUBDIRECTORY 0x8996 // 150 can be changed later (note written by server people).
16134+#define NO_DISK_SPACE_FOR_SPOOL_FILE 0x8997 // 151
16135+#define ERR_AUDITING_NOT_ENABLED 0x8997 // 151
16136+#define VOLUME_DOES_NOT_EXIST 0x8998 // 152
16137+#define DIRECTORY_FULL 0x8999 // 153
16138+#define RENAMING_ACROSS_VOLUMES 0x899A // 154
16139+#define BAD_DIRECTORY_HANDLE 0x899B // 155
16140+#define INVALID_PATH 0x899C // 156
16141+#define NO_MORE_TRUSTEES 0x899C // 156
16142+#define NO_MORE_DIRECTORY_HANDLES 0x899D // 157
16143+#define INVALID_FILENAME 0x899E // 158
16144+#define DIRECTORY_ACTIVE 0x899F // 159
16145+#define DIRECTORY_NOT_EMPTY 0x89A0 // 160
16146+#define DIRECTORY_IO_ERROR 0x89A1 // 161
16147+#define READ_FILE_WITH_RECORD_LOCKED 0x89A2 // 162
16148+#define ERR_TRANSACTION_RESTARTED 0x89A3 // 163
16149+#define ERR_RENAME_DIR_INVALID 0x89A4 // 164
16150+#define ERR_INVALID_OPENCREATE_MODE 0x89A5 // 165
16151+#define ERR_ALREADY_IN_USE 0x89A6 // 166
16152+#define ERR_AUDITING_ACTIVE 0x89A6 // 166
16153+#define ERR_INVALID_RESOURCE_TAG 0x89A7 // 167
16154+#define ERR_ACCESS_DENIED 0x89A8 // 168
16155+#define ERR_AUDITING_NO_RIGHTS 0x89A8 // 168
16156+#define ERR_LINK_IN_PATH 0x89A9 // 169
16157+#define INVALID_DATA_TYPE 0x89AA // 170
16158+#define INVALID_DATA_STREAM 0x89BE // 190
16159+#define INVALID_NAME_SPACE 0x89BF // 191
16160+#define NO_ACCOUNTING_PRIVILEGES 0x89C0 // 192
16161+#define LOGIN_DENIED_NO_ACCOUNT_BALANCE 0x89C1 // 193
16162+#define LOGIN_DENIED_NO_CREDIT 0x89C2 // 194
16163+#define ERR_AUDITING_RECORD_SIZE 0x89C2 // 194
16164+#define ERR_TOO_MANY_HOLDS 0x89C3 // 195
16165+#define ACCOUNTING_DISABLED 0x89C4 // 196
16166+#define INTRUDER_DETECTION_LOCK 0x89C5 // 197
16167+#define NO_CONSOLE_OPERATOR 0x89C6 // 198
16168+#define NO_CONSOLE_PRIVILEGES 0x89C6 // 198
16169+#define ERR_Q_IO_FAILURE 0x89D0 // 208
16170+#define ERR_NO_QUEUE 0x89D1 // 209
16171+#define ERR_NO_Q_SERVER 0x89D2 // 210
16172+#define ERR_NO_Q_RIGHTS 0x89D3 // 211
16173+#define ERR_Q_FULL 0x89D4 // 212
16174+#define ERR_NO_Q_JOB 0x89D5 // 213
16175+#define ERR_NO_Q_JOB_RIGHTS 0x89D6 // 214
16176+#define ERR_Q_IN_SERVICE 0x89D7 // 215
16177+#define PASSWORD_NOT_UNIQUE 0x89D7 // 215
16178+#define ERR_Q_NOT_ACTIVE 0x89D8 // 216
16179+#define PASSWORD_TOO_SHORT 0x89D8 // 216
16180+#define ERR_Q_STN_NOT_SERVER 0x89D9 // 217
16181+#define LOGIN_DENIED_NO_CONNECTION 0x89D9 // 217
16182+#define ERR_MAXIMUM_LOGINS_EXCEEDED 0x89D9 // 217
16183+#define ERR_Q_HALTED 0x89DA // 218
16184+#define UNAUTHORIZED_LOGIN_TIME 0x89DA // 218
16185+#define UNAUTHORIZED_LOGIN_STATION 0x89DB // 219
16186+#define ERR_Q_MAX_SERVERS 0x89DB // 219
16187+#define ACCOUNT_DISABLED 0x89DC // 220
16188+#define PASSWORD_HAS_EXPIRED_NO_GRACE 0x89DE // 222
16189+#define PASSWORD_HAS_EXPIRED 0x89DF // 223
16190+#define E_NO_MORE_USERS 0x89E7 // 231
16191+#define NOT_ITEM_PROPERTY 0x89E8 // 232
16192+#define WRITE_PROPERTY_TO_GROUP 0x89E8 // 232
16193+#define MEMBER_ALREADY_EXISTS 0x89E9 // 233
16194+#define NO_SUCH_MEMBER 0x89EA // 234
16195+#define NOT_GROUP_PROPERTY 0x89EB // 235
16196+#define NO_SUCH_SEGMENT 0x89EC // 236
16197+#define PROPERTY_ALREADY_EXISTS 0x89ED // 237
16198+#define OBJECT_ALREADY_EXISTS 0x89EE // 238
16199+#define INVALID_NAME 0x89EF // 239
16200+#define WILD_CARD_NOT_ALLOWED 0x89F0 // 240
16201+#define INVALID_BINDERY_SECURITY 0x89F1 // 241
16202+#define NO_OBJECT_READ_PRIVILEGE 0x89F2 // 242
16203+#define NO_OBJECT_RENAME_PRIVILEGE 0x89F3 // 243
16204+#define NO_OBJECT_DELETE_PRIVILEGE 0x89F4 // 244
16205+#define NO_OBJECT_CREATE_PRIVILEGE 0x89F5 // 245
16206+#define NO_PROPERTY_DELETE_PRIVILEGE 0x89F6 // 246
16207+#define NO_PROPERTY_CREATE_PRIVILEGE 0x89F7 // 247
16208+#define NO_PROPERTY_WRITE_PRIVILEGE 0x89F8 // 248
16209+#define NO_FREE_CONNECTION_SLOTS 0x89F9 // 249
16210+#define NO_PROPERTY_READ_PRIVILEGE 0x89F9 // 249
16211+#define NO_MORE_SERVER_SLOTS 0x89FA // 250
16212+#define TEMP_REMAP_ERROR 0x89FA // 250
16213+#define INVALID_PARAMETERS 0x89FB // 251
16214+#define NO_SUCH_PROPERTY 0x89FB // 251
16215+#define ERR_NCP_NOT_SUPPORTED 0x89FB // 251
16216+#define INTERNET_PACKET_REQT_CANCELED 0x89FC // 252
16217+#define UNKNOWN_FILE_SERVER 0x89FC // 252
16218+#define MESSAGE_QUEUE_FULL 0x89FC // 252
16219+#define NO_SUCH_OBJECT 0x89FC // 252
16220+#define LOCK_COLLISION 0x89FD // 253
16221+#define BAD_STATION_NUMBER 0x89FD // 253
16222+#define INVALID_PACKET_LENGTH 0x89FD // 253
16223+#define UNKNOWN_REQUEST 0x89FD // 253
16224+#define BINDERY_LOCKED 0x89FE // 254
16225+#define TRUSTEE_NOT_FOUND 0x89FE // 254
16226+#define DIRECTORY_LOCKED 0x89FE // 254
16227+#define INVALID_SEMAPHORE_NAME_LENGTH 0x89FE // 254
16228+#define PACKET_NOT_DELIVERABLE 0x89FE // 254
16229+#define SERVER_BINDERY_LOCKED 0x89FE // 254
16230+#define SOCKET_TABLE_FULL 0x89FE // 254
16231+#define SPOOL_DIRECTORY_ERROR 0x89FE // 254
16232+#define SUPERVISOR_HAS_DISABLED_LOGIN 0x89FE // 254
16233+#define TIMEOUT_FAILURE 0x89FE // 254
16234+#define BAD_PRINTER_ERROR 0x89FF // 255
16235+#define BAD_RECORD_OFFSET 0x89FF // 255
16236+#define CLOSE_FCB_ERROR 0x89FF // 255
16237+#define FILE_EXTENSION_ERROR 0x89FF // 255
16238+#define FILE_NAME_ERROR 0x89FF // 255
16239+#define HARDWARE_FAILURE 0x89FF // 255
16240+#define INVALID_DRIVE_NUMBER 0x89FF // 255
16241+#define DOS_INVALID_DRIVE 0x000F // 255
16242+#define INVALID_INITIAL_SEMAPHORE_VALUE 0x89FF // 255
16243+#define INVALID_SEMAPHORE_HANDLE 0x89FF // 255
16244+#define IO_BOUND_ERROR 0x89FF // 255
16245+#define NO_FILES_FOUND_ERROR 0x89FF // 255
16246+#define NO_RESPONSE_FROM_SERVER 0x89FF // 255
16247+#define NO_SUCH_OBJECT_OR_BAD_PASSWORD 0x89FF // 255
16248+#define PATH_NOT_LOCATABLE 0x89FF // 255
16249+#define QUEUE_FULL_ERROR 0x89FF // 255
16250+#define REQUEST_NOT_OUTSTANDING 0x89FF // 255
16251+#ifndef SOCKET_ALREADY_OPEN
16252+#define SOCKET_ALREADY_OPEN 0x89FF // 255
16253+#endif
16254+#define LOCK_ERROR 0x89FF // 255
16255+#ifndef FAILURE
16256+#define FAILURE 0x89FF // 255 Generic Failure
16257+#endif
16258+
16259+#if 0
16260+#define NOT_SAME_LOCAL_DRIVE 0x89F6
16261+#define TARGET_DRIVE_NOT_LOCAL 0x89F7
16262+#define ALREADY_ATTACHED_TO_SERVER 0x89F8 // 248
16263+#define NOT_ATTACHED_TO_SERVER 0x89F8
16264+#endif
16265+
16266+/*
16267+ * Network errors
16268+ * Decimal values at end of line are 32768 lower than actual
16269+ */
16270+#define NWE_ALREADY_ATTACHED 0x8800 // 0 - Attach attempted to server with valid, existing connection
16271+#define NWE_CONN_INVALID 0x8801 // 1 - Request attempted with invalid or non-attached connection handle
16272+#define NWE_DRIVE_IN_USE 0x8802 // 2 - OS/2 only (NOT USED)
16273+#define NWE_DRIVE_CANNOT_MAP 0x8803 // 3 - Map drive attempted but unable to add new current directory structure
16274+#define NWE_DRIVE_BAD_PATH 0x8804 // 4 - Map drive attempted with invalid path specification
16275+#define NWE_NET_RECEIVE 0x8805 // 5 - Attempt to receive from the selected transport failed
16276+#define NWE_NET_UNKNOWN 0x8806 // 6 - Network send attempted with an un-specific network error
16277+#define NWE_SERVER_BAD_SLOT 0x8807 // 7 - Server request attempted with invalid server connection slot
16278+#define NWE_SERVER_NO_SLOTS 0x8808 // 8 - Attach attempted to server with no connection slots available
16279+#define NWE_NET_SEND 0x8809 // 9 - Attempt to send on the selected transport failed
16280+#define NWE_SERVER_NO_ROUTE 0x880A // 10 - Attempted to find route to server where no route exists
16281+#define NWE_BAD_LOCAL_TARGET 0x880B // 11 - OS/2 only
16282+#define NWE_REQ_TOO_MANY_REQ_FRAGS 0x880C // 12 - Attempted request with too many request fragments specified
16283+#define NWE_CONN_LIST_OVERFLOW 0x880D // 13
16284+#define NWE_BUFFER_OVERFLOW 0x880E // 14 - Attempt to receive more data than the reply buffer had room for
16285+#define NWE_SERVER_NO_CONN 0x880F // 15 - Attempt to get connection for a server not connected
16286+#define NWE_NO_ROUTER_FOUND 0x8810 // 16 - OS/2 only
16287+#define NWE_FUNCTION_INVALID 0x8811 // 17 - Attempted function call to non- existent or illegal function
16288+#define NWE_SCAN_COMPLETE 0x8812
16289+#define NWE_UNSUPPORTED_NAME_FORMAT_TYP 0x8813
16290+#define NWE_HANDLE_ALREADY_LICENSED 0x8814
16291+#define NWE_HANDLE_ALREADY_UNLICENSED 0x8815
16292+#define NWE_INVALID_NCP_PACKET_LENGTH 0x8816
16293+#define NWE_SETTING_UP_TIMEOUT 0x8817
16294+#define NWE_SETTING_SIGNALS 0x8818
16295+#define NWE_SERVER_CONNECTION_LOST 0x8819
16296+#define NWE_OUT_OF_HEAP_SPACE 0x881A
16297+#define NWE_INVALID_SERVICE_REQUEST 0x881B
16298+#define NWE_INVALID_TASK_NUMBER 0x881C
16299+#define NWE_INVALID_MESSAGE_LENGTH 0x881D
16300+#define NWE_EA_SCAN_DONE 0x881E
16301+#define NWE_BAD_CONNECTION_NUMBER 0x881F
16302+#define NWE_MULT_TREES_NOT_SUPPORTED 0x8820 // 32 - Attempt to open a connection to a DS tree other than the default tree
16303+#define NWE_CONN_NOT_SAME 0x8830 // 48 - Internal server request attempted across different server connections
16304+#define NWE_CONN_PRIMARY_NOT_SET 0x8831 // 49 - Attempt to retrieve default connection with no primary connection set
16305+#define NWE_PRN_CAPTURE_NOT_IN_PROGRESS 0x8832 // 50 - Capture information requested on port with no capture in progress
16306+#define NWE_BUFFER_INVALID_LEN 0x8833 // 51 - Used to indicate length which caller requested on a GetDNC or SetDNC was too large
16307+#define NWE_USER_NO_NAME 0x8834 // 52
16308+#define NWE_PRN_NO_LOCAL_SPOOLER 0x8835 // 53 - Capture requested without having the local print spooler installed
16309+#define NWE_PARAM_INVALID 0x8836 // 54 - Attempted function with an invalid function parameter specified
16310+#define NWE_CFG_OPEN_FAILED 0x8837 // 55 - OS/2 only
16311+#define NWE_CFG_NO_FILE 0x8838 // 56 - OS/2 only
16312+#define NWE_CFG_READ_FAILED 0x8839 // 57 - OS/2 only
16313+#define NWE_CFG_LINE_TOO_LONG 0x883A // 58 - OS/2 only
16314+#define NWE_CFG_LINES_IGNORED 0x883B // 59 - OS/2 only
16315+#define NWE_RESOURCE_NOT_OWNED 0x883C // 60 - Attempted request made with a parameter using foriegn resource
16316+#define NWE_DAEMON_INSTALLED 0x883D // 61 - OS/2 only
16317+#define NWE_PRN_SPOOLER_INSTALLED 0x883E // 62 - Attempted load of print spooler with print spooler already installed
16318+#define NWE_CONN_TABLE_FULL 0x883F // 63 - Attempted to allocate a connection handle with no more local connection table entries
16319+#define NWE_CFG_SECTION_NOT_FOUND 0x8840 // 64 - OS/2 only
16320+#define NWE_TRAN_INVALID_TYPE 0x8841 // 65 - Attempted function on a connection with an invalid transport selected
16321+#define NWE_TDS_TAG_IN_USE 0x8842 // 66 - OS/2 only
16322+#define NWE_TDS_OUT_OF_MEMORY 0x8843 // 67 - OS/2 only
16323+#define NWE_TDS_INVALID_TAG 0x8844 // 68 - Attempted TDS function with invalid tag
16324+#define NWE_TDS_WRITE_TRUNCATED 0x8845 // 69 - Attempted TDS write with buffer that exceeded buffer
16325+#define NWE_DS_NO_CONN 0x8846 // 70
16326+#define NWE_SERVICE_BUSY 0x8846 // 70 - Attempted request made to partially asynchronous function in busy state
16327+#define NWE_SERVER_NOT_FOUND 0x8847 // 71 - Attempted connect failed to find any servers responding
16328+#define NWE_VLM_INVALID 0x8848 // 72 - Attempted function call to non-existant or not-loaded overlay
16329+#define NWE_DRIVE_ALREADY_MAPPED 0x8849 // 73 - Attempted map to network drive that was already mapped
16330+#define NWE_DRIVE_LOCAL_IN_USE 0x884A // 74 - Attempted map to local drive that was in use
16331+#define NWE_DRIVE_NONE_AVAILABLE 0x884B // 75 - Attempted map to next available drive when none were available
16332+#define NWE_DEVICE_NOT_REDIRECTED 0x884C // 76 - The device is not redirected
16333+#define NWE_FILE_MAX_REACHED 0x884D // 77 - Maximum number of files was reached
16334+#define NWE_UNLOAD_FAILED 0x884E // 78 - Attempted unload failed
16335+#define NWE_CONN_IN_USE 0x884F // 79 - Attempted re-use of already in use connection entry
16336+#define NWE_REQ_TOO_MANY_REP_FRAGS 0x8850 // 80 - Attempted request with too many reply fragments specified
16337+#define NWE_NAME_TABLE_FULL 0x8851 // 81 - Attempted to add a name into the name table after it was full
16338+#define NWE_SOCKET_NOT_OPEN 0x8852 // 82 - Listen was posted on unopened socket
16339+#define NWE_MEMORY_MGR_ERROR 0x8853 // 83 - Attempted enhanced memory operation failed
16340+#define NWE_SFT3_ERROR 0x8854 // 84 - An SFT3 switch occured mid-transfer
16341+#define NWE_DS_PREFERRED_NOT_FOUND 0x8855 // 85 - the preferred directory server was not established but another directory server was returned
16342+#define NWE_DEVICE_NOT_RECOGNIZED 0x8856 // 86 - used to determine if the device is not used by VISE so pass it on to the next redirector, if any.
16343+#define NWE_NET_INVALID_TYPE 0x8857 // 87 - the network type (Bind/NDS) does not match the server version
16344+#define NWE_FILE_OPEN_FAILED 0x8858 // 88 - generic open failure error, invalid path, access denied, etc..
16345+#define NWE_DS_PREFERRED_NOT_SPECIFIED 0x8859 // 89 - no preferred name specified
16346+#define NWE_SOCKET_OPEN_FAILED 0x885A // 90 - error opening a socket
16347+#define NWE_SIGNATURE_LEVEL_CONFLICT 0x8861
16348+#define NWE_NO_LOCK_FOUND 0x8862 // OS/2 - process lock on conn handle failed, process ID not recognized
16349+#define NWE_LOCK_TABLE_FULL 0x8863 // OS/2 - process lock on conn handle failed, process lock table full
16350+#define NWE_INVALID_MATCH_DATA 0x8864
16351+#define NWE_MATCH_FAILED 0x8865
16352+#define NWE_NO_MORE_ENTRIES 0x8866
16353+#define NWE_INSUFFICIENT_RESOURCES 0x8867
16354+#define NWE_STRING_TRANSLATION 0x8868
16355+#define NWE_ACCESS_VIOLATION 0x8869
16356+#define NWE_NOT_AUTHENTICATED 0x886A
16357+#define NWE_INVALID_LEVEL 0x886B
16358+#define NWE_RESOURCE_LOCK 0x886C
16359+#define NWE_INVALID_NAME_FORMAT 0x886D
16360+#define NWE_OBJECT_EXISTS 0x886E
16361+#define NWE_OBJECT_NOT_FOUND 0x886F
16362+#define NWE_UNSUPPORTED_TRAN_TYPE 0x8870
16363+#define NWE_INVALID_STRING_TYPE 0x8871
16364+#define NWE_INVALID_OWNER 0x8872
16365+#define NWE_UNSUPPORTED_AUTHENTICATOR 0x8873
16366+#define NWE_IO_PENDING 0x8874
16367+#define NWE_INVALID_DRIVE_NUMBER 0x8875
16368+#define NWE_REPLY_TRUNCATED 0x88e6 // 230 NLM
16369+#define NWE_REQUESTER_FAILURE 0x88FF
16370+
16371+/*
16372+ * Server Errors
16373+ */
16374+#define NWE_INSUFFICIENT_SPACE 0x8901 // 001
16375+#define NWE_INVALID_CONNECTION 0x890a // 010 - nlm invalid connection
16376+#define NWE_TIMEOUT 0x8910 // 016 - nlm connection timeout
16377+#define NWE_NO_MORE_ENTRY 0x8914 // 020
16378+#define NWE_BUFFER_TOO_SMALL 0x8977 // 119
16379+#define NWE_VOL_FLAG_NOT_SET 0x8978 // 120 the service requested, not avail. on the selected vol.
16380+#define NWE_NO_ITEMS_FOUND 0x8979 // 121
16381+#define NWE_CONN_ALREADY_TEMP 0x897a // 122
16382+#define NWE_CONN_ALREADY_LOGGED_IN 0x897b // 123
16383+#define NWE_CONN_NOT_AUTHENTICATED 0x897c // 124
16384+#define NWE_CONN_NOT_LOGGED_IN 0x897d // 125
16385+#define NWE_NCP_BOUNDARY_CHECK_FAILED 0x897e // 126
16386+#define NWE_LOCK_WAITING 0x897f // 127
16387+#define NWE_LOCK_FAIL 0x8980 // 128
16388+#define NWE_FILE_IN_USE 0x8980 // 128
16389+#define NWE_FILE_NO_HANDLES 0x8981 // 129
16390+#define NWE_FILE_NO_OPEN_PRIV 0x8982 // 130
16391+#define NWE_DISK_IO_ERROR 0x8983 // 131
16392+#define NWE_AUDITING_HARD_IO_ERROR 0x8983 // 131
16393+#define NWE_FILE_NO_CREATE_PRIV 0x8984 // 132
16394+#define NWE_AUDITING_NOT_SUPV 0x8984 // 132
16395+#define NWE_FILE_NO_CREATE_DEL_PRIV 0x8985 // 133
16396+#define NWE_FILE_EXISTS_READ_ONLY 0x8986 // 134
16397+#define NWE_FILE_WILD_CARDS_IN_NAME 0x8987 // 135
16398+#define NWE_FILE_INVALID_HANDLE 0x8988 // 136
16399+#define NWE_FILE_NO_SRCH_PRIV 0x8989 // 137
16400+#define NWE_FILE_NO_DEL_PRIV 0x898A // 138
16401+#define NWE_FILE_NO_RENAME_PRIV 0x898B // 139
16402+#define NWE_FILE_NO_MOD_PRIV 0x898C // 140
16403+#define NWE_FILE_SOME_IN_USE 0x898D // 141
16404+#define NWE_FILE_NONE_IN_USE 0x898E // 142
16405+#define NWE_FILE_SOME_READ_ONLY 0x898F // 143
16406+#define NWE_FILE_NONE_READ_ONLY 0x8990 // 144
16407+#define NWE_FILE_SOME_RENAMED_EXIST 0x8991 // 145
16408+#define NWE_FILE_NONE_RENAMED_EXIST 0x8992 // 146
16409+#define NWE_FILE_NO_READ_PRIV 0x8993 // 147
16410+#define NWE_FILE_NO_WRITE_PRIV 0x8994 // 148
16411+#define NWE_FILE_READ_ONLY 0x8994 // 148
16412+#define NWE_FILE_DETACHED 0x8995 // 149
16413+#define NWE_SERVER_OUT_OF_MEMORY 0x8996 // 150
16414+#define NWE_DIR_TARGET_INVALID 0x8996 // 150
16415+#define NWE_DISK_NO_SPOOL_SPACE 0x8997 // 151
16416+#define NWE_AUDITING_NOT_ENABLED 0x8997 // 151
16417+#define NWE_VOL_INVALID 0x8998 // 152
16418+#define NWE_DIR_FULL 0x8999 // 153
16419+#define NWE_VOL_RENAMING_ACROSS 0x899A // 154
16420+#define NWE_DIRHANDLE_INVALID 0x899B // 155
16421+#define NWE_PATH_INVALID 0x899C // 156
16422+#define NWE_TRUSTEES_NO_MORE 0x899C // 156
16423+#define NWE_DIRHANDLE_NO_MORE 0x899D // 157
16424+#define NWE_FILE_NAME_INVALID 0x899E // 158
16425+#define NWE_DIR_ACTIVE 0x899F // 159
16426+#define NWE_DIR_NOT_EMPTY 0x89A0 // 160
16427+#define NWE_DIR_IO_ERROR 0x89A1 // 161
16428+#define NWE_FILE_IO_LOCKED 0x89A2 // 162
16429+#define NWE_TTS_RANSACTION_RESTARTED 0x89A3 // 163
16430+#define NWE_TTS_TRANSACTION_RESTARTED 0x89A3 // 163
16431+#define NWE_DIR_RENAME_INVALID 0x89A4 // 164
16432+#define NWE_FILE_OPENCREAT_MODE_INVALID 0x89A5 // 165
16433+#define NWE_ALREADY_IN_USE 0x89A6 // 166
16434+#define NWE_AUDITING_ACTIVE 0x89A6 // 166
16435+#define NWE_RESOURCE_TAG_INVALID 0x89A7 // 167
16436+#define NWE_ACCESS_DENIED 0x89A8 // 168
16437+#define NWE_AUDITING_NO_RIGHTS 0x89A8 // 168
16438+#define NWE_LINK_IN_PATH 0x89A9 // 169
16439+#define NWE_INVALID_DATA_TYPE_FLAG 0x89AA // 170 (legacy vol with UTF8)
16440+#define NWE_DATA_STREAM_INVALID 0x89BE // 190
16441+#define NWE_NAME_SPACE_INVALID 0x89BF // 191
16442+#define NWE_ACCTING_NO_PRIV 0x89C0 // 192
16443+#define NWE_ACCTING_NO_BALANCE 0x89C1 // 193
16444+#define NWE_ACCTING_NO_CREDIT 0x89C2 // 194
16445+#define NWE_AUDITING_RECORD_SIZE 0x89C2 // 194
16446+#define NWE_ACCTING_TOO_MANY_HOLDS 0x89C3 // 195
16447+#define NWE_ACCTING_DISABLED 0x89C4 // 196
16448+#define NWE_LOGIN_LOCKOUT 0x89C5 // 197
16449+#define NWE_CONSOLE_NO_PRIV 0x89C6 // 198
16450+#define NWE_Q_IO_FAILURE 0x89D0 // 208
16451+#define NWE_Q_NONE 0x89D1 // 209
16452+#define NWE_Q_NO_SERVER 0x89D2 // 210
16453+#define NWE_Q_NO_RIGHTS 0x89D3 // 211
16454+#define NWE_Q_FULL 0x89D4 // 212
16455+#define NWE_Q_NO_JOB 0x89D5 // 213
16456+#define NWE_Q_NO_JOB_RIGHTS 0x89D6 // 214
16457+#define NWE_PASSWORD_UNENCRYPTED 0x89D6 // 214
16458+#define NWE_Q_IN_SERVICE 0x89D7 // 215
16459+#define NWE_PASSWORD_NOT_UNIQUE 0x89D7 // 215
16460+#define NWE_Q_NOT_ACTIVE 0x89D8 // 216
16461+#define NWE_PASSWORD_TOO_SHORT 0x89D8 // 216
16462+#define NWE_Q_STN_NOT_SERVER 0x89D9 // 217
16463+#define NWE_LOGIN_NO_CONN 0x89D9 // 217
16464+#define NWE_LOGIN_MAX_EXCEEDED 0x89D9 // 217
16465+#define NWE_Q_HALTED 0x89DA // 218
16466+#define NWE_LOGIN_UNAUTHORIZED_TIME 0x89DA // 218
16467+#define NWE_LOGIN_UNAUTHORIZED_STATION 0x89DB // 219
16468+#define NWE_Q_MAX_SERVERS 0x89DB // 219
16469+#define NWE_ACCT_DISABLED 0x89DC // 220
16470+#define NWE_PASSWORD_INVALID 0x89DE // 222
16471+#define NWE_PASSWORD_EXPIRED 0x89DF // 223
16472+#define NWE_LOGIN_NO_CONN_AVAIL 0x89E0 // 224
16473+#define NWE_E_NO_MORE_USERS 0x89E7 // 231
16474+#define NWE_BIND_NOT_ITEM_PROP 0x89E8 // 232
16475+#define NWE_BIND_WRITE_TO_GROUP_PROP 0x89E8 // 232
16476+#define NWE_BIND_MEMBER_ALREADY_EXISTS 0x89E9 // 233
16477+#define NWE_BIND_NO_SUCH_MEMBER 0x89EA // 234
16478+#define NWE_BIND_NOT_GROUP_PROP 0x89EB // 235
16479+#define NWE_BIND_NO_SUCH_SEGMENT 0x89EC // 236
16480+#define NWE_BIND_PROP_ALREADY_EXISTS 0x89ED // 237
16481+#define NWE_BIND_OBJ_ALREADY_EXISTS 0x89EE // 238
16482+#define NWE_BIND_NAME_INVALID 0x89EF // 239
16483+#define NWE_BIND_WILDCARD_INVALID 0x89F0 // 240
16484+#define NWE_BIND_SECURITY_INVALID 0x89F1 // 241
16485+#define NWE_BIND_OBJ_NO_READ_PRIV 0x89F2 // 242
16486+#define NWE_BIND_OBJ_NO_RENAME_PRIV 0x89F3 // 243
16487+#define NWE_BIND_OBJ_NO_DELETE_PRIV 0x89F4 // 244
16488+#define NWE_BIND_OBJ_NO_CREATE_PRIV 0x89F5 // 245
16489+#define NWE_BIND_PROP_NO_DELETE_PRIV 0x89F6 // 246
16490+#define NWE_BIND_PROP_NO_CREATE_PRIV 0x89F7 // 247
16491+#define NWE_BIND_PROP_NO_WRITE_PRIV 0x89F8 // 248
16492+#define NWE_BIND_PROP_NO_READ_PRIV 0x89F9 // 249
16493+#define NWE_NO_FREE_CONN_SLOTS 0x89F9 // 249
16494+#define NWE_NO_MORE_SERVER_SLOTS 0x89FA // 250
16495+#define NWE_TEMP_REMAP_ERROR 0x89FA // 250
16496+#define NWE_PARAMETERS_INVALID 0x89FB // 251
16497+#define NWE_BIND_NO_SUCH_PROP 0x89FB // 251
16498+#define NWE_NCP_NOT_SUPPORTED 0x89FB // 251
16499+#define NWE_INET_PACKET_REQ_CANCELED 0x89FC // 252
16500+#define NWE_SERVER_UNKNOWN 0x89FC // 252
16501+#define NWE_MSG_Q_FULL 0x89FC // 252
16502+#define NWE_BIND_NO_SUCH_OBJ 0x89FC // 252
16503+#define NWE_LOCK_COLLISION 0x89FD // 253
16504+#define NWE_CONN_NUM_INVALID 0x89FD // 253
16505+#define NWE_PACKET_LEN_INVALID 0x89FD // 253
16506+#define NWE_UNKNOWN_REQ 0x89FD // 253
16507+#define NWE_BIND_LOCKED 0x89FE // 254
16508+#define NWE_TRUSTEE_NOT_FOUND 0x89FE // 254
16509+#define NWE_DIR_LOCKED 0x89FE // 254
16510+#define NWE_SEM_INVALID_NAME_LEN 0x89FE // 254
16511+#define NWE_PACKET_NOT_DELIVERABLE 0x89FE // 254
16512+#define NWE_SOCKET_TABLE_FULL 0x89FE // 254
16513+#define NWE_SPOOL_DIR_ERROR 0x89FE // 254
16514+#define NWE_LOGIN_DISABLED_BY_SUPER 0x89FE // 254
16515+#define NWE_TIMEOUT_FAILURE 0x89FE // 254
16516+#define NWE_FILE_EXT 0x89FF // 255
16517+#define NWE_FILE_NAME 0x89FF // 255
16518+#define NWE_HARD_FAILURE 0x89FF // 255
16519+#define NWE_FCB_CLOSE 0x89FF // 255
16520+#define NWE_IO_BOUND 0x89FF // 255
16521+#define NWE_BAD_SPOOL_PRINTER 0x89FF // 255
16522+#define NWE_BAD_RECORD_OFFSET 0x89FF // 255
16523+#define NWE_DRIVE_INVALID_NUM 0x89FF // 255
16524+#define NWE_SEM_INVALID_INIT_VAL 0x89FF // 255
16525+#define NWE_SEM_INVALID_HANDLE 0x89FF // 255
16526+#define NWE_NO_FILES_FOUND_ERROR 0x89FF // 255
16527+#define NWE_NO_RESPONSE_FROM_SERVER 0x89FF // 255
16528+#define NWE_NO_OBJ_OR_BAD_PASSWORD 0x89FF // 255
16529+#define NWE_PATH_NOT_LOCATABLE 0x89FF // 255
16530+#define NWE_Q_FULL_ERROR 0x89FF // 255
16531+#define NWE_REQ_NOT_OUTSTANDING 0x89FF // 255
16532+#define NWE_SOCKET_ALREADY_OPEN 0x89FF // 255
16533+#define NWE_LOCK_ERROR 0x89FF // 255
16534+#define NWE_FAILURE 0x89FF // 255 Generic Failure
16535+
16536+#endif /* __NOVFS_ERROR_H */
16537--- /dev/null
16538+++ b/fs/novfs/proc.c
16539@@ -0,0 +1,152 @@
16540+/*
16541+ * Novell NCP Redirector for Linux
16542+ * Author: James Turner
16543+ *
16544+ * This module contains functions that create the interface to the proc
16545+ * filesystem.
16546+ *
16547+ * Copyright (C) 2005 Novell, Inc.
16548+ *
16549+ * This program is free software; you can redistribute it and/or
16550+ * modify it under the terms of the GNU General Public License
16551+ * as published by the Free Software Foundation; either version 2
16552+ * of the License, or (at your option) any later version.
16553+ */
16554+
16555+#include <linux/module.h>
16556+#include <linux/kernel.h>
16557+#include <linux/proc_fs.h>
16558+#include <linux/smp_lock.h>
16559+
16560+#include "vfs.h"
16561+
16562+struct proc_dir_entry *Novfs_Procfs_dir;
16563+static struct proc_dir_entry *Novfs_Control;
16564+static struct proc_dir_entry *Novfs_Library;
16565+static struct proc_dir_entry *Novfs_Version;
16566+
16567+static struct file_operations Daemon_proc_fops;
16568+static struct file_operations Library_proc_fops;
16569+
16570+/*===[ Code ]=============================================================*/
16571+
16572+static int Novfs_Get_Version(char *page, char **start, off_t off, int count, int *eof, void *data)
16573+{
16574+ char *buf, tbuf[48];
16575+ int len = 0, i;
16576+
16577+ if (!off) {
16578+ buf = page + off;
16579+ *start = buf;
16580+ len = sprintf(buf, "Novfs Version=%s\n", NOVFS_VERSION_STRING);
16581+ i = Daemon_getversion(tbuf, sizeof(tbuf));
16582+ if ((i > 0) && i < (count - len)) {
16583+ len += sprintf(buf + len, "Novfsd Version=%s\n", tbuf);
16584+ }
16585+
16586+ if (Novfs_CurrentMount) {
16587+ i = strlen(Novfs_CurrentMount);
16588+ if ((i > 0) && i < (count - len)) {
16589+ len +=
16590+ sprintf(buf + len, "Novfs mount=%s\n",
16591+ Novfs_CurrentMount);
16592+ }
16593+ }
16594+ DbgPrint("Novfs_Get_Version:\n%s\n", buf);
16595+ }
16596+ *eof = 1;
16597+ return (len);
16598+}
16599+
16600+int Init_Procfs_Interface(void)
16601+{
16602+ int retCode = 0;
16603+
16604+ Novfs_Procfs_dir = proc_mkdir(MODULE_NAME, NULL);
16605+ if (Novfs_Procfs_dir) {
16606+ Novfs_Procfs_dir->owner = THIS_MODULE;
16607+
16608+ Novfs_Control = create_proc_entry("Control", 0600, Novfs_Procfs_dir);
16609+
16610+ if (Novfs_Control) {
16611+ Novfs_Control->owner = THIS_MODULE;
16612+ Novfs_Control->size = 0;
16613+ memcpy(&Daemon_proc_fops, Novfs_Control->proc_fops,
16614+ sizeof(struct file_operations));
16615+
16616+ /*
16617+ * Setup our functions
16618+ */
16619+ Daemon_proc_fops.owner = THIS_MODULE;
16620+ Daemon_proc_fops.open = Daemon_Open_Control;
16621+ Daemon_proc_fops.release = Daemon_Close_Control;
16622+ Daemon_proc_fops.read = Daemon_Send_Command;
16623+ Daemon_proc_fops.write = Daemon_Receive_Reply;
16624+ Daemon_proc_fops.ioctl = Daemon_ioctl;
16625+
16626+ Novfs_Control->proc_fops = &Daemon_proc_fops;
16627+ } else {
16628+ remove_proc_entry(MODULE_NAME, NULL);
16629+ return (-ENOENT);
16630+ }
16631+
16632+ Novfs_Library = create_proc_entry("Library", 0666, Novfs_Procfs_dir);
16633+ if (Novfs_Library) {
16634+ Novfs_Library->owner = THIS_MODULE;
16635+ Novfs_Library->size = 0;
16636+
16637+ /*
16638+ * Setup our file functions
16639+ */
16640+ memcpy(&Library_proc_fops, Novfs_Library->proc_fops,
16641+ sizeof(struct file_operations));
16642+ Library_proc_fops.owner = THIS_MODULE;
16643+ Library_proc_fops.open = Daemon_Library_open;
16644+ Library_proc_fops.release = Daemon_Library_close;
16645+ Library_proc_fops.read = Daemon_Library_read;
16646+ Library_proc_fops.write = Daemon_Library_write;
16647+ Library_proc_fops.llseek = Daemon_Library_llseek;
16648+ Library_proc_fops.ioctl = Daemon_Library_ioctl;
16649+ Novfs_Library->proc_fops = &Library_proc_fops;
16650+ } else {
16651+ remove_proc_entry("Control", Novfs_Procfs_dir);
16652+ remove_proc_entry(MODULE_NAME, NULL);
16653+ return (-ENOENT);
16654+ }
16655+
16656+ Novfs_Version =
16657+ create_proc_read_entry("Version", 0444, Novfs_Procfs_dir,
16658+ Novfs_Get_Version, NULL);
16659+ if (Novfs_Version) {
16660+ Novfs_Version->owner = THIS_MODULE;
16661+ Novfs_Version->size = 0;
16662+ } else {
16663+ remove_proc_entry("Library", Novfs_Procfs_dir);
16664+ remove_proc_entry("Control", Novfs_Procfs_dir);
16665+ remove_proc_entry(MODULE_NAME, NULL);
16666+ retCode = -ENOENT;
16667+ }
16668+ } else {
16669+ retCode = -ENOENT;
16670+ }
16671+ return (retCode);
16672+}
16673+
16674+void Uninit_Procfs_Interface(void)
16675+{
16676+
16677+ DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Version, NULL)\n");
16678+ remove_proc_entry("Version", Novfs_Procfs_dir);
16679+
16680+ DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Control, NULL)\n");
16681+ remove_proc_entry("Control", Novfs_Procfs_dir);
16682+
16683+ DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Library, NULL)\n");
16684+ remove_proc_entry("Library", Novfs_Procfs_dir);
16685+
16686+ DbgPrint("Uninit_Procfs_Interface remove_proc_entry(%s, NULL)\n",
16687+ MODULE_NAME);
16688+ remove_proc_entry(MODULE_NAME, NULL);
16689+
16690+ DbgPrint("Uninit_Procfs_Interface done\n");
16691+}
16692--- /dev/null
16693+++ b/fs/novfs/profile.c
16694@@ -0,0 +1,687 @@
16695+/*
16696+ * Novell NCP Redirector for Linux
16697+ * Author: James Turner
16698+ *
16699+ * This file contains a debugging code for the novfs VFS.
16700+ *
16701+ * Copyright (C) 2005 Novell, Inc.
16702+ *
16703+ * This program is free software; you can redistribute it and/or
16704+ * modify it under the terms of the GNU General Public License
16705+ * as published by the Free Software Foundation; either version 2
16706+ * of the License, or (at your option) any later version.
16707+ */
16708+
16709+#include <linux/module.h>
16710+#include <linux/kernel.h>
16711+#include <linux/init.h>
16712+#include <linux/proc_fs.h>
16713+#include <linux/sched.h>
16714+#include <linux/vmalloc.h>
16715+#include <linux/time.h>
16716+#include <linux/profile.h>
16717+#include <linux/notifier.h>
16718+#include <asm/uaccess.h>
16719+
16720+#include "vfs.h"
16721+
16722+/*===[ Manifest constants ]===============================================*/
16723+#define DBGBUFFERSIZE (1024*1024*32)
16724+
16725+/*===[ Type definitions ]=================================================*/
16726+struct local_rtc_time {
16727+ int tm_sec;
16728+ int tm_min;
16729+ int tm_hour;
16730+ int tm_mday;
16731+ int tm_mon;
16732+ int tm_year;
16733+ int tm_wday;
16734+ int tm_yday;
16735+ int tm_isdst;
16736+};
16737+
16738+static char *DbgPrintBuffer = NULL;
16739+static char DbgPrintOn = 0;
16740+static char DbgSyslogOn = 0;
16741+static char DbgProfileOn = 0;
16742+
16743+static unsigned long DbgPrintBufferOffset = 0;
16744+static unsigned long DbgPrintBufferReadOffset = 0;
16745+static unsigned long DbgPrintBufferSize = DBGBUFFERSIZE;
16746+
16747+static struct file_operations Dbg_proc_file_operations;
16748+static struct file_operations dentry_proc_file_ops;
16749+static struct file_operations inode_proc_file_ops;
16750+
16751+static struct proc_dir_entry *dbg_dir = NULL;
16752+static struct proc_dir_entry *dbg_file = NULL;
16753+static struct proc_dir_entry *dentry_file = NULL;
16754+static struct proc_dir_entry *inode_file = NULL;
16755+
16756+static DECLARE_MUTEX(LocalPrint_lock);
16757+
16758+static ssize_t User_proc_write_DbgBuffer(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
16759+{
16760+ ssize_t retval = nbytes;
16761+ unsigned char *lbuf;
16762+ unsigned char *p;
16763+ int i;
16764+
16765+ lbuf = kmalloc(nbytes + 1, GFP_KERNEL);
16766+ if (lbuf) {
16767+ if (copy_from_user(lbuf, buf, nbytes))
16768+ return -EFAULT;
16769+
16770+ lbuf[nbytes] = 0;
16771+ DbgPrint("User_proc_write_DbgBuffer: %s\n", lbuf);
16772+
16773+ for (i = 0; lbuf[i] && lbuf[i] != '\n'; i++)
16774+ ;
16775+
16776+ if ('\n' == lbuf[i])
16777+ lbuf[i] = '\0';
16778+
16779+ if (!strcmp("on", lbuf)) {
16780+ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0;
16781+ DbgPrintOn = 1;
16782+ } else if (!strcmp("off", lbuf)) {
16783+ DbgPrintOn = 0;
16784+ } else if (!strcmp("reset", lbuf)) {
16785+ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0;
16786+ } else if (NULL != (p = strchr(lbuf, ' '))) {
16787+ *p++ = '\0';
16788+ if (!strcmp("syslog", lbuf)) {
16789+
16790+ if (!strcmp("on", p)) {
16791+ DbgSyslogOn = 1;
16792+ } else if (!strcmp("off", p)) {
16793+ DbgSyslogOn = 0;
16794+ }
16795+ } else if (!strcmp("novfsd", lbuf)) {
16796+ Daemon_SendDebugCmd(p);
16797+ } else if (!strcmp("file_update_timeout", lbuf)) {
16798+ File_update_timeout =
16799+ simple_strtoul(p, NULL, 0);
16800+ } else if (!strcmp("cache", lbuf)) {
16801+ if (!strcmp("on", p)) {
16802+ PageCache = 1;
16803+ } else if (!strcmp("off", p)) {
16804+ PageCache = 0;
16805+ }
16806+ } else if (!strcmp("profile", lbuf)) {
16807+ if (!strcmp("on", p)) {
16808+ DbgProfileOn = 1;
16809+ } else if (!strcmp("off", p)) {
16810+ DbgProfileOn = 0;
16811+ }
16812+ }
16813+ }
16814+ kfree(lbuf);
16815+ }
16816+
16817+ return (retval);
16818+}
16819+
16820+static ssize_t User_proc_read_DbgBuffer(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
16821+{
16822+ ssize_t retval = 0;
16823+ size_t count;
16824+
16825+ if (0 != (count = DbgPrintBufferOffset - DbgPrintBufferReadOffset)) {
16826+
16827+ if (count > nbytes) {
16828+ count = nbytes;
16829+ }
16830+
16831+ count -=
16832+ copy_to_user(buf, &DbgPrintBuffer[DbgPrintBufferReadOffset],
16833+ count);
16834+
16835+ if (count == 0) {
16836+ if (retval == 0)
16837+ retval = -EFAULT;
16838+ } else {
16839+ DbgPrintBufferReadOffset += count;
16840+ if (DbgPrintBufferReadOffset >= DbgPrintBufferOffset) {
16841+ DbgPrintBufferOffset =
16842+ DbgPrintBufferReadOffset = 0;
16843+ }
16844+ retval = count;
16845+ }
16846+ }
16847+
16848+ return retval;
16849+}
16850+
16851+static int proc_read_DbgBuffer(char *page, char **start, off_t off, int count, int *eof, void *data)
16852+{
16853+ int len;
16854+
16855+ printk(KERN_ALERT "proc_read_DbgBuffer: off=%ld count=%d DbgPrintBufferOffset=%lu DbgPrintBufferReadOffset=%lu\n", off, count, DbgPrintBufferOffset, DbgPrintBufferReadOffset);
16856+
16857+ len = DbgPrintBufferOffset - DbgPrintBufferReadOffset;
16858+
16859+ if ((int)(DbgPrintBufferOffset - DbgPrintBufferReadOffset) > count)
16860+ len = count;
16861+
16862+ if (len) {
16863+ memcpy(page, &DbgPrintBuffer[DbgPrintBufferReadOffset], len);
16864+ DbgPrintBufferReadOffset += len;
16865+ }
16866+
16867+ if (DbgPrintBufferReadOffset >= DbgPrintBufferOffset)
16868+ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0;
16869+
16870+ printk(KERN_ALERT "proc_read_DbgBuffer: return %d\n", len);
16871+
16872+ return len;
16873+}
16874+
16875+#define DBG_BUFFER_SIZE (2*1024)
16876+
16877+static int LocalPrint(char *Fmt, ...)
16878+{
16879+ int len = 0;
16880+ va_list args;
16881+
16882+ if (DbgPrintBuffer) {
16883+ va_start(args, Fmt);
16884+ len += vsnprintf(DbgPrintBuffer + DbgPrintBufferOffset,
16885+ DbgPrintBufferSize - DbgPrintBufferOffset,
16886+ Fmt, args);
16887+ DbgPrintBufferOffset += len;
16888+ }
16889+
16890+ return (len);
16891+}
16892+
16893+int DbgPrint(char *Fmt, ...)
16894+{
16895+ char *buf;
16896+ int len = 0;
16897+ unsigned long offset;
16898+ va_list args;
16899+
16900+ if ((DbgPrintBuffer && DbgPrintOn) || DbgSyslogOn) {
16901+ buf = kmalloc(DBG_BUFFER_SIZE, GFP_KERNEL);
16902+
16903+ if (buf) {
16904+ va_start(args, Fmt);
16905+ len = sprintf(buf, "[%d] ", current->pid);
16906+
16907+ len +=
16908+ vsnprintf(buf + len, DBG_BUFFER_SIZE - len, Fmt,
16909+ args);
16910+ if (-1 == len) {
16911+ len = DBG_BUFFER_SIZE - 1;
16912+ buf[len] = '\0';
16913+ }
16914+ /*
16915+ len = sprintf(&DbgPrintBuffer[offset], "[%llu] ", ts);
16916+ len += vsprintf(&DbgPrintBuffer[offset+len], Fmt, args);
16917+ */
16918+
16919+ if (len) {
16920+ if (DbgSyslogOn) {
16921+ printk("<6>%s", buf);
16922+ }
16923+
16924+ if (DbgPrintBuffer && DbgPrintOn) {
16925+ if ((DbgPrintBufferOffset + len) >
16926+ DbgPrintBufferSize) {
16927+ offset = DbgPrintBufferOffset;
16928+ DbgPrintBufferOffset = 0;
16929+ memset(&DbgPrintBuffer[offset],
16930+ 0,
16931+ DbgPrintBufferSize -
16932+ offset);
16933+ }
16934+
16935+ mb();
16936+
16937+ if ((DbgPrintBufferOffset + len) <
16938+ DbgPrintBufferSize) {
16939+ DbgPrintBufferOffset += len;
16940+ offset =
16941+ DbgPrintBufferOffset - len;
16942+ memcpy(&DbgPrintBuffer[offset],
16943+ buf, len + 1);
16944+ }
16945+ }
16946+ }
16947+ kfree(buf);
16948+ }
16949+ }
16950+
16951+ return (len);
16952+}
16953+
16954+static void doline(unsigned char *b, unsigned char *e, unsigned char *l)
16955+{
16956+ unsigned char c;
16957+
16958+ *b++ = ' ';
16959+
16960+ while (l < e) {
16961+ c = *l++;
16962+ if ((c < ' ') || (c > '~')) {
16963+ c = '.';
16964+ }
16965+ *b++ = c;
16966+ *b = '\0';
16967+ }
16968+}
16969+
16970+void mydump(int size, void *dumpptr)
16971+{
16972+ unsigned char *ptr = (unsigned char *)dumpptr;
16973+ unsigned char *line = NULL, buf[100], *bptr = buf;
16974+ int i;
16975+
16976+ if (DbgPrintBuffer || DbgSyslogOn) {
16977+ if (size) {
16978+ for (i = 0; i < size; i++) {
16979+ if (0 == (i % 16)) {
16980+ if (line) {
16981+ doline(bptr, ptr, line);
16982+ DbgPrint("%s\n", buf);
16983+ bptr = buf;
16984+ }
16985+ bptr += sprintf(bptr, "0x%p: ", ptr);
16986+ line = ptr;
16987+ }
16988+ bptr += sprintf(bptr, "%02x ", *ptr++);
16989+ }
16990+ doline(bptr, ptr, line);
16991+ DbgPrint("%s\n", buf);
16992+ }
16993+ }
16994+}
16995+
16996+#define FEBRUARY 2
16997+#define STARTOFTIME 1970
16998+#define SECDAY 86400L
16999+#define SECYR (SECDAY * 365)
17000+#define leapyear(year) ((year) % 4 == 0)
17001+#define days_in_year(a) (leapyear(a) ? 366 : 365)
17002+#define days_in_month(a) (month_days[(a) - 1])
17003+
17004+static int month_days[12] = {
17005+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
17006+};
17007+
17008+/*
17009+ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
17010+ */
17011+static void Novfs_GregorianDay(struct local_rtc_time *tm)
17012+{
17013+ int leapsToDate;
17014+ int lastYear;
17015+ int day;
17016+ int MonthOffset[] =
17017+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
17018+
17019+ lastYear = tm->tm_year - 1;
17020+
17021+ /*
17022+ * Number of leap corrections to apply up to end of last year
17023+ */
17024+ leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400;
17025+
17026+ /*
17027+ * This year is a leap year if it is divisible by 4 except when it is
17028+ * divisible by 100 unless it is divisible by 400
17029+ *
17030+ * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
17031+ */
17032+ if ((tm->tm_year % 4 == 0) &&
17033+ ((tm->tm_year % 100 != 0) || (tm->tm_year % 400 == 0)) &&
17034+ (tm->tm_mon > 2)) {
17035+ /*
17036+ * We are past Feb. 29 in a leap year
17037+ */
17038+ day = 1;
17039+ } else {
17040+ day = 0;
17041+ }
17042+
17043+ day += lastYear * 365 + leapsToDate + MonthOffset[tm->tm_mon - 1] +
17044+ tm->tm_mday;
17045+
17046+ tm->tm_wday = day % 7;
17047+}
17048+
17049+static void private_to_tm(int tim, struct local_rtc_time *tm)
17050+{
17051+ register int i;
17052+ register long hms, day;
17053+
17054+ day = tim / SECDAY;
17055+ hms = tim % SECDAY;
17056+
17057+ /* Hours, minutes, seconds are easy */
17058+ tm->tm_hour = hms / 3600;
17059+ tm->tm_min = (hms % 3600) / 60;
17060+ tm->tm_sec = (hms % 3600) % 60;
17061+
17062+ /* Number of years in days */
17063+ for (i = STARTOFTIME; day >= days_in_year(i); i++)
17064+ day -= days_in_year(i);
17065+ tm->tm_year = i;
17066+
17067+ /* Number of months in days left */
17068+ if (leapyear(tm->tm_year))
17069+ days_in_month(FEBRUARY) = 29;
17070+ for (i = 1; day >= days_in_month(i); i++)
17071+ day -= days_in_month(i);
17072+ days_in_month(FEBRUARY) = 28;
17073+ tm->tm_mon = i;
17074+
17075+ /* Days are what is left over (+1) from all that. */
17076+ tm->tm_mday = day + 1;
17077+
17078+ /*
17079+ * Determine the day of week
17080+ */
17081+ Novfs_GregorianDay(tm);
17082+}
17083+
17084+char *ctime_r(time_t * clock, char *buf)
17085+{
17086+ struct local_rtc_time tm;
17087+ static char *DAYOFWEEK[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
17088+ static char *MONTHOFYEAR[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
17089+
17090+ private_to_tm(*clock, &tm);
17091+
17092+ sprintf(buf, "%s %s %d %d:%02d:%02d %d", DAYOFWEEK[tm.tm_wday],
17093+ MONTHOFYEAR[tm.tm_mon - 1], tm.tm_mday, tm.tm_hour, tm.tm_min,
17094+ tm.tm_sec, tm.tm_year);
17095+ return (buf);
17096+}
17097+
17098+static void profile_dump_dt(struct dentry *parent, void *pf)
17099+{
17100+ void (*pfunc) (char *Fmt, ...) = pf;
17101+ struct l {
17102+ struct l *next;
17103+ struct dentry *dentry;
17104+ } *l, *n, *start;
17105+ struct list_head *p;
17106+ struct dentry *d;
17107+ char *buf, *path, *sd;
17108+ char inode_number[16];
17109+
17110+ buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
17111+ if (!buf)
17112+ return;
17113+
17114+ if (parent) {
17115+ pfunc("starting 0x%p %.*s\n", parent, parent->d_name.len,
17116+ parent->d_name.name);
17117+ if (parent->d_subdirs.next == &parent->d_subdirs) {
17118+ pfunc("No children...\n");
17119+ } else {
17120+ start = kmalloc(sizeof(*start), GFP_KERNEL);
17121+ if (start) {
17122+ start->next = NULL;
17123+ start->dentry = parent;
17124+ l = start;
17125+ while (l) {
17126+ p = l->dentry->d_subdirs.next;
17127+ while (p != &l->dentry->d_subdirs) {
17128+ d = list_entry(p, struct dentry,
17129+ D_CHILD);
17130+ p = p->next;
17131+
17132+ if (d->d_subdirs.next != &d->d_subdirs) {
17133+ n = kmalloc(sizeof(*n), GFP_KERNEL);
17134+ if (n) {
17135+ n->next = l->next;
17136+ l->next = n;
17137+ n->dentry = d;
17138+ }
17139+ } else {
17140+ path = Scope_dget_path(d, buf, PATH_LENGTH_BUFFER, 1);
17141+ if (path) {
17142+ pfunc("1-0x%p %s\n"
17143+ " d_name: %.*s\n"
17144+ " d_parent: 0x%p\n"
17145+ " d_count: %d\n"
17146+ " d_flags: 0x%x\n"
17147+ " d_subdirs: 0x%p\n"
17148+ " d_inode: 0x%p\n",
17149+ d, path,
17150+ d->d_name.len,
17151+ d->d_name.name,
17152+ d->d_parent,
17153+ atomic_read(&d->d_count),
17154+ d->d_flags,
17155+ d->d_subdirs.
17156+ next,
17157+ d->d_inode);
17158+ }
17159+ }
17160+ }
17161+ l = l->next;
17162+ }
17163+ l = start;
17164+ while (l) {
17165+ d = l->dentry;
17166+ path = Scope_dget_path(d, buf, PATH_LENGTH_BUFFER, 1);
17167+ if (path) {
17168+ sd = " (None)";
17169+ if (&d->d_subdirs != d->d_subdirs.next)
17170+ sd = "";
17171+ inode_number[0] = '\0';
17172+ if (d->d_inode) {
17173+ sprintf(inode_number,
17174+ " (%lu)",
17175+ d->d_inode->
17176+ i_ino);
17177+ }
17178+ pfunc("0x%p %s\n"
17179+ " d_parent: 0x%p\n"
17180+ " d_count: %d\n"
17181+ " d_flags: 0x%x\n"
17182+ " d_subdirs: 0x%p%s\n"
17183+ " d_inode: 0x%p%s\n",
17184+ d, path, d->d_parent,
17185+ atomic_read(&d->d_count),
17186+ d->d_flags,
17187+ d->d_subdirs.next, sd,
17188+ d->d_inode, inode_number);
17189+ }
17190+
17191+ n = l;
17192+ l = l->next;
17193+ kfree(n);
17194+ }
17195+ }
17196+ }
17197+ }
17198+
17199+ kfree(buf);
17200+
17201+}
17202+
17203+static ssize_t profile_common_read(char __user *buf, size_t len, loff_t *off)
17204+{
17205+ ssize_t retval = 0;
17206+ size_t count;
17207+ unsigned long offset = *off;
17208+
17209+ if (0 != (count = DbgPrintBufferOffset - offset)) {
17210+ if (count > len) {
17211+ count = len;
17212+ }
17213+
17214+ count -= copy_to_user(buf, &DbgPrintBuffer[offset], count);
17215+
17216+ if (count == 0) {
17217+ retval = -EFAULT;
17218+ } else {
17219+ *off += (loff_t) count;
17220+ retval = count;
17221+ }
17222+ }
17223+ return retval;
17224+
17225+}
17226+
17227+static ssize_t profile_inode_read(struct file * file, char __user *buf, size_t len, loff_t *off)
17228+{
17229+ ssize_t retval = 0;
17230+ unsigned long offset = *off;
17231+ static char save_DbgPrintOn;
17232+
17233+ if (offset == 0) {
17234+ down(&LocalPrint_lock);
17235+ save_DbgPrintOn = DbgPrintOn;
17236+ DbgPrintOn = 0;
17237+
17238+ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0;
17239+ Novfs_dump_inode(LocalPrint);
17240+ }
17241+
17242+ retval = profile_common_read(buf, len, off);
17243+
17244+ if (0 == retval) {
17245+ DbgPrintOn = save_DbgPrintOn;
17246+ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0;
17247+
17248+ up(&LocalPrint_lock);
17249+ }
17250+
17251+ return retval;
17252+
17253+}
17254+
17255+static ssize_t profile_dentry_read(struct file *file, char __user *buf, size_t len, loff_t * off)
17256+{
17257+ ssize_t retval = 0;
17258+ unsigned long offset = *off;
17259+ static char save_DbgPrintOn;
17260+
17261+ if (offset == 0) {
17262+ down(&LocalPrint_lock);
17263+ save_DbgPrintOn = DbgPrintOn;
17264+ DbgPrintOn = 0;
17265+ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0;
17266+ profile_dump_dt(Novfs_root, LocalPrint);
17267+ }
17268+
17269+ retval = profile_common_read(buf, len, off);
17270+
17271+ if (0 == retval) {
17272+ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0;
17273+ DbgPrintOn = save_DbgPrintOn;
17274+
17275+ up(&LocalPrint_lock);
17276+ }
17277+
17278+ return retval;
17279+
17280+}
17281+
17282+uint64_t get_nanosecond_time(void)
17283+{
17284+ struct timespec ts;
17285+ uint64_t retVal;
17286+
17287+ ts = current_kernel_time();
17288+
17289+ retVal = (uint64_t) NSEC_PER_SEC;
17290+ retVal *= (uint64_t) ts.tv_sec;
17291+ retVal += (uint64_t) ts.tv_nsec;
17292+
17293+ return (retVal);
17294+}
17295+
17296+int init_profile(void)
17297+{
17298+ int retCode = 0;
17299+
17300+ if (Novfs_Procfs_dir) {
17301+ dbg_dir = Novfs_Procfs_dir;
17302+ } else {
17303+ dbg_dir = proc_mkdir(MODULE_NAME, NULL);
17304+ }
17305+
17306+ if (dbg_dir) {
17307+ dbg_dir->owner = THIS_MODULE;
17308+ dbg_file = create_proc_read_entry("Debug",
17309+ 0600,
17310+ dbg_dir,
17311+ proc_read_DbgBuffer, NULL);
17312+ if (dbg_file) {
17313+ dbg_file->owner = THIS_MODULE;
17314+ dbg_file->size = DBGBUFFERSIZE;
17315+ memcpy(&Dbg_proc_file_operations, dbg_file->proc_fops,
17316+ sizeof(struct file_operations));
17317+ Dbg_proc_file_operations.read = User_proc_read_DbgBuffer;
17318+ Dbg_proc_file_operations.write = User_proc_write_DbgBuffer;
17319+ dbg_file->proc_fops = &Dbg_proc_file_operations;
17320+ } else {
17321+ remove_proc_entry(MODULE_NAME, NULL);
17322+ vfree(DbgPrintBuffer);
17323+ DbgPrintBuffer = NULL;
17324+ }
17325+ }
17326+
17327+ if (DbgPrintBuffer) {
17328+ if (dbg_dir) {
17329+ inode_file = create_proc_entry("inode", 0600, dbg_dir);
17330+ if (inode_file) {
17331+ inode_file->owner = THIS_MODULE;
17332+ inode_file->size = 0;
17333+ memcpy(&inode_proc_file_ops,
17334+ inode_file->proc_fops,
17335+ sizeof(struct file_operations));
17336+ inode_proc_file_ops.owner = THIS_MODULE;
17337+ inode_proc_file_ops.read = profile_inode_read;
17338+ inode_file->proc_fops = &inode_proc_file_ops;
17339+ }
17340+
17341+ dentry_file = create_proc_entry("dentry",
17342+ 0600, dbg_dir);
17343+ if (dentry_file) {
17344+ dentry_file->owner = THIS_MODULE;
17345+ dentry_file->size = 0;
17346+ memcpy(&dentry_proc_file_ops,
17347+ dentry_file->proc_fops,
17348+ sizeof(struct file_operations));
17349+ dentry_proc_file_ops.owner = THIS_MODULE;
17350+ dentry_proc_file_ops.read = profile_dentry_read;
17351+ dentry_file->proc_fops = &dentry_proc_file_ops;
17352+ }
17353+ } else {
17354+ vfree(DbgPrintBuffer);
17355+ DbgPrintBuffer = NULL;
17356+ }
17357+ }
17358+ return (retCode);
17359+}
17360+
17361+void uninit_profile(void)
17362+{
17363+ if (dbg_file) {
17364+ DbgPrint("Calling remove_proc_entry(Debug, NULL)\n");
17365+ remove_proc_entry("Debug", dbg_dir);
17366+ }
17367+ if (inode_file) {
17368+ DbgPrint("Calling remove_proc_entry(inode, NULL)\n");
17369+ remove_proc_entry("inode", dbg_dir);
17370+ }
17371+ if (dentry_file) {
17372+ DbgPrint("Calling remove_proc_entry(dentry, NULL)\n");
17373+ remove_proc_entry("dentry", dbg_dir);
17374+ }
17375+ if (dbg_dir && (dbg_dir != Novfs_Procfs_dir)) {
17376+ DbgPrint("Calling remove_proc_entry(%s, NULL)\n", MODULE_NAME);
17377+ remove_proc_entry(MODULE_NAME, NULL);
17378+ }
17379+}
17380+
17381+
17382--- /dev/null
17383+++ b/fs/novfs/scope.c
17384@@ -0,0 +1,675 @@
17385+/*
17386+ * Novell NCP Redirector for Linux
17387+ * Author: James Turner
17388+ *
17389+ * This file contains functions used to scope users.
17390+ *
17391+ * Copyright (C) 2005 Novell, Inc.
17392+ *
17393+ * This program is free software; you can redistribute it and/or
17394+ * modify it under the terms of the GNU General Public License
17395+ * as published by the Free Software Foundation; either version 2
17396+ * of the License, or (at your option) any later version.
17397+ */
17398+
17399+#include <linux/version.h>
17400+#include <linux/module.h>
17401+#include <linux/kthread.h>
17402+#include <linux/fs.h>
17403+#include <linux/file.h>
17404+#include <linux/sched.h>
17405+#include <linux/personality.h>
17406+#include <linux/module.h>
17407+#include <linux/slab.h>
17408+#include <linux/synclink.h>
17409+#include <linux/smp_lock.h>
17410+#include <linux/semaphore.h>
17411+#include <linux/security.h>
17412+#include <linux/syscalls.h>
17413+
17414+#include "vfs.h"
17415+
17416+#define SHUTDOWN_INTERVAL 5
17417+#define CLEANUP_INTERVAL 10
17418+#define MAX_USERNAME_LENGTH 32
17419+
17420+struct scope_list {
17421+ struct list_head entry;
17422+ struct schandle ScopeId;
17423+ struct schandle SessionId;
17424+ pid_t ScopePid;
17425+ struct task_struct *ScopeTask;
17426+ unsigned int ScopeHash;
17427+ uid_t ScopeUid;
17428+ u64 ScopeUSize;
17429+ u64 ScopeUFree;
17430+ u64 ScopeUTEnties;
17431+ u64 ScopeUAEnties;
17432+ int ScopeUserNameLength;
17433+ unsigned char ScopeUserName[MAX_USERNAME_LENGTH];
17434+};
17435+
17436+static struct list_head Scope_List;
17437+static struct semaphore Scope_Lock;
17438+static struct semaphore Scope_Thread_Delay;
17439+static int Scope_Thread_Terminate;
17440+static struct timer_list Scope_Timer;
17441+static unsigned int Scope_Hash_Val = 1;
17442+
17443+static struct scope_list *Scope_Search4Scope(struct schandle *Id, bool Session,
17444+ bool Locked)
17445+{
17446+ struct scope_list *scope;
17447+ struct scope_list *rscope = NULL;
17448+ struct schandle *cur_scope;
17449+ struct list_head *sl;
17450+ int offset;
17451+
17452+ DbgPrint("Scope_Search4Scope: 0x%p:%p 0x%x 0x%x\n",
17453+ Id->hTypeId, Id->hId, Session, Locked);
17454+
17455+ if (Session)
17456+ offset = offsetof(struct scope_list, SessionId);
17457+ else
17458+ offset = offsetof(struct scope_list, ScopeId);
17459+
17460+ if (!Locked)
17461+ down(&Scope_Lock);
17462+
17463+ sl = Scope_List.next;
17464+ DbgPrint("Scope_Search4Scope: 0x%p\n", sl);
17465+ while (sl != &Scope_List) {
17466+ scope = list_entry(sl, struct scope_list, entry);
17467+
17468+ cur_scope = (session_t *) ((char *)scope + offset);
17469+ if (SC_EQUAL(Id, cur_scope)) {
17470+ rscope = scope;
17471+ break;
17472+ }
17473+
17474+ sl = sl->next;
17475+ }
17476+
17477+ if (!Locked)
17478+ up(&Scope_Lock);
17479+
17480+ DbgPrint("Scope_Search4Scope: return 0x%p\n", rscope);
17481+ return rscope;
17482+}
17483+
17484+static struct scope_list *Scope_Find_Scope(bool Create)
17485+{
17486+ struct scope_list *scope = NULL;
17487+ struct scope_list *pscope = NULL;
17488+ struct task_struct *task;
17489+ struct schandle scopeId;
17490+ int addscope = 0;
17491+
17492+ task = current;
17493+
17494+ DbgPrint("Scope_Find_Scope: %d %d %d %d\n", task->uid, task->euid,
17495+ task->suid, task->fsuid);
17496+
17497+ /* scopeId = task->euid; */
17498+ UID_TO_SCHANDLE(scopeId, task->euid);
17499+
17500+ scope = Scope_Search4Scope(&scopeId, 0, 0);
17501+ if (scope || (!Create))
17502+ return scope;
17503+
17504+ scope = kmalloc(sizeof(*pscope), GFP_KERNEL);
17505+ if (!scope)
17506+ return NULL;
17507+ scope->ScopeId = scopeId;
17508+ SC_INITIALIZE(scope->SessionId);
17509+ scope->ScopePid = task->pid;
17510+ scope->ScopeTask = task;
17511+ scope->ScopeHash = 0;
17512+ scope->ScopeUid = task->euid;
17513+ scope->ScopeUserName[0] = '\0';
17514+
17515+ if (!Daemon_CreateSessionId(&scope->SessionId)) {
17516+ DbgPrint("Scope_Find_Scope2: %d %d %d %d\n", task->uid,
17517+ task->euid, task->suid, task->fsuid);
17518+ memset(scope->ScopeUserName, 0, sizeof(scope->ScopeUserName));
17519+ scope->ScopeUserNameLength = 0;
17520+ Daemon_getpwuid(task->euid, sizeof(scope->ScopeUserName),
17521+ scope->ScopeUserName);
17522+ scope->ScopeUserNameLength = strlen(scope->ScopeUserName);
17523+ addscope = 1;
17524+ }
17525+
17526+ scope->ScopeHash = Scope_Hash_Val++;
17527+ DbgPrint("Scope_Find_Scope: Adding 0x%p\n"
17528+ " ScopeId: 0x%p:%p\n"
17529+ " SessionId: 0x%p:%p\n"
17530+ " ScopePid: %d\n"
17531+ " ScopeTask: 0x%p\n"
17532+ " ScopeHash: %u\n"
17533+ " ScopeUid: %u\n"
17534+ " ScopeUserNameLength: %u\n"
17535+ " ScopeUserName: %s\n",
17536+ scope,
17537+ scope->ScopeId.hTypeId, scope->ScopeId.hId,
17538+ scope->SessionId.hTypeId, scope->SessionId.hId,
17539+ scope->ScopePid,
17540+ scope->ScopeTask,
17541+ scope->ScopeHash,
17542+ scope->ScopeUid,
17543+ scope->ScopeUserNameLength,
17544+ scope->ScopeUserName);
17545+
17546+ if (SC_PRESENT(scope->SessionId)) {
17547+ down(&Scope_Lock);
17548+ pscope = Scope_Search4Scope(&scopeId, 0, 1);
17549+ if (!pscope)
17550+ list_add(&scope->entry, &Scope_List);
17551+ up(&Scope_Lock);
17552+
17553+ if (pscope) {
17554+ printk(KERN_ERR "Scope_Find_Scope scope not added "
17555+ "because it was already there...\n");
17556+ Daemon_DestroySessionId(&scope->SessionId);
17557+ kfree(scope);
17558+ scope = pscope;
17559+ addscope = 0;
17560+ }
17561+ } else {
17562+ kfree(scope);
17563+ scope = NULL;
17564+ }
17565+
17566+ if (addscope)
17567+ Novfs_Add_to_Root(scope->ScopeUserName);
17568+
17569+ return scope;
17570+}
17571+
17572+static int Scope_Validate_Scope(struct scope_list *Scope)
17573+{
17574+ struct scope_list *s;
17575+ struct list_head *sl;
17576+ int retVal = 0;
17577+
17578+ DbgPrint("Scope_Validate_Scope: 0x%p\n", Scope);
17579+
17580+ down(&Scope_Lock);
17581+
17582+ sl = Scope_List.next;
17583+ while (sl != &Scope_List) {
17584+ s = list_entry(sl, struct scope_list, entry);
17585+
17586+ if (s == Scope) {
17587+ retVal = 1;
17588+ break;
17589+ }
17590+
17591+ sl = sl->next;
17592+ }
17593+
17594+ up(&Scope_Lock);
17595+
17596+ return retVal;
17597+}
17598+
17599+/* FIXME void stuff */
17600+uid_t Scope_Get_Uid(void *foo)
17601+{
17602+ struct scope_list *scope = foo;
17603+ uid_t uid = 0;
17604+
17605+ if (!scope)
17606+ scope = Scope_Find_Scope(1);
17607+
17608+ if (scope && Scope_Validate_Scope(scope))
17609+ uid = scope->ScopeUid;
17610+
17611+ return uid;
17612+}
17613+
17614+char *Scope_Get_UserName(void)
17615+{
17616+ char *name = NULL;
17617+ struct scope_list *Scope;
17618+
17619+ Scope = Scope_Find_Scope(1);
17620+
17621+ if (Scope && Scope_Validate_Scope(Scope))
17622+ name = Scope->ScopeUserName;
17623+
17624+ return name;
17625+}
17626+
17627+/* FIXME the void * needs to get fixed... */
17628+session_t Scope_Get_SessionId(void *foo)
17629+{
17630+ session_t sessionId;
17631+ struct scope_list *Scope = foo;
17632+
17633+ DbgPrint("Scope_Get_SessionId: 0x%p\n", Scope);
17634+ SC_INITIALIZE(sessionId);
17635+ if (!Scope)
17636+ Scope = Scope_Find_Scope(1);
17637+
17638+ if (Scope && Scope_Validate_Scope(Scope))
17639+ sessionId = Scope->SessionId;
17640+
17641+ DbgPrint("Scope_Get_SessionId: return 0x%p:%p\n", sessionId.hTypeId,
17642+ sessionId.hId);
17643+ return sessionId;
17644+}
17645+
17646+struct scope_list *Scope_Get_ScopefromName(struct qstr *name)
17647+{
17648+ struct scope_list *scope;
17649+ struct scope_list *rscope = NULL;
17650+ struct list_head *sl;
17651+
17652+ DbgPrint("Scope_Get_ScopefromName: %.*s\n", name->len, name->name);
17653+
17654+ down(&Scope_Lock);
17655+
17656+ sl = Scope_List.next;
17657+ while (sl != &Scope_List) {
17658+ scope = list_entry(sl, struct scope_list, entry);
17659+
17660+ if ((name->len == scope->ScopeUserNameLength) &&
17661+ (strncmp(scope->ScopeUserName, name->name, name->len) == 0)) {
17662+ rscope = scope;
17663+ break;
17664+ }
17665+ sl = sl->next;
17666+ }
17667+
17668+ up(&Scope_Lock);
17669+
17670+ return rscope;
17671+}
17672+
17673+int Scope_Set_UserSpace(u64 *TotalSize, u64 *Free,
17674+ u64 *TotalEnties, u64 *FreeEnties)
17675+{
17676+ struct scope_list *scope;
17677+ int retVal = 0;
17678+
17679+ scope = Scope_Find_Scope(1);
17680+
17681+ if (scope) {
17682+ if (TotalSize)
17683+ scope->ScopeUSize = *TotalSize;
17684+ if (Free)
17685+ scope->ScopeUFree = *Free;
17686+ if (TotalEnties)
17687+ scope->ScopeUTEnties = *TotalEnties;
17688+ if (FreeEnties)
17689+ scope->ScopeUAEnties = *FreeEnties;
17690+ }
17691+
17692+ return retVal;
17693+}
17694+
17695+int Scope_Get_UserSpace(u64 *TotalSize, u64 *Free,
17696+ u64 *TotalEnties, u64 *FreeEnties)
17697+{
17698+ struct scope_list *scope;
17699+ int retVal = 0;
17700+
17701+ u64 td, fd, te, fe;
17702+
17703+ scope = Scope_Find_Scope(1);
17704+
17705+ td = fd = te = fe = 0;
17706+ if (scope) {
17707+
17708+ retVal = Daemon_Get_UserSpace(&scope->SessionId,
17709+ &td, &fd, &te, &fe);
17710+
17711+ scope->ScopeUSize = td;
17712+ scope->ScopeUFree = fd;
17713+ scope->ScopeUTEnties = te;
17714+ scope->ScopeUAEnties = fe;
17715+ }
17716+
17717+ if (TotalSize)
17718+ *TotalSize = td;
17719+ if (Free)
17720+ *Free = fd;
17721+ if (TotalEnties)
17722+ *TotalEnties = te;
17723+ if (FreeEnties)
17724+ *FreeEnties = fe;
17725+
17726+ return retVal;
17727+}
17728+
17729+struct scope_list *Scope_Get_ScopefromPath(struct dentry *dentry)
17730+{
17731+ struct scope_list *scope = NULL;
17732+ char *buf, *path, *cp;
17733+ struct qstr name;
17734+
17735+ buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
17736+ if (buf) {
17737+ path = Scope_dget_path(dentry, buf, PATH_LENGTH_BUFFER, 0);
17738+ if (path) {
17739+ DbgPrint("Scope_Get_ScopefromPath: %s\n", path);
17740+
17741+ if (*path == '/')
17742+ path++;
17743+
17744+ cp = path;
17745+ if (*cp) {
17746+ while (*cp && (*cp != '/'))
17747+ cp++;
17748+
17749+ *cp = '\0';
17750+ name.hash = 0;
17751+ name.len = (int)(cp - path);
17752+ name.name = path;
17753+ scope = Scope_Get_ScopefromName(&name);
17754+ }
17755+ }
17756+ kfree(buf);
17757+ }
17758+
17759+ return scope;
17760+}
17761+
17762+static char *add_to_list(char *name, char *list, char *endoflist)
17763+{
17764+ while (*name && (list < endoflist))
17765+ *list++ = *name++;
17766+
17767+ if (list < endoflist)
17768+ *list++ = '\0';
17769+
17770+ return list;
17771+}
17772+
17773+char *Scope_Get_ScopeUsers(void)
17774+{
17775+ struct scope_list *scope;
17776+ struct list_head *sl;
17777+ int asize = 8 * MAX_USERNAME_LENGTH;
17778+ char *list, *cp, *ep;
17779+
17780+ DbgPrint("Scope_Get_ScopeUsers\n");
17781+
17782+ do { /* Copy list until done or out of memory */
17783+ list = kmalloc(asize, GFP_KERNEL);
17784+
17785+ DbgPrint("Scope_Get_ScopeUsers list=0x%p\n", list);
17786+ if (list) {
17787+ cp = list;
17788+ ep = cp + asize;
17789+
17790+ /*
17791+ * Add the tree and server entries
17792+ */
17793+ cp = add_to_list(TREE_DIRECTORY_NAME, cp, ep);
17794+ cp = add_to_list(SERVER_DIRECTORY_NAME, cp, ep);
17795+
17796+ down(&Scope_Lock);
17797+
17798+ sl = Scope_List.next;
17799+ while ((sl != &Scope_List) && (cp < ep)) {
17800+ scope = list_entry(sl, struct scope_list, entry);
17801+
17802+ DbgPrint("Scope_Get_ScopeUsers found 0x%p %s\n",
17803+ scope, scope->ScopeUserName);
17804+
17805+ cp = add_to_list(scope->ScopeUserName, cp, ep);
17806+
17807+ sl = sl->next;
17808+ }
17809+
17810+ up(&Scope_Lock);
17811+
17812+ if (cp < ep) {
17813+ *cp++ = '\0';
17814+ asize = 0;
17815+ } else { /* Allocation was to small, up size */
17816+ asize *= 4;
17817+ kfree(list);
17818+ list = NULL;
17819+ }
17820+ } else { /* if allocation fails return an empty list */
17821+
17822+ break;
17823+ }
17824+ } while (!list); /* list was to small try again */
17825+
17826+ return list;
17827+}
17828+
17829+void *Scope_Lookup(void)
17830+{
17831+ return Scope_Find_Scope(1);
17832+}
17833+
17834+static void Scope_Timer_Function(unsigned long context)
17835+{
17836+ up(&Scope_Thread_Delay);
17837+}
17838+
17839+static int Scope_Cleanup_Thread(void *Args)
17840+{
17841+ struct scope_list *scope;
17842+ struct scope_list *rscope;
17843+ struct list_head *sl, cleanup;
17844+ struct task_struct *task;
17845+
17846+ DbgPrint("Scope_Cleanup_Thread: %d\n", current->pid);
17847+
17848+ /*
17849+ * Setup and start que timer
17850+ */
17851+ init_timer(&Scope_Timer);
17852+
17853+ while (0 == Scope_Thread_Terminate) {
17854+ DbgPrint("Scope_Cleanup_Thread: looping\n");
17855+ if (Scope_Thread_Terminate)
17856+ break;
17857+
17858+ /*
17859+ * Check scope list for any terminated processes
17860+ */
17861+ down(&Scope_Lock);
17862+
17863+ sl = Scope_List.next;
17864+ INIT_LIST_HEAD(&cleanup);
17865+
17866+ while (sl != &Scope_List) {
17867+ scope = list_entry(sl, struct scope_list, entry);
17868+ sl = sl->next;
17869+
17870+ rscope = NULL;
17871+ rcu_read_lock();
17872+ for_each_process(task) {
17873+ if ((task->uid == scope->ScopeUid)
17874+ || (task->euid == scope->ScopeUid)) {
17875+ rscope = scope;
17876+ break;
17877+ }
17878+ }
17879+ rcu_read_unlock();
17880+
17881+ if (!rscope) {
17882+ list_move(&scope->entry, &cleanup);
17883+ DbgPrint("Scope_Cleanup_Thread: Scope=0x%p\n",
17884+ rscope);
17885+ }
17886+ }
17887+
17888+ up(&Scope_Lock);
17889+
17890+ sl = cleanup.next;
17891+ while (sl != &cleanup) {
17892+ scope = list_entry(sl, struct scope_list, entry);
17893+ sl = sl->next;
17894+
17895+ DbgPrint("Scope_Cleanup_Thread: Removing 0x%p\n"
17896+ " ScopeId: 0x%p:%p\n"
17897+ " SessionId: 0x%p:%p\n"
17898+ " ScopePid: %d\n"
17899+ " ScopeTask: 0x%p\n"
17900+ " ScopeHash: %u\n"
17901+ " ScopeUid: %u\n"
17902+ " ScopeUserName: %s\n",
17903+ scope,
17904+ scope->ScopeId,
17905+ scope->SessionId,
17906+ scope->ScopePid,
17907+ scope->ScopeTask,
17908+ scope->ScopeHash,
17909+ scope->ScopeUid, scope->ScopeUserName);
17910+ if (!Scope_Search4Scope(&scope->SessionId, 1, 0)) {
17911+ Novfs_Remove_from_Root(scope->ScopeUserName);
17912+ Daemon_DestroySessionId(&scope->SessionId);
17913+ }
17914+ kfree(scope);
17915+ }
17916+
17917+ Scope_Timer.expires = jiffies + HZ * CLEANUP_INTERVAL;
17918+ Scope_Timer.data = (unsigned long)0;
17919+ Scope_Timer.function = Scope_Timer_Function;
17920+ add_timer(&Scope_Timer);
17921+ DbgPrint("Scope_Cleanup_Thread: sleeping\n");
17922+
17923+ if (down_interruptible(&Scope_Thread_Delay))
17924+ break;
17925+
17926+ del_timer(&Scope_Timer);
17927+ }
17928+ Scope_Thread_Terminate = 0;
17929+
17930+ printk(KERN_INFO "Scope_Cleanup_Thread: Exit\n");
17931+ DbgPrint("Scope_Cleanup_Thread: Exit\n");
17932+ return 0;
17933+}
17934+
17935+void Scope_Cleanup(void)
17936+{
17937+ struct scope_list *scope;
17938+ struct list_head *sl;
17939+
17940+ DbgPrint("Scope_Cleanup:\n");
17941+
17942+ /*
17943+ * Check scope list for any terminated processes
17944+ */
17945+ down(&Scope_Lock);
17946+
17947+ sl = Scope_List.next;
17948+
17949+ while (sl != &Scope_List) {
17950+ scope = list_entry(sl, struct scope_list, entry);
17951+ sl = sl->next;
17952+
17953+ list_del(&scope->entry);
17954+
17955+ DbgPrint("Scope_Cleanup: Removing 0x%p\n"
17956+ " ScopeId: 0x%p:%p\n"
17957+ " SessionId: 0x%p:%p\n"
17958+ " ScopePid: %d\n"
17959+ " ScopeTask: 0x%p\n"
17960+ " ScopeHash: %u\n"
17961+ " ScopeUid: %u\n"
17962+ " ScopeUserName: %s\n",
17963+ scope,
17964+ scope->ScopeId,
17965+ scope->SessionId,
17966+ scope->ScopePid,
17967+ scope->ScopeTask,
17968+ scope->ScopeHash,
17969+ scope->ScopeUid, scope->ScopeUserName);
17970+ if (!Scope_Search4Scope(&scope->SessionId, 1, 1)) {
17971+ Novfs_Remove_from_Root(scope->ScopeUserName);
17972+ Daemon_DestroySessionId(&scope->SessionId);
17973+ }
17974+ kfree(scope);
17975+ }
17976+
17977+ up(&Scope_Lock);
17978+
17979+}
17980+
17981+/*
17982+ * Arguments: struct dentry *dentry - starting entry
17983+ * char *Buf - pointer to memory buffer
17984+ * unsigned int Buflen - size of memory buffer
17985+ *
17986+ * Returns: pointer to path.
17987+ *
17988+ * Abstract: Walks the dentry chain building a path.
17989+ */
17990+char *Scope_dget_path(struct dentry *dentry, char *Buf, unsigned int Buflen,
17991+ int Flags)
17992+{
17993+ char *retval = &Buf[Buflen];
17994+ struct dentry *p = dentry;
17995+ int len;
17996+
17997+ *(--retval) = '\0';
17998+ Buflen--;
17999+
18000+ do {
18001+ if (Buflen > p->d_name.len) {
18002+ retval -= p->d_name.len;
18003+ Buflen -= p->d_name.len;
18004+ memcpy(retval, p->d_name.name, p->d_name.len);
18005+ *(--retval) = '/';
18006+ Buflen--;
18007+ p = p->d_parent;
18008+ } else {
18009+ retval = NULL;
18010+ break;
18011+ }
18012+ } while (!IS_ROOT(p));
18013+
18014+ if (IS_ROOT(dentry))
18015+ retval++;
18016+
18017+ if (Flags) {
18018+ len = strlen(p->d_sb->s_type->name);
18019+ if (Buflen - len > 0) {
18020+ retval -= len;
18021+ Buflen -= len;
18022+ memcpy(retval, p->d_sb->s_type->name, len);
18023+ *(--retval) = '/';
18024+ Buflen--;
18025+ }
18026+ }
18027+
18028+ return retval;
18029+}
18030+
18031+void Scope_Init(void)
18032+{
18033+ INIT_LIST_HEAD(&Scope_List);
18034+ init_MUTEX(&Scope_Lock);
18035+ init_MUTEX_LOCKED(&Scope_Thread_Delay);
18036+
18037+ kthread_run(Scope_Cleanup_Thread, NULL, "novfs_ST");
18038+}
18039+
18040+void Scope_Uninit(void)
18041+{
18042+ unsigned long expires = jiffies + HZ * SHUTDOWN_INTERVAL;
18043+
18044+ printk(KERN_INFO "Scope_Uninit: Start\n");
18045+
18046+ Scope_Thread_Terminate = 1;
18047+
18048+ up(&Scope_Thread_Delay);
18049+
18050+ mb();
18051+ while (Scope_Thread_Terminate && (jiffies < expires))
18052+ yield();
18053+
18054+ /* down(&Scope_Thread_Delay); */
18055+ printk(KERN_INFO "Scope_Uninit: Exit\n");
18056+
18057+}
18058+
18059+
18060--- /dev/null
18061+++ b/fs/novfs/vfs.h
18062@@ -0,0 +1,436 @@
18063+/*
18064+ * Novell NCP Redirector for Linux
18065+ * Author: James Turner
18066+ *
18067+ * Include file for novfs.
18068+ *
18069+ * Copyright (C) 2005 Novell, Inc.
18070+ *
18071+ * This program is free software; you can redistribute it and/or
18072+ * modify it under the terms of the GNU General Public License
18073+ * as published by the Free Software Foundation; either version 2
18074+ * of the License, or (at your option) any later version.
18075+ */
18076+#ifndef __NOVFS_H
18077+#define __NOVFS_H
18078+
18079+#ifndef __STDC_VERSION__
18080+#define __STDC_VERSION__ 0L
18081+#endif
18082+
18083+#include <linux/version.h>
18084+#include <linux/namei.h>
18085+#include <linux/string.h>
18086+
18087+#include "nwcapi.h"
18088+
18089+typedef void *HANDLE;
18090+
18091+struct schandle {
18092+ void *hTypeId;
18093+ void *hId;
18094+};
18095+
18096+static inline void copy_schandle(struct schandle *dest, struct schandle *source)
18097+{
18098+ memcpy(dest, source, sizeof(struct schandle));
18099+}
18100+#define copy_session_id copy_schandle
18101+
18102+typedef struct schandle session_t;
18103+
18104+#include "commands.h"
18105+
18106+#define SC_PRESENT(X) ((X.hTypeId != NULL) || (X.hId != NULL)) ? 1 : 0
18107+#define SC_EQUAL(X, Y) ((X->hTypeId == Y->hTypeId) && (X->hId == Y->hId)) ? 1 : 0
18108+#define SC_INITIALIZE(X) {X.hTypeId = X.hId = NULL;}
18109+
18110+#define UID_TO_SCHANDLE(hSC, uid) \
18111+ { \
18112+ hSC.hTypeId = NULL; \
18113+ hSC.hId = (HANDLE)(unsigned long)(uid); \
18114+ }
18115+
18116+
18117+
18118+/*===[ Manifest constants ]===============================================*/
18119+#define NOVFS_MAGIC 0x4e574653
18120+#define MODULE_NAME "novfs"
18121+
18122+#define TREE_DIRECTORY_NAME ".Trees"
18123+#define SERVER_DIRECTORY_NAME ".Servers"
18124+
18125+#define PATH_LENGTH_BUFFER PATH_MAX
18126+#define NW_MAX_PATH_LENGTH 255
18127+
18128+#define XA_BUFFER (8 * 1024)
18129+
18130+#define IOC_LOGIN 0x4a540000
18131+#define IOC_LOGOUT 0x4a540001
18132+#define IOC_XPLAT 0x4a540002
18133+#define IOC_SESSION 0x4a540003
18134+#define IOC_DEBUGPRINT 0x4a540004
18135+
18136+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
18137+#define D_CHILD d_u.d_child
18138+#define AS_TREE_LOCK(l) read_lock_irq(l)
18139+#define AS_TREE_UNLOCK(l) read_unlock_irq(l)
18140+#else
18141+#define D_CHILD d_child
18142+#define AS_TREE_LOCK(l) spin_lock_irq(l)
18143+#define AS_TREE_UNLOCK(l) spin_unlock_irq(l)
18144+#endif
18145+
18146+/*
18147+ * NetWare file attributes
18148+ */
18149+
18150+#define NW_ATTRIBUTE_NORMAL 0x00
18151+#define NW_ATTRIBUTE_READ_ONLY 0x01
18152+#define NW_ATTRIBUTE_HIDDEN 0x02
18153+#define NW_ATTRIBUTE_SYSTEM 0x04
18154+#define NW_ATTRIBUTE_EXECUTE_ONLY 0x08
18155+#define NW_ATTRIBUTE_DIRECTORY 0x10
18156+#define NW_ATTRIBUTE_ARCHIVE 0x20
18157+#define NW_ATTRIBUTE_EXECUTE 0x40
18158+#define NW_ATTRIBUTE_SHAREABLE 0x80
18159+
18160+/*
18161+ * Define READ/WRITE flag for struct data_list
18162+ */
18163+#define DLREAD 0
18164+#define DLWRITE 1
18165+
18166+/*
18167+ * Define list type
18168+ */
18169+#define USER_LIST 1
18170+#define SERVER_LIST 2
18171+#define VOLUME_LIST 3
18172+
18173+/*
18174+ * Define flags used in for inodes
18175+ */
18176+#define USER_INODE 1
18177+#define UPDATE_INODE 2
18178+
18179+/*
18180+ * Define flags for directory cache flags
18181+ */
18182+#define ENTRY_VALID 0x00000001
18183+
18184+#ifdef INTENT_MAGIC
18185+#define NDOPENFLAGS intent.it_flags
18186+#else
18187+#define NDOPENFLAGS intent.open.flags
18188+#endif
18189+
18190+/*
18191+ * daemon_command_t flags values
18192+ */
18193+#define INTERRUPTIBLE 1
18194+
18195+#ifndef NOVFS_VFS_MAJOR
18196+#define NOVFS_VFS_MAJOR 0
18197+#endif
18198+
18199+#ifndef NOVFS_VFS_MINOR
18200+#define NOVFS_VFS_MINOR 0
18201+#endif
18202+
18203+#ifndef NOVFS_VFS_SUB
18204+#define NOVFS_VFS_SUB 0
18205+#endif
18206+
18207+#ifndef NOVFS_VFS_RELEASE
18208+#define NOVFS_VFS_RELEASE 0
18209+#endif
18210+
18211+#define VALUE_TO_STR( value ) #value
18212+#define DEFINE_TO_STR(value) VALUE_TO_STR(value)
18213+
18214+#define NOVFS_VERSION_STRING \
18215+ DEFINE_TO_STR(NOVFS_VFS_MAJOR)"." \
18216+ DEFINE_TO_STR(NOVFS_VFS_MINOR)"." \
18217+ DEFINE_TO_STR(NOVFS_VFS_SUB)"-" \
18218+ DEFINE_TO_STR(NOVFS_VFS_RELEASE) \
18219+ "\0"
18220+
18221+struct entry_info {
18222+ int type;
18223+ umode_t mode;
18224+ uid_t uid;
18225+ gid_t gid;
18226+ loff_t size;
18227+ struct timespec atime;
18228+ struct timespec mtime;
18229+ struct timespec ctime;
18230+ int namelength;
18231+ unsigned char name[1];
18232+};
18233+
18234+struct novfs_string {
18235+ int length;
18236+ unsigned char *data;
18237+};
18238+
18239+struct login {
18240+ struct novfs_string Server;
18241+ struct novfs_string UserName;
18242+ struct novfs_string Password;
18243+};
18244+
18245+struct logout {
18246+ struct novfs_string Server;
18247+};
18248+
18249+struct dir_cache {
18250+ struct list_head list;
18251+ int flags;
18252+ u64 jiffies;
18253+ ino_t ino;
18254+ loff_t size;
18255+ umode_t mode;
18256+ struct timespec atime;
18257+ struct timespec mtime;
18258+ struct timespec ctime;
18259+ unsigned long hash;
18260+ int nameLen;
18261+ char name[1];
18262+};
18263+
18264+struct data_list {
18265+ void *page;
18266+ void *offset;
18267+ int len;
18268+ int rwflag;
18269+};
18270+
18271+
18272+extern char *ctime_r(time_t * clock, char *buf);
18273+
18274+static inline u32 HandletoUint32(HANDLE h)
18275+/*
18276+ *
18277+ * Arguments: HANDLE h - handle value
18278+ *
18279+ * Returns: u32 - u32 value
18280+ *
18281+ * Abstract: Converts a HANDLE to a u32 type.
18282+ *
18283+ * Notes:
18284+ *
18285+ * Environment:
18286+ *
18287+ *========================================================================*/
18288+{
18289+ return (u32) ((unsigned long) h);
18290+}
18291+
18292+/*++======================================================================*/
18293+static inline HANDLE Uint32toHandle(u32 ui32)
18294+/*
18295+ *
18296+ * Arguments: u32 ui32
18297+ *
18298+ * Returns: HANDLE - Handle type.
18299+ *
18300+ * Abstract: Converts a u32 to a HANDLE type.
18301+ *
18302+ * Notes:
18303+ *
18304+ * Environment:
18305+ *
18306+ *========================================================================*/
18307+{
18308+ return ((HANDLE) (unsigned long) ui32);
18309+}
18310+
18311+/* Global variables */
18312+
18313+extern int Novfs_Version_Major;
18314+extern int Novfs_Version_Minor;
18315+extern int Novfs_Version_Sub;
18316+extern int Novfs_Version_Release;
18317+extern struct dentry *Novfs_root;
18318+extern struct proc_dir_entry *Novfs_Procfs_dir;
18319+extern unsigned long File_update_timeout;
18320+extern int PageCache;
18321+extern char *Novfs_CurrentMount;
18322+extern struct dentry_operations Novfs_dentry_operations;
18323+extern int MaxIoSize;
18324+
18325+
18326+/* Global functions */
18327+extern int Novfs_Remove_from_Root(char *);
18328+extern void Novfs_dump_inode(void *pf);
18329+
18330+extern void mydump(int size, void *dumpptr);
18331+
18332+extern int Queue_Daemon_Command(void *request, unsigned long reqlen, void *data,
18333+ int dlen, void **reply, unsigned long * replen,
18334+ int interruptible);
18335+
18336+extern int Init_Procfs_Interface(void);
18337+extern void Uninit_Procfs_Interface(void);
18338+
18339+/*
18340+ * daemon.c functions
18341+ */
18342+extern void Init_Daemon_Queue(void);
18343+extern void Uninit_Daemon_Queue(void);
18344+extern int do_login(NclString * Server, NclString * Username, NclString * Password, HANDLE * lgnId, struct schandle *Session);
18345+extern int do_logout(struct qstr *Server, struct schandle *Session);
18346+extern int Daemon_SetMountPoint(char *Path);
18347+extern int Daemon_CreateSessionId(struct schandle *SessionId);
18348+extern int Daemon_DestroySessionId(struct schandle *SessionId);
18349+extern int Daemon_getpwuid(uid_t uid, int unamelen, char *uname);
18350+extern int Daemon_Get_UserSpace(struct schandle *session_id, u64 *TotalSize,
18351+ u64 *TotalFree, u64 *TotalDirectoryEnties,
18352+ u64 *FreeDirectoryEnties);
18353+extern int Daemon_SendDebugCmd(char *Command);
18354+extern ssize_t Daemon_Receive_Reply(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos);
18355+extern ssize_t Daemon_Send_Command(struct file *file, char __user *buf, size_t len, loff_t *off);
18356+extern int Daemon_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
18357+extern int Daemon_Library_close(struct inode *inode, struct file *file);
18358+extern int Daemon_Library_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
18359+extern int Daemon_Library_open(struct inode *inode, struct file *file);
18360+extern ssize_t Daemon_Library_write(struct file *file, const char __user *buf, size_t len, loff_t * off);
18361+extern ssize_t Daemon_Library_read(struct file *file, char __user *buf, size_t len, loff_t * off);
18362+extern loff_t Daemon_Library_llseek(struct file *file, loff_t offset, int origin);
18363+extern int Daemon_Open_Control(struct inode *Inode, struct file *File);
18364+extern int Daemon_Close_Control(struct inode *Inode, struct file *File);
18365+extern int Daemon_getversion(char *Buf, int Length);
18366+
18367+
18368+/*
18369+ * file.c functions
18370+ */
18371+extern int Novfs_get_alltrees(struct dentry *parent);
18372+extern int Novfs_Get_Connected_Server_List(unsigned char **ServerList, struct schandle *SessionId);
18373+extern int Novfs_Get_Server_Volume_List(struct qstr *Server, unsigned char **VolumeList, struct schandle *SessionId);
18374+extern int Novfs_Get_File_Info(unsigned char *Path, struct entry_info *Info, struct schandle *SessionId);
18375+extern int Novfs_GetX_File_Info(char *Path, const char *Name, char *buffer, ssize_t buffer_size, ssize_t *dataLen, struct schandle *SessionId);
18376+extern int Novfs_ListX_File_Info(char *Path, char *buffer, ssize_t buffer_size, ssize_t * dataLen, struct schandle *SessionId);
18377+extern int Novfs_SetX_File_Info(char *Path, const char *Name, const void *Value,
18378+ unsigned long valueLen,
18379+ unsigned long *bytesWritten, int flags,
18380+ struct schandle *SessionId);
18381+
18382+extern int Novfs_Get_Directory_ListEx(unsigned char *Path, HANDLE *EnumHandle,
18383+ int *Count, struct entry_info **Info,
18384+ struct schandle *SessionId);
18385+extern int Novfs_Open_File(unsigned char *Path, int Flags, struct entry_info *info,
18386+ HANDLE * Handle, session_t SessionId);
18387+extern int Novfs_Create(unsigned char *Path, int DirectoryFlag,
18388+ session_t SessionId);
18389+extern int Novfs_Close_File(HANDLE Handle, session_t SessionId);
18390+extern int Novfs_Read_File(HANDLE Handle, unsigned char *Buffer, size_t * Bytes,
18391+ loff_t * Offset, session_t SessionId);
18392+extern int Novfs_Read_Pages(HANDLE Handle, struct data_list *dlist, int DList_Cnt,
18393+ size_t * Bytes, loff_t * Offset,
18394+ session_t SessionId);
18395+extern int Novfs_Write_File(HANDLE Handle, unsigned char *Buffer,
18396+ size_t * Bytes, loff_t * Offset,
18397+ session_t SessionId);
18398+extern int Novfs_Write_Page(HANDLE Handle, struct page *Page,
18399+ session_t SessionId);
18400+extern int Novfs_Write_Pages(HANDLE Handle, struct data_list *dlist, int DList_Cnt,
18401+ size_t Bytes, loff_t Offset, session_t SessionId);
18402+extern int Novfs_Delete(unsigned char *Path, int DirectoryFlag,
18403+ session_t SessionId);
18404+extern int Novfs_Truncate_File(unsigned char *Path, int PathLen,
18405+ session_t SessionId);
18406+extern int Novfs_Truncate_File_Ex(HANDLE Handle, loff_t Offset,
18407+ session_t SessionId);
18408+extern int Novfs_Rename_File(int DirectoryFlag, unsigned char *OldName,
18409+ int OldLen, unsigned char *NewName, int NewLen,
18410+ session_t SessionId);
18411+extern int Novfs_Set_Attr(unsigned char *Path, struct iattr *Attr,
18412+ session_t SessionId);
18413+extern int Novfs_Get_File_Cache_Flag(unsigned char * Path, session_t SessionId);
18414+extern int Novfs_Set_File_Lock(session_t SessionId, HANDLE fhandle,
18415+ unsigned char fl_type, loff_t fl_start,
18416+ loff_t len);
18417+
18418+extern struct inode *Novfs_get_inode(struct super_block *sb, int mode, int dev, uid_t uid, ino_t ino, struct qstr *name);
18419+extern int Novfs_Read_Stream(HANDLE ConnHandle, unsigned char * Handle,
18420+ unsigned char * Buffer, size_t * Bytes, loff_t * Offset,
18421+ int User, session_t SessionId);
18422+extern int Novfs_Write_Stream(HANDLE ConnHandle, unsigned char * Handle,
18423+ unsigned char * Buffer, size_t * Bytes, loff_t * Offset,
18424+ session_t SessionId);
18425+extern int Novfs_Close_Stream(HANDLE ConnHandle, unsigned char * Handle,
18426+ session_t SessionId);
18427+
18428+extern int Novfs_Add_to_Root(char *);
18429+
18430+
18431+/*
18432+ * scope.c functions
18433+ */
18434+extern void Scope_Init(void);
18435+extern void Scope_Uninit(void);
18436+extern void *Scope_Lookup(void);
18437+extern uid_t Scope_Get_Uid(void *);
18438+extern session_t Scope_Get_SessionId(void *Scope);
18439+//extern session_t Scope_Get_SessionId(PSCOPE_LIST Scope);
18440+extern char *Scope_Get_ScopeUsers(void);
18441+extern int Scope_Set_UserSpace(u64 *TotalSize, u64 *Free,
18442+ u64 *TotalEnties, u64 *FreeEnties);
18443+extern int Scope_Get_UserSpace(u64 *TotalSize, u64 *Free,
18444+ u64 *TotalEnties, u64 *FreeEnties);
18445+extern char *Scope_dget_path(struct dentry *Dentry, char *Buf,
18446+ unsigned int Buflen, int Flags);
18447+extern char *Scope_Get_UserName(void);
18448+extern void Scope_Cleanup(void);
18449+
18450+/*
18451+ * profile.c functions
18452+ */
18453+extern u64 get_nanosecond_time(void);
18454+static inline void *Novfs_Malloc(size_t size, int flags) { return kmalloc(size, flags); }
18455+extern int DbgPrint(char *Fmt, ...);
18456+extern int init_profile(void);
18457+extern void uninit_profile(void);
18458+
18459+/*
18460+ * nwcapi.c functions
18461+ */
18462+extern int NwAuthConnWithId(PXPLAT pdata, session_t Session);
18463+extern int NwConnClose(PXPLAT pdata, HANDLE * Handle, session_t Session);
18464+extern int NwGetConnInfo(PXPLAT pdata, session_t Session);
18465+extern int NwSetConnInfo(PXPLAT pdata, session_t Session);
18466+extern int NwGetDaemonVersion(PXPLAT pdata, session_t Session);
18467+extern int NwGetIdentityInfo(PXPLAT pdata, session_t Session);
18468+extern int NwLicenseConn(PXPLAT pdata, session_t Session);
18469+extern int NwLoginIdentity(PXPLAT pdata, struct schandle *Session);
18470+extern int NwLogoutIdentity(PXPLAT pdata, session_t Session);
18471+extern int NwOpenConnByAddr(PXPLAT pdata, HANDLE * Handle, session_t Session);
18472+extern int NwOpenConnByName(PXPLAT pdata, HANDLE * Handle, session_t Session);
18473+extern int NwOpenConnByRef(PXPLAT pdata, HANDLE * Handle, session_t Session);
18474+extern int NwQueryFeature(PXPLAT pdata, session_t Session);
18475+extern int NwRawSend(PXPLAT pdata, session_t Session);
18476+extern int NwScanConnInfo(PXPLAT pdata, session_t Session);
18477+extern int NwSysConnClose(PXPLAT pdata, unsigned long * Handle, session_t Session);
18478+extern int NwUnAuthenticate(PXPLAT pdata, session_t Session);
18479+extern int NwUnlicenseConn(PXPLAT pdata, session_t Session);
18480+extern int NwcChangeAuthKey(PXPLAT pdata, session_t Session);
18481+extern int NwcEnumIdentities(PXPLAT pdata, session_t Session);
18482+extern int NwcGetDefaultNameCtx(PXPLAT pdata, session_t Session);
18483+extern int NwcGetPreferredDSTree(PXPLAT pdata, session_t Session);
18484+extern int NwcGetTreeMonitoredConn(PXPLAT pdata, session_t Session);
18485+extern int NwcSetDefaultNameCtx(PXPLAT pdata, session_t Session);
18486+extern int NwcSetPreferredDSTree(PXPLAT pdata, session_t Session);
18487+extern int NwcSetPrimaryConn(PXPLAT pdata, session_t Session);
18488+extern int NwcGetPrimaryConn(PXPLAT pdata, session_t Session);
18489+extern int NwcSetMapDrive(PXPLAT pdata, session_t Session);
18490+extern int NwcUnMapDrive(PXPLAT pdata, session_t Session);
18491+extern int NwcEnumerateDrives(PXPLAT pdata, session_t Session);
18492+extern int NwcGetBroadcastMessage(PXPLAT pdata, session_t Session);
18493+extern int NwdSetKeyValue(PXPLAT pdata, session_t Session);
18494+extern int NwdVerifyKeyValue(PXPLAT pdata, session_t Session);
18495+
18496+
18497+#endif /* __NOVFS_H */
18498+