1/* 2 * Copyright (c) 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 _WEBDAV_CACHE_H_INCLUDE 25#define _WEBDAV_CACHE_H_INCLUDE 26 27#include <sys/types.h> 28#include <sys/queue.h> 29#include <CoreServices/CoreServices.h> 30 31/*****************************************************************************/ 32 33/* define node_head structure */ 34LIST_HEAD(node_head, node_entry); 35 36struct webdav_stat_attr { 37 struct stat attr_stat; /* stat attributes */ 38 struct timespec attr_create_time; /* time file was created */ 39 void* data; 40 Boolean start; 41}; 42 43struct node_entry 44{ 45 LIST_ENTRY(node_entry) entries; /* the other nodes on the parent's children list */ 46 struct node_entry *parent; /* the parent node_entry, or NULL if this is the root node */ 47 LIST_HEAD(, node_entry) children; /* this node's children (if any) */ 48 49 /* 50 * Node identification fields 51 */ 52 size_t name_length; /* length of name */ 53 char *name; /* the utf8 name */ 54 CFStringRef name_ref; /* the name as a CFString */ 55 webdav_ino_t fileid; /* file ID number */ 56 webdav_filetype_t node_type; /* (int) either WEBDAV_FILE_TYPE or WEBDAV_DIR_TYPE */ 57 u_int32_t flags; 58 opaque_id nodeid; /* opaque_id assigned to this node */ 59 time_t node_time; /* local time - when node was validated on server */ 60 61 /* 62 * Attribute fields 63 * 64 * Set attr_time to 0 and free the memory used by attr_ref (if any) to invalidate attributes. 65 */ 66 uid_t attr_uid; /* user authorized to use attribute data */ 67 time_t attr_time; /* local time - when attribute data was received from server */ 68 struct webdav_stat_attr attr_stat_info; /* stat attributes + misc. timestamps */ 69 70 /* file system specific attribute data */ 71 time_t attr_appledoubleheader_time; /* local time - when attr_appledoubleheader was received from server */ 72 char *attr_appledoubleheader; /* NULL if no appledoubleheader data */ 73 74 /* 75 * File cache fields 76 * 77 * Clear the nodeInFileList flag bit and insert into the from the file_list make it a valid cache file. 78 * 79 * Clear the nodeInFileList flag bit and remove from the file_list to invalidate a cache file. Don't forget to free the 80 * file_ref before you free the node. 81 * 82 * A valid cache file can be either active (the file or directory it is a 83 * cache for is open) or inactive (the file or directory it is a cache for 84 * is closed). Active cache files have a file_inactive_time of zero; 85 * inactive cache files have the time the cache file was made inactive so 86 * that they can be aged out of the cache. 87 */ 88 LIST_ENTRY(node_entry) file_list; /* the g_file_list */ 89 int file_fd; /* the cache file's file descriptor or -1 if none */ 90 u_int32_t file_status; /* the status of the cache file download: 91 * WEBDAV_DOWNLOAD_NEVER (never downloaded) 92 * WEBDAV_DOWNLOAD_IN_PROGRESS (download still in progress) 93 * WEBDAV_DOWNLOAD_FINISHED (download complete) 94 * WEBDAV_DOWNLOAD_ABORTED (download was stopped before complete because of close or error) 95 * If WEBDAV_DOWNLOAD_TERMINATED is set, an in-progress download should be stopped. 96 * Note: the download_status field should be word aligned. 97 */ 98 time_t file_validated_time; /* local time - when cache file was last validated by server */ 99 time_t file_inactive_time; /* local time - when cache file was made inactive (the file this cache is for was closed) - 0 if active */ 100 /* file system specific file cache data */ 101 time_t file_last_modified; /* the HTTP-date converted to time_t from the Last-Modified entity-header or from the getlastmodified property, or -1 if no valid Last-Modified date */ 102 char *file_entity_tag; /* The entity-tag from the ETag response-header or from the getetag property */ 103 uid_t file_locktoken_uid; /* the uid associated with the locktoken (filesystem_close and filesystem_lock need it to renew locks and to unlock). */ 104 char *file_locktoken; /* the lock token, or NULL */ 105 106 /* Context for sequential writes */ 107 struct stream_put_ctx* put_ctx; 108 109 /* Fields used for HTTP 3xx Redirects */ 110 boolean_t isRedirected; /* TRUE if this node has been redirected */ 111 size_t redir_name_length; /* length of redirected name */ 112 char *redir_name; /* the redirected utf8 name (From Location header of 3xx response) */ 113}; 114 115#define WEBDAV_DOWNLOAD_NEVER 0 116#define WEBDAV_DOWNLOAD_IN_PROGRESS 1 117#define WEBDAV_DOWNLOAD_FINISHED 2 118#define WEBDAV_DOWNLOAD_ABORTED 3 119#define WEBDAV_DOWNLOAD_STATUS_MASK 0x7fffffff 120#define WEBDAV_DOWNLOAD_TERMINATED 0x80000000 121 122/* node_entry flags */ 123enum 124{ 125 nodeDeletedBit = 0, /* the node is deleted and is on the deleted list */ 126 nodeDeletedMask = 0x00000001, 127 nodeInFileListBit = 1, /* the node is cached and is on the file list */ 128 nodeInFileListMask = 0x00000002, 129 nodeRecentBit = 2, /* the file node was recently created by this client or the directory was recently read */ 130 nodeRecentMask = 0x00000004 131}; 132 133/*****************************************************************************/ 134 135#define ATTRIBUTES_TIMEOUT_MIN 2 /* Minimum number of seconds attributes are valid */ 136#define ATTRIBUTES_TIMEOUT_MAX 60 /* Maximum number of seconds attributes are valid */ 137#define FILE_VALIDATION_TIMEOUT 60 /* Number of seconds file is valid from file_validated_time */ 138#define FILE_CACHE_TIMEOUT 3600 /* 1 hour */ 139#define FILE_RECENTLY_CREATED_TIMEOUT 1 /* Maximum number of seconds to skip GETs on opens after a create */ 140 141#define NODE_IS_DELETED(node) (((node)->flags & nodeDeletedMask) != 0) 142 143int node_appledoubleheader_valid( 144 struct node_entry *node, 145 uid_t uid); 146int node_attributes_valid( 147 struct node_entry *node, 148 uid_t uid); 149 150#define NODE_FILE_IS_CACHED(node) ( ((node)->flags & nodeInFileListMask) != 0 ) 151#define NODE_FILE_IS_OPEN(node) ( (node)->file_inactive_time == 0 ) 152#define NODE_FILE_CACHE_INVALID(node) ( ((node)->file_inactive_time != 0) && \ 153 (time(NULL) >= ((node)->file_inactive_time + FILE_CACHE_TIMEOUT)) ) 154#define NODE_FILE_INVALID(node) ( ((node)->file_validated_time == 0) || \ 155 (time(NULL) >= ((node)->file_validated_time + FILE_VALIDATION_TIMEOUT)) ) 156#define NODE_FILE_RECENTLY_CREATED(node) ( ((node)->node_time != 0) && \ 157 (((node)->flags & nodeRecentMask) != 0) && \ 158 (time(NULL) <= ((node)->node_time + FILE_RECENTLY_CREATED_TIMEOUT)) ) 159 160/*****************************************************************************/ 161 162int nodecache_init( 163 size_t name_length, /* length of root node name */ 164 char *name, /* the utf8 name of root node */ 165 struct node_entry **root_node); /* the root node */ 166 167int nodecache_get_node( 168 struct node_entry *parent, /* the parent node_entry */ 169 size_t name_length, /* length of name */ 170 const char *name, /* the utf8 name of the node */ 171 int make_entry, /* TRUE if a new node_entry should be created if needed*/ 172 int client_created, /* TRUE if this client created the node (used in conjunction with make_entry */ 173 webdav_filetype_t node_type, /* if make_entry is TRUE, the type of node to create */ 174 struct node_entry **node); /* the found (or new) node_entry */ 175 176void nodecache_free_nodes(void); 177 178int nodecache_move_node( 179 struct node_entry *node, /* the node_entry to move */ 180 struct node_entry *new_parent, /* the new parent node_entry */ 181 size_t new_name_length, /* length of new_name or 0 if not renaming */ 182 char *new_name); /* the utf8 new name of the node or NULL */ 183 184int nodecache_delete_node( 185 struct node_entry *node, /* the node_entry to delete */ 186 int recursive); /* delete recursively if node is a directory */ 187 188int nodecache_add_attributes( 189 struct node_entry *node, /* the node_entry to update or add attributes_entry to */ 190 uid_t uid, /* the uid these attributes are valid for */ 191 struct webdav_stat_attr *statp, /* the stat buffer */ 192 char *appledoubleheader); /* pointer appledoubleheader or NULL */ 193 194int nodecache_remove_attributes( 195 struct node_entry *node); /* the node_entry to remove attributes from */ 196 197void nodecache_invalidate_caches(void); 198 199int nodecache_add_file_cache( 200 struct node_entry *node, /* the node_entry to add a file_cache_entry to */ 201 int fd); /* the file descriptor of the cache file */ 202 203void nodecache_remove_file_cache( 204 struct node_entry *node); /* the node_entry to remove file_cache_entry from */ 205 206struct node_entry *nodecache_get_next_file_cache_node( 207 int get_first); /* if true, return first file cache node; otherwise, the next one */ 208 209int nodecache_get_path_from_node( 210 struct node_entry *node, /* -> node */ 211 bool *pathHasRedirection, /* true if path contains a URL from a redirected node (http 3xx redirect) */ 212 char **path); /* <- relative path to root node */ 213 214int nodecache_redirect_node( 215 CFURLRef url, /* original url that caused the redirect */ 216 struct node_entry *redirected_node, /* the node being redirected NULL if root node */ 217 CFHTTPMessageRef responseRef, /* the 3xx redirect response message */ 218 CFIndex statusCode); /* Actual 3xx status code from response message */ 219 220int nodecache_invalidate_directory_node_time( 221 struct node_entry *dir_node); /* parent directory node */ 222 223int nodecache_delete_invalid_directory_nodes( 224 struct node_entry *dir_node); /* parent directory node */ 225 226CFURLRef nodecache_get_baseURL(void); 227 228CFArrayRef nodecache_get_locktokens( 229 struct node_entry *a_node); /* node or directory node */ 230 231void lock_node_cache(void); 232void unlock_node_cache(void); 233 234 235/*****************************************************************************/ 236 237#if 0 238void nodecache_display_node_tree(void); 239void nodecache_display_file_cache(void); 240#endif 241 242/*****************************************************************************/ 243 244#endif 245