From e76af514c3a99a6c65398a9d7a99012ff73583eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Aug 2009 12:50:16 -0700 Subject: Put SMB_INFO_STANDARD back into setfileinfo, but do it right this time :-). Jeremy. --- source3/smbd/trans2.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 184a858097..21c5062257 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6109,6 +6109,41 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, true); } +/**************************************************************************** + Deal with SMB_INFO_STANDARD. +****************************************************************************/ + +static NTSTATUS smb_set_info_standard(connection_struct *conn, + const char *pdata, + int total_data, + files_struct *fsp, + const struct smb_filename *smb_fname) +{ + struct smb_file_time ft; + + ZERO_STRUCT(ft); + + if (total_data < 12) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* create time */ + ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata)); + /* access time */ + ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4)); + /* write time */ + ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8)); + + DEBUG(10,("smb_set_info_standard: file %s\n", + smb_fname_str_dbg(smb_fname))); + + return smb_set_file_time(conn, + fsp, + smb_fname, + &ft, + true); +} + /**************************************************************************** Deal with SMB_SET_FILE_ALLOCATION_INFO. ****************************************************************************/ @@ -7086,6 +7121,16 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, switch (info_level) { + case SMB_INFO_STANDARD: + { + status = smb_set_info_standard(conn, + pdata, + total_data, + fsp, + smb_fname); + break; + } + case SMB_INFO_SET_EA: { status = smb_info_set_ea(conn, -- cgit From 890dfe003c91f8df737e5e2e4e440e1a9f416ae8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Aug 2009 15:47:05 -0700 Subject: Remove a const warning. Jeremy. --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0a3b0dff75..8c5393871f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4360,7 +4360,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_ on the directory. ****************************************************************************/ -bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, +bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf, uint16 num_def_acls, const char *pdata) { SMB_ACL_T def_acl = NULL; -- cgit From 457191e9f396898b8a511cf860f24986f36fd879 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Thu, 6 Aug 2009 15:53:33 -0700 Subject: s3: Fix a bug in renames of directories Recently code was added to match windows semantics of denying the rename of a directory if there are open files underneath it. This does partly match windows semantics, but it turns out the rename should be allowed if the open file handle is for the directory being renamed, or for a stream on the directory being renamed. This patch refines the check to better follow these rename semantics. --- source3/smbd/files.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index a170f774fe..146d809738 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -404,14 +404,15 @@ bool file_find_subpath(files_struct *dir_fsp) { files_struct *fsp; size_t dlen; - char *d_fullname; + char *d_fullname = NULL; + bool ret = false; d_fullname = talloc_asprintf(talloc_tos(), "%s/%s", dir_fsp->conn->connectpath, dir_fsp->fsp_name->base_name); if (!d_fullname) { - return false; + goto out; } dlen = strlen(d_fullname); @@ -429,15 +430,27 @@ bool file_find_subpath(files_struct *dir_fsp) fsp->fsp_name->base_name); if (strnequal(d_fullname, d1_fullname, dlen)) { - TALLOC_FREE(d_fullname); + int d1_len = strlen(d1_fullname); + + /* + * If the open file is a second file handle to the + * same name or is a stream on the original file, then + * don't return true. + */ + if (d1_len == dlen) { + TALLOC_FREE(d1_fullname); + continue; + } + TALLOC_FREE(d1_fullname); - return true; + ret = true; + goto out; } TALLOC_FREE(d1_fullname); } - + out: TALLOC_FREE(d_fullname); - return false; + return ret; } /**************************************************************************** -- cgit From 8e419aab48ace1fe0d075e2a25935e650805a23c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Aug 2009 21:16:38 +0200 Subject: s3:smbd: don't ignore check_descend in get_dir_entry() metze --- source3/smbd/dir.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 642fb09362..7acd349b72 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -875,6 +875,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, if ((strcmp(mask,"*.*") == 0) || mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { + bool isdots = (ISDOT(dname) || ISDOTDOT(dname)); char mname[13]; struct smb_filename *smb_fname = NULL; NTSTATUS status; @@ -891,6 +892,11 @@ bool get_dir_entry(TALLOC_CTX *ctx, } } + if (check_descend && !isdots) { + TALLOC_FREE(filename); + continue; + } + if (needslash) { pathreal = talloc_asprintf(ctx, "%s/%s", -- cgit From c54e6b19e395724eb84f6e7157073e8772bc8594 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Aug 2009 13:22:33 +0200 Subject: s3:smbd: add a smbd_server_connection pointer to connection_struct This can be NULL for faked connection structs used in the rpc server or printing code. metze --- source3/smbd/conn.c | 23 +++++++++++++++-------- source3/smbd/ipc.c | 3 +-- source3/smbd/reply.c | 5 ++--- source3/smbd/service.c | 33 ++++++++++++++++----------------- source3/smbd/smb2_tcon.c | 2 +- 5 files changed, 35 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index af6e0919a4..9d1bbee8c9 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -101,6 +101,7 @@ connection_struct *conn_new(struct smbd_server_connection *sconn) TALLOC_FREE(conn); return NULL; } + conn->sconn = sconn; return conn; } @@ -154,6 +155,7 @@ find_again: TALLOC_FREE(conn); return NULL; } + conn->sconn = sconn; conn->cnum = i; conn->force_group_gid = (gid_t)-1; @@ -181,7 +183,7 @@ bool conn_close_all(struct smbd_server_connection *sconn) for (conn=sconn->smb1.tcons.Connections;conn;conn=next) { next=conn->next; set_current_service(conn, 0, True); - close_cnum(sconn, conn, conn->vuid); + close_cnum(conn, conn->vuid); ret = true; } return ret; @@ -294,19 +296,24 @@ void conn_free_internal(connection_struct *conn) Free a conn structure. ****************************************************************************/ -void conn_free(struct smbd_server_connection *sconn, connection_struct *conn) +void conn_free(connection_struct *conn) { - if (sconn->allow_smb2) { + if (conn->sconn == NULL) { + conn_free_internal(conn); + return; + } + + if (conn->sconn->allow_smb2) { conn_free_internal(conn); return; } - DLIST_REMOVE(sconn->smb1.tcons.Connections, conn); + DLIST_REMOVE(conn->sconn->smb1.tcons.Connections, conn); - bitmap_clear(sconn->smb1.tcons.bmap, conn->cnum); + bitmap_clear(conn->sconn->smb1.tcons.bmap, conn->cnum); - SMB_ASSERT(sconn->smb1.tcons.num_open > 0); - sconn->smb1.tcons.num_open--; + SMB_ASSERT(conn->sconn->smb1.tcons.num_open > 0); + conn->sconn->smb1.tcons.num_open--; conn_free_internal(conn); } @@ -340,7 +347,7 @@ void msg_force_tdis(struct messaging_context *msg, if (strequal(lp_servicename(SNUM(conn)), sharename)) { DEBUG(1,("Forcing close of share %s cnum=%d\n", sharename, conn->cnum)); - close_cnum(sconn, conn, (uint16)-1); + close_cnum(conn, (uint16)-1); } } } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 96a411dd70..12d4922844 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -534,7 +534,6 @@ static void named_pipe(connection_struct *conn, uint16 vuid, static void handle_trans(connection_struct *conn, struct smb_request *req, struct trans_state *state) { - struct smbd_server_connection *sconn = smbd_server_conn; char *local_machine_name; int name_offset = 0; @@ -585,7 +584,7 @@ static void handle_trans(connection_struct *conn, struct smb_request *req, state->max_param_return); if (state->close_on_completion) { - close_cnum(sconn, conn,state->vuid); + close_cnum(conn,state->vuid); req->conn = NULL; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 77e122a90c..750915b1cb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -703,7 +703,7 @@ void reply_tcon_and_X(struct smb_request *req) /* we might have to close an old one */ if ((tcon_flags & 0x1) && conn) { - close_cnum(sconn, conn,req->vuid); + close_cnum(conn,req->vuid); req->conn = NULL; conn = NULL; } @@ -4868,7 +4868,6 @@ void reply_unlock(struct smb_request *req) void reply_tdis(struct smb_request *req) { - struct smbd_server_connection *sconn = smbd_server_conn; connection_struct *conn = req->conn; START_PROFILE(SMBtdis); @@ -4881,7 +4880,7 @@ void reply_tdis(struct smb_request *req) conn->used = False; - close_cnum(sconn, conn,req->vuid); + close_cnum(conn,req->vuid); req->conn = NULL; reply_outbuf(req, 0, 0); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a043288bc9..c24b2264c1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -673,7 +673,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, DEBUG(1, ("create_connection_server_info failed: %s\n", nt_errstr(status))); *pstatus = status; - conn_free(sconn, conn); + conn_free(conn); return NULL; } @@ -730,7 +730,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, fuser = talloc_string_sub(conn, lp_force_user(snum), "%S", lp_servicename(snum)); if (fuser == NULL) { - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } @@ -739,7 +739,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, conn, fuser, conn->server_info->guest, &forced_serverinfo); if (!NT_STATUS_IS_OK(status)) { - conn_free(sconn, conn); + conn_free(conn); *pstatus = status; return NULL; } @@ -764,7 +764,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, &conn->server_info->utok.gid); if (!NT_STATUS_IS_OK(status)) { - conn_free(sconn, conn); + conn_free(conn); *pstatus = status; return NULL; } @@ -790,14 +790,14 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, pdb_get_domain(conn->server_info->sam_account), lp_pathname(snum)); if (!s) { - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } if (!set_conn_connectpath(conn,s)) { TALLOC_FREE(s); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } @@ -829,7 +829,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, "denied due to security " "descriptor.\n", lp_servicename(snum))); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } else { @@ -842,7 +842,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, if (!smbd_vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -860,7 +860,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, "for service %s, path %s\n", lp_servicename(snum), conn->connectpath)); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -884,7 +884,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, DEBUG(1, ("Max connections (%d) exceeded for %s\n", lp_max_connections(snum), lp_servicename(snum))); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } @@ -894,7 +894,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, */ if (!claim_connection(conn, lp_servicename(snum), 0)) { DEBUG(1, ("Could not store connections entry\n")); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_INTERNAL_DB_ERROR; return NULL; } @@ -918,7 +918,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, DEBUG(1,("root preexec gave %d - failing " "connection\n", ret)); yield_connection(conn, lp_servicename(snum)); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } @@ -929,7 +929,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, /* No point continuing if they fail the basic checks */ DEBUG(0,("Can't become connected user!\n")); yield_connection(conn, lp_servicename(snum)); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_LOGON_FAILURE; return NULL; } @@ -1072,7 +1072,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, SMB_VFS_DISCONNECT(conn); } yield_connection(conn, lp_servicename(snum)); - conn_free(sconn, conn); + conn_free(conn); return NULL; } @@ -1219,8 +1219,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn, Close a cnum. ****************************************************************************/ -void close_cnum(struct smbd_server_connection *sconn, - connection_struct *conn, uint16 vuid) +void close_cnum(connection_struct *conn, uint16 vuid) { file_close_conn(conn); @@ -1274,5 +1273,5 @@ void close_cnum(struct smbd_server_connection *sconn, TALLOC_FREE(cmd); } - conn_free(sconn, conn); + conn_free(conn); } diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c index 8c4b1f1b6f..090f9b7908 100644 --- a/source3/smbd/smb2_tcon.c +++ b/source3/smbd/smb2_tcon.c @@ -127,7 +127,7 @@ static int smbd_smb2_tcon_destructor(struct smbd_smb2_tcon *tcon) idr_remove(tcon->session->tcons.idtree, tcon->tid); DLIST_REMOVE(tcon->session->tcons.list, tcon); - conn_free(tcon->session->conn, tcon->compat_conn); + conn_free(tcon->compat_conn); tcon->compat_conn = NULL; tcon->tid = 0; -- cgit From 70afd419a602ff4067bf3c25cf25a5d4084b4164 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 7 Aug 2009 11:48:03 +0200 Subject: s3:smbd: conn_free_internal() can be static now metze --- source3/smbd/conn.c | 4 ++-- source3/smbd/msdfs.c | 22 +++++++++++----------- source3/smbd/posix_acls.c | 8 ++++---- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 9d1bbee8c9..da67db978b 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -257,9 +257,9 @@ void conn_clear_vuid_caches(struct smbd_server_connection *sconn,uint16_t vuid) Free a conn structure - internal part. ****************************************************************************/ -void conn_free_internal(connection_struct *conn) +static void conn_free_internal(connection_struct *conn) { - vfs_handle_struct *handle = NULL, *thandle = NULL; + vfs_handle_struct *handle = NULL, *thandle = NULL; struct trans_state *state = NULL; /* Free vfs_connection_struct */ diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 22fb8c3ad6..767c8fe297 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -268,7 +268,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, if (!smbd_vfs_init(conn)) { NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); - conn_free_internal(conn); + conn_free(conn); return status; } @@ -284,7 +284,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, if (oldcwd == NULL) { NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno))); - conn_free_internal(conn); + conn_free(conn); return status; } @@ -293,7 +293,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. " "Error was %s\n", conn->connectpath, strerror(errno) )); - conn_free_internal(conn); + conn_free(conn); return status; } @@ -939,7 +939,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); vfs_ChDir(conn, oldpath); - conn_free_internal(conn); + conn_free(conn); TALLOC_FREE(pdp); return status; } @@ -951,13 +951,13 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); vfs_ChDir(conn, oldpath); - conn_free_internal(conn); + conn_free(conn); TALLOC_FREE(pdp); return NT_STATUS_NOT_FOUND; } vfs_ChDir(conn, oldpath); - conn_free_internal(conn); + conn_free(conn); TALLOC_FREE(pdp); return NT_STATUS_OK; } @@ -1374,7 +1374,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, jucn->volume_name); if (!*pp_path_out) { vfs_ChDir(*conn_out, *oldpath); - conn_free_internal(*conn_out); + conn_free(*conn_out); return False; } return True; @@ -1462,7 +1462,7 @@ bool create_msdfs_link(const struct junction_map *jucn) out: vfs_ChDir(conn, cwd); - conn_free_internal(conn); + conn_free(conn); return ret; } @@ -1493,7 +1493,7 @@ bool remove_msdfs_link(const struct junction_map *jucn) TALLOC_FREE(smb_fname); vfs_ChDir(conn, cwd); - conn_free_internal(conn); + conn_free(conn); return ret; } @@ -1554,7 +1554,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) out: vfs_ChDir(conn, cwd); - conn_free_internal(conn); + conn_free(conn); return cnt; } @@ -1680,7 +1680,7 @@ out: } vfs_ChDir(conn, cwd); - conn_free_internal(conn); + conn_free(conn); return cnt; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 8c5393871f..b61421dc8f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4616,7 +4616,7 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) if (!smbd_vfs_init(conn)) { DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n")); - conn_free_internal( conn ); + conn_free(conn); return NULL; } @@ -4631,21 +4631,21 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL, &finfo.fsp_name); if (!NT_STATUS_IS_OK(status)) { - conn_free_internal( conn ); + conn_free(conn); return NULL; } if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, DACL_SECURITY_INFORMATION, &psd))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); TALLOC_FREE(finfo.fsp_name); - conn_free_internal( conn ); + conn_free(conn); return NULL; } ret_sd = dup_sec_desc( ctx, psd ); TALLOC_FREE(finfo.fsp_name); - conn_free_internal( conn ); + conn_free(conn); return ret_sd; } -- cgit From daa71c42369ca3586f6b5cf5c7c72cddcbcdf1ad Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Aug 2009 20:53:13 +0200 Subject: s3:smbd: add generic smbd_dirptr_get_entry() metze --- source3/smbd/dir.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/globals.h | 21 ++++++++ 2 files changed, 163 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7acd349b72..4c802ab893 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -825,6 +825,148 @@ static bool mangle_mask_match(connection_struct *conn, return mask_match_search(mname,mask,False); } +bool smbd_dirptr_get_entry(TALLOC_CTX *ctx, + struct dptr_struct *dirptr, + const char *mask, + uint32_t dirtype, + bool dont_descend, + bool ask_sharemode, + bool (*match_fn)(TALLOC_CTX *ctx, + void *private_data, + const char *dname, + const char *mask, + char **_fname), + bool (*mode_fn)(TALLOC_CTX *ctx, + void *private_data, + struct smb_filename *smb_fname, + uint32_t *_mode), + void *private_data, + char **_fname, + struct smb_filename **_smb_fname, + uint32_t *_mode, + long *_prev_offset) +{ + connection_struct *conn = dirptr->conn; + bool needslash; + + *_smb_fname = NULL; + *_mode = 0; + + needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/'); + + while (true) { + long cur_offset; + long prev_offset; + SMB_STRUCT_STAT sbuf; + char *dname = NULL; + bool isdots; + char *fname = NULL; + char *pathreal = NULL; + struct smb_filename *smb_fname = NULL; + uint32_t mode = 0; + bool ok; + NTSTATUS status; + + cur_offset = dptr_TellDir(dirptr); + prev_offset = cur_offset; + dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf); + + DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n", + (long)dirptr, cur_offset)); + + if (dname == NULL) { + return false; + } + + isdots = (ISDOT(dname) || ISDOTDOT(dname)); + if (dont_descend && !isdots) { + TALLOC_FREE(dname); + continue; + } + + /* + * fname may get mangled, dname is never mangled. + * Whenever we're accessing the filesystem we use + * pathreal which is composed from dname. + */ + + ok = match_fn(ctx, private_data, dname, mask, &fname); + if (!ok) { + TALLOC_FREE(dname); + continue; + } + + pathreal = talloc_asprintf(ctx, "%s%s%s", + dirptr->path, + needslash?"/":"", + dname); + if (!pathreal) { + TALLOC_FREE(dname); + TALLOC_FREE(fname); + return false; + } + + /* Create smb_fname with NULL stream_name. */ + status = create_synthetic_smb_fname(ctx, pathreal, + NULL, &sbuf, + &smb_fname); + TALLOC_FREE(pathreal); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(dname); + TALLOC_FREE(fname); + return false; + } + + ok = mode_fn(ctx, private_data, smb_fname, &mode); + if (!ok) { + TALLOC_FREE(dname); + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + continue; + } + + if (!dir_check_ftype(conn, mode, dirtype)) { + DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n", + fname, (unsigned int)mode, (unsigned int)dirtype)); + TALLOC_FREE(dname); + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + continue; + } + + if (ask_sharemode) { + struct timespec write_time_ts; + struct file_id fileid; + + fileid = vfs_file_id_from_sbuf(conn, + &smb_fname->st); + get_file_infos(fileid, NULL, &write_time_ts); + if (!null_timespec(write_time_ts)) { + update_stat_ex_mtime(&smb_fname->st, + write_time_ts); + } + } + + DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s " + "fname=%s (%s)\n", + mask, smb_fname_str_dbg(smb_fname), + dname, fname)); + + DirCacheAdd(dirptr->dir_hnd, dname, cur_offset); + + TALLOC_FREE(dname); + + *_fname = fname; + *_smb_fname = smb_fname; + *_mode = mode; + *_prev_offset = prev_offset; + + return true; + } + + return false; +} + /**************************************************************************** Get an 8.3 directory entry. ****************************************************************************/ diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 434204b60d..6a62cf6a21 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -218,6 +218,27 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, char **ppdata, int *ret_data_len); +bool smbd_dirptr_get_entry(TALLOC_CTX *ctx, + struct dptr_struct *dirptr, + const char *mask, + uint32_t dirtype, + bool dont_descend, + bool ask_sharemode, + bool (*match_fn)(TALLOC_CTX *ctx, + void *private_data, + const char *dname, + const char *mask, + char **_fname), + bool (*mode_fn)(TALLOC_CTX *ctx, + void *private_data, + struct smb_filename *smb_fname, + uint32_t *_mode), + void *private_data, + char **_fname, + struct smb_filename **_smb_fname, + uint32_t *_mode, + long *_prev_offset); + void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn, const char *reason, const char *location); -- cgit From 862c6aa19fbfe45f8daaf738d7edbb319a674ff2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 7 Aug 2009 08:54:06 +0200 Subject: s3:smbd: let get_dir_entry() use smbd_dirptr_get_entry() metze --- source3/smbd/dir.c | 228 +++++++++++++++++++++-------------------------------- 1 file changed, 89 insertions(+), 139 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 4c802ab893..e2f8e69449 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -971,158 +971,108 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx, Get an 8.3 directory entry. ****************************************************************************/ -bool get_dir_entry(TALLOC_CTX *ctx, - connection_struct *conn, - const char *mask, - uint32 dirtype, - char **pp_fname_out, - SMB_OFF_T *size, - uint32 *mode, - struct timespec *date, - bool check_descend, - bool ask_sharemode) +static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx, + void *private_data, + const char *dname, + const char *mask, + char **_fname) { - char *dname = NULL; - bool found = False; - SMB_STRUCT_STAT sbuf; - char *pathreal = NULL; - char *filename = NULL; - bool needslash; - - *pp_fname_out = NULL; - - needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - - if (!conn->dirptr) { - return(False); - } - - while (!found) { - long curoff = dptr_TellDir(conn->dirptr); - dname = dptr_ReadDirName(ctx, conn->dirptr, &curoff, &sbuf); - - DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n", - (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd))); - - if (dname == NULL) { - return(False); - } - - filename = dname; - - /* notice the special *.* handling. This appears to be the only difference - between the wildcard handling in this routine and in the trans2 routines. - see masktest for a demo - */ - if ((strcmp(mask,"*.*") == 0) || - mask_match_search(filename,mask,False) || - mangle_mask_match(conn,filename,mask)) { - bool isdots = (ISDOT(dname) || ISDOTDOT(dname)); - char mname[13]; - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - if (!mangle_is_8_3(filename, False, conn->params)) { - if (!name_to_8_3(filename,mname,False, - conn->params)) { - TALLOC_FREE(filename); - continue; - } - filename = talloc_strdup(ctx, mname); - if (!filename) { - return False; - } - } - - if (check_descend && !isdots) { - TALLOC_FREE(filename); - continue; - } - - if (needslash) { - pathreal = talloc_asprintf(ctx, - "%s/%s", - conn->dirpath, - dname); - } else { - pathreal = talloc_asprintf(ctx, - "%s%s", - conn->dirpath, - dname); - } - if (!pathreal) { - TALLOC_FREE(filename); - return False; - } - - /* Create smb_fname with NULL stream_name. */ - status = create_synthetic_smb_fname(ctx, pathreal, - NULL, &sbuf, - &smb_fname); - - TALLOC_FREE(pathreal); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(filename); + connection_struct *conn = (connection_struct *)private_data; + + if ((strcmp(mask,"*.*") == 0) || + mask_match_search(dname, mask, false) || + mangle_mask_match(conn, dname, mask)) { + char mname[13]; + const char *fname; + + if (!mangle_is_8_3(dname, false, conn->params)) { + bool ok = name_to_8_3(dname, mname, false, + conn->params); + if (!ok) { return false; } + fname = mname; + } else { + fname = dname; + } - if (!VALID_STAT(smb_fname->st)) { - if ((SMB_VFS_STAT(conn, smb_fname)) != 0) { - DEBUG(5,("Couldn't stat 1 [%s]. Error " - "= %s\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - TALLOC_FREE(smb_fname); - TALLOC_FREE(filename); - continue; - } - } - - *mode = dos_mode(conn, smb_fname); - - if (!dir_check_ftype(conn,*mode,dirtype)) { - DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype)); - TALLOC_FREE(smb_fname); - TALLOC_FREE(filename); - continue; - } - - *size = smb_fname->st.st_ex_size; - *date = smb_fname->st.st_ex_mtime; + *_fname = talloc_strdup(ctx, fname); + if (*_fname == NULL) { + return false; + } - if (ask_sharemode) { - struct timespec write_time_ts; - struct file_id fileid; + return true; + } - fileid = vfs_file_id_from_sbuf(conn, - &smb_fname->st); - get_file_infos(fileid, NULL, &write_time_ts); - if (!null_timespec(write_time_ts)) { - *date = write_time_ts; - } - } + return false; +} - DEBUG(3,("get_dir_entry mask=[%s] found %s " - "fname=%s (%s)\n", - mask, - smb_fname_str_dbg(smb_fname), - dname, - filename)); +static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx, + void *private_data, + struct smb_filename *smb_fname, + uint32_t *_mode) +{ + connection_struct *conn = (connection_struct *)private_data; + + if (!VALID_STAT(smb_fname->st)) { + if ((SMB_VFS_STAT(conn, smb_fname)) != 0) { + DEBUG(5,("smbd_dirptr_8_3_mode_fn: " + "Couldn't stat [%s]. Error " + "= %s\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + return false; + } + } - found = True; + *_mode = dos_mode(conn, smb_fname); + return true; +} - SMB_ASSERT(filename != NULL); - *pp_fname_out = filename; +bool get_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + const char *mask, + uint32_t dirtype, + char **_fname, + SMB_OFF_T *_size, + uint32_t *_mode, + struct timespec *_date, + bool check_descend, + bool ask_sharemode) +{ + char *fname = NULL; + struct smb_filename *smb_fname = NULL; + uint32_t mode = 0; + long prev_offset; + bool ok; - DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff); - TALLOC_FREE(smb_fname); - } + if (!conn->dirptr) { + return false; + } - if (!found) - TALLOC_FREE(filename); + ok = smbd_dirptr_get_entry(ctx, + conn->dirptr, + mask, + dirtype, + check_descend, + ask_sharemode, + smbd_dirptr_8_3_match_fn, + smbd_dirptr_8_3_mode_fn, + conn, + &fname, + &smb_fname, + &mode, + &prev_offset); + if (!ok) { + return false; } - return(found); + *_fname = talloc_move(ctx, &fname); + *_size = smb_fname->st.st_ex_size; + *_mode = mode; + *_date = smb_fname->st.st_ex_mtime; + TALLOC_FREE(smb_fname); + return true; } /******************************************************************* -- cgit From dfae090c5d0c238f2c620d77edc6bb6cf1bb027b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 7 Aug 2009 08:55:35 +0200 Subject: s3:smbd: implement get_lanman2_dir_entry() on top of smbd_dirptr_get_entry() metze --- source3/smbd/trans2.c | 444 ++++++++++++++++++++++++-------------------------- 1 file changed, 215 insertions(+), 229 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 21c5062257..e48ffac150 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1165,19 +1165,24 @@ static void call_trans2open(connection_struct *conn, Case can be significant or not. **********************************************************/ -static bool exact_match(connection_struct *conn, - const char *str, - const char *mask) +static bool exact_match(bool has_wild, + bool case_sensitive, + const char *str, + const char *mask) { - if (mask[0] == '.' && mask[1] == 0) - return False; - if (dptr_has_wild(conn->dirptr)) { - return False; + if (mask[0] == '.' && mask[1] == 0) { + return false; } - if (conn->case_sensitive) + + if (has_wild) { + return false; + } + + if (case_sensitive) { return strcmp(str,mask)==0; - else + } else { return StrCaseCmp(str,mask) == 0; + } } /**************************************************************************** @@ -1317,6 +1322,130 @@ static bool check_msdfs_link(connection_struct *conn, Get a level dependent lanman2 dir entry. ****************************************************************************/ +struct smbd_dirptr_lanman2_state { + connection_struct *conn; + uint32_t info_level; + bool check_mangled_names; + bool has_wild; + bool got_exact_match; +}; + +static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx, + void *private_data, + const char *dname, + const char *mask, + char **_fname) +{ + struct smbd_dirptr_lanman2_state *state = + (struct smbd_dirptr_lanman2_state *)private_data; + bool ok; + char mangled_name[13]; /* mangled 8.3 name. */ + bool got_match; + const char *fname; + + /* Mangle fname if it's an illegal name. */ + if (mangle_must_mangle(dname, state->conn->params)) { + ok = name_to_8_3(dname, mangled_name, + true, state->conn->params); + if (!ok) { + return false; + } + fname = mangled_name; + } else { + fname = dname; + } + + got_match = exact_match(state->has_wild, + state->conn->case_sensitive, + fname, mask); + state->got_exact_match = got_match; + if (!got_match) { + got_match = mask_match(fname, mask, + state->conn->case_sensitive); + } + + if(!got_match && state->check_mangled_names && + !mangle_is_8_3(fname, false, state->conn->params)) { + /* + * It turns out that NT matches wildcards against + * both long *and* short names. This may explain some + * of the wildcard wierdness from old DOS clients + * that some people have been seeing.... JRA. + */ + /* Force the mangling into 8.3. */ + ok = name_to_8_3(fname, mangled_name, + false, state->conn->params); + if (!ok) { + return false; + } + + got_match = exact_match(state->has_wild, + state->conn->case_sensitive, + mangled_name, mask); + state->got_exact_match = got_match; + if (!got_match) { + got_match = mask_match(mangled_name, mask, + state->conn->case_sensitive); + } + } + + if (!got_match) { + return false; + } + + *_fname = talloc_strdup(ctx, fname); + if (*_fname == NULL) { + return false; + } + + return true; +} + +static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx, + void *private_data, + struct smb_filename *smb_fname, + uint32_t *_mode) +{ + struct smbd_dirptr_lanman2_state *state = + (struct smbd_dirptr_lanman2_state *)private_data; + bool ms_dfs_link = false; + uint32_t mode = 0; + + if (INFO_LEVEL_IS_UNIX(state->info_level)) { + if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) { + DEBUG(5,("smbd_dirptr_lanman2_mode_fn: " + "Couldn't lstat [%s] (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + return false; + } + } else if (!VALID_STAT(smb_fname->st) && + SMB_VFS_STAT(state->conn, smb_fname) != 0) { + /* Needed to show the msdfs symlinks as + * directories */ + + ms_dfs_link = check_msdfs_link(state->conn, + smb_fname->base_name, + &smb_fname->st); + if (!ms_dfs_link) { + DEBUG(5,("smbd_dirptr_lanman2_mode_fn: " + "Couldn't stat [%s] (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + return false; + } + } + + if (ms_dfs_link) { + mode = dos_mode_msdfs(state->conn, smb_fname); + } else { + mode = dos_mode(state->conn, smb_fname); + } + + *_mode = mode; + return true; +} + static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, connection_struct *conn, uint16 flags2, @@ -1335,12 +1464,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, int *last_entry_off, struct ea_list *name_list) { - char *dname; - bool found = False; - SMB_STRUCT_STAT sbuf; const char *mask = NULL; - char *pathreal = NULL; - char *fname = NULL; char *p, *q, *pdata = *ppdata; uint32 reskey=0; long prev_dirpos=0; @@ -1354,9 +1478,17 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, char *last_entry_ptr; bool was_8_3; uint32 nt_extmode; /* Used for NT connections instead of mode */ - bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - bool check_mangled_names = lp_manglednames(conn->params); - char mangled_name[13]; /* mangled 8.3 name. */ + char *fname = NULL; + struct smb_filename *smb_fname = NULL; + struct smbd_dirptr_lanman2_state state; + bool ok; + + ZERO_STRUCT(state); + state.conn = conn; + state.info_level = info_level; + state.check_mangled_names = lp_manglednames(conn->params); + state.has_wild = dptr_has_wild(conn->dirptr); + state.got_exact_match = false; *out_of_space = False; *got_exact_match = False; @@ -1366,13 +1498,13 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, ZERO_STRUCT(create_date_ts); if (!conn->dirptr) { - return(False); + return false; } p = strrchr_m(path_mask,'/'); if(p != NULL) { if(p[1] == '\0') { - mask = talloc_strdup(ctx,"*.*"); + mask = "*.*"; } else { mask = p+1; } @@ -1380,206 +1512,44 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, mask = path_mask; } - while (!found) { - bool got_match; - bool ms_dfs_link = False; - - /* Needed if we run out of space */ - long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr); - dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf); - - /* - * Due to bugs in NT client redirectors we are not using - * resume keys any more - set them to zero. - * Check out the related comments in findfirst/findnext. - * JRA. - */ - - reskey = 0; - - DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n", - (long)conn->dirptr,curr_dirpos)); - - if (!dname) { - return(False); - } - - /* - * fname may get mangled, dname is never mangled. - * Whenever we're accessing the filesystem we use - * pathreal which is composed from dname. - */ - - pathreal = NULL; - fname = dname; - - /* Mangle fname if it's an illegal name. */ - if (mangle_must_mangle(dname,conn->params)) { - if (!name_to_8_3(dname,mangled_name,True,conn->params)) { - TALLOC_FREE(fname); - continue; /* Error - couldn't mangle. */ - } - fname = talloc_strdup(ctx, mangled_name); - if (!fname) { - return False; - } - } - - if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) { - got_match = mask_match(fname, mask, conn->case_sensitive); - } - - if(!got_match && check_mangled_names && - !mangle_is_8_3(fname, False, conn->params)) { - /* - * It turns out that NT matches wildcards against - * both long *and* short names. This may explain some - * of the wildcard wierdness from old DOS clients - * that some people have been seeing.... JRA. - */ - /* Force the mangling into 8.3. */ - if (!name_to_8_3( fname, mangled_name, False, conn->params)) { - TALLOC_FREE(fname); - continue; /* Error - couldn't mangle. */ - } - - if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) { - got_match = mask_match(mangled_name, mask, conn->case_sensitive); - } - } - - if (got_match) { - bool isdots = (ISDOT(dname) || ISDOTDOT(dname)); - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - if (dont_descend && !isdots) { - TALLOC_FREE(fname); - continue; - } - - if (needslash) { - pathreal = NULL; - pathreal = talloc_asprintf(ctx, - "%s/%s", - conn->dirpath, - dname); - } else { - pathreal = talloc_asprintf(ctx, - "%s%s", - conn->dirpath, - dname); - } - - if (!pathreal) { - TALLOC_FREE(fname); - return False; - } - - /* A dirent from dptr_ReadDirName isn't a stream. */ - status = create_synthetic_smb_fname(ctx, pathreal, - NULL, &sbuf, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(fname); - return false; - } - - if (INFO_LEVEL_IS_UNIX(info_level)) { - if (SMB_VFS_LSTAT(conn, smb_fname) != 0) { - DEBUG(5,("get_lanman2_dir_entry: " - "Couldn't lstat [%s] (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - TALLOC_FREE(smb_fname); - TALLOC_FREE(pathreal); - TALLOC_FREE(fname); - continue; - } - } else if (!VALID_STAT(smb_fname->st) && - SMB_VFS_STAT(conn, smb_fname) != 0) { - /* Needed to show the msdfs symlinks as - * directories */ - - ms_dfs_link = - check_msdfs_link(conn, - smb_fname->base_name, - &smb_fname->st); - if (!ms_dfs_link) { - DEBUG(5,("get_lanman2_dir_entry: " - "Couldn't stat [%s] (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - TALLOC_FREE(smb_fname); - TALLOC_FREE(pathreal); - TALLOC_FREE(fname); - continue; - } - } - - if (ms_dfs_link) { - mode = dos_mode_msdfs(conn, smb_fname); - } else { - mode = dos_mode(conn, smb_fname); - } - - if (!dir_check_ftype(conn,mode,dirtype)) { - DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype)); - TALLOC_FREE(smb_fname); - TALLOC_FREE(pathreal); - TALLOC_FREE(fname); - continue; - } - - if (!(mode & aDIR)) { - file_size = get_file_size_stat(&smb_fname->st); - } - allocation_size = - SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st); - - if (ask_sharemode) { - struct timespec write_time_ts; - struct file_id fileid; - - ZERO_STRUCT(write_time_ts); - fileid = vfs_file_id_from_sbuf(conn, - &smb_fname->st); - get_file_infos(fileid, NULL, &write_time_ts); - if (!null_timespec(write_time_ts)) { - update_stat_ex_mtime(&smb_fname->st, - write_time_ts); - } - } - - mdate_ts = smb_fname->st.st_ex_mtime; - adate_ts = smb_fname->st.st_ex_atime; - create_date_ts = smb_fname->st.st_ex_btime; - - if (lp_dos_filetime_resolution(SNUM(conn))) { - dos_filetime_timespec(&create_date_ts); - dos_filetime_timespec(&mdate_ts); - dos_filetime_timespec(&adate_ts); - } - - create_date = convert_timespec_to_time_t(create_date_ts); - mdate = convert_timespec_to_time_t(mdate_ts); - adate = convert_timespec_to_time_t(adate_ts); + ok = smbd_dirptr_get_entry(ctx, + conn->dirptr, + mask, + dirtype, + dont_descend, + ask_sharemode, + smbd_dirptr_lanman2_match_fn, + smbd_dirptr_lanman2_mode_fn, + &state, + &fname, + &smb_fname, + &mode, + &prev_dirpos); + if (!ok) { + return false; + } - DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n", - smb_fname_str_dbg(smb_fname), fname)); + *got_exact_match = state.got_exact_match; - found = True; + if (!(mode & aDIR)) { + file_size = get_file_size_stat(&smb_fname->st); + } + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st); - dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos); - sbuf = smb_fname->st; + mdate_ts = smb_fname->st.st_ex_mtime; + adate_ts = smb_fname->st.st_ex_atime; + create_date_ts = smb_fname->st.st_ex_btime; - TALLOC_FREE(smb_fname); - } - - if (!found) - TALLOC_FREE(fname); + if (lp_dos_filetime_resolution(SNUM(conn))) { + dos_filetime_timespec(&create_date_ts); + dos_filetime_timespec(&mdate_ts); + dos_filetime_timespec(&adate_ts); } + create_date = convert_timespec_to_time_t(create_date_ts); + mdate = convert_timespec_to_time_t(mdate_ts); + adate = convert_timespec_to_time_t(adate_ts); + p = pdata; last_entry_ptr = p; @@ -1635,7 +1605,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, SIVAL(p,16,(uint32)allocation_size); SSVAL(p,20,mode); { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); SIVAL(p,22,ea_size); /* Extended attributes */ } p += 27; @@ -1668,6 +1639,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); if (!name_list) { + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); return False; } if(requires_resume_key) { @@ -1682,12 +1655,16 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, SSVAL(p,20,mode); p += 22; /* p now points to the EA area. */ - file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len); + file_list = get_ea_list_from_file(ctx, conn, NULL, + smb_fname->base_name, + &ea_len); name_list = ea_list_union(name_list, file_list, &ea_len); /* We need to determine if this entry will fit in the space available. */ /* Max string size is 255 bytes. */ if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); /* Move the dirptr back to prev_dirpos */ dptr_SeekDir(conn->dirptr, prev_dirpos); *out_of_space = True; @@ -1734,7 +1711,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, SIVAL(p,0,nt_extmode); p += 4; q = p; p += 4; /* q is placeholder for name length. */ { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); SIVAL(p,0,ea_size); /* Extended attributes */ p += 4; } @@ -1742,7 +1720,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, * IMPORTANT as not doing so will trigger * a Win2k client bug. JRA. */ - if (!was_8_3 && check_mangled_names) { + if (!was_8_3 && state.check_mangled_names) { + char mangled_name[13]; /* mangled 8.3 name. */ if (!name_to_8_3(fname,mangled_name,True, conn->params)) { /* Error - mangle failed ! */ @@ -1808,7 +1787,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, SIVAL(p,0,nt_extmode); p += 4; q = p; p += 4; /* q is placeholder for name length. */ { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); SIVAL(p,0,ea_size); /* Extended attributes */ p +=4; } @@ -1857,13 +1837,14 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, SIVAL(p,0,nt_extmode); p += 4; q = p; p += 4; /* q is placeholder for name length. */ { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); SIVAL(p,0,ea_size); /* Extended attributes */ p +=4; } SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ - SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */ + SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ len = srvstr_push(base_data, flags2, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII); @@ -1890,7 +1871,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, SIVAL(p,0,nt_extmode); p += 4; q = p; p += 4; /* q is placeholder for name length */ { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); SIVAL(p,0,ea_size); /* Extended attributes */ p +=4; } @@ -1898,7 +1880,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, * IMPORTANT as not doing so will trigger * a Win2k client bug. JRA. */ - if (!was_8_3 && check_mangled_names) { + if (!was_8_3 && state.check_mangled_names) { + char mangled_name[13]; /* mangled 8.3 name. */ if (!name_to_8_3(fname,mangled_name,True, conn->params)) { /* Error - mangle failed ! */ @@ -1918,8 +1901,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, } p += 26; SSVAL(p,0,0); p += 2; /* Reserved ? */ - SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */ + SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ len = srvstr_push(base_data, flags2, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII); @@ -1944,14 +1927,14 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, if (info_level == SMB_FIND_FILE_UNIX) { DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); p = store_file_unix_basic(conn, p, - NULL, &sbuf); + NULL, &smb_fname->st); len = srvstr_push(base_data, flags2, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE); } else { DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); p = store_file_unix_basic_info2(conn, p, - NULL, &sbuf); + NULL, &smb_fname->st); nameptr = p; p += 4; len = srvstr_push(base_data, flags2, p, fname, @@ -1972,10 +1955,13 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, default: TALLOC_FREE(fname); - return(False); + TALLOC_FREE(smb_fname); + return false; } TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + if (PTR_DIFF(p,pdata) > space_remaining) { /* Move the dirptr back to prev_dirpos */ dptr_SeekDir(conn->dirptr, prev_dirpos); @@ -1989,7 +1975,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, /* Advance the data pointer to the next slot */ *ppdata = p; - return(found); + return true; } /**************************************************************************** -- cgit From c50a03e4e2c47b828f81f2e4dc214ec84d9cae63 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 7 Aug 2009 09:31:45 +0200 Subject: s3:smbd: remove dirptr and dirpath from connection_struct They're both only used in the context of a function, so we can make them stack variables. metze --- source3/smbd/conn.c | 2 -- source3/smbd/dir.c | 11 +++-------- source3/smbd/reply.c | 33 +++++++++++++++++++-------------- source3/smbd/service.c | 2 -- source3/smbd/trans2.c | 46 ++++++++++++++++++++++++---------------------- 5 files changed, 46 insertions(+), 48 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index da67db978b..959fcd7754 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -163,7 +163,6 @@ find_again: sconn->smb1.tcons.num_open++; - string_set(&conn->dirpath,""); string_set(&conn->connectpath,""); string_set(&conn->origpath,""); @@ -284,7 +283,6 @@ static void conn_free_internal(connection_struct *conn) free_namearray(conn->veto_oplock_list); free_namearray(conn->aio_write_behind_list); - string_free(&conn->dirpath); string_free(&conn->connectpath); string_free(&conn->origpath); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index e2f8e69449..1c84decbde 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -407,8 +407,6 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, return map_nt_error_from_unix(errno); } - string_set(&conn->dirpath,path); - if (dirhandles_open >= MAX_OPEN_DIRECTORIES) { dptr_idleoldest(); } @@ -1030,7 +1028,7 @@ static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx, } bool get_dir_entry(TALLOC_CTX *ctx, - connection_struct *conn, + struct dptr_struct *dirptr, const char *mask, uint32_t dirtype, char **_fname, @@ -1040,18 +1038,15 @@ bool get_dir_entry(TALLOC_CTX *ctx, bool check_descend, bool ask_sharemode) { + connection_struct *conn = dirptr->conn; char *fname = NULL; struct smb_filename *smb_fname = NULL; uint32_t mode = 0; long prev_offset; bool ok; - if (!conn->dirptr) { - return false; - } - ok = smbd_dirptr_get_entry(ctx, - conn->dirptr, + dirptr, mask, dirtype, check_descend, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 750915b1cb..f6028a3eef 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1366,6 +1366,7 @@ void reply_search(struct smb_request *req) bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; TALLOC_CTX *ctx = talloc_tos(); bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); + struct dptr_struct *dirptr = NULL; START_PROFILE(SMBsearch); @@ -1446,14 +1447,15 @@ void reply_search(struct smb_request *req) mask, mask_contains_wcard, dirtype, - &conn->dirptr); + &dirptr); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); goto out; } - dptr_num = dptr_dnum(conn->dirptr); + dptr_num = dptr_dnum(dirptr); } else { int status_dirtype; + const char *dirpath; memcpy(status,p,21); status_dirtype = CVAL(status,0) & 0x1F; @@ -1461,11 +1463,17 @@ void reply_search(struct smb_request *req) dirtype = status_dirtype; } - conn->dirptr = dptr_fetch(status+12,&dptr_num); - if (!conn->dirptr) { + dirptr = dptr_fetch(status+12,&dptr_num); + if (!dirptr) { goto SearchEmpty; } - string_set(&conn->dirpath,dptr_path(dptr_num)); + dirpath = dptr_path(dptr_num); + directory = talloc_strdup(ctx, dirpath); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + goto out; + } + mask = dptr_wcard(dptr_num); if (!mask) { goto SearchEmpty; @@ -1481,7 +1489,7 @@ void reply_search(struct smb_request *req) DEBUG(4,("dptr_num is %d\n",dptr_num)); /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */ - dptr_init_search_op(conn->dirptr); + dptr_init_search_op(dirptr); if ((dirtype&0x1F) == aVOLID) { char buf[DIR_STRUCT_SIZE]; @@ -1512,14 +1520,14 @@ void reply_search(struct smb_request *req) /DIR_STRUCT_SIZE)); DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", - conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) { + directory,lp_dontdescend(SNUM(conn)))); + if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) { check_descend = True; } for (i=numentries;(ioutbuf, smb_flg2, (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); - if (!directory) { - directory = dptr_path(dptr_num); - } - DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n", smb_fn_name(req->cmd), mask, - directory ? directory : "./", + directory, dirtype, numentries, maxentries )); out: + TALLOC_FREE(directory); TALLOC_FREE(smb_fname); END_PROFILE(SMBsearch); return; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c24b2264c1..fc56105adf 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -692,7 +692,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, conn->printer = (strncmp(dev,"LPT",3) == 0); conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); - conn->dirptr = NULL; /* Case options for the share. */ if (lp_casesensitive(snum) == Auto) { @@ -712,7 +711,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, conn->hide_list = NULL; conn->veto_oplock_list = NULL; conn->aio_write_behind_list = NULL; - string_set(&conn->dirpath,""); conn->read_only = lp_readonly(SNUM(conn)); conn->admin_user = False; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e48ffac150..3f93b3d571 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1448,6 +1448,7 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx, static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, connection_struct *conn, + struct dptr_struct *dirptr, uint16 flags2, const char *path_mask, uint32 dirtype, @@ -1487,7 +1488,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, state.conn = conn; state.info_level = info_level; state.check_mangled_names = lp_manglednames(conn->params); - state.has_wild = dptr_has_wild(conn->dirptr); + state.has_wild = dptr_has_wild(dirptr); state.got_exact_match = false; *out_of_space = False; @@ -1497,10 +1498,6 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, ZERO_STRUCT(adate_ts); ZERO_STRUCT(create_date_ts); - if (!conn->dirptr) { - return false; - } - p = strrchr_m(path_mask,'/'); if(p != NULL) { if(p[1] == '\0') { @@ -1513,7 +1510,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, } ok = smbd_dirptr_get_entry(ctx, - conn->dirptr, + dirptr, mask, dirtype, dont_descend, @@ -1666,7 +1663,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, TALLOC_FREE(fname); TALLOC_FREE(smb_fname); /* Move the dirptr back to prev_dirpos */ - dptr_SeekDir(conn->dirptr, prev_dirpos); + dptr_SeekDir(dirptr, prev_dirpos); *out_of_space = True; DEBUG(9,("get_lanman2_dir_entry: out of space\n")); return False; /* Not finished - just out of space */ @@ -1964,7 +1961,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, if (PTR_DIFF(p,pdata) > space_remaining) { /* Move the dirptr back to prev_dirpos */ - dptr_SeekDir(conn->dirptr, prev_dirpos); + dptr_SeekDir(dirptr, prev_dirpos); *out_of_space = True; DEBUG(9,("get_lanman2_dir_entry: out of space\n")); return False; /* Not finished - just out of space */ @@ -2020,6 +2017,7 @@ static void call_trans2findfirst(connection_struct *conn, NTSTATUS ntstatus = NT_STATUS_OK; bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); TALLOC_CTX *ctx = talloc_tos(); + struct dptr_struct *dirptr = NULL; if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2177,24 +2175,25 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd mask, mask_contains_wcard, dirtype, - &conn->dirptr); + &dirptr); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); goto out; } - dptr_num = dptr_dnum(conn->dirptr); + dptr_num = dptr_dnum(dirptr); DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype)); /* Initialize per TRANS2_FIND_FIRST operation data */ - dptr_init_search_op(conn->dirptr); + dptr_init_search_op(dirptr); /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", + directory,lp_dontdescend(SNUM(conn)))); + if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) dont_descend = True; p = pdata; @@ -2212,6 +2211,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } else { finished = !get_lanman2_dir_entry(ctx, conn, + dirptr, req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, @@ -2355,6 +2355,7 @@ static void call_trans2findnext(connection_struct *conn, NTSTATUS ntstatus = NT_STATUS_OK; bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); TALLOC_CTX *ctx = talloc_tos(); + struct dptr_struct *dirptr; if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2476,12 +2477,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd params = *pparams; /* Check that the dptr is valid */ - if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) { + if(!(dirptr = dptr_fetch_lanman2(dptr_num))) { reply_doserror(req, ERRDOS, ERRnofiles); return; } - string_set(&conn->dirpath,dptr_path(dptr_num)); + directory = dptr_path(dptr_num); /* Get the wildcard mask from the dptr */ if((p = dptr_wcard(dptr_num))== NULL) { @@ -2491,24 +2492,24 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } mask = p; - directory = conn->dirpath; /* Get the attr mask from the dptr */ dirtype = dptr_attr(dptr_num); DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n", dptr_num, mask, dirtype, - (long)conn->dirptr, - dptr_TellDir(conn->dirptr))); + (long)dirptr, + dptr_TellDir(dirptr))); /* Initialize per TRANS2_FIND_NEXT operation data */ - dptr_init_search_op(conn->dirptr); + dptr_init_search_op(dirptr); /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", + directory,lp_dontdescend(SNUM(conn)))); + if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) dont_descend = True; p = pdata; @@ -2550,7 +2551,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * should already be at the correct place. */ - finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st); + finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st); } /* end if resume_name && !continue_bit */ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) { @@ -2564,6 +2565,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } else { finished = !get_lanman2_dir_entry(ctx, conn, + dirptr, req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, -- cgit From 59c3f5e3ca8885266fef65261ecae3f51ce78729 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Aug 2009 12:15:51 +0200 Subject: s3:smbd: move dptr globals into struct smbd_server_connection metze --- source3/smbd/dir.c | 153 +++++++++++++++++++++++++++++++------------------ source3/smbd/globals.c | 4 -- source3/smbd/globals.h | 11 ++-- source3/smbd/process.c | 3 + source3/smbd/reply.c | 27 +++++---- source3/smbd/server.c | 2 - source3/smbd/trans2.c | 23 ++++---- 7 files changed, 135 insertions(+), 88 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 1c84decbde..73c4cbb3e7 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -115,15 +115,19 @@ bool make_dir_struct(TALLOC_CTX *ctx, Initialise the dir bitmap. ****************************************************************************/ -void init_dptrs(void) +bool init_dptrs(struct smbd_server_connection *sconn) { - if (dptr_bmap) - return; + if (sconn->smb1.searches.dptr_bmap) { + return true; + } - dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); + sconn->smb1.searches.dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); + + if (sconn->smb1.searches.dptr_bmap == NULL) { + return false; + } - if (!dptr_bmap) - exit_server("out of memory in init_dptrs"); + return true; } /**************************************************************************** @@ -142,14 +146,14 @@ static void dptr_idle(struct dptr_struct *dptr) Idle the oldest dptr. ****************************************************************************/ -static void dptr_idleoldest(void) +static void dptr_idleoldest(struct smbd_server_connection *sconn) { struct dptr_struct *dptr; /* * Go to the end of the list. */ - for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) + for(dptr = sconn->smb1.searches.dirptrs; dptr && dptr->next; dptr = dptr->next) ; if(!dptr) { @@ -173,15 +177,16 @@ static void dptr_idleoldest(void) Get the struct dptr_struct for a dir index. ****************************************************************************/ -static struct dptr_struct *dptr_get(int key, bool forclose) +static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn, + int key, bool forclose) { struct dptr_struct *dptr; - for(dptr = dirptrs; dptr; dptr = dptr->next) { + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = dptr->next) { if(dptr->dnum == key) { if (!forclose && !dptr->dir_hnd) { - if (dirhandles_open >= MAX_OPEN_DIRECTORIES) - dptr_idleoldest(); + if (sconn->smb1.searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) + dptr_idleoldest(sconn); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); if (!(dptr->dir_hnd = OpenDir( NULL, dptr->conn, dptr->path, @@ -191,7 +196,7 @@ static struct dptr_struct *dptr_get(int key, bool forclose) return False; } } - DLIST_PROMOTE(dirptrs,dptr); + DLIST_PROMOTE(sconn->smb1.searches.dirptrs,dptr); return dptr; } } @@ -202,9 +207,9 @@ static struct dptr_struct *dptr_get(int key, bool forclose) Get the dir path for a dir index. ****************************************************************************/ -char *dptr_path(int key) +char *dptr_path(struct smbd_server_connection *sconn, int key) { - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); if (dptr) return(dptr->path); return(NULL); @@ -214,9 +219,9 @@ char *dptr_path(int key) Get the dir wcard for a dir index. ****************************************************************************/ -char *dptr_wcard(int key) +char *dptr_wcard(struct smbd_server_connection *sconn, int key) { - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); if (dptr) return(dptr->wcard); return(NULL); @@ -226,9 +231,9 @@ char *dptr_wcard(int key) Get the dir attrib for a dir index. ****************************************************************************/ -uint16 dptr_attr(int key) +uint16 dptr_attr(struct smbd_server_connection *sconn, int key) { - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); if (dptr) return(dptr->attr); return(0); @@ -240,22 +245,29 @@ uint16 dptr_attr(int key) static void dptr_close_internal(struct dptr_struct *dptr) { + struct smbd_server_connection *sconn = dptr->conn->sconn; + DEBUG(4,("closing dptr key %d\n",dptr->dnum)); - DLIST_REMOVE(dirptrs, dptr); + if (sconn == NULL) { + goto done; + } + + DLIST_REMOVE(sconn->smb1.searches.dirptrs, dptr); /* * Free the dnum in the bitmap. Remember the dnum value is always * biased by one with respect to the bitmap. */ - if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) { + if(bitmap_query(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1) != true) { DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n", dptr->dnum )); } - bitmap_clear(dptr_bmap, dptr->dnum - 1); + bitmap_clear(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1); +done: TALLOC_FREE(dptr->dir_hnd); /* Lanman 2 specific code */ @@ -268,7 +280,7 @@ static void dptr_close_internal(struct dptr_struct *dptr) Close a dptr given a key. ****************************************************************************/ -void dptr_close(int *key) +void dptr_close(struct smbd_server_connection *sconn, int *key) { struct dptr_struct *dptr; @@ -278,7 +290,7 @@ void dptr_close(int *key) /* OS/2 seems to use -1 to indicate "close all directories" */ if (*key == -1) { struct dptr_struct *next; - for(dptr = dirptrs; dptr; dptr = next) { + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) { next = dptr->next; dptr_close_internal(dptr); } @@ -286,7 +298,7 @@ void dptr_close(int *key) return; } - dptr = dptr_get(*key, True); + dptr = dptr_get(sconn, *key, true); if (!dptr) { DEBUG(0,("Invalid key %d given to dptr_close\n", *key)); @@ -305,10 +317,17 @@ void dptr_close(int *key) void dptr_closecnum(connection_struct *conn) { struct dptr_struct *dptr, *next; - for(dptr = dirptrs; dptr; dptr = next) { + struct smbd_server_connection *sconn = conn->sconn; + + if (sconn == NULL) { + return; + } + + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) { next = dptr->next; - if (dptr->conn == conn) + if (dptr->conn == conn) { dptr_close_internal(dptr); + } } } @@ -319,9 +338,16 @@ void dptr_closecnum(connection_struct *conn) void dptr_idlecnum(connection_struct *conn) { struct dptr_struct *dptr; - for(dptr = dirptrs; dptr; dptr = dptr->next) { - if (dptr->conn == conn && dptr->dir_hnd) + struct smbd_server_connection *sconn = conn->sconn; + + if (sconn == NULL) { + return; + } + + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = dptr->next) { + if (dptr->conn == conn && dptr->dir_hnd) { dptr_idle(dptr); + } } } @@ -329,10 +355,11 @@ void dptr_idlecnum(connection_struct *conn) Close a dptr that matches a given path, only if it matches the spid also. ****************************************************************************/ -void dptr_closepath(char *path,uint16 spid) +void dptr_closepath(struct smbd_server_connection *sconn, + char *path,uint16 spid) { struct dptr_struct *dptr, *next; - for(dptr = dirptrs; dptr; dptr = next) { + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) { next = dptr->next; if (spid == dptr->spid && strequal(dptr->path,path)) dptr_close_internal(dptr); @@ -345,14 +372,15 @@ void dptr_closepath(char *path,uint16 spid) finished with that one. ****************************************************************************/ -static void dptr_close_oldest(bool old) +static void dptr_close_oldest(struct smbd_server_connection *sconn, + bool old) { struct dptr_struct *dptr; /* * Go to the end of the list. */ - for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) + for(dptr = sconn->smb1.searches.dirptrs; dptr && dptr->next; dptr = dptr->next) ; if(!dptr) { @@ -387,12 +415,18 @@ static void dptr_close_oldest(bool old) NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, bool expect_close,uint16 spid, const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret) { + struct smbd_server_connection *sconn = conn->sconn; struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; NTSTATUS status; DEBUG(5,("dptr_create dir=%s\n", path)); + if (sconn == NULL) { + DEBUG(0,("dptr_create: called with fake connection_struct\n")); + return NT_STATUS_INTERNAL_ERROR; + } + if (!wcard) { return NT_STATUS_INVALID_PARAMETER; } @@ -407,8 +441,8 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, return map_nt_error_from_unix(errno); } - if (dirhandles_open >= MAX_OPEN_DIRECTORIES) { - dptr_idleoldest(); + if (sconn->smb1.searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) { + dptr_idleoldest(sconn); } dptr = SMB_MALLOC_P(struct dptr_struct); @@ -427,7 +461,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, * value we return will fit in the range 1-255. */ - dptr->dnum = bitmap_find(dptr_bmap, 0); + dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 0); if(dptr->dnum == -1 || dptr->dnum > 254) { @@ -437,10 +471,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, * finished with that one. */ - dptr_close_oldest(True); + dptr_close_oldest(sconn, true); /* Now try again... */ - dptr->dnum = bitmap_find(dptr_bmap, 0); + dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 0); if(dptr->dnum == -1 || dptr->dnum > 254) { DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); SAFE_FREE(dptr); @@ -455,7 +489,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, * a range that will return 256 - MAX_DIRECTORY_HANDLES. */ - dptr->dnum = bitmap_find(dptr_bmap, 255); + dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 255); if(dptr->dnum == -1 || dptr->dnum < 255) { @@ -466,10 +500,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, * directory handles. */ - dptr_close_oldest(False); + dptr_close_oldest(sconn, false); /* Now try again... */ - dptr->dnum = bitmap_find(dptr_bmap, 255); + dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 255); if(dptr->dnum == -1 || dptr->dnum < 255) { DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); @@ -480,7 +514,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, } } - bitmap_set(dptr_bmap, dptr->dnum); + bitmap_set(sconn->smb1.searches.dptr_bmap, dptr->dnum); dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */ @@ -491,7 +525,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, dptr->expect_close = expect_close; dptr->wcard = SMB_STRDUP(wcard); if (!dptr->wcard) { - bitmap_clear(dptr_bmap, dptr->dnum - 1); + bitmap_clear(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1); SAFE_FREE(dptr); TALLOC_FREE(dir_hnd); return NT_STATUS_NO_MEMORY; @@ -504,7 +538,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, dptr->attr = attr; - DLIST_ADD(dirptrs, dptr); + DLIST_ADD(sconn->smb1.searches.dirptrs, dptr); DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", dptr->dnum,path,expect_close)); @@ -521,7 +555,8 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, int dptr_CloseDir(struct dptr_struct *dptr) { - DLIST_REMOVE(dirptrs, dptr); + struct smbd_server_connection *sconn = dptr->conn->sconn; + DLIST_REMOVE(sconn->smb1.searches.dirptrs, dptr); TALLOC_FREE(dptr->dir_hnd); return 0; } @@ -724,10 +759,11 @@ void dptr_init_search_op(struct dptr_struct *dptr) Fill the 5 byte server reserved dptr field. ****************************************************************************/ -bool dptr_fill(char *buf1,unsigned int key) +bool dptr_fill(struct smbd_server_connection *sconn, + char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); uint32 offset; if (!dptr) { DEBUG(1,("filling null dirptr %d\n",key)); @@ -745,10 +781,11 @@ bool dptr_fill(char *buf1,unsigned int key) Fetch the dir ptr and seek it given the 5 byte server field. ****************************************************************************/ -struct dptr_struct *dptr_fetch(char *buf,int *num) +struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn, + char *buf, int *num) { unsigned int key = *(unsigned char *)buf; - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); uint32 offset; long seekoff; @@ -765,7 +802,7 @@ struct dptr_struct *dptr_fetch(char *buf,int *num) } SeekDir(dptr->dir_hnd,seekoff); DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", - key,dptr_path(key),(int)seekoff)); + key, dptr->path, (int)seekoff)); return(dptr); } @@ -773,15 +810,16 @@ struct dptr_struct *dptr_fetch(char *buf,int *num) Fetch the dir ptr. ****************************************************************************/ -struct dptr_struct *dptr_fetch_lanman2(int dptr_num) +struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn, + int dptr_num) { - struct dptr_struct *dptr = dptr_get(dptr_num, False); + struct dptr_struct *dptr = dptr_get(sconn, dptr_num, false); if (!dptr) { DEBUG(3,("fetched null dirptr %d\n",dptr_num)); return(NULL); } - DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num))); + DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path)); return(dptr); } @@ -1245,7 +1283,9 @@ static int smb_Dir_destructor(struct smb_Dir *dirp) if (dirp->dir) { SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); } - dirhandles_open--; + if (dirp->conn->sconn) { + dirp->conn->sconn->smb1.searches.dirhandles_open--; + } return 0; } @@ -1257,6 +1297,7 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *name, const char *mask, uint32 attr) { struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir); + struct smbd_server_connection *sconn = conn->sconn; if (!dirp) { return NULL; @@ -1271,7 +1312,9 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, goto fail; } - dirhandles_open++; + if (sconn) { + sconn->smb1.searches.dirhandles_open++; + } talloc_set_destructor(dirp, smb_Dir_destructor); dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 317304a86d..f680b76369 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -46,10 +46,6 @@ struct smbd_dmapi_context *dmapi_ctx = NULL; bool dfree_broken = false; -struct bitmap *dptr_bmap = NULL; -struct dptr_struct *dirptrs = NULL; -int dirhandles_open = 0; - /* how many write cache buffers have been allocated */ unsigned int allocated_write_caches = 0; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 6a62cf6a21..338398968a 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -44,11 +44,6 @@ extern struct smbd_dmapi_context *dmapi_ctx; extern bool dfree_broken; -extern struct bitmap *dptr_bmap; -//struct dptr_struct; -extern struct dptr_struct *dirptrs; -extern int dirhandles_open; - /* how many write cache buffers have been allocated */ extern unsigned int allocated_write_caches; @@ -453,6 +448,12 @@ struct smbd_server_connection { struct pending_auth_data *pd_list; struct notify_mid_map *notify_mid_maps; + + struct { + struct bitmap *dptr_bmap; + struct dptr_struct *dirptrs; + int dirhandles_open; + } searches; } smb1; struct { struct tevent_context *event_ctx; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 99c862300d..6ec46071ff 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2206,6 +2206,9 @@ void smbd_process(void) #endif conn_init(smbd_server_conn); + if (!init_dptrs(smbd_server_conn)) { + exit_server("init_dptrs() failed"); + } smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(), smbd_server_conn, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f6028a3eef..3498109f12 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1367,6 +1367,7 @@ void reply_search(struct smb_request *req) TALLOC_CTX *ctx = talloc_tos(); bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); struct dptr_struct *dirptr = NULL; + struct smbd_server_connection *sconn = smbd_server_conn; START_PROFILE(SMBsearch); @@ -1463,18 +1464,18 @@ void reply_search(struct smb_request *req) dirtype = status_dirtype; } - dirptr = dptr_fetch(status+12,&dptr_num); + dirptr = dptr_fetch(sconn, status+12,&dptr_num); if (!dirptr) { goto SearchEmpty; } - dirpath = dptr_path(dptr_num); + dirpath = dptr_path(sconn, dptr_num); directory = talloc_strdup(ctx, dirpath); if (!directory) { reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } - mask = dptr_wcard(dptr_num); + mask = dptr_wcard(sconn, dptr_num); if (!mask) { goto SearchEmpty; } @@ -1483,7 +1484,7 @@ void reply_search(struct smb_request *req) * check from the initial saved string. */ mask_contains_wcard = ms_has_wild(mask); - dirtype = dptr_attr(dptr_num); + dirtype = dptr_attr(sconn, dptr_num); } DEBUG(4,("dptr_num is %d\n",dptr_num)); @@ -1499,7 +1500,7 @@ void reply_search(struct smb_request *req) reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } - dptr_fill(buf+12,dptr_num); + dptr_fill(sconn, buf+12,dptr_num); if (dptr_zero(buf+12) && (status_len==0)) { numentries = 1; } else { @@ -1550,7 +1551,7 @@ void reply_search(struct smb_request *req) reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } - if (!dptr_fill(buf+12,dptr_num)) { + if (!dptr_fill(sconn, buf+12,dptr_num)) { break; } if (message_push_blob(&req->outbuf, @@ -1571,15 +1572,15 @@ void reply_search(struct smb_request *req) (X/Open spec) */ if (numentries == 0) { - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } else if(expect_close && status_len == 0) { /* Close the dptr - we know it's gone */ - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } /* If we were called as SMBfunique, then we can close the dirptr now ! */ if(dptr_num >= 0 && req->cmd == SMBfunique) { - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } if ((numentries == 0) && !mask_contains_wcard) { @@ -1633,6 +1634,7 @@ void reply_fclose(struct smb_request *req) NTSTATUS err; bool path_contains_wcard = False; TALLOC_CTX *ctx = talloc_tos(); + struct smbd_server_connection *sconn = smbd_server_conn; START_PROFILE(SMBfclose); @@ -1662,9 +1664,9 @@ void reply_fclose(struct smb_request *req) memcpy(status,p,21); - if(dptr_fetch(status+12,&dptr_num)) { + if(dptr_fetch(sconn, status+12,&dptr_num)) { /* Close the dptr - we know it's gone */ - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } reply_outbuf(req, 1, 0); @@ -5532,6 +5534,7 @@ void reply_rmdir(struct smb_request *req) char *directory = NULL; NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); + struct smbd_server_connection *sconn = smbd_server_conn; START_PROFILE(SMBrmdir); @@ -5563,7 +5566,7 @@ void reply_rmdir(struct smb_request *req) goto out; } - dptr_closepath(smb_dname->base_name, req->smbpid); + dptr_closepath(sconn, smb_dname->base_name, req->smbpid); status = rmdir_internals(ctx, conn, smb_dname); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4b1c803d75..ace3124842 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -914,8 +914,6 @@ static bool init_structs(void ) file_init(); - init_dptrs(); - if (!secrets_init()) return False; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3f93b3d571..9273339b71 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2018,6 +2018,7 @@ static void call_trans2findfirst(connection_struct *conn, bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); TALLOC_CTX *ctx = talloc_tos(); struct dptr_struct *dirptr = NULL; + struct smbd_server_connection *sconn = smbd_server_conn; if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2250,7 +2251,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Check if we can close the dirptr */ if(close_after_first || (finished && close_if_end)) { DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } /* @@ -2261,7 +2262,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd */ if(numentries == 0) { - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); if (Protocol < PROTOCOL_NT1) { reply_doserror(req, ERRDOS, ERRnofiles); goto out; @@ -2284,8 +2285,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes); - if ((! *directory) && dptr_path(dptr_num)) { - directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num)); + if ((! *directory) && dptr_path(sconn, dptr_num)) { + directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num)); if (!directory) { reply_nterror(req, NT_STATUS_NO_MEMORY); } @@ -2356,6 +2357,7 @@ static void call_trans2findnext(connection_struct *conn, bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); TALLOC_CTX *ctx = talloc_tos(); struct dptr_struct *dirptr; + struct smbd_server_connection *sconn = smbd_server_conn; if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2477,15 +2479,15 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd params = *pparams; /* Check that the dptr is valid */ - if(!(dirptr = dptr_fetch_lanman2(dptr_num))) { + if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) { reply_doserror(req, ERRDOS, ERRnofiles); return; } - directory = dptr_path(dptr_num); + directory = dptr_path(sconn, dptr_num); /* Get the wildcard mask from the dptr */ - if((p = dptr_wcard(dptr_num))== NULL) { + if((p = dptr_wcard(sconn, dptr_num))== NULL) { DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); reply_doserror(req, ERRDOS, ERRnofiles); return; @@ -2494,7 +2496,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd mask = p; /* Get the attr mask from the dptr */ - dirtype = dptr_attr(dptr_num); + dirtype = dptr_attr(sconn, dptr_num); DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n", dptr_num, mask, dirtype, @@ -2602,7 +2604,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Check if we can close the dirptr */ if(close_after_request || (finished && close_if_end)) { DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); - dptr_close(&dptr_num); /* This frees up the saved mask */ + dptr_close(sconn, &dptr_num); /* This frees up the saved mask */ } /* Set up the return parameter block */ @@ -7851,6 +7853,7 @@ static void call_trans2ioctl(connection_struct *conn, void reply_findclose(struct smb_request *req) { int dptr_num; + struct smbd_server_connection *sconn = smbd_server_conn; START_PROFILE(SMBfindclose); @@ -7864,7 +7867,7 @@ void reply_findclose(struct smb_request *req) DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num)); - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); reply_outbuf(req, 0, 0); -- cgit From 50f54250f4b566e10d0be40dc2d0117c6cb7a73d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Aug 2009 12:15:51 +0200 Subject: s3:smbd: split the dir entry marshalling into smbd_marshall_dir_entry() So that we can reuse it for SMB2 Find. metze --- source3/smbd/trans2.c | 925 ++++++++++++++++++++++++++------------------------ 1 file changed, 482 insertions(+), 443 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9273339b71..780d7d606c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1446,88 +1446,41 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx, return true; } -static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, - connection_struct *conn, - struct dptr_struct *dirptr, - uint16 flags2, - const char *path_mask, - uint32 dirtype, - int info_level, - int requires_resume_key, - bool dont_descend, - bool ask_sharemode, - char **ppdata, - char *base_data, - char *end_data, - int space_remaining, - bool *out_of_space, - bool *got_exact_match, - int *last_entry_off, - struct ea_list *name_list) +static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + uint16_t flags2, + uint32_t info_level, + struct ea_list *name_list, + bool check_mangled_names, + bool requires_resume_key, + uint32_t mode, + const char *fname, + const struct smb_filename *smb_fname, + uint64_t space_remaining, + char *base_data, + char **ppdata, + char *end_data, + bool *out_of_space, + uint64_t *last_entry_off) { - const char *mask = NULL; char *p, *q, *pdata = *ppdata; - uint32 reskey=0; - long prev_dirpos=0; - uint32 mode=0; - SMB_OFF_T file_size = 0; + uint32_t reskey=0; + uint64_t file_size = 0; uint64_t allocation_size = 0; - uint32 len; + uint32_t len; struct timespec mdate_ts, adate_ts, create_date_ts; time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0; char *nameptr; char *last_entry_ptr; bool was_8_3; - uint32 nt_extmode; /* Used for NT connections instead of mode */ - char *fname = NULL; - struct smb_filename *smb_fname = NULL; - struct smbd_dirptr_lanman2_state state; - bool ok; + uint32_t nt_extmode; /* Used for NT connections instead of mode */ - ZERO_STRUCT(state); - state.conn = conn; - state.info_level = info_level; - state.check_mangled_names = lp_manglednames(conn->params); - state.has_wild = dptr_has_wild(dirptr); - state.got_exact_match = false; - - *out_of_space = False; - *got_exact_match = False; + *out_of_space = false; ZERO_STRUCT(mdate_ts); ZERO_STRUCT(adate_ts); ZERO_STRUCT(create_date_ts); - p = strrchr_m(path_mask,'/'); - if(p != NULL) { - if(p[1] == '\0') { - mask = "*.*"; - } else { - mask = p+1; - } - } else { - mask = path_mask; - } - - ok = smbd_dirptr_get_entry(ctx, - dirptr, - mask, - dirtype, - dont_descend, - ask_sharemode, - smbd_dirptr_lanman2_match_fn, - smbd_dirptr_lanman2_mode_fn, - &state, - &fname, - &smb_fname, - &mode, - &prev_dirpos); - if (!ok) { - return false; - } - - *got_exact_match = state.got_exact_match; - if (!(mode & aDIR)) { file_size = get_file_size_stat(&smb_fname->st); } @@ -1553,418 +1506,405 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; switch (info_level) { - case SMB_FIND_INFO_STANDARD: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n")); - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - p += 23; - nameptr = p; - if (flags2 & FLAGS2_UNICODE_STRINGS) { - p += ucs2_align(base_data, p, 0); - } - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - SCVAL(nameptr, -1, len - 2); - } else { - SCVAL(nameptr, -1, 0); - } + case SMB_FIND_INFO_STANDARD: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n")); + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); + p += 23; + nameptr = p; + if (flags2 & FLAGS2_UNICODE_STRINGS) { + p += ucs2_align(base_data, p, 0); + } + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + SCVAL(nameptr, -1, len - 2); } else { - if (len > 1) { - SCVAL(nameptr, -1, len - 1); - } else { - SCVAL(nameptr, -1, 0); - } - } - p += len; - break; - - case SMB_FIND_EA_SIZE: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - { - unsigned int ea_size = estimate_ea_size(conn, NULL, - smb_fname->base_name); - SIVAL(p,22,ea_size); /* Extended attributes */ + SCVAL(nameptr, -1, 0); } - p += 27; - nameptr = p - 1; - len = srvstr_push(base_data, flags2, - p, fname, PTR_DIFF(end_data, p), - STR_TERMINATE | STR_NOALIGN); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - len -= 2; - } else { - len = 0; - } + } else { + if (len > 1) { + SCVAL(nameptr, -1, len - 1); } else { - if (len > 1) { - len -= 1; - } else { - len = 0; - } + SCVAL(nameptr, -1, 0); } - SCVAL(nameptr,0,len); - p += len; - SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ - break; + } + p += len; + break; - case SMB_FIND_EA_LIST: + case SMB_FIND_EA_SIZE: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); + if (requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); { - struct ea_list *file_list = NULL; - size_t ea_len = 0; - - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); - if (!name_list) { - TALLOC_FREE(fname); - TALLOC_FREE(smb_fname); - return False; - } - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - p += 22; /* p now points to the EA area. */ - - file_list = get_ea_list_from_file(ctx, conn, NULL, - smb_fname->base_name, - &ea_len); - name_list = ea_list_union(name_list, file_list, &ea_len); - - /* We need to determine if this entry will fit in the space available. */ - /* Max string size is 255 bytes. */ - if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { - TALLOC_FREE(fname); - TALLOC_FREE(smb_fname); - /* Move the dirptr back to prev_dirpos */ - dptr_SeekDir(dirptr, prev_dirpos); - *out_of_space = True; - DEBUG(9,("get_lanman2_dir_entry: out of space\n")); - return False; /* Not finished - just out of space */ + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,22,ea_size); /* Extended attributes */ + } + p += 27; + nameptr = p - 1; + len = srvstr_push(base_data, flags2, + p, fname, PTR_DIFF(end_data, p), + STR_TERMINATE | STR_NOALIGN); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; } - - /* Push the ea_data followed by the name. */ - p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list); - nameptr = p; - len = srvstr_push(base_data, flags2, - p + 1, fname, PTR_DIFF(end_data, p+1), - STR_TERMINATE | STR_NOALIGN); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - len -= 2; - } else { - len = 0; - } + } else { + if (len > 1) { + len -= 1; } else { - if (len > 1) { - len -= 1; - } else { - len = 0; - } + len = 0; } - SCVAL(nameptr,0,len); - p += len + 1; - SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ - break; } + SCVAL(nameptr,0,len); + p += len; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, conn->params); + case SMB_FIND_EA_LIST: + { + struct ea_list *file_list = NULL; + size_t ea_len = 0; + + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); + if (!name_list) { + return false; + } + if (requires_resume_key) { + SIVAL(p,0,reskey); p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; /* q is placeholder for name length. */ - { - unsigned int ea_size = estimate_ea_size(conn, NULL, - smb_fname->base_name); - SIVAL(p,0,ea_size); /* Extended attributes */ - p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); + p += 22; /* p now points to the EA area. */ + + file_list = get_ea_list_from_file(ctx, conn, NULL, + smb_fname->base_name, + &ea_len); + name_list = ea_list_union(name_list, file_list, &ea_len); + + /* We need to determine if this entry will fit in the space available. */ + /* Max string size is 255 bytes. */ + if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { + *out_of_space = true; + DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + return False; /* Not finished - just out of space */ + } + + /* Push the ea_data followed by the name. */ + p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list); + nameptr = p; + len = srvstr_push(base_data, flags2, + p + 1, fname, PTR_DIFF(end_data, p+1), + STR_TERMINATE | STR_NOALIGN); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; } - /* Clear the short name buffer. This is - * IMPORTANT as not doing so will trigger - * a Win2k client bug. JRA. - */ - if (!was_8_3 && state.check_mangled_names) { - char mangled_name[13]; /* mangled 8.3 name. */ - if (!name_to_8_3(fname,mangled_name,True, - conn->params)) { - /* Error - mangle failed ! */ - memset(mangled_name,'\0',12); - } - mangled_name[12] = 0; - len = srvstr_push(base_data, flags2, - p+2, mangled_name, 24, - STR_UPPER|STR_UNICODE); - if (len < 24) { - memset(p + 2 + len,'\0',24 - len); - } - SSVAL(p, 0, len); + } else { + if (len > 1) { + len -= 1; } else { - memset(p,'\0',26); + len = 0; } - p += 2 + 24; - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q,0,len); - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + } + SCVAL(nameptr,0,len); + p += len + 1; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; + } - case SMB_FIND_FILE_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n")); + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); + was_8_3 = mangle_is_8_3(fname, True, conn->params); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; + } + /* Clear the short name buffer. This is + * IMPORTANT as not doing so will trigger + * a Win2k client bug. JRA. + */ + if (!was_8_3 && check_mangled_names) { + char mangled_name[13]; /* mangled 8.3 name. */ + if (!name_to_8_3(fname,mangled_name,True, + conn->params)) { + /* Error - mangle failed ! */ + memset(mangled_name,'\0',12); + } + mangled_name[12] = 0; len = srvstr_push(base_data, flags2, - p + 4, fname, PTR_DIFF(end_data, p+4), - STR_TERMINATE_ASCII); - SIVAL(p,0,len); - p += 4 + len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; - - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n")); - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; /* q is placeholder for name length. */ - { - unsigned int ea_size = estimate_ea_size(conn, NULL, - smb_fname->base_name); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; + p+2, mangled_name, 24, + STR_UPPER|STR_UNICODE); + if (len < 24) { + memset(p + 2 + len,'\0',24 - len); } - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q, 0, len); - p += len; + SSVAL(p, 0, len); + } else { + memset(p,'\0',26); + } + p += 2 + 24; + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(q,0,len); + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n")); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + len = srvstr_push(base_data, flags2, + p + 4, fname, PTR_DIFF(end_data, p+4), + STR_TERMINATE_ASCII); + SIVAL(p,0,len); + p += 4 + len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_FILE_NAMES_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n")); - p += 4; - SIVAL(p,0,reskey); p += 4; - p += 4; - /* this must *not* be null terminated or w2k gets in a loop trying to set an - acl on a dir (tridge) */ - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(p, -4, len); - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n")); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(q, 0, len); + p += len; + + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_ID_FULL_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n")); - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; /* q is placeholder for name length. */ - { - unsigned int ea_size = estimate_ea_size(conn, NULL, - smb_fname->base_name); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; - } - SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ - SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q, 0, len); - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_NAMES_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n")); + p += 4; + SIVAL(p,0,reskey); p += 4; + p += 4; + /* this must *not* be null terminated or w2k gets in a loop trying to set an + acl on a dir (tridge) */ + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(p, -4, len); + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_ID_BOTH_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, conn->params); - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; /* q is placeholder for name length */ - { - unsigned int ea_size = estimate_ea_size(conn, NULL, - smb_fname->base_name); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; + case SMB_FIND_ID_FULL_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n")); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ + SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(q, 0, len); + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; + + case SMB_FIND_ID_BOTH_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); + was_8_3 = mangle_is_8_3(fname, True, conn->params); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + /* Clear the short name buffer. This is + * IMPORTANT as not doing so will trigger + * a Win2k client bug. JRA. + */ + if (!was_8_3 && check_mangled_names) { + char mangled_name[13]; /* mangled 8.3 name. */ + if (!name_to_8_3(fname,mangled_name,True, + conn->params)) { + /* Error - mangle failed ! */ + memset(mangled_name,'\0',12); } - /* Clear the short name buffer. This is - * IMPORTANT as not doing so will trigger - * a Win2k client bug. JRA. - */ - if (!was_8_3 && state.check_mangled_names) { - char mangled_name[13]; /* mangled 8.3 name. */ - if (!name_to_8_3(fname,mangled_name,True, - conn->params)) { - /* Error - mangle failed ! */ - memset(mangled_name,'\0',12); - } - mangled_name[12] = 0; - len = srvstr_push(base_data, flags2, - p+2, mangled_name, 24, - STR_UPPER|STR_UNICODE); - SSVAL(p, 0, len); - if (len < 24) { - memset(p + 2 + len,'\0',24 - len); - } - SSVAL(p, 0, len); - } else { - memset(p,'\0',26); + mangled_name[12] = 0; + len = srvstr_push(base_data, flags2, + p+2, mangled_name, 24, + STR_UPPER|STR_UNICODE); + SSVAL(p, 0, len); + if (len < 24) { + memset(p + 2 + len,'\0',24 - len); } - p += 26; - SSVAL(p,0,0); p += 2; /* Reserved ? */ - SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q,0,len); - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + SSVAL(p, 0, len); + } else { + memset(p,'\0',26); + } + p += 26; + SSVAL(p,0,0); p += 2; /* Reserved ? */ + SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(q,0,len); + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - /* CIFS UNIX Extension. */ + /* CIFS UNIX Extension. */ - case SMB_FIND_FILE_UNIX: - case SMB_FIND_FILE_UNIX_INFO2: - p+= 4; - SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ + case SMB_FIND_FILE_UNIX: + case SMB_FIND_FILE_UNIX_INFO2: + p+= 4; + SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ - /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ + /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ - if (info_level == SMB_FIND_FILE_UNIX) { - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); - p = store_file_unix_basic(conn, p, - NULL, &smb_fname->st); - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE); - } else { - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); - p = store_file_unix_basic_info2(conn, p, - NULL, &smb_fname->st); - nameptr = p; - p += 4; - len = srvstr_push(base_data, flags2, p, fname, - PTR_DIFF(end_data, p), 0); - SIVAL(nameptr, 0, len); - } + if (info_level == SMB_FIND_FILE_UNIX) { + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); + p = store_file_unix_basic(conn, p, + NULL, &smb_fname->st); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE); + } else { + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); + p = store_file_unix_basic_info2(conn, p, + NULL, &smb_fname->st); + nameptr = p; + p += 4; + len = srvstr_push(base_data, flags2, p, fname, + PTR_DIFF(end_data, p), 0); + SIVAL(nameptr, 0, len); + } - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */ - p = pdata + len; - /* End of SMB_QUERY_FILE_UNIX_BASIC */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */ + p = pdata + len; + /* End of SMB_QUERY_FILE_UNIX_BASIC */ - break; + break; - default: - TALLOC_FREE(fname); - TALLOC_FREE(smb_fname); - return false; + default: + return false; } - TALLOC_FREE(fname); - TALLOC_FREE(smb_fname); - if (PTR_DIFF(p,pdata) > space_remaining) { - /* Move the dirptr back to prev_dirpos */ - dptr_SeekDir(dirptr, prev_dirpos); - *out_of_space = True; + *out_of_space = true; DEBUG(9,("get_lanman2_dir_entry: out of space\n")); - return False; /* Not finished - just out of space */ + return false; /* Not finished - just out of space */ } /* Setup the last entry pointer, as an offset from base_data */ @@ -1975,6 +1915,105 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, return true; } +static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + struct dptr_struct *dirptr, + uint16 flags2, + const char *path_mask, + uint32 dirtype, + int info_level, + int requires_resume_key, + bool dont_descend, + bool ask_sharemode, + char **ppdata, + char *base_data, + char *end_data, + int space_remaining, + bool *out_of_space, + bool *got_exact_match, + int *_last_entry_off, + struct ea_list *name_list) +{ + const char *p; + const char *mask = NULL; + long prev_dirpos = 0; + uint32_t mode = 0; + char *fname = NULL; + struct smb_filename *smb_fname = NULL; + struct smbd_dirptr_lanman2_state state; + bool ok; + uint64_t last_entry_off = 0; + + ZERO_STRUCT(state); + state.conn = conn; + state.info_level = info_level; + state.check_mangled_names = lp_manglednames(conn->params); + state.has_wild = dptr_has_wild(dirptr); + state.got_exact_match = false; + + *out_of_space = false; + *got_exact_match = false; + + p = strrchr_m(path_mask,'/'); + if(p != NULL) { + if(p[1] == '\0') { + mask = "*.*"; + } else { + mask = p+1; + } + } else { + mask = path_mask; + } + + ok = smbd_dirptr_get_entry(ctx, + dirptr, + mask, + dirtype, + dont_descend, + ask_sharemode, + smbd_dirptr_lanman2_match_fn, + smbd_dirptr_lanman2_mode_fn, + &state, + &fname, + &smb_fname, + &mode, + &prev_dirpos); + if (!ok) { + return false; + } + + *got_exact_match = state.got_exact_match; + + ok = smbd_marshall_dir_entry(ctx, + conn, + flags2, + info_level, + name_list, + state.check_mangled_names, + requires_resume_key, + mode, + fname, + smb_fname, + space_remaining, + base_data, + ppdata, + end_data, + out_of_space, + &last_entry_off); + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + if (*out_of_space) { + dptr_SeekDir(dirptr, prev_dirpos); + return false; + } + if (!ok) { + return false; + } + + *_last_entry_off = last_entry_off; + return true; +} + /**************************************************************************** Reply to a TRANS2_FINDFIRST. ****************************************************************************/ -- cgit From ea6819ae7565c22b0d6276acebfbab472a4e4c18 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Aug 2009 10:19:20 -0700 Subject: Correctly send out notify messages for timestamp changes. "change time" has no notify message, so don't send anything out when we change it. Use FILE_NOTIFY_CHANGE_CREATION correctly when changing the create time. Jeremy. --- source3/smbd/trans2.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 780d7d606c..a8b721120d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5224,7 +5224,6 @@ NTSTATUS smb_set_file_time(connection_struct *conn, FILE_NOTIFY_CHANGE_LAST_ACCESS |FILE_NOTIFY_CHANGE_LAST_WRITE; bool set_createtime = false; - bool set_ctime = false; NTSTATUS status; if (!VALID_STAT(smb_fname->st)) { @@ -5240,8 +5239,6 @@ NTSTATUS smb_set_file_time(connection_struct *conn, if (null_timespec(ft->ctime)) { ft->ctime = smb_fname->st.st_ex_ctime; - } else { - set_ctime = true; } if (null_timespec(ft->atime)) { @@ -5278,8 +5275,9 @@ NTSTATUS smb_set_file_time(connection_struct *conn, struct timespec ats = smb_fname->st.st_ex_atime; if ((timespec_compare(&ft->atime, &ats) == 0) && (timespec_compare(&ft->mtime, &mts) == 0)) { - if (set_createtime || set_ctime) { - notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE, + if (set_createtime) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_CREATION, smb_fname->base_name); } return NT_STATUS_OK; -- cgit From d296c774c5981baa863c697782dba1b6280d632e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Aug 2009 12:38:31 -0700 Subject: Move the checks for null timestamps down below the VFS_NTIMES layer (as it's done in onefs). This simplifies greatly the code in smb_set_file_time() w.r.t. changenotify messages. Jeremy. --- source3/smbd/trans2.c | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a8b721120d..2e47eab4f0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5222,8 +5222,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn, struct smb_filename *smb_fname_base = NULL; uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS - |FILE_NOTIFY_CHANGE_LAST_WRITE; - bool set_createtime = false; + |FILE_NOTIFY_CHANGE_LAST_WRITE + |FILE_NOTIFY_CHANGE_CREATION; NTSTATUS status; if (!VALID_STAT(smb_fname->st)) { @@ -5232,22 +5232,14 @@ NTSTATUS smb_set_file_time(connection_struct *conn, /* get some defaults (no modifications) if any info is zero or -1. */ if (null_timespec(ft->create_time)) { - ft->create_time = smb_fname->st.st_ex_btime; - } else { - set_createtime = true; - } - - if (null_timespec(ft->ctime)) { - ft->ctime = smb_fname->st.st_ex_ctime; + action &= ~FILE_NOTIFY_CHANGE_CREATION; } if (null_timespec(ft->atime)) { - ft->atime= smb_fname->st.st_ex_atime; action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; } if (null_timespec(ft->mtime)) { - ft->mtime = smb_fname->st.st_ex_mtime; action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } @@ -5265,25 +5257,6 @@ NTSTATUS smb_set_file_time(connection_struct *conn, DEBUG(5,("smb_set_file_time: createtime: %s\n ", time_to_asc(convert_timespec_to_time_t(ft->create_time)))); - /* - * Try and set the times of this file if - * they are different from the current values. - */ - - { - struct timespec mts = smb_fname->st.st_ex_mtime; - struct timespec ats = smb_fname->st.st_ex_atime; - if ((timespec_compare(&ft->atime, &ats) == 0) && - (timespec_compare(&ft->mtime, &mts) == 0)) { - if (set_createtime) { - notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_CREATION, - smb_fname->base_name); - } - return NT_STATUS_OK; - } - } - if (setting_write_time) { /* * This was a Windows setfileinfo on an open file. -- cgit