1/* 2 Unix SMB/CIFS implementation. 3 RAW_CLOSE_* individual test suite 4 Copyright (C) Andrew Tridgell 2003 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 "torture/torture.h" 22#include "system/time.h" 23#include "libcli/raw/libcliraw.h" 24#include "libcli/raw/raw_proto.h" 25#include "libcli/libcli.h" 26#include "torture/util.h" 27 28/** 29 * basic testing of all RAW_CLOSE_* calls 30*/ 31bool torture_raw_close(struct torture_context *torture, 32 struct smbcli_state *cli) 33{ 34 bool ret = true; 35 union smb_close io; 36 union smb_flush io_flush; 37 int fnum; 38 const char *fname = "\\torture_close.txt"; 39 time_t basetime = (time(NULL) + 3*86400) & ~1; 40 union smb_fileinfo finfo, finfo2; 41 NTSTATUS status; 42 43#define REOPEN do { \ 44 fnum = create_complex_file(cli, torture, fname); \ 45 if (fnum == -1) { \ 46 printf("(%d) Failed to create %s\n", __LINE__, fname); \ 47 ret = false; \ 48 goto done; \ 49 }} while (0) 50 51#define CHECK_STATUS(status, correct) do { \ 52 if (!NT_STATUS_EQUAL(status, correct)) { \ 53 printf("(%d) Incorrect status %s - should be %s\n", \ 54 __LINE__, nt_errstr(status), nt_errstr(correct)); \ 55 ret = false; \ 56 goto done; \ 57 }} while (0) 58 59 REOPEN; 60 61 io.close.level = RAW_CLOSE_CLOSE; 62 io.close.in.file.fnum = fnum; 63 io.close.in.write_time = basetime; 64 status = smb_raw_close(cli->tree, &io); 65 CHECK_STATUS(status, NT_STATUS_OK); 66 67 status = smb_raw_close(cli->tree, &io); 68 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); 69 70 printf("testing close.in.write_time\n"); 71 72 /* the file should have the write time set */ 73 finfo.generic.level = RAW_FILEINFO_ALL_INFO; 74 finfo.generic.in.file.path = fname; 75 status = smb_raw_pathinfo(cli->tree, torture, &finfo); 76 CHECK_STATUS(status, NT_STATUS_OK); 77 78 if (basetime != nt_time_to_unix(finfo.all_info.out.write_time)) { 79 printf("Incorrect write time on file - %s - %s\n", 80 timestring(torture, basetime), 81 nt_time_string(torture, finfo.all_info.out.write_time)); 82 dump_all_info(torture, &finfo); 83 ret = false; 84 } 85 86 printf("testing other times\n"); 87 88 /* none of the other times should be set to that time */ 89 if (nt_time_equal(&finfo.all_info.out.write_time, 90 &finfo.all_info.out.access_time) || 91 nt_time_equal(&finfo.all_info.out.write_time, 92 &finfo.all_info.out.create_time) || 93 nt_time_equal(&finfo.all_info.out.write_time, 94 &finfo.all_info.out.change_time)) { 95 printf("Incorrect times after close - only write time should be set\n"); 96 dump_all_info(torture, &finfo); 97 98 if (!torture_setting_bool(torture, "samba3", false)) { 99 /* 100 * In Samba3 as of 3.0.23d we don't yet support all 101 * file times, so don't mark this as a critical 102 * failure 103 */ 104 ret = false; 105 } 106 } 107 108 109 smbcli_unlink(cli->tree, fname); 110 REOPEN; 111 112 finfo2.generic.level = RAW_FILEINFO_ALL_INFO; 113 finfo2.generic.in.file.path = fname; 114 status = smb_raw_pathinfo(cli->tree, torture, &finfo2); 115 CHECK_STATUS(status, NT_STATUS_OK); 116 117 io.close.level = RAW_CLOSE_CLOSE; 118 io.close.in.file.fnum = fnum; 119 io.close.in.write_time = 0; 120 status = smb_raw_close(cli->tree, &io); 121 CHECK_STATUS(status, NT_STATUS_OK); 122 123 /* the file should have the write time set equal to access time */ 124 finfo.generic.level = RAW_FILEINFO_ALL_INFO; 125 finfo.generic.in.file.path = fname; 126 status = smb_raw_pathinfo(cli->tree, torture, &finfo); 127 CHECK_STATUS(status, NT_STATUS_OK); 128 129 if (!nt_time_equal(&finfo.all_info.out.write_time, 130 &finfo2.all_info.out.write_time)) { 131 printf("Incorrect write time on file - 0 time should be ignored\n"); 132 dump_all_info(torture, &finfo); 133 ret = false; 134 } 135 136 printf("testing splclose\n"); 137 138 /* check splclose on a file */ 139 REOPEN; 140 io.splclose.level = RAW_CLOSE_SPLCLOSE; 141 io.splclose.in.file.fnum = fnum; 142 status = smb_raw_close(cli->tree, &io); 143 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRerror)); 144 145 printf("testing flush\n"); 146 smbcli_close(cli->tree, fnum); 147 148 io_flush.flush.level = RAW_FLUSH_FLUSH; 149 io_flush.flush.in.file.fnum = fnum; 150 status = smb_raw_flush(cli->tree, &io_flush); 151 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); 152 153 io_flush.flush_all.level = RAW_FLUSH_ALL; 154 status = smb_raw_flush(cli->tree, &io_flush); 155 CHECK_STATUS(status, NT_STATUS_OK); 156 157 REOPEN; 158 159 io_flush.flush.level = RAW_FLUSH_FLUSH; 160 io_flush.flush.in.file.fnum = fnum; 161 status = smb_raw_flush(cli->tree, &io_flush); 162 CHECK_STATUS(status, NT_STATUS_OK); 163 164 printf("Testing SMBexit\n"); 165 smb_raw_exit(cli->session); 166 167 io_flush.flush.level = RAW_FLUSH_FLUSH; 168 io_flush.flush.in.file.fnum = fnum; 169 status = smb_raw_flush(cli->tree, &io_flush); 170 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); 171 172 173done: 174 smbcli_close(cli->tree, fnum); 175 smbcli_unlink(cli->tree, fname); 176 return ret; 177} 178