LCOV - code coverage report
Current view: top level - source4/torture/unix - unix_info2.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 182 229 79.5 %
Date: 2024-02-28 12:06:22 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /*
       2             :    Test the SMB_QUERY_FILE_UNIX_INFO2 Unix extension.
       3             : 
       4             :    Copyright (C) 2007 James Peach
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "libcli/libcli.h"
      22             : #include "libcli/raw/raw_proto.h"
      23             : #include "torture/util.h"
      24             : #include "torture/unix/proto.h"
      25             : #include "lib/cmdline/cmdline.h"
      26             : #include "libcli/resolve/resolve.h"
      27             : #include "param/param.h"
      28             : 
      29             : struct unix_info2 {
      30             :         uint64_t end_of_file;
      31             :         uint64_t num_bytes;
      32             :         NTTIME status_change_time;
      33             :         NTTIME access_time;
      34             :         NTTIME change_time;
      35             :         uint64_t uid;
      36             :         uint64_t gid;
      37             :         uint32_t file_type;
      38             :         uint64_t dev_major;
      39             :         uint64_t dev_minor;
      40             :         uint64_t unique_id;
      41             :         uint64_t permissions;
      42             :         uint64_t nlink;
      43             :         NTTIME create_time;
      44             :         uint32_t file_flags;
      45             :         uint32_t flags_mask;
      46             : };
      47             : 
      48           4 : static struct smbcli_state *connect_to_server(struct torture_context *tctx)
      49             : {
      50           0 :         NTSTATUS status;
      51           0 :         struct smbcli_state *cli;
      52             : 
      53           4 :         const char *host = torture_setting_string(tctx, "host", NULL);
      54           4 :         const char *share = torture_setting_string(tctx, "share", NULL);
      55           0 :         struct smbcli_options options;
      56           0 :         struct smbcli_session_options session_options;
      57           0 :         struct smb_trans2 tp;
      58           0 :         uint16_t setup;
      59           0 :         uint8_t data[12];
      60           0 :         uint8_t params[4];
      61             : 
      62           4 :         lpcfg_smbcli_options(tctx->lp_ctx, &options);
      63           4 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
      64             : 
      65           4 :         status = smbcli_full_connection(tctx, &cli, host, 
      66             :                                         lpcfg_smb_ports(tctx->lp_ctx),
      67             :                                         share, NULL, lpcfg_socket_options(tctx->lp_ctx),
      68             :                                         samba_cmdline_get_creds(),
      69             :                                         lpcfg_resolve_context(tctx->lp_ctx),
      70             :                                         tctx->ev, &options, &session_options,
      71             :                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx));
      72             : 
      73           4 :         if (!NT_STATUS_IS_OK(status)) {
      74           0 :                 torture_comment(tctx, "failed to connect to //%s/%s: %s\n",
      75             :                                host, share, nt_errstr(status));
      76           0 :                 torture_result(tctx, TORTURE_FAIL, "Failed to connect to server");
      77           0 :                 return NULL;
      78             :         }
      79             : 
      80             :         /* Setup POSIX on the server. */
      81           4 :         SSVAL(data, 0, CIFS_UNIX_MAJOR_VERSION);
      82           4 :         SSVAL(data, 2, CIFS_UNIX_MINOR_VERSION);
      83           4 :         SBVAL(data,4,((uint64_t)(
      84             :                 CIFS_UNIX_POSIX_ACLS_CAP|
      85             :                 CIFS_UNIX_POSIX_PATHNAMES_CAP|
      86             :                 CIFS_UNIX_FCNTL_LOCKS_CAP|
      87             :                 CIFS_UNIX_EXTATTR_CAP|
      88             :                 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
      89           4 :         setup = TRANSACT2_SETFSINFO;
      90           4 :         tp.in.max_setup = 0;
      91           4 :         tp.in.flags = 0;
      92           4 :         tp.in.timeout = 0;
      93           4 :         tp.in.setup_count = 1;
      94           4 :         tp.in.max_param = 0;
      95           4 :         tp.in.max_data = 0;
      96           4 :         tp.in.setup = &setup;
      97           4 :         tp.in.trans_name = NULL;
      98           4 :         SSVAL(params, 0, 0);
      99           4 :         SSVAL(params, 2, SMB_SET_CIFS_UNIX_INFO);
     100           4 :         tp.in.params = data_blob_talloc(tctx, params, 4);
     101           4 :         tp.in.data = data_blob_talloc(tctx, data, 12);
     102             : 
     103           4 :         status = smb_raw_trans2(cli->tree, tctx, &tp);
     104           4 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
     105             :                 "doing SMB_SET_CIFS_UNIX_INFO");
     106             : 
     107           4 :         return cli;
     108             : }
     109             : 
     110          16 : static bool check_unix_info2(struct torture_context *torture,
     111             :                         struct unix_info2 *info2)
     112             : {
     113          16 :         printf("\tcreate_time=0x%016llu flags=0x%08x mask=0x%08x\n",
     114          16 :                         (unsigned long long)info2->create_time,
     115             :                         info2->file_flags, info2->flags_mask);
     116             : 
     117          16 :         if (info2->file_flags == 0) {
     118          16 :                 return true;
     119             :         }
     120             : 
     121             :         /* If we have any file_flags set, they must be within the range
     122             :          * defined by flags_mask.
     123             :          */
     124           0 :         if ((info2->flags_mask & info2->file_flags) == 0) {
     125           0 :                 torture_result(torture, TORTURE_FAIL,
     126             :                         __location__": UNIX_INFO2 flags field 0x%08x, "
     127             :                         "does not match mask 0x%08x\n",
     128             :                         info2->file_flags, info2->flags_mask);
     129             :         }
     130             : 
     131           0 :         return true;
     132             : }
     133             : 
     134         132 : static NTSTATUS set_path_info2(void *mem_ctx,
     135             :                                 struct smbcli_state *cli,
     136             :                                 const char *fname,
     137             :                                 struct unix_info2 *info2)
     138             : {
     139           0 :         union smb_setfileinfo sfinfo;
     140             : 
     141         132 :         ZERO_STRUCT(sfinfo.basic_info.in);
     142         132 :         sfinfo.generic.level = RAW_SFILEINFO_UNIX_INFO2;
     143         132 :         sfinfo.generic.in.file.path = fname;
     144             : 
     145         132 :         sfinfo.unix_info2.in.end_of_file = info2->end_of_file;
     146         132 :         sfinfo.unix_info2.in.num_bytes = info2->num_bytes;
     147         132 :         sfinfo.unix_info2.in.status_change_time = info2->status_change_time;
     148         132 :         sfinfo.unix_info2.in.access_time = info2->access_time;
     149         132 :         sfinfo.unix_info2.in.change_time = info2->change_time;
     150         132 :         sfinfo.unix_info2.in.uid = info2->uid;
     151         132 :         sfinfo.unix_info2.in.gid = info2->gid;
     152         132 :         sfinfo.unix_info2.in.file_type = info2->file_type;
     153         132 :         sfinfo.unix_info2.in.dev_major = info2->dev_major;
     154         132 :         sfinfo.unix_info2.in.dev_minor = info2->dev_minor;
     155         132 :         sfinfo.unix_info2.in.unique_id = info2->unique_id;
     156         132 :         sfinfo.unix_info2.in.permissions = info2->permissions;
     157         132 :         sfinfo.unix_info2.in.nlink = info2->nlink;
     158         132 :         sfinfo.unix_info2.in.create_time = info2->create_time;
     159         132 :         sfinfo.unix_info2.in.file_flags = info2->file_flags;
     160         132 :         sfinfo.unix_info2.in.flags_mask = info2->flags_mask;
     161             : 
     162         132 :         return smb_raw_setpathinfo(cli->tree, &sfinfo);
     163             : }
     164             : 
     165          12 : static bool query_file_path_info2(void *mem_ctx,
     166             :                         struct torture_context *torture,
     167             :                         struct smbcli_state *cli,
     168             :                         int fnum,
     169             :                         const char *fname,
     170             :                         struct unix_info2 *info2)
     171             : {
     172           0 :         NTSTATUS result;
     173           0 :         union smb_fileinfo finfo;
     174             : 
     175          12 :         finfo.generic.level = RAW_FILEINFO_UNIX_INFO2;
     176             : 
     177          12 :         if (fname) {
     178           8 :                 finfo.generic.in.file.path = fname;
     179           8 :                 result = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
     180             :         } else {
     181           4 :                 finfo.generic.in.file.fnum = fnum;
     182           4 :                 result = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
     183             :         }
     184             : 
     185          12 :         torture_assert_ntstatus_equal(torture, result, NT_STATUS_OK,
     186             :                         smbcli_errstr(cli->tree));
     187             : 
     188          12 :         info2->end_of_file = finfo.unix_info2.out.end_of_file;
     189          12 :         info2->num_bytes = finfo.unix_info2.out.num_bytes;
     190          12 :         info2->status_change_time = finfo.unix_info2.out.status_change_time;
     191          12 :         info2->access_time = finfo.unix_info2.out.access_time;
     192          12 :         info2->change_time = finfo.unix_info2.out.change_time;
     193          12 :         info2->uid = finfo.unix_info2.out.uid;
     194          12 :         info2->gid = finfo.unix_info2.out.gid;
     195          12 :         info2->file_type = finfo.unix_info2.out.file_type;
     196          12 :         info2->dev_major = finfo.unix_info2.out.dev_major;
     197          12 :         info2->dev_minor = finfo.unix_info2.out.dev_minor;
     198          12 :         info2->unique_id = finfo.unix_info2.out.unique_id;
     199          12 :         info2->permissions = finfo.unix_info2.out.permissions;
     200          12 :         info2->nlink = finfo.unix_info2.out.nlink;
     201          12 :         info2->create_time = finfo.unix_info2.out.create_time;
     202          12 :         info2->file_flags = finfo.unix_info2.out.file_flags;
     203          12 :         info2->flags_mask = finfo.unix_info2.out.flags_mask;
     204             : 
     205          12 :         if (!check_unix_info2(torture, info2)) {
     206           0 :                 return false;
     207             :         }
     208             : 
     209          12 :         return true;
     210             : }
     211             : 
     212           4 : static bool query_file_info2(void *mem_ctx,
     213             :                         struct torture_context *torture,
     214             :                         struct smbcli_state *cli,
     215             :                         int fnum,
     216             :                         struct unix_info2 *info2)
     217             : {
     218           4 :         return query_file_path_info2(mem_ctx, torture, cli, 
     219             :                         fnum, NULL, info2);
     220             : }
     221             : 
     222           8 : static bool query_path_info2(void *mem_ctx,
     223             :                         struct torture_context *torture,
     224             :                         struct smbcli_state *cli,
     225             :                         const char *fname,
     226             :                         struct unix_info2 *info2)
     227             : {
     228           8 :         return query_file_path_info2(mem_ctx, torture, cli, 
     229             :                         -1, fname, info2);
     230             : }
     231             : 
     232           4 : static bool search_callback(void *private_data, const union smb_search_data *fdata)
     233             : {
     234           4 :         struct unix_info2 *info2 = (struct unix_info2 *)private_data;
     235             : 
     236           4 :         info2->end_of_file = fdata->unix_info2.end_of_file;
     237           4 :         info2->num_bytes = fdata->unix_info2.num_bytes;
     238           4 :         info2->status_change_time = fdata->unix_info2.status_change_time;
     239           4 :         info2->access_time = fdata->unix_info2.access_time;
     240           4 :         info2->change_time = fdata->unix_info2.change_time;
     241           4 :         info2->uid = fdata->unix_info2.uid;
     242           4 :         info2->gid = fdata->unix_info2.gid;
     243           4 :         info2->file_type = fdata->unix_info2.file_type;
     244           4 :         info2->dev_major = fdata->unix_info2.dev_major;
     245           4 :         info2->dev_minor = fdata->unix_info2.dev_minor;
     246           4 :         info2->unique_id = fdata->unix_info2.unique_id;
     247           4 :         info2->permissions = fdata->unix_info2.permissions;
     248           4 :         info2->nlink = fdata->unix_info2.nlink;
     249           4 :         info2->create_time = fdata->unix_info2.create_time;
     250           4 :         info2->file_flags = fdata->unix_info2.file_flags;
     251           4 :         info2->flags_mask = fdata->unix_info2.flags_mask;
     252             : 
     253           4 :         return true;
     254             : }
     255             : 
     256           4 : static bool find_single_info2(void *mem_ctx,
     257             :                         struct torture_context *torture,
     258             :                         struct smbcli_state *cli,
     259             :                         const char *fname,
     260             :                         struct unix_info2 *info2)
     261             : {
     262           0 :         union smb_search_first search;
     263           0 :         NTSTATUS status;
     264             : 
     265             :         /* Set up a new search for a single item, not using resume keys. */
     266           4 :         ZERO_STRUCT(search);
     267           4 :         search.t2ffirst.level = RAW_SEARCH_TRANS2;
     268           4 :         search.t2ffirst.data_level = SMB_FIND_UNIX_INFO2;
     269           4 :         search.t2ffirst.in.max_count = 1;
     270           4 :         search.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE;
     271           4 :         search.t2ffirst.in.pattern = fname;
     272             : 
     273           4 :         status = smb_raw_search_first(cli->tree, mem_ctx,
     274             :                                       &search, info2, search_callback);
     275           4 :         torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK,
     276             :                         smbcli_errstr(cli->tree));
     277             : 
     278           4 :         torture_assert_int_equal(torture, search.t2ffirst.out.count, 1,
     279             :                         "expected exactly one result");
     280             :         /*
     281             :          * In smbd directory listings using POSIX extensions
     282             :          * always treat the search pathname as a wildcard,
     283             :          * so don't expect end_of_search to be set here. Wildcard
     284             :          * searches always need a findnext to end the search.
     285             :          */
     286           4 :         torture_assert_int_equal(torture, search.t2ffirst.out.end_of_search, 0,
     287             :                         "expected end_of_search to be false");
     288             : 
     289           4 :         return check_unix_info2(torture, info2);
     290             : }
     291             : 
     292             : #define ASSERT_FLAGS_MATCH(info2, expected) \
     293             :         if ((info2)->file_flags != (1 << i)) { \
     294             :                 torture_result(torture, TORTURE_FAIL, \
     295             :                         __location__": INFO2 flags field was 0x%08x, "\
     296             :                                 "expected 0x%08x\n",\
     297             :                                 (info2)->file_flags, expected); \
     298             :         }
     299             : 
     300         132 : static void set_no_metadata_change(struct unix_info2 *info2)
     301             : {
     302         132 :         info2->uid = SMB_UID_NO_CHANGE;
     303         132 :         info2->gid = SMB_GID_NO_CHANGE;
     304         132 :         info2->permissions = SMB_MODE_NO_CHANGE;
     305             : 
     306         132 :         info2->end_of_file =
     307             :                 ((uint64_t)SMB_SIZE_NO_CHANGE_HI << 32) | SMB_SIZE_NO_CHANGE_LO;
     308             : 
     309         132 :         info2->status_change_time =
     310         132 :                 info2->access_time =
     311         132 :                 info2->change_time =
     312         132 :                 info2->create_time =
     313             :                 ((uint64_t)SMB_SIZE_NO_CHANGE_HI << 32) | SMB_SIZE_NO_CHANGE_LO;
     314         132 : }
     315             : 
     316           4 : static bool verify_setinfo_flags(void *mem_ctx,
     317             :                         struct torture_context *torture,
     318             :                         struct smbcli_state *cli,
     319             :                         const char *fname)
     320             : {
     321           0 :         struct unix_info2 info2;
     322           0 :         uint32_t smb_fmask;
     323           0 :         int i;
     324             : 
     325           4 :         bool ret = true;
     326           0 :         NTSTATUS status;
     327             : 
     328           4 :         if (!query_path_info2(mem_ctx, torture, cli, fname, &info2)) {
     329           0 :                 return false;
     330             :         }
     331             : 
     332           4 :         smb_fmask = info2.flags_mask;
     333             : 
     334             :         /* For each possible flag, ask to set exactly 1 flag, making sure
     335             :          * that flag is in our requested mask.
     336             :          */
     337         132 :         for (i = 0; i < 32; ++i) {
     338         128 :                 info2.file_flags = ((uint32_t)1 << i);
     339         128 :                 info2.flags_mask = smb_fmask | info2.file_flags;
     340             : 
     341         128 :                 set_no_metadata_change(&info2);
     342         128 :                 status = set_path_info2(mem_ctx, cli, fname, &info2);
     343             : 
     344         128 :                 if (info2.file_flags & smb_fmask) {
     345           0 :                         torture_assert_ntstatus_equal(torture,
     346             :                                         status, NT_STATUS_OK,
     347             :                                         "setting valid UNIX_INFO2 flag");
     348             : 
     349           0 :                         if (!query_path_info2(mem_ctx, torture, cli,
     350             :                                                 fname, &info2)) {
     351           0 :                                 return false;
     352             :                         }
     353             : 
     354           0 :                         ASSERT_FLAGS_MATCH(&info2, 1 << i);
     355             : 
     356             : 
     357             :                 } else {
     358             :                         /* We tried to set a flag the server doesn't
     359             :                          * understand.
     360             :                          */
     361         128 :                         torture_assert_ntstatus_equal(torture,
     362             :                                         status, NT_STATUS_INVALID_PARAMETER,
     363             :                                         "setting invalid UNIX_INFO2 flag");
     364             :                 }
     365             :         }
     366             : 
     367             :         /* Make sure that a zero flags field does nothing. */
     368           4 :         set_no_metadata_change(&info2);
     369           4 :         info2.file_flags = 0xFFFFFFFF;
     370           4 :         info2.flags_mask = 0;
     371           4 :         status = set_path_info2(mem_ctx, cli, fname, &info2);
     372           4 :         torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK,
     373             :                         "setting empty flags mask");
     374             : 
     375           4 :         return ret;
     376             : 
     377             : }
     378             : 
     379           4 : static int create_file(struct smbcli_state *cli, const char * fname)
     380             : {
     381             : 
     382           4 :         return smbcli_nt_create_full(cli->tree, fname, 0,
     383             :                 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
     384             :                 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF,
     385             :                 0, 0);
     386             : }
     387             : 
     388           8 : static bool match_info2(struct torture_context *torture,
     389             :                 const struct unix_info2 *pinfo,
     390             :                 const struct unix_info2 *finfo)
     391             : {
     392           8 :         printf("checking results match\n");
     393             : 
     394           8 :         torture_assert_u64_equal(torture, finfo->end_of_file, 0,
     395             :                         "end_of_file should be 0");
     396           8 :         torture_assert_u64_equal(torture, finfo->num_bytes, 0,
     397             :                         "num_bytes should be 0");
     398             : 
     399           8 :         torture_assert_u64_equal(torture, finfo->end_of_file,
     400             :                         pinfo->end_of_file, "end_of_file mismatch");
     401           8 :         torture_assert_u64_equal(torture, finfo->num_bytes, pinfo->num_bytes,
     402             :                         "num_bytes mismatch");
     403             : 
     404             :         /* Don't match access_time. */
     405             : 
     406           8 :         torture_assert_u64_equal(torture, finfo->status_change_time,
     407             :                         pinfo->status_change_time,
     408             :                         "status_change_time mismatch");
     409           8 :         torture_assert_u64_equal(torture, finfo->change_time,
     410             :                         pinfo->change_time, "change_time mismatch");
     411             : 
     412           8 :         torture_assert_u64_equal(torture, finfo->uid, pinfo->uid,
     413             :                         "UID mismatch");
     414           8 :         torture_assert_u64_equal(torture, finfo->gid, pinfo->gid,
     415             :                         "GID mismatch");
     416           8 :         torture_assert_int_equal(torture, finfo->file_type, pinfo->file_type,
     417             :                         "file_type mismatch");
     418           8 :         torture_assert_u64_equal(torture, finfo->dev_major, pinfo->dev_major,
     419             :                         "dev_major mismatch");
     420           8 :         torture_assert_u64_equal(torture, finfo->dev_minor, pinfo->dev_minor,
     421             :                         "dev_minor mismatch");
     422           8 :         torture_assert_u64_equal(torture, finfo->unique_id, pinfo->unique_id,
     423             :                         "unique_id mismatch");
     424           8 :         torture_assert_u64_equal(torture, finfo->permissions,
     425             :                         pinfo->permissions, "permissions mismatch");
     426           8 :         torture_assert_u64_equal(torture, finfo->nlink, pinfo->nlink,
     427             :                         "nlink mismatch");
     428           8 :         torture_assert_u64_equal(torture, finfo->create_time, pinfo->create_time,
     429             :                         "create_time mismatch");
     430             : 
     431           8 :         return true;
     432             : }
     433             : 
     434             : 
     435             : #define FILENAME "\\smb_unix_info2.txt"
     436             : 
     437           4 : bool unix_torture_unix_info2(struct torture_context *torture)
     438             : {
     439           0 :         void *mem_ctx;
     440           0 :         struct smbcli_state *cli;
     441           0 :         int fnum;
     442             : 
     443           0 :         struct unix_info2 pinfo, finfo;
     444             : 
     445           4 :         mem_ctx = talloc_init("smb_query_unix_info2");
     446           4 :         torture_assert(torture, mem_ctx != NULL, "out of memory");
     447             : 
     448           4 :         if (!(cli = connect_to_server(torture))) {
     449           0 :                 talloc_free(mem_ctx);
     450           0 :                 return false;
     451             :         }
     452             : 
     453           4 :         smbcli_unlink(cli->tree, FILENAME);
     454             : 
     455           4 :         fnum = create_file(cli, FILENAME);
     456           4 :         torture_assert(torture, fnum != -1, smbcli_errstr(cli->tree));
     457             : 
     458           4 :         printf("checking SMB_QFILEINFO_UNIX_INFO2 for QueryFileInfo\n");
     459           4 :         if (!query_file_info2(mem_ctx, torture, cli, fnum, &finfo)) {
     460           0 :                 goto fail;
     461             :         }
     462             : 
     463           4 :         printf("checking SMB_QFILEINFO_UNIX_INFO2 for QueryPathInfo\n");
     464           4 :         if (!query_path_info2(mem_ctx, torture, cli, FILENAME, &pinfo)) {
     465           0 :                 goto fail;
     466             :         }
     467             : 
     468           4 :         if (!match_info2(torture, &pinfo, &finfo)) {
     469           0 :                 goto fail;
     470             :         }
     471             : 
     472           4 :         printf("checking SMB_FIND_UNIX_INFO2 for FindFirst\n");
     473           4 :         if (!find_single_info2(mem_ctx, torture, cli, FILENAME, &pinfo)) {
     474           0 :                 goto fail;
     475             :         }
     476             : 
     477           4 :         if (!match_info2(torture, &pinfo, &finfo)) {
     478           0 :                 goto fail;
     479             :         }
     480             : 
     481             :         /* XXX: should repeat this test with SetFileInfo. */
     482           4 :         printf("checking SMB_SFILEINFO_UNIX_INFO2 for SetPathInfo\n");
     483           4 :         if (!verify_setinfo_flags(mem_ctx, torture, cli, FILENAME)) {
     484           0 :                 goto fail;
     485             :         }
     486             : 
     487           4 :         smbcli_close(cli->tree, fnum);
     488           4 :         smbcli_unlink(cli->tree, FILENAME);
     489           4 :         torture_close_connection(cli);
     490           4 :         talloc_free(mem_ctx);
     491           4 :         return true;
     492             : 
     493           0 : fail:
     494             : 
     495           0 :         smbcli_close(cli->tree, fnum);
     496           0 :         smbcli_unlink(cli->tree, FILENAME);
     497           0 :         torture_close_connection(cli);
     498           0 :         talloc_free(mem_ctx);
     499           0 :         return false;
     500             : 
     501             : }
     502             : 
     503             : /* vim: set sts=8 sw=8 : */

Generated by: LCOV version 1.14