1/*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#ifndef _WEBDAVD_H_INCLUDE
25#define _WEBDAVD_H_INCLUDE
26
27/*
28 * DEBUG (which defines the state of DEBUG_ASSERT_PRODUCTION_CODE),
29 * DEBUG_ASSERT_COMPONENT_NAME_STRING, and DEBUG_ASSERT_MESSAGE must be
30 * defined before including AssertMacros.h
31 */
32/* we want non-quiet asserts to be logged */
33#define DEBUG_ASSERT_PRODUCTION_CODE 0
34/* and we want them logged as errors */
35#define WEBDAV_LOG_LEVEL LOG_ERR
36#define DEBUG_ASSERT_COMPONENT_NAME_STRING "webdavfs"
37#define DEBUG_ASSERT_MESSAGE(componentNameString, assertionString, exceptionLabelString, errorString, fileName, lineNumber, errorCode) \
38	webdav_debug_assert(componentNameString, assertionString, exceptionLabelString, errorString, fileName, lineNumber, errorCode)
39
40#include <AssertMacros.h>
41
42#include <sys/types.h>
43#include <sys/param.h>
44#include <sys/syslog.h>
45#include "../webdav_fs.kextproj/webdav_fs.kmodproj/webdav.h"
46#include <errno.h>
47#include <mach/boolean.h>
48#include <unistd.h>
49#include <CoreFoundation/CFURL.h>
50#include <CoreFoundation/CoreFoundation.h>
51#include <CoreServices/CoreServices.h>
52
53/* Global Defines */
54
55/*
56 * WEBDAV_RLIMIT_NOFILE needs to be large enough for us to have WEBDAV_MAX_OPEN_FILES cache files
57 * open, plus some for the defaults (stdin/out, etc), the sockets opened by threads,
58 * the dup'd file descriptors passed back to the kext, the socket used to
59 * communicate with the kext, and a few extras for libraries we call that might
60 * need a few. The most I've ever seen in use is just under 530, so 1024 is
61 * more than enough.
62 */
63#define WEBDAV_RLIMIT_NOFILE 1024
64#define WEBDAV_MAX_OPEN_FILES 512
65
66// The default maximum size of a download to allow the file system to cache
67#define WEBDAV_DEFAULT_CACHE_MAX_SIZE 0x02000000  /* 32M */
68#define WEBDAV_ONE_GIGABYTE			  0x40000000  /* 1G */
69
70/* the number of threads available to handle requests from the kernel file system and downloads */
71#define WEBDAV_REQUEST_THREADS 5
72
73#define PRIVATE_CERT_UI_COMMAND "/System/Library/Filesystems/webdav.fs/Support/webdav_cert_ui.app/Contents/MacOS/webdav_cert_ui"
74#define PRIVATE_UNMOUNT_COMMAND "/sbin/umount"
75#define PRIVATE_UNMOUNT_FLAGS "-f"
76
77/* the time interval (in seconds) for holding LOCKs on the server. The pulse thread runs at doublew this rate. */
78#define WEBDAV_PULSE_TIMEOUT "600"		/* Default time out = 10 minutes */
79
80#define APPLEDOUBLEHEADER_LENGTH 82		/* length of AppleDouble header property */
81
82/*
83 * BODY_BUFFER_SIZE is the initial size of the buffer used to read an
84 * HTTP entity body. The largest bodies are typically the XML data
85 * returned by the PROPFIND method for a large collection (directory).
86 * 64K is large enough to handle directories with 100-150 items.
87 */
88#define BODY_BUFFER_SIZE 0x10000	/* 64K */
89
90/* special file ID values */
91#define WEBDAV_ROOTPARENTFILEID 2
92#define WEBDAV_ROOTFILEID 3
93
94/* sizes passed to the kernel file system */
95#define WEBDAV_DIR_SIZE 2048			/* the directory size -- a made up value */
96#define WEBDAV_IOSIZE (4*1024)			/* should be < PIPSIZ (8K) */
97
98#define WEBDAV_WRITESEQ_RSPBUF_LEN 4096
99#define WEBDAV_WRITESEQ_REQUEST_TIMEOUT 30  /* in seconds  */
100#define WEBDAV_MANAGER_STARTUP_TIMEOUT 5 /* in seconds */
101
102/* Macro to simplify common CFRelease usage */
103#define CFReleaseNull(obj) do { if(obj != NULL) { CFRelease(obj); obj = NULL; } } while (0)
104
105struct seqwrite_mgr_req;
106
107enum WriteMgrStatus {WR_MGR_VIRGIN=0, WR_MGR_RUNNING, WR_MGR_DONE};
108struct stream_put_ctx {
109	/* Stream Pair */
110	CFReadStreamRef rdStreamRef;
111	CFWriteStreamRef wrStreamRef;
112	struct ReadStreamRec* readStreamRec;
113	CFReadStreamRef rspStreamRef;
114	int sockfd[2];
115	CFTypeRef theResponsePropertyRef;
116	off_t curr_offset;
117
118	// The outgoing request message
119	CFHTTPMessageRef request;
120
121	// ***********************
122	// *** Synchronization ***
123	// ***********************
124	pthread_mutex_t ctx_lock;
125	pthread_cond_t ctx_condvar;  /* close thread waits on finalStatusValid */
126
127	// Sequential write manager stuff
128	CFRunLoopRef mgr_rl;
129	enum WriteMgrStatus mgr_status;
130	uint32_t canAcceptBytesEvents;
131
132	// Request queue for manager thread, and
133	// message port
134	CFMessagePortRef mgrPort;
135	struct seqwrite_mgr_req *req_head, *req_tail;
136
137	// *************************************
138	// *** Response stream thread fields ***
139	// *************************************
140	bool finalStatusValid;
141	int finalStatus;
142
143	CFIndex totalRead;
144	UInt8 rspBuf[WEBDAV_WRITESEQ_RSPBUF_LEN];
145
146	// ***************************
147	// *** Write thread fields ***
148	// ***************************
149
150	// writeStreamOpenEventReceived is set to true when
151	// a kCFStreamEventOpenCompleted event has been received
152	// on the stream
153	bool writeStreamOpenEventReceived;
154	bool rspStreamOpenEventReceived;
155
156	// True if current write is a retry (due to previous EPIPE)
157	uint32_t is_retry;
158};
159
160// Sequential write manager request
161enum SeqWriteMgrReqType {SEQWRITE_CHUNK, SEQWRITE_CLOSE};
162struct seqwrite_mgr_req
163{
164	enum SeqWriteMgrReqType type;
165
166	struct seqwrite_mgr_req *prev, *next;
167
168	// ***********************
169	// *** Synchronization ***
170	// ***********************
171	pthread_mutex_t req_lock;
172	pthread_cond_t req_condvar;
173
174	// state of this request
175	struct webdav_request_writeseq *req;
176	bool request_done;
177	uint32_t is_retry;	// true if this request is a retry (due to a previous EPIPE)
178	int  error;
179
180	// chunk state
181	CFIndex chunkLen, chunkWritten;
182
183	uint32_t refCount;
184
185	// Where we store data read from the cache before we throw it on the wire.
186	unsigned char *data;
187};
188
189/* Global functions */
190extern void webdav_debug_assert(const char *componentNameString, const char *assertionString,
191	const char *exceptionLabelString, const char *errorString,
192	const char *fileName, long lineNumber, uint64_t errorCode);
193extern void webdav_kill(int message);
194
195/* Global variables */
196extern unsigned int gtimeout_val;		/* the pulse_thread runs at double this rate */
197extern char * gtimeout_string;			/* the length of time LOCKs are held on on the server */
198extern int gWebdavfsDebug;				/* TRUE if the WEBDAVFS_DEBUG environment variable is set */
199extern uid_t gProcessUID;				/* the daemon's UID */
200extern int gSuppressAllUI;				/* if TRUE, the mount requested that all UI be supressed */
201extern int gSecureServerAuth;			/* if TRUE, the authentication for server challenges must be sent securely (not clear-text) */
202
203extern char gWebdavCachePath[MAXPATHLEN + 1]; /* the current path to the cache directory */
204extern int gSecureConnection;			/* if TRUE, the connection is secure */
205extern CFURLRef gBaseURL;				/* the base URL for this mount */
206extern CFStringRef gBasePath;			/* the base path (from gBaseURL) for this mount */
207extern char gBasePathStr[MAXPATHLEN];	/* gBasePath as a c-string */
208extern uint32_t	gServerIdent;			/* identifies some (not all) types of servers we are connected to (i.e. WEBDAV_IDISK_SERVER) */
209
210/*
211 * filesystem functions
212 */
213// there should be a filesystem.h and these prototypes should be moved there
214#include "webdav_cache.h"
215
216extern int filesystem_lookup(struct webdav_request_lookup *request_lookup,
217		struct webdav_reply_lookup *reply_lookup);
218
219extern int filesystem_create(struct webdav_request_create *request_create,
220		struct webdav_reply_create *reply_create);
221
222extern int filesystem_open(struct webdav_request_open *request_open,
223		struct webdav_reply_open *reply_open);
224
225extern int filesystem_close(struct webdav_request_close *request_close);
226
227extern int filesystem_getattr(struct webdav_request_getattr *request_getattr,
228		struct webdav_reply_getattr *reply_getattr);
229
230extern int filesystem_read(struct webdav_request_read *request_read,
231		char **a_byte_addr, size_t *a_size);
232
233extern int filesystem_fsync(struct webdav_request_fsync *request_fsync);
234
235extern int filesystem_remove(struct webdav_request_remove *request_remove);
236
237extern int filesystem_rename(struct webdav_request_rename *request_rename);
238
239extern int filesystem_mkdir(struct webdav_request_mkdir *request_mkdir,
240		struct webdav_reply_mkdir *reply_mkdir);
241
242extern int filesystem_rmdir(struct webdav_request_rmdir *request_rmdir);
243
244extern int filesystem_write_seq(struct webdav_request_writeseq *request_sq_wr);
245
246extern int filesystem_readdir(struct webdav_request_readdir *request_readdir);
247
248extern int filesystem_statfs(struct webdav_request_statfs *request_statfs,
249		struct webdav_reply_statfs *reply_statfs);
250
251extern int filesystem_invalidate_caches(struct webdav_request_invalcaches *request_invalcaches);
252
253extern int filesystem_mount(int *a_mount_args);
254
255extern int filesystem_lock(struct node_entry *node);
256
257extern int filesystem_init(int typenum);
258
259#endif /*ifndef _WEBDAVD_H_INCLUDE */
260