From 81e20b1027627d348597227e839763defb8bc425 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Tue, 12 Sep 2017 17:14:14 +0200 Subject: [PATCH] libsmb: Add toggle for POSIX extensions https://bugzilla.samba.org/show_bug.cgi?id=5926 --- source3/include/libsmb_internal.h | 8 ++++ source3/include/libsmbclient.h | 6 +++ source3/libsmb/libsmb_context.c | 1 + source3/libsmb/libsmb_dir.c | 5 ++- source3/libsmb/libsmb_file.c | 2 +- source3/libsmb/libsmb_server.c | 95 +++++++++++++++++++++++++++++++++++++++ source3/libsmb/libsmb_setget.c | 14 ++++++ source3/libsmb/libsmb_stat.c | 4 ++ 8 files changed, 133 insertions(+), 2 deletions(-) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 0e0045e..aa84f6d 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -157,6 +157,14 @@ struct SMBC_internal_data { */ bool full_time_names; + /* + * Enable POSIX extensions before opening files/directories + * Will silently ignore if the server does not support the POSIX + * extensions + */ + + bool posix_extensions; + /* * The share mode of a file being opened. To match POSIX semantics * (and maintain backward compatibility), DENY_NONE is the default. diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index cf67b1d..5486dea 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -765,7 +765,13 @@ smbc_getOptionUseNTHash(SMBCCTX *c); void smbc_setOptionUseNTHash(SMBCCTX *c, smbc_bool b); +/** Get whether to enable POSIX extensions if available */ +smbc_bool +smbc_getOptionPosixExtensions(SMBCCTX *c); +/** Set whether to enable POSIX extensions if available */ +void +smbc_setOptionPosixExtensions(SMBCCTX *c, smbc_bool b); /************************************* * Getters and setters for FUNCTIONS * diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index ed6ca2b..14e9e89 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -177,6 +177,7 @@ smbc_new_context(void) smbc_setOptionBrowseMaxLmbCount(context, 3); /* # LMBs to query */ smbc_setOptionUrlEncodeReaddirEntries(context, False); smbc_setOptionOneSharePerServer(context, False); + smbc_setOptionPosixExtensions(context, True); if (getenv("LIBSMBCLIENT_NO_CCACHE") != NULL) { smbc_setOptionUseCCache(context, false); } diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 72441c4..1e8dfa7 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -785,6 +785,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } + d_printf("targetpath %s\n",targetpath); } else { @@ -816,7 +817,8 @@ SMBC_opendir_ctx(SMBCCTX *context, /* Now, list the files ... */ path_len = strlen(path); - path = talloc_asprintf_append(path, "\\*"); + if (!context->internal->posix_extensions) + path = talloc_asprintf_append(path, "\\*"); if (!path) { if (dir) { SAFE_FREE(dir->fname); @@ -826,6 +828,7 @@ SMBC_opendir_ctx(SMBCCTX *context, return NULL; } + d_printf("path %s\n",path); status = cli_resolve_path( frame, "", context->internal->auth_info, srv->cli, path, &targetcli, &targetpath); diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 6b43676..56dae8e 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -491,7 +491,7 @@ SMBC_getatr(SMBCCTX * context, trim_string(fixedpath, NULL, "\\.."); trim_string(fixedpath, NULL, "\\."); } - DEBUG(4,("SMBC_getatr: sending qpathinfo\n")); + DEBUG(4,("SMBC_getatr: sending qpathinfo for %s (%s)\n",fixedpath,path)); status = cli_resolve_path(frame, "", context->internal->auth_info, srv->cli, fixedpath, diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index b0e5926..34a966e 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -245,6 +245,98 @@ check_server_cache: return NULL; } +static smbc_bool +SMBC_enable_posix(SMBCCTX *smbctx, TALLOC_CTX *ctx, struct cli_state *cli) +{ + uint16 major, minor; + uint32 caplow, caphigh; + char *caps; + + if (!SERVER_HAS_UNIX_CIFS(cli)) { + d_printf("Server doesn't support UNIX CIFS extensions.\n"); + return 1; + } + + if (!cli_unix_extensions_version(cli, &major, &minor, &caplow, &caphigh)) { + d_printf("Can't get UNIX CIFS extensions version from server.\n"); + return 1; + } + + //d_printf("Server supports CIFS extensions %u.%u\n", (unsigned int)major, (unsigned int)minor); + + caps = talloc_strdup(ctx, ""); + if (!caps) { + return 1; + } + if (caplow & CIFS_UNIX_FCNTL_LOCKS_CAP) { + caps = talloc_asprintf_append(caps, "locks "); + if (!caps) { + return 1; + } + } + if (caplow & CIFS_UNIX_POSIX_ACLS_CAP) { + caps = talloc_asprintf_append(caps, "acls "); + if (!caps) { + return 1; + } + } + if (caplow & CIFS_UNIX_XATTTR_CAP) { + caps = talloc_asprintf_append(caps, "eas "); + if (!caps) { + return 1; + } + } + if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) { + caps = talloc_asprintf_append(caps, "pathnames "); + if (!caps) { + return 1; + } + } + if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) { + caps = talloc_asprintf_append(caps, "posix_path_operations "); + if (!caps) { + return 1; + } + } + if (caplow & CIFS_UNIX_LARGE_READ_CAP) { + caps = talloc_asprintf_append(caps, "large_read "); + if (!caps) { + return 1; + } + } + if (caplow & CIFS_UNIX_LARGE_WRITE_CAP) { + caps = talloc_asprintf_append(caps, "large_write "); + if (!caps) { + return 1; + } + } + if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) { + caps = talloc_asprintf_append(caps, "posix_encrypt "); + if (!caps) { + return 1; + } + } + if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) { + caps = talloc_asprintf_append(caps, "mandatory_posix_encrypt "); + if (!caps) { + return 1; + } + } + + if (*caps && caps[strlen(caps)-1] == ' ') { + caps[strlen(caps)-1] = '\0'; + } + + //d_printf("Server supports CIFS capabilities %s\n", caps); + + if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) { + d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli)); + return 1; + } + + return 0; +} + /* * Connect to a server, possibly on an existing connection * @@ -717,6 +809,9 @@ SMBC_server(TALLOC_CTX *ctx, DEBUG(2, ("Server connect ok: //%s/%s: %p\n", server, share, srv)); + if (context->internal->posix_extensions) + SMBC_enable_posix(context, ctx, srv->cli); + DLIST_ADD(context->internal->servers, srv); return srv; } diff --git a/source3/libsmb/libsmb_setget.c b/source3/libsmb/libsmb_setget.c index 80ac673..cfe549d 100644 --- a/source3/libsmb/libsmb_setget.c +++ b/source3/libsmb/libsmb_setget.c @@ -503,6 +503,20 @@ smbc_setOptionUseNTHash(SMBCCTX *c, smbc_bool b) } } +/** Get whether to enable POSIX extensions if available */ +smbc_bool +smbc_getOptionPosixExtensions(SMBCCTX *c) +{ + return c->internal->posix_extensions; +} + +/** Set whether to enable POSIX extensions if available */ +void +smbc_setOptionPosixExtensions(SMBCCTX *c, smbc_bool b) +{ + c->internal->posix_extensions = b; +} + /** Get the function for obtaining authentication data */ smbc_get_auth_data_fn smbc_getFunctionAuthData(SMBCCTX *c) diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index 4191ad6..8519989 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -151,9 +151,13 @@ SMBC_stat_ctx(SMBCCTX *context, NULL)) { errno = EINVAL; TALLOC_FREE(frame); + d_printf("path parse failure for '%s'!\n",fname); return -1; } + DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' " + "path='%s'\n", + fname, server, share, path)); if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { -- 2.14.1