データ構造 | |
struct | notify_change_request |
struct | notify_mid_map |
関数 | |
static void | notify_fsp (files_struct *fsp, uint32 action, const char *name) |
static BOOL | notify_change_record_identical (struct notify_change *c1, struct notify_change *c2) |
static BOOL | notify_marshall_changes (int num_changes, uint32 max_offset, struct notify_change *changes, prs_struct *ps) |
static void | change_notify_reply_packet (const char *request_buf, NTSTATUS error_code) |
void | change_notify_reply (const char *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) |
static void | notify_callback (void *private_data, const struct notify_event *e) |
NTSTATUS | change_notify_create (struct files_struct *fsp, uint32 filter, BOOL recursive) |
NTSTATUS | change_notify_add_request (const char *inbuf, uint32 max_param, uint32 filter, BOOL recursive, struct files_struct *fsp) |
static void | change_notify_remove_request (struct notify_change_request *remove_req) |
void | remove_pending_change_notify_requests_by_mid (uint16 mid) |
void | remove_pending_change_notify_requests_by_fid (files_struct *fsp, NTSTATUS status) |
void | notify_fname (connection_struct *conn, uint32 action, uint32 filter, const char *path) |
char * | notify_filter_string (TALLOC_CTX *mem_ctx, uint32 filter) |
sys_notify_context * | sys_notify_context_create (connection_struct *conn, TALLOC_CTX *mem_ctx, struct event_context *ev) |
NTSTATUS | sys_notify_watch (struct sys_notify_context *ctx, struct notify_entry *e, void(*callback)(struct sys_notify_context *ctx, void *private_data, struct notify_event *ev), void *private_data, void *handle) |
変数 | |
int | max_send |
static struct notify_mid_map * | notify_changes_by_mid |
static void notify_fsp | ( | files_struct * | fsp, | |
uint32 | action, | |||
const char * | name | |||
) | [static] |
参照先 change・change_notify_remove_request()・change_notify_reply()・notify_change_buf::changes・notify_change_request::max_param・files_struct::notify・notify_change_buf::num_changes・notify_change_request::request_buf・notify_change_buf::requests・string_replace()・talloc_strdup().
参照元 notify_callback().
00374 { 00375 struct notify_change *change, *changes; 00376 pstring name2; 00377 00378 if (fsp->notify == NULL) { 00379 /* 00380 * Nobody is waiting, don't queue 00381 */ 00382 return; 00383 } 00384 00385 pstrcpy(name2, name); 00386 string_replace(name2, '/', '\\'); 00387 00388 /* 00389 * Someone has triggered a notify previously, queue the change for 00390 * later. 00391 */ 00392 00393 if ((fsp->notify->num_changes > 1000) || (name == NULL)) { 00394 /* 00395 * The real number depends on the client buf, just provide a 00396 * guard against a DoS here. 00397 */ 00398 TALLOC_FREE(fsp->notify->changes); 00399 fsp->notify->num_changes = -1; 00400 return; 00401 } 00402 00403 if (fsp->notify->num_changes == -1) { 00404 return; 00405 } 00406 00407 if (!(changes = TALLOC_REALLOC_ARRAY( 00408 fsp->notify, fsp->notify->changes, 00409 struct notify_change, fsp->notify->num_changes+1))) { 00410 DEBUG(0, ("talloc_realloc failed\n")); 00411 return; 00412 } 00413 00414 fsp->notify->changes = changes; 00415 00416 change = &(fsp->notify->changes[fsp->notify->num_changes]); 00417 00418 if (!(change->name = talloc_strdup(changes, name2))) { 00419 DEBUG(0, ("talloc_strdup failed\n")); 00420 return; 00421 } 00422 00423 change->action = action; 00424 fsp->notify->num_changes += 1; 00425 00426 if (fsp->notify->requests == NULL) { 00427 /* 00428 * Nobody is waiting, so don't send anything. The ot 00429 */ 00430 return; 00431 } 00432 00433 if (action == NOTIFY_ACTION_OLD_NAME) { 00434 /* 00435 * We have to send the two rename events in one reply. So hold 00436 * the first part back. 00437 */ 00438 return; 00439 } 00440 00441 /* 00442 * Someone is waiting for the change, trigger the reply immediately. 00443 * 00444 * TODO: do we have to walk the lists of requests pending? 00445 */ 00446 00447 change_notify_reply(fsp->notify->requests->request_buf, 00448 fsp->notify->requests->max_param, 00449 fsp->notify); 00450 00451 change_notify_remove_request(fsp->notify->requests); 00452 }
static BOOL notify_change_record_identical | ( | struct notify_change * | c1, | |
struct notify_change * | c2 | |||
) | [static] |
参照先 notify_change::action・notify_change::name.
参照元 notify_marshall_changes().
00055 { 00056 /* Note this is deliberately case sensitive. */ 00057 if (c1->action == c2->action && 00058 strcmp(c1->name, c2->name) == 0) { 00059 return True; 00060 } 00061 return False; 00062 }
static BOOL notify_marshall_changes | ( | int | num_changes, | |
uint32 | max_offset, | |||
struct notify_change * | changes, | |||
prs_struct * | ps | |||
) | [static] |
参照先 UNISTR::buffer・c・CH_UNIX・CH_UTF16LE・convert_string_allocate()・notify_change_record_identical().
00068 { 00069 int i; 00070 UNISTR uni_name; 00071 00072 uni_name.buffer = NULL; 00073 00074 for (i=0; i<num_changes; i++) { 00075 struct notify_change *c; 00076 size_t namelen; 00077 uint32 u32_tmp; /* Temp arg to prs_uint32 to avoid 00078 * signed/unsigned issues */ 00079 00080 /* Coalesce any identical records. */ 00081 while (i+1 < num_changes && 00082 notify_change_record_identical(&changes[i], 00083 &changes[i+1])) { 00084 i++; 00085 } 00086 00087 c = &changes[i]; 00088 00089 namelen = convert_string_allocate( 00090 NULL, CH_UNIX, CH_UTF16LE, c->name, strlen(c->name)+1, 00091 &uni_name.buffer, True); 00092 if ((namelen == -1) || (uni_name.buffer == NULL)) { 00093 goto fail; 00094 } 00095 00096 namelen -= 2; /* Dump NULL termination */ 00097 00098 /* 00099 * Offset to next entry, only if there is one 00100 */ 00101 00102 u32_tmp = (i == num_changes-1) ? 0 : namelen + 12; 00103 if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; 00104 00105 u32_tmp = c->action; 00106 if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail; 00107 00108 u32_tmp = namelen; 00109 if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail; 00110 00111 if (!prs_unistr("name", ps, 1, &uni_name)) goto fail; 00112 00113 /* 00114 * Not NULL terminated, decrease by the 2 UCS2 \0 chars 00115 */ 00116 prs_set_offset(ps, prs_offset(ps)-2); 00117 00118 SAFE_FREE(uni_name.buffer); 00119 00120 if (prs_offset(ps) > max_offset) { 00121 /* Too much data for client. */ 00122 return False; 00123 } 00124 } 00125 00126 return True; 00127 00128 fail: 00129 SAFE_FREE(uni_name.buffer); 00130 return False; 00131 }
static void change_notify_reply_packet | ( | const char * | request_buf, | |
NTSTATUS | error_code | |||
) | [static] |
参照先 construct_reply_common()・exit_server_cleanly()・send_smb()・set_message()・show_msg()・smbd_server_fd().
参照元 change_notify_reply()・remove_pending_change_notify_requests_by_fid().
00139 { 00140 char outbuf[smb_size+38]; 00141 00142 memset(outbuf, '\0', sizeof(outbuf)); 00143 construct_reply_common(request_buf, outbuf); 00144 00145 ERROR_NT(error_code); 00146 00147 /* 00148 * Seems NT needs a transact command with an error code 00149 * in it. This is a longer packet than a simple error. 00150 */ 00151 set_message(outbuf,18,0,False); 00152 00153 show_msg(outbuf); 00154 if (!send_smb(smbd_server_fd(),outbuf)) 00155 exit_server_cleanly("change_notify_reply_packet: send_smb " 00156 "failed."); 00157 }
void change_notify_reply | ( | const char * | request_buf, | |
uint32 | max_param, | |||
struct notify_change_buf * | notify_buf | |||
) |
参照先 change_notify_reply_packet()・notify_change_buf::changes・construct_reply_common()・exit_server()・max_send・notify_marshall_changes()・notify_change_buf::num_changes・prs_init()・prs_mem_free()・send_nt_replies().
参照元 call_nt_transact_notify_change()・notify_fsp().
00161 { 00162 char *outbuf = NULL; 00163 prs_struct ps; 00164 size_t buflen; 00165 00166 if (notify_buf->num_changes == -1) { 00167 change_notify_reply_packet(request_buf, NT_STATUS_OK); 00168 notify_buf->num_changes = 0; 00169 return; 00170 } 00171 00172 prs_init(&ps, 0, NULL, MARSHALL); 00173 00174 if (!notify_marshall_changes(notify_buf->num_changes, max_param, 00175 notify_buf->changes, &ps)) { 00176 /* 00177 * We exceed what the client is willing to accept. Send 00178 * nothing. 00179 */ 00180 change_notify_reply_packet(request_buf, NT_STATUS_OK); 00181 goto done; 00182 } 00183 00184 buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; 00185 00186 if (buflen > max_send) { 00187 /* 00188 * We exceed what the client is willing to accept. Send 00189 * nothing. 00190 */ 00191 change_notify_reply_packet(request_buf, NT_STATUS_OK); 00192 goto done; 00193 } 00194 00195 if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { 00196 change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); 00197 goto done; 00198 } 00199 00200 construct_reply_common(request_buf, outbuf); 00201 00202 if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), 00203 prs_offset(&ps), NULL, 0) == -1) { 00204 exit_server("change_notify_reply_packet: send_smb failed."); 00205 } 00206 00207 done: 00208 SAFE_FREE(outbuf); 00209 prs_mem_free(&ps); 00210 00211 TALLOC_FREE(notify_buf->changes); 00212 notify_buf->num_changes = 0; 00213 }
static void notify_callback | ( | void * | private_data, | |
const struct notify_event * | e | |||
) | [static] |
参照先 notify_event::action・notify_change_request::fsp・files_struct::fsp_name・notify_fsp()・notify_event::path.
00216 { 00217 files_struct *fsp = (files_struct *)private_data; 00218 DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name)); 00219 notify_fsp(fsp, e->action, e->path); 00220 }
NTSTATUS change_notify_create | ( | struct files_struct * | fsp, | |
uint32 | filter, | |||
BOOL | recursive | |||
) |
参照先 asprintf()・files_struct::conn・connection_struct::connectpath・notify_entry::filter・files_struct::fsp_name・fullpath()・files_struct::notify・notify_add()・notify_callback()・connection_struct::notify_ctx・notify_entry::path・status・notify_entry::subdir_filter.
参照元 call_nt_transact_notify_change().
00224 { 00225 char *fullpath; 00226 struct notify_entry e; 00227 NTSTATUS status; 00228 00229 SMB_ASSERT(fsp->notify == NULL); 00230 00231 if (!(fsp->notify = TALLOC_ZERO_P(NULL, struct notify_change_buf))) { 00232 DEBUG(0, ("talloc failed\n")); 00233 return NT_STATUS_NO_MEMORY; 00234 } 00235 00236 if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath, 00237 fsp->fsp_name) == -1) { 00238 DEBUG(0, ("asprintf failed\n")); 00239 return NT_STATUS_NO_MEMORY; 00240 } 00241 00242 e.path = fullpath; 00243 e.filter = filter; 00244 e.subdir_filter = 0; 00245 if (recursive) { 00246 e.subdir_filter = filter; 00247 } 00248 00249 status = notify_add(fsp->conn->notify_ctx, &e, notify_callback, fsp); 00250 SAFE_FREE(fullpath); 00251 00252 return status; 00253 }
NTSTATUS change_notify_add_request | ( | const char * | inbuf, | |
uint32 | max_param, | |||
uint32 | filter, | |||
BOOL | recursive, | |||
struct files_struct * | fsp | |||
) |
参照先 notify_change_request::backend_data・notify_change_request::filter・notify_change_request::fsp・notify_change_request::max_param・notify_mid_map::mid・notify_change_request::mid_map・files_struct::notify・notify_changes_by_mid・notify_mid_map::req・notify_change_request::request_buf・notify_change_buf::requests・srv_defer_sign_response().
参照元 call_nt_transact_notify_change().
00258 { 00259 struct notify_change_request *request = NULL; 00260 struct notify_mid_map *map = NULL; 00261 00262 if (!(request = SMB_MALLOC_P(struct notify_change_request)) 00263 || !(map = SMB_MALLOC_P(struct notify_mid_map))) { 00264 SAFE_FREE(request); 00265 return NT_STATUS_NO_MEMORY; 00266 } 00267 00268 request->mid_map = map; 00269 map->req = request; 00270 00271 memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); 00272 request->max_param = max_param; 00273 request->filter = filter; 00274 request->fsp = fsp; 00275 request->backend_data = NULL; 00276 00277 DLIST_ADD_END(fsp->notify->requests, request, 00278 struct notify_change_request *); 00279 00280 map->mid = SVAL(inbuf, smb_mid); 00281 DLIST_ADD(notify_changes_by_mid, map); 00282 00283 /* Push the MID of this packet on the signing queue. */ 00284 srv_defer_sign_response(SVAL(inbuf,smb_mid)); 00285 00286 return NT_STATUS_OK; 00287 }
static void change_notify_remove_request | ( | struct notify_change_request * | remove_req | ) | [static] |
参照先 notify_change_request::backend_data・notify_change_request::fsp・notify_change_request::mid_map・notify_change_request::next・files_struct::notify・notify_changes_by_mid・notify_change_buf::requests・smb_panic().
参照元 notify_fsp()・remove_pending_change_notify_requests_by_fid().
00290 { 00291 files_struct *fsp; 00292 struct notify_change_request *req; 00293 00294 /* 00295 * Paranoia checks, the fsp referenced must must have the request in 00296 * its list of pending requests 00297 */ 00298 00299 fsp = remove_req->fsp; 00300 SMB_ASSERT(fsp->notify != NULL); 00301 00302 for (req = fsp->notify->requests; req; req = req->next) { 00303 if (req == remove_req) { 00304 break; 00305 } 00306 } 00307 00308 if (req == NULL) { 00309 smb_panic("notify_req not found in fsp's requests\n"); 00310 } 00311 00312 DLIST_REMOVE(fsp->notify->requests, req); 00313 DLIST_REMOVE(notify_changes_by_mid, req->mid_map); 00314 SAFE_FREE(req->mid_map); 00315 TALLOC_FREE(req->backend_data); 00316 SAFE_FREE(req); 00317 }
void remove_pending_change_notify_requests_by_mid | ( | uint16 | mid | ) |
参照先 notify_mid_map::mid・notify_mid_map::next・notify_changes_by_mid.
参照元 reply_ntcancel().
00324 { 00325 struct notify_mid_map *map; 00326 00327 for (map = notify_changes_by_mid; map; map = map->next) { 00328 if (map->mid == mid) { 00329 break; 00330 } 00331 } 00332 00333 if (map == NULL) { 00334 return; 00335 } 00336 00337 change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); 00338 change_notify_remove_request(map->req); 00339 }
void remove_pending_change_notify_requests_by_fid | ( | files_struct * | fsp, | |
NTSTATUS | status | |||
) |
参照先 change_notify_remove_request()・change_notify_reply_packet()・files_struct::notify・notify_change_request::request_buf・notify_change_buf::requests・status.
00347 { 00348 if (fsp->notify == NULL) { 00349 return; 00350 } 00351 00352 while (fsp->notify->requests != NULL) { 00353 change_notify_reply_packet( 00354 fsp->notify->requests->request_buf, status); 00355 change_notify_remove_request(fsp->notify->requests); 00356 } 00357 }
void notify_fname | ( | connection_struct * | conn, | |
uint32 | action, | |||
uint32 | filter, | |||
const char * | path | |||
) |
参照先 asprintf()・connection_struct::connectpath・fullpath()・connection_struct::notify_ctx・notify_trigger().
参照元 mkdir_internal()・notify_rename()・open_file()・rmdir_internals()・set_ea_dos_attribute()・smb_set_file_time()・unlink_internals()・vfs_set_filelen().
00361 { 00362 char *fullpath; 00363 00364 if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) { 00365 DEBUG(0, ("asprintf failed\n")); 00366 return; 00367 } 00368 00369 notify_trigger(conn->notify_ctx, action, filter, fullpath); 00370 SAFE_FREE(fullpath); 00371 }
char* notify_filter_string | ( | TALLOC_CTX * | mem_ctx, | |
uint32 | filter | |||
) |
参照先 result・talloc_asprintf_append()・talloc_strdup().
参照元 call_nt_transact_notify_change().
00455 { 00456 char *result = NULL; 00457 00458 result = talloc_strdup(mem_ctx, ""); 00459 00460 if (filter & FILE_NOTIFY_CHANGE_FILE_NAME) 00461 result = talloc_asprintf_append(result, "FILE_NAME|"); 00462 if (filter & FILE_NOTIFY_CHANGE_DIR_NAME) 00463 result = talloc_asprintf_append(result, "DIR_NAME|"); 00464 if (filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) 00465 result = talloc_asprintf_append(result, "ATTRIBUTES|"); 00466 if (filter & FILE_NOTIFY_CHANGE_SIZE) 00467 result = talloc_asprintf_append(result, "SIZE|"); 00468 if (filter & FILE_NOTIFY_CHANGE_LAST_WRITE) 00469 result = talloc_asprintf_append(result, "LAST_WRITE|"); 00470 if (filter & FILE_NOTIFY_CHANGE_LAST_ACCESS) 00471 result = talloc_asprintf_append(result, "LAST_ACCESS|"); 00472 if (filter & FILE_NOTIFY_CHANGE_CREATION) 00473 result = talloc_asprintf_append(result, "CREATION|"); 00474 if (filter & FILE_NOTIFY_CHANGE_EA) 00475 result = talloc_asprintf_append(result, "EA|"); 00476 if (filter & FILE_NOTIFY_CHANGE_SECURITY) 00477 result = talloc_asprintf_append(result, "SECURITY|"); 00478 if (filter & FILE_NOTIFY_CHANGE_STREAM_NAME) 00479 result = talloc_asprintf_append(result, "STREAM_NAME|"); 00480 if (filter & FILE_NOTIFY_CHANGE_STREAM_SIZE) 00481 result = talloc_asprintf_append(result, "STREAM_SIZE|"); 00482 if (filter & FILE_NOTIFY_CHANGE_STREAM_WRITE) 00483 result = talloc_asprintf_append(result, "STREAM_WRITE|"); 00484 00485 if (result == NULL) return NULL; 00486 if (*result == '\0') return result; 00487 00488 result[strlen(result)-1] = '\0'; 00489 return result; 00490 }
struct sys_notify_context* sys_notify_context_create | ( | connection_struct * | conn, | |
TALLOC_CTX * | mem_ctx, | |||
struct event_context * | ev | |||
) |
参照先 sys_notify_context::conn・ctx・sys_notify_context::ev.
参照元 notify_init().
00495 { 00496 struct sys_notify_context *ctx; 00497 00498 if (!(ctx = TALLOC_P(mem_ctx, struct sys_notify_context))) { 00499 DEBUG(0, ("talloc failed\n")); 00500 return NULL; 00501 } 00502 00503 ctx->ev = ev; 00504 ctx->conn = conn; 00505 ctx->private_data = NULL; 00506 return ctx; 00507 }
NTSTATUS sys_notify_watch | ( | struct sys_notify_context * | ctx, | |
struct notify_entry * | e, | |||
void(*)(struct sys_notify_context *ctx, void *private_data, struct notify_event *ev) | callback, | |||
void * | private_data, | |||
void * | handle | |||
) |
参照元 notify_add().
00515 { 00516 return SMB_VFS_NOTIFY_WATCH(ctx->conn, ctx, e, callback, private_data, 00517 handle); 00518 }
struct notify_mid_map* notify_changes_by_mid [static] |