smbd/notify.c

ソースコードを見る。

データ構造

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_contextsys_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_mapnotify_changes_by_mid


関数

static void notify_fsp ( files_struct fsp,
uint32  action,
const char *  name 
) [static]

notify.c373 行で定義されています。

参照先 changechange_notify_remove_request()change_notify_reply()notify_change_buf::changesnotify_change_request::max_paramfiles_struct::notifynotify_change_buf::num_changesnotify_change_request::request_bufnotify_change_buf::requestsstring_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.c53 行で定義されています。

参照先 notify_change::actionnotify_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]

notify.c64 行で定義されています。

参照先 UNISTR::buffercCH_UNIXCH_UTF16LEconvert_string_allocate()notify_change_record_identical().

参照元 change_notify_reply().

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]

notify.c137 行で定義されています。

参照先 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 
)

notify.c159 行で定義されています。

参照先 change_notify_reply_packet()notify_change_buf::changesconstruct_reply_common()exit_server()max_sendnotify_marshall_changes()notify_change_buf::num_changesprs_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.c215 行で定義されています。

参照先 notify_event::actionnotify_change_request::fspfiles_struct::fsp_namenotify_fsp()notify_event::path.

参照元 change_notify_create().

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 
)

notify.c222 行で定義されています。

参照先 asprintf()files_struct::connconnection_struct::connectpathnotify_entry::filterfiles_struct::fsp_namefullpath()files_struct::notifynotify_add()notify_callback()connection_struct::notify_ctxnotify_entry::pathstatusnotify_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.c255 行で定義されています。

参照先 notify_change_request::backend_datanotify_change_request::filternotify_change_request::fspnotify_change_request::max_paramnotify_mid_map::midnotify_change_request::mid_mapfiles_struct::notifynotify_changes_by_midnotify_mid_map::reqnotify_change_request::request_bufnotify_change_buf::requestssrv_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.c289 行で定義されています。

参照先 notify_change_request::backend_datanotify_change_request::fspnotify_change_request::mid_mapnotify_change_request::nextfiles_struct::notifynotify_changes_by_midnotify_change_buf::requestssmb_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.c323 行で定義されています。

参照先 notify_mid_map::midnotify_mid_map::nextnotify_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 
)

notify.c345 行で定義されています。

参照先 change_notify_remove_request()change_notify_reply_packet()files_struct::notifynotify_change_request::request_bufnotify_change_buf::requestsstatus.

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 
)

notify.c359 行で定義されています。

参照先 asprintf()connection_struct::connectpathfullpath()connection_struct::notify_ctxnotify_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 
)

notify.c454 行で定義されています。

参照先 resulttalloc_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 
)

notify.c492 行で定義されています。

参照先 sys_notify_context::connctxsys_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.c509 行で定義されています。

参照元 notify_add().

00515 {
00516         return SMB_VFS_NOTIFY_WATCH(ctx->conn, ctx, e, callback, private_data,
00517                                     handle);
00518 }


変数

int max_send

process.c38 行で定義されています。

struct notify_mid_map* notify_changes_by_mid [static]

notify.c40 行で定義されています。

参照元 change_notify_add_request()change_notify_remove_request()remove_pending_change_notify_requests_by_mid().


Sambaに対してSat Aug 29 21:24:02 2009に生成されました。  doxygen 1.4.7