diff options
author | Volker Lendecke <vl@samba.org> | 2015-06-26 13:36:43 +0200 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2015-07-10 09:35:13 +0200 |
commit | 8a58a48f8692880df7f42980c9a981d4ed08e3b7 (patch) | |
tree | 1e1a7734237b34dd3a3b09d00ef72341e01be025 /source3 | |
parent | b1ea9856e03c21b52c13aee29971a5326c8cd652 (diff) | |
download | samba-8a58a48f8692880df7f42980c9a981d4ed08e3b7.tar.gz |
libsmb: Implement smbc_notify
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Fri Jul 10 09:35:13 CEST 2015 on sn-devel-104
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/libsmb_internal.h | 7 | ||||
-rw-r--r-- | source3/include/libsmbclient.h | 65 | ||||
-rw-r--r-- | source3/libsmb/ABI/smbclient-0.2.3.sigs | 179 | ||||
-rw-r--r-- | source3/libsmb/libsmb_compat.c | 11 | ||||
-rw-r--r-- | source3/libsmb/libsmb_context.c | 1 | ||||
-rw-r--r-- | source3/libsmb/libsmb_dir.c | 254 | ||||
-rw-r--r-- | source3/libsmb/libsmb_setget.c | 12 | ||||
-rw-r--r-- | source3/libsmb/wscript | 2 |
8 files changed, 530 insertions, 1 deletions
diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index cf51f34fcca..0e0045e8c0e 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -247,6 +247,7 @@ struct SMBC_internal_data { struct { smbc_splice_fn splice_fn; + smbc_notify_fn notify_fn; } smb; uint16_t port; @@ -344,6 +345,12 @@ SMBC_rename_ctx(SMBCCTX *ocontext, SMBCCTX *ncontext, const char *nname); +int +SMBC_notify_ctx(SMBCCTX *c, SMBCFILE *dir, smbc_bool recursive, + uint32_t completion_filter, unsigned callback_timeout_ms, + smbc_notify_callback_fn cb, void *private_data); + + /* Functions in libsmb_file.c */ SMBCFILE * diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index faaab2e3688..cf67b1d47a4 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -993,6 +993,30 @@ typedef int (*smbc_fstatdir_fn)(SMBCCTX *c, smbc_fstatdir_fn smbc_getFunctionFstatdir(SMBCCTX *c); void smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn); +#define SMBC_NOTIFY_ACTION_ADDED 1 +#define SMBC_NOTIFY_ACTION_REMOVED 2 +#define SMBC_NOTIFY_ACTION_MODIFIED 3 +#define SMBC_NOTIFY_ACTION_OLD_NAME 4 +#define SMBC_NOTIFY_ACTION_NEW_NAME 5 +#define SMBC_NOTIFY_ACTION_ADDED_STREAM 6 +#define SMBC_NOTIFY_ACTION_REMOVED_STREAM 7 +#define SMBC_NOTIFY_ACTION_MODIFIED_STREAM 8 + +struct smbc_notify_callback_action { + uint32_t action; + const char *filename; +}; + +typedef int (*smbc_notify_callback_fn)( + const struct smbc_notify_callback_action *actions, + size_t num_actions, void *private_data); + +typedef int (*smbc_notify_fn)(SMBCCTX *c, SMBCFILE *dir, smbc_bool recursive, + uint32_t completion_filter, + unsigned callback_timeout_ms, + smbc_notify_callback_fn cb, void *private_data); +smbc_notify_fn smbc_getFunctionNotify(SMBCCTX *c); +void smbc_setFunctionNotify(SMBCCTX *c, smbc_notify_fn fn); /***************************************************************** @@ -1620,6 +1644,47 @@ int smbc_mkdir(const char *durl, mode_t mode); */ int smbc_rmdir(const char *durl); +/**@ingroup directory + * Request directory notifications + * + * @param dh Valid directory as returned by smbc_opendir() + * + * @param recursive Are changes in subdirectories wanted? + * + * @param completion_filter Bitwise-or of the SMBC_NOTIFY_CHANGE_* + * events that are interesting + * + * @param callback_timeout_ms If set to non-zero, interval in milliseconds + * that "cb" will be called with 0 actions. + * This gives "cb" the chance to cancel the + * smbc_notify call. + * + * @param cb Callback functions taking events. If "cb" + * returns nonzero, smbc_notify will return. + * + * @param private_data Pointer given to "cb" + * + * @return 0 on success, -1 on error with errno set + * + * @see smbc_opendir(), smbc_closedir() + */ + +#define SMBC_NOTIFY_CHANGE_FILE_NAME 0x001 +#define SMBC_NOTIFY_CHANGE_DIR_NAME 0x002 +#define SMBC_NOTIFY_CHANGE_ATTRIBUTES 0x004 +#define SMBC_NOTIFY_CHANGE_SIZE 0x008 +#define SMBC_NOTIFY_CHANGE_LAST_WRITE 0x010 +#define SMBC_NOTIFY_CHANGE_LAST_ACCESS 0x020 +#define SMBC_NOTIFY_CHANGE_CREATION 0x040 +#define SMBC_NOTIFY_CHANGE_EA 0x080 +#define SMBC_NOTIFY_CHANGE_SECURITY 0x100 +#define SMBC_NOTIFY_CHANGE_STREAM_NAME 0x200 +#define SMBC_NOTIFY_CHANGE_STREAM_SIZE 0x400 +#define SMBC_NOTIFY_CHANGE_STREAM_WRITE 0x800 + +int smbc_notify(int dh, smbc_bool recursive, uint32_t completion_filter, + unsigned callback_timeout_ms, + smbc_notify_callback_fn cb, void *private_data); /**@ingroup attribute * Get information about a file or directory. diff --git a/source3/libsmb/ABI/smbclient-0.2.3.sigs b/source3/libsmb/ABI/smbclient-0.2.3.sigs new file mode 100644 index 00000000000..cda537cb097 --- /dev/null +++ b/source3/libsmb/ABI/smbclient-0.2.3.sigs @@ -0,0 +1,179 @@ +smbc_chmod: int (const char *, mode_t) +smbc_close: int (int) +smbc_closedir: int (int) +smbc_creat: int (const char *, mode_t) +smbc_fgetxattr: int (int, const char *, const void *, size_t) +smbc_flistxattr: int (int, char *, size_t) +smbc_free_context: int (SMBCCTX *, int) +smbc_fremovexattr: int (int, const char *) +smbc_fsetxattr: int (int, const char *, const void *, size_t, int) +smbc_fstat: int (int, struct stat *) +smbc_fstatvfs: int (int, struct statvfs *) +smbc_ftruncate: int (int, off_t) +smbc_getDebug: int (SMBCCTX *) +smbc_getFunctionAddCachedServer: smbc_add_cached_srv_fn (SMBCCTX *) +smbc_getFunctionAuthData: smbc_get_auth_data_fn (SMBCCTX *) +smbc_getFunctionAuthDataWithContext: smbc_get_auth_data_with_context_fn (SMBCCTX *) +smbc_getFunctionCheckServer: smbc_check_server_fn (SMBCCTX *) +smbc_getFunctionChmod: smbc_chmod_fn (SMBCCTX *) +smbc_getFunctionClose: smbc_close_fn (SMBCCTX *) +smbc_getFunctionClosedir: smbc_closedir_fn (SMBCCTX *) +smbc_getFunctionCreat: smbc_creat_fn (SMBCCTX *) +smbc_getFunctionFstat: smbc_fstat_fn (SMBCCTX *) +smbc_getFunctionFstatVFS: smbc_fstatvfs_fn (SMBCCTX *) +smbc_getFunctionFstatdir: smbc_fstatdir_fn (SMBCCTX *) +smbc_getFunctionFtruncate: smbc_ftruncate_fn (SMBCCTX *) +smbc_getFunctionGetCachedServer: smbc_get_cached_srv_fn (SMBCCTX *) +smbc_getFunctionGetdents: smbc_getdents_fn (SMBCCTX *) +smbc_getFunctionGetxattr: smbc_getxattr_fn (SMBCCTX *) +smbc_getFunctionListPrintJobs: smbc_list_print_jobs_fn (SMBCCTX *) +smbc_getFunctionListxattr: smbc_listxattr_fn (SMBCCTX *) +smbc_getFunctionLseek: smbc_lseek_fn (SMBCCTX *) +smbc_getFunctionLseekdir: smbc_lseekdir_fn (SMBCCTX *) +smbc_getFunctionMkdir: smbc_mkdir_fn (SMBCCTX *) +smbc_getFunctionNotify: smbc_notify_fn (SMBCCTX *) +smbc_getFunctionOpen: smbc_open_fn (SMBCCTX *) +smbc_getFunctionOpenPrintJob: smbc_open_print_job_fn (SMBCCTX *) +smbc_getFunctionOpendir: smbc_opendir_fn (SMBCCTX *) +smbc_getFunctionPrintFile: smbc_print_file_fn (SMBCCTX *) +smbc_getFunctionPurgeCachedServers: smbc_purge_cached_fn (SMBCCTX *) +smbc_getFunctionRead: smbc_read_fn (SMBCCTX *) +smbc_getFunctionReaddir: smbc_readdir_fn (SMBCCTX *) +smbc_getFunctionRemoveCachedServer: smbc_remove_cached_srv_fn (SMBCCTX *) +smbc_getFunctionRemoveUnusedServer: smbc_remove_unused_server_fn (SMBCCTX *) +smbc_getFunctionRemovexattr: smbc_removexattr_fn (SMBCCTX *) +smbc_getFunctionRename: smbc_rename_fn (SMBCCTX *) +smbc_getFunctionRmdir: smbc_rmdir_fn (SMBCCTX *) +smbc_getFunctionSetxattr: smbc_setxattr_fn (SMBCCTX *) +smbc_getFunctionSplice: smbc_splice_fn (SMBCCTX *) +smbc_getFunctionStat: smbc_stat_fn (SMBCCTX *) +smbc_getFunctionStatVFS: smbc_statvfs_fn (SMBCCTX *) +smbc_getFunctionTelldir: smbc_telldir_fn (SMBCCTX *) +smbc_getFunctionUnlink: smbc_unlink_fn (SMBCCTX *) +smbc_getFunctionUnlinkPrintJob: smbc_unlink_print_job_fn (SMBCCTX *) +smbc_getFunctionUtimes: smbc_utimes_fn (SMBCCTX *) +smbc_getFunctionWrite: smbc_write_fn (SMBCCTX *) +smbc_getNetbiosName: char *(SMBCCTX *) +smbc_getOptionBrowseMaxLmbCount: int (SMBCCTX *) +smbc_getOptionCaseSensitive: smbc_bool (SMBCCTX *) +smbc_getOptionDebugToStderr: smbc_bool (SMBCCTX *) +smbc_getOptionFallbackAfterKerberos: smbc_bool (SMBCCTX *) +smbc_getOptionFullTimeNames: smbc_bool (SMBCCTX *) +smbc_getOptionNoAutoAnonymousLogin: smbc_bool (SMBCCTX *) +smbc_getOptionOneSharePerServer: smbc_bool (SMBCCTX *) +smbc_getOptionOpenShareMode: smbc_share_mode (SMBCCTX *) +smbc_getOptionSmbEncryptionLevel: smbc_smb_encrypt_level (SMBCCTX *) +smbc_getOptionUrlEncodeReaddirEntries: smbc_bool (SMBCCTX *) +smbc_getOptionUseCCache: smbc_bool (SMBCCTX *) +smbc_getOptionUseKerberos: smbc_bool (SMBCCTX *) +smbc_getOptionUseNTHash: smbc_bool (SMBCCTX *) +smbc_getOptionUserData: void *(SMBCCTX *) +smbc_getPort: uint16_t (SMBCCTX *) +smbc_getServerCacheData: struct smbc_server_cache *(SMBCCTX *) +smbc_getTimeout: int (SMBCCTX *) +smbc_getUser: char *(SMBCCTX *) +smbc_getWorkgroup: char *(SMBCCTX *) +smbc_getdents: int (unsigned int, struct smbc_dirent *, int) +smbc_getxattr: int (const char *, const char *, const void *, size_t) +smbc_init: int (smbc_get_auth_data_fn, int) +smbc_init_context: SMBCCTX *(SMBCCTX *) +smbc_lgetxattr: int (const char *, const char *, const void *, size_t) +smbc_list_print_jobs: int (const char *, smbc_list_print_job_fn) +smbc_listxattr: int (const char *, char *, size_t) +smbc_llistxattr: int (const char *, char *, size_t) +smbc_lremovexattr: int (const char *, const char *) +smbc_lseek: off_t (int, off_t, int) +smbc_lseekdir: int (int, off_t) +smbc_lsetxattr: int (const char *, const char *, const void *, size_t, int) +smbc_mkdir: int (const char *, mode_t) +smbc_new_context: SMBCCTX *(void) +smbc_notify: int (int, smbc_bool, uint32_t, unsigned int, smbc_notify_callback_fn, void *) +smbc_open: int (const char *, int, mode_t) +smbc_open_print_job: int (const char *) +smbc_opendir: int (const char *) +smbc_option_get: void *(SMBCCTX *, char *) +smbc_option_set: void (SMBCCTX *, char *, ...) +smbc_print_file: int (const char *, const char *) +smbc_read: ssize_t (int, void *, size_t) +smbc_readdir: struct smbc_dirent *(unsigned int) +smbc_removexattr: int (const char *, const char *) +smbc_rename: int (const char *, const char *) +smbc_rmdir: int (const char *) +smbc_setDebug: void (SMBCCTX *, int) +smbc_setFunctionAddCachedServer: void (SMBCCTX *, smbc_add_cached_srv_fn) +smbc_setFunctionAuthData: void (SMBCCTX *, smbc_get_auth_data_fn) +smbc_setFunctionAuthDataWithContext: void (SMBCCTX *, smbc_get_auth_data_with_context_fn) +smbc_setFunctionCheckServer: void (SMBCCTX *, smbc_check_server_fn) +smbc_setFunctionChmod: void (SMBCCTX *, smbc_chmod_fn) +smbc_setFunctionClose: void (SMBCCTX *, smbc_close_fn) +smbc_setFunctionClosedir: void (SMBCCTX *, smbc_closedir_fn) +smbc_setFunctionCreat: void (SMBCCTX *, smbc_creat_fn) +smbc_setFunctionFstat: void (SMBCCTX *, smbc_fstat_fn) +smbc_setFunctionFstatVFS: void (SMBCCTX *, smbc_fstatvfs_fn) +smbc_setFunctionFstatdir: void (SMBCCTX *, smbc_fstatdir_fn) +smbc_setFunctionFtruncate: void (SMBCCTX *, smbc_ftruncate_fn) +smbc_setFunctionGetCachedServer: void (SMBCCTX *, smbc_get_cached_srv_fn) +smbc_setFunctionGetdents: void (SMBCCTX *, smbc_getdents_fn) +smbc_setFunctionGetxattr: void (SMBCCTX *, smbc_getxattr_fn) +smbc_setFunctionListPrintJobs: void (SMBCCTX *, smbc_list_print_jobs_fn) +smbc_setFunctionListxattr: void (SMBCCTX *, smbc_listxattr_fn) +smbc_setFunctionLseek: void (SMBCCTX *, smbc_lseek_fn) +smbc_setFunctionLseekdir: void (SMBCCTX *, smbc_lseekdir_fn) +smbc_setFunctionMkdir: void (SMBCCTX *, smbc_mkdir_fn) +smbc_setFunctionNotify: void (SMBCCTX *, smbc_notify_fn) +smbc_setFunctionOpen: void (SMBCCTX *, smbc_open_fn) +smbc_setFunctionOpenPrintJob: void (SMBCCTX *, smbc_open_print_job_fn) +smbc_setFunctionOpendir: void (SMBCCTX *, smbc_opendir_fn) +smbc_setFunctionPrintFile: void (SMBCCTX *, smbc_print_file_fn) +smbc_setFunctionPurgeCachedServers: void (SMBCCTX *, smbc_purge_cached_fn) +smbc_setFunctionRead: void (SMBCCTX *, smbc_read_fn) +smbc_setFunctionReaddir: void (SMBCCTX *, smbc_readdir_fn) +smbc_setFunctionRemoveCachedServer: void (SMBCCTX *, smbc_remove_cached_srv_fn) +smbc_setFunctionRemoveUnusedServer: void (SMBCCTX *, smbc_remove_unused_server_fn) +smbc_setFunctionRemovexattr: void (SMBCCTX *, smbc_removexattr_fn) +smbc_setFunctionRename: void (SMBCCTX *, smbc_rename_fn) +smbc_setFunctionRmdir: void (SMBCCTX *, smbc_rmdir_fn) +smbc_setFunctionSetxattr: void (SMBCCTX *, smbc_setxattr_fn) +smbc_setFunctionSplice: void (SMBCCTX *, smbc_splice_fn) +smbc_setFunctionStat: void (SMBCCTX *, smbc_stat_fn) +smbc_setFunctionStatVFS: void (SMBCCTX *, smbc_statvfs_fn) +smbc_setFunctionTelldir: void (SMBCCTX *, smbc_telldir_fn) +smbc_setFunctionUnlink: void (SMBCCTX *, smbc_unlink_fn) +smbc_setFunctionUnlinkPrintJob: void (SMBCCTX *, smbc_unlink_print_job_fn) +smbc_setFunctionUtimes: void (SMBCCTX *, smbc_utimes_fn) +smbc_setFunctionWrite: void (SMBCCTX *, smbc_write_fn) +smbc_setNetbiosName: void (SMBCCTX *, char *) +smbc_setOptionBrowseMaxLmbCount: void (SMBCCTX *, int) +smbc_setOptionCaseSensitive: void (SMBCCTX *, smbc_bool) +smbc_setOptionDebugToStderr: void (SMBCCTX *, smbc_bool) +smbc_setOptionFallbackAfterKerberos: void (SMBCCTX *, smbc_bool) +smbc_setOptionFullTimeNames: void (SMBCCTX *, smbc_bool) +smbc_setOptionNoAutoAnonymousLogin: void (SMBCCTX *, smbc_bool) +smbc_setOptionOneSharePerServer: void (SMBCCTX *, smbc_bool) +smbc_setOptionOpenShareMode: void (SMBCCTX *, smbc_share_mode) +smbc_setOptionSmbEncryptionLevel: void (SMBCCTX *, smbc_smb_encrypt_level) +smbc_setOptionUrlEncodeReaddirEntries: void (SMBCCTX *, smbc_bool) +smbc_setOptionUseCCache: void (SMBCCTX *, smbc_bool) +smbc_setOptionUseKerberos: void (SMBCCTX *, smbc_bool) +smbc_setOptionUseNTHash: void (SMBCCTX *, smbc_bool) +smbc_setOptionUserData: void (SMBCCTX *, void *) +smbc_setPort: void (SMBCCTX *, uint16_t) +smbc_setServerCacheData: void (SMBCCTX *, struct smbc_server_cache *) +smbc_setTimeout: void (SMBCCTX *, int) +smbc_setUser: void (SMBCCTX *, char *) +smbc_setWorkgroup: void (SMBCCTX *, char *) +smbc_set_context: SMBCCTX *(SMBCCTX *) +smbc_set_credentials: void (const char *, const char *, const char *, smbc_bool, const char *) +smbc_set_credentials_with_fallback: void (SMBCCTX *, const char *, const char *, const char *) +smbc_setxattr: int (const char *, const char *, const void *, size_t, int) +smbc_stat: int (const char *, struct stat *) +smbc_statvfs: int (char *, struct statvfs *) +smbc_telldir: off_t (int) +smbc_unlink: int (const char *) +smbc_unlink_print_job: int (const char *, int) +smbc_urldecode: int (char *, char *, size_t) +smbc_urlencode: int (char *, char *, int) +smbc_utime: int (const char *, struct utimbuf *) +smbc_utimes: int (const char *, struct timeval *) +smbc_version: const char *(void) +smbc_write: ssize_t (int, const void *, size_t) diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c index 38f7d36a897..5fed44abc4a 100644 --- a/source3/libsmb/libsmb_compat.c +++ b/source3/libsmb/libsmb_compat.c @@ -314,6 +314,17 @@ smbc_rmdir(const char *durl) } int +smbc_notify(int dh, smbc_bool recursive, uint32_t completion_filter, + unsigned callback_timeout_ms, + smbc_notify_callback_fn cb, void *private_data) +{ + SMBCFILE *dir = find_fd(dh); + return smbc_getFunctionNotify(statcont)( + statcont, dir, recursive, completion_filter, + callback_timeout_ms, cb, private_data); +} + +int smbc_stat(const char *url, struct stat *st) { diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index 9541fc1f816..5e31dfbafb1 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -214,6 +214,7 @@ smbc_new_context(void) smbc_setFunctionTelldir(context, SMBC_telldir_ctx); smbc_setFunctionLseekdir(context, SMBC_lseekdir_ctx); smbc_setFunctionFstatdir(context, SMBC_fstatdir_ctx); + smbc_setFunctionNotify(context, SMBC_notify_ctx); smbc_setFunctionChmod(context, SMBC_chmod_ctx); smbc_setFunctionUtimes(context, SMBC_utimes_ctx); smbc_setFunctionSetxattr(context, SMBC_setxattr_ctx); diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index d131c30c772..f332525983e 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -31,6 +31,8 @@ #include "../librpc/gen_ndr/ndr_srvsvc_c.h" #include "libsmb/nmblib.h" #include "../libcli/smb/smbXcli_base.h" +#include "../libcli/security/security.h" +#include "lib/util/tevent_ntstatus.h" /* * Routine to open a directory @@ -2047,3 +2049,255 @@ SMBC_rename_ctx(SMBCCTX *ocontext, return 0; /* Success */ } +struct smbc_notify_cb_state { + struct tevent_context *ev; + struct cli_state *cli; + uint16_t fnum; + bool recursive; + uint32_t completion_filter; + unsigned callback_timeout_ms; + smbc_notify_callback_fn cb; + void *private_data; +}; + +static void smbc_notify_cb_got_changes(struct tevent_req *subreq); +static void smbc_notify_cb_timedout(struct tevent_req *subreq); + +static struct tevent_req *smbc_notify_cb_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, + uint16_t fnum, bool recursive, uint32_t completion_filter, + unsigned callback_timeout_ms, + smbc_notify_callback_fn cb, void *private_data) +{ + struct tevent_req *req, *subreq; + struct smbc_notify_cb_state *state; + + req = tevent_req_create(mem_ctx, &state, struct smbc_notify_cb_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->cli = cli; + state->fnum = fnum; + state->recursive = recursive; + state->completion_filter = completion_filter; + state->callback_timeout_ms = callback_timeout_ms; + state->cb = cb; + state->private_data = private_data; + + subreq = cli_notify_send( + state, state->ev, state->cli, state->fnum, 1000, + state->completion_filter, state->recursive); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, smbc_notify_cb_got_changes, req); + + if (state->callback_timeout_ms == 0) { + return req; + } + + subreq = tevent_wakeup_send( + state, state->ev, + tevent_timeval_current_ofs(state->callback_timeout_ms/1000, + state->callback_timeout_ms*1000)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, smbc_notify_cb_timedout, req); + + return req; +} + +static void smbc_notify_cb_got_changes(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct smbc_notify_cb_state *state = tevent_req_data( + req, struct smbc_notify_cb_state); + uint32_t num_changes; + struct notify_change *changes; + NTSTATUS status; + int cb_ret; + + status = cli_notify_recv(subreq, state, &num_changes, &changes); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + { + struct smbc_notify_callback_action actions[num_changes]; + uint32_t i; + + for (i=0; i<num_changes; i++) { + actions[i].action = changes[i].action; + actions[i].filename = changes[i].name; + } + + cb_ret = state->cb(actions, num_changes, state->private_data); + } + + TALLOC_FREE(changes); + + if (cb_ret != 0) { + tevent_req_done(req); + return; + } + + subreq = cli_notify_send( + state, state->ev, state->cli, state->fnum, 1000, + state->completion_filter, state->recursive); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, smbc_notify_cb_got_changes, req); +} + +static void smbc_notify_cb_timedout(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct smbc_notify_cb_state *state = tevent_req_data( + req, struct smbc_notify_cb_state); + int cb_ret; + bool ok; + + ok = tevent_wakeup_recv(subreq); + TALLOC_FREE(subreq); + if (!ok) { + tevent_req_oom(req); + return; + } + + cb_ret = state->cb(NULL, 0, state->private_data); + if (cb_ret != 0) { + tevent_req_done(req); + return; + } + + subreq = tevent_wakeup_send( + state, state->ev, + tevent_timeval_current_ofs(state->callback_timeout_ms/1000, + state->callback_timeout_ms*1000)); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, smbc_notify_cb_timedout, req); +} + +static NTSTATUS smbc_notify_cb_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + +static NTSTATUS smbc_notify_cb(struct cli_state *cli, uint16_t fnum, + bool recursive, uint32_t completion_filter, + unsigned callback_timeout_ms, + smbc_notify_callback_fn cb, void *private_data) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = smbc_notify_cb_send(frame, ev, cli, fnum, recursive, + completion_filter, + callback_timeout_ms, cb, private_data); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = smbc_notify_cb_recv(req); + TALLOC_FREE(req); +fail: + TALLOC_FREE(frame); + return status; +} + +int +SMBC_notify_ctx(SMBCCTX *context, SMBCFILE *dir, smbc_bool recursive, + uint32_t completion_filter, unsigned callback_timeout_ms, + smbc_notify_callback_fn cb, void *private_data) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct cli_state *cli = dir->srv->cli; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *options = NULL; + char *workgroup = NULL; + char *path = NULL; + uint16_t port; + NTSTATUS status; + uint16_t fnum; + + if ((context == NULL) || !context->internal->initialized) { + TALLOC_FREE(frame); + errno = EINVAL; + return -1; + } + if ((dir == NULL) || + !SMBC_dlist_contains(context->internal->files, dir)) { + TALLOC_FREE(frame); + errno = EBADF; + return -1; + } + + if (SMBC_parse_path(frame, + context, + dir->fname, + &workgroup, + &server, + &port, + &share, + &path, + &user, + &password, + &options)) { + DEBUG(4, ("no valid path\n")); + TALLOC_FREE(frame); + errno = EINVAL + 8194; + return -1; + } + + DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' " + "path='%s' options='%s'\n", + dir->fname, server, share, path, options)); + + DEBUG(4, ("%s(%p, %d, %"PRIu32")\n", __func__, dir, + (int)recursive, completion_filter)); + + status = cli_ntcreate( + cli, path, 0, FILE_READ_DATA, 0, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + FILE_OPEN, 0, 0, &fnum, NULL); + if (!NT_STATUS_IS_OK(status)) { + int err = SMBC_errno(context, cli); + TALLOC_FREE(frame); + errno = err; + return -1; + } + + status = smbc_notify_cb(cli, fnum, recursive != 0, completion_filter, + callback_timeout_ms, cb, private_data); + if (!NT_STATUS_IS_OK(status)) { + int err = SMBC_errno(context, cli); + cli_close(cli, fnum); + TALLOC_FREE(frame); + errno = err; + return -1; + } + + cli_close(cli, fnum); + + TALLOC_FREE(frame); + return 0; +} diff --git a/source3/libsmb/libsmb_setget.c b/source3/libsmb/libsmb_setget.c index 0bdb7150f5d..80ac6739fe8 100644 --- a/source3/libsmb/libsmb_setget.c +++ b/source3/libsmb/libsmb_setget.c @@ -928,6 +928,18 @@ smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn) c->fstatdir = fn; } +smbc_notify_fn +smbc_getFunctionNotify(SMBCCTX *c) +{ + return c->internal->smb.notify_fn; +} + +void +smbc_setFunctionNotify(SMBCCTX *c, smbc_notify_fn fn) +{ + c->internal->smb.notify_fn = fn; +} + /** * Callable functions applicable to both files and directories. diff --git a/source3/libsmb/wscript b/source3/libsmb/wscript index 8770aa30da1..4f8b2171673 100644 --- a/source3/libsmb/wscript +++ b/source3/libsmb/wscript @@ -27,5 +27,5 @@ def build(bld): public_headers='../include/libsmbclient.h', abi_directory='ABI', abi_match='smbc_*', - vnum='0.2.2', + vnum='0.2.3', pc_files='smbclient.pc') |