static bool print_printjob(struct torture_context *tctx, struct smbcli_tree *tree) { int fnum; DATA_BLOB data; ssize_t size_written; const char *str; torture_comment(tctx, "creating printjob %s\n", TORTURE_PRINT_FILE); fnum = smbcli_open(tree, TORTURE_PRINT_FILE, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE); if (fnum == -1) { torture_fail(tctx, "failed to open file"); } str = talloc_asprintf(tctx, "TortureTestPage: %d\nData\n",0); data = data_blob_string_const(str); size_written = smbcli_write(tree, fnum, 0, data.data, 0, data.length); if (size_written != data.length) { torture_fail(tctx, "failed to write file"); } torture_assert_ntstatus_ok(tctx, smbcli_close(tree, fnum), "failed to close file"); return true; }
static int /* O - 0 = success, non-0 = failure */ smb_print(struct smbcli_state *cli, /* I - SMB connection */ char *title, /* I - Title/job name */ FILE *fp) /* I - File to print */ { int fnum; /* File number */ int nbytes, /* Number of bytes read */ tbytes; /* Total bytes read */ char buffer[8192], /* Buffer for copy */ *ptr; /* Pointer into tile */ /* * Sanitize the title... */ for (ptr = title; *ptr; ptr ++) if (!isalnum((int)*ptr) && !isspace((int)*ptr)) *ptr = '_'; /* * Open the printer device... */ if ((fnum = smbcli_open(cli, title, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE)) == -1) { fprintf(stderr, "ERROR: %s opening remote file %s\n", smbcli_errstr(cli), title); return (1); } /* * Copy the file to the printer... */ if (fp != stdin) rewind(fp); tbytes = 0; while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { if (smbcli_write(cli, fnum, 0, buffer, tbytes, nbytes) != nbytes) { fprintf(stderr, "ERROR: Error writing file: %s\n", smbcli_errstr(cli)); break; } tbytes += nbytes; } if (!smbcli_close(cli, fnum)) { fprintf(stderr, "ERROR: %s closing remote file %s\n", smbcli_errstr(cli), title); return (1); } else return (0); }
/** sometimes we need a fairly complex file to work with, so we can test all possible attributes. */ _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *fname) { int fnum; char buf[7] = "abc"; union smb_setfileinfo setfile; union smb_fileinfo fileinfo; time_t t = (time(NULL) & ~1); NTSTATUS status; smbcli_unlink(cli->tree, fname); fnum = smbcli_nt_create_full(cli->tree, fname, 0, SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_DELETE| NTCREATEX_SHARE_ACCESS_READ| NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0); if (fnum == -1) return -1; smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)); if (strchr(fname, ':') == NULL) { /* setup some EAs */ setfile.generic.level = RAW_SFILEINFO_EA_SET; setfile.generic.in.file.fnum = fnum; setfile.ea_set.in.num_eas = 2; setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2); setfile.ea_set.in.eas[0].flags = 0; setfile.ea_set.in.eas[0].name.s = "EAONE"; setfile.ea_set.in.eas[0].value = data_blob_talloc(mem_ctx, "VALUE1", 6); setfile.ea_set.in.eas[1].flags = 0; setfile.ea_set.in.eas[1].name.s = "SECONDEA"; setfile.ea_set.in.eas[1].value = data_blob_talloc(mem_ctx, "ValueTwo", 8); status = smb_raw_setfileinfo(cli->tree, &setfile); if (!NT_STATUS_IS_OK(status)) { printf("Failed to setup EAs\n"); } }
/* test seek ops */ static BOOL test_seek(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { union smb_seek io; union smb_fileinfo finfo; union smb_setfileinfo sfinfo; NTSTATUS status; BOOL ret = True; int fnum, fnum2; const char *fname = BASEDIR "\\test.txt"; uint8_t c[2]; if (!torture_setup_dir(cli, BASEDIR)) { return False; } fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE); if (fnum == -1) { printf("Failed to open test.txt - %s\n", smbcli_errstr(cli->tree)); ret = False; goto done; } finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.fnum = fnum; printf("Trying bad handle\n"); io.lseek.in.file.fnum = fnum+1; io.lseek.in.mode = SEEK_MODE_START; io.lseek.in.offset = 0; status = smb_raw_seek(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); printf("Trying simple seek\n"); io.lseek.in.file.fnum = fnum; io.lseek.in.mode = SEEK_MODE_START; io.lseek.in.offset = 17; status = smb_raw_seek(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.lseek.out.offset, 17); status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 0); printf("Trying relative seek\n"); io.lseek.in.file.fnum = fnum; io.lseek.in.mode = SEEK_MODE_CURRENT; io.lseek.in.offset = -3; status = smb_raw_seek(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.lseek.out.offset, 14); printf("Trying end seek\n"); io.lseek.in.file.fnum = fnum; io.lseek.in.mode = SEEK_MODE_END; io.lseek.in.offset = 0; status = smb_raw_seek(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.all_info.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.lseek.out.offset, finfo.all_info.out.size); printf("Trying max seek\n"); io.lseek.in.file.fnum = fnum; io.lseek.in.mode = SEEK_MODE_START; io.lseek.in.offset = -1; status = smb_raw_seek(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.lseek.out.offset, 0xffffffff); printf("Testing position information change\n"); finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 0); printf("Trying max overflow\n"); io.lseek.in.file.fnum = fnum; io.lseek.in.mode = SEEK_MODE_CURRENT; io.lseek.in.offset = 1000; status = smb_raw_seek(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.lseek.out.offset, 999); printf("Testing position information change\n"); finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 0); printf("trying write to update offset\n"); ZERO_STRUCT(c); if (smbcli_write(cli->tree, fnum, 0, c, 0, 2) != 2) { printf("Write failed - %s\n", smbcli_errstr(cli->tree)); ret = False; goto done; } printf("Testing position information change\n"); finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 0); io.lseek.in.file.fnum = fnum; io.lseek.in.mode = SEEK_MODE_CURRENT; io.lseek.in.offset = 0; status = smb_raw_seek(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.lseek.out.offset, 2); if (smbcli_read(cli->tree, fnum, c, 0, 1) != 1) { printf("Read failed - %s\n", smbcli_errstr(cli->tree)); ret = False; goto done; } printf("Testing position information change\n"); finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 1); status = smb_raw_seek(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.lseek.out.offset, 1); printf("Testing position information\n"); fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE); if (fnum2 == -1) { printf("2nd open failed - %s\n", smbcli_errstr(cli->tree)); ret = False; goto done; } sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION; sfinfo.position_information.in.file.fnum = fnum2; sfinfo.position_information.in.position = 25; status = smb_raw_setfileinfo(cli->tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.fnum = fnum2; status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 25); finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.fnum = fnum; status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 1); printf("position_information via paths\n"); sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION; sfinfo.position_information.in.file.path = fname; sfinfo.position_information.in.position = 32; status = smb_raw_setpathinfo(cli->tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.fnum = fnum2; status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 25); finfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; finfo.position_information.in.file.path = fname; status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.position_information.out.position, 0); done: smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); return ret; }
/* test SMBntrename ops */ static bool test_ntrename(struct torture_context *tctx, struct smbcli_state *cli) { union smb_rename io; NTSTATUS status; bool ret = true; int fnum, i; const char *fname1 = BASEDIR "\\test1.txt"; const char *fname2 = BASEDIR "\\test2.txt"; union smb_fileinfo finfo; torture_comment(tctx, "Testing SMBntrename\n"); if (!torture_setup_dir(cli, BASEDIR)) { return false; } torture_comment(tctx, "Trying simple rename\n"); fnum = create_complex_file(cli, tctx, fname1); io.generic.level = RAW_RENAME_NTRENAME; io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.cluster_size = 0; io.ntrename.in.flags = RENAME_FLAG_RENAME; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); smbcli_close(cli->tree, fnum); status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "Trying self rename\n"); io.ntrename.in.old_name = fname2; io.ntrename.in.new_name = fname2; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname1; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); torture_comment(tctx, "trying wildcard rename\n"); io.ntrename.in.old_name = BASEDIR "\\*.txt"; io.ntrename.in.new_name = fname1; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); torture_comment(tctx, "Checking attrib handling\n"); torture_set_file_attribute(cli->tree, fname2, FILE_ATTRIBUTE_HIDDEN); io.ntrename.in.old_name = fname2; io.ntrename.in.new_name = fname1; io.ntrename.in.attrib = 0; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE); io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL); torture_comment(tctx, "Checking hard link\n"); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.flags = RENAME_FLAG_HARD_LINK; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.path = fname2; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 2); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM); finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 2); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL); smbcli_unlink(cli->tree, fname2); finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL); torture_comment(tctx, "Checking copy\n"); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.flags = RENAME_FLAG_COPY; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.path = fname2; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM); finfo.generic.level = RAW_FILEINFO_ALL_INFO; finfo.generic.in.file.path = fname2; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL); finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM); torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL); smbcli_unlink(cli->tree, fname2); finfo.generic.in.file.path = fname1; status = smb_raw_pathinfo(cli->tree, tctx, &finfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(finfo.all_info.out.nlink, 1); torture_comment(tctx, "Checking invalid flags\n"); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.flags = 0; status = smb_raw_rename(cli->tree, &io); if (TARGET_IS_WIN7(tctx)) { CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } io.ntrename.in.flags = 300; status = smb_raw_rename(cli->tree, &io); if (TARGET_IS_WIN7(tctx)) { CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } io.ntrename.in.flags = 0x106; status = smb_raw_rename(cli->tree, &io); if (TARGET_IS_WIN7(tctx)) { CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "Checking unknown field\n"); io.ntrename.in.old_name = fname1; io.ntrename.in.new_name = fname2; io.ntrename.in.attrib = 0; io.ntrename.in.flags = RENAME_FLAG_RENAME; io.ntrename.in.cluster_size = 0xff; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n"); io.ntrename.in.old_name = fname2; io.ntrename.in.new_name = fname1; io.ntrename.in.attrib = 0; io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION; io.ntrename.in.cluster_size = 1; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); io.ntrename.in.flags = RENAME_FLAG_COPY; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); #if 0 { char buf[16384]; fnum = smbcli_open(cli->tree, fname1, O_RDWR, DENY_NONE); memset(buf, 1, sizeof(buf)); smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)); smbcli_close(cli->tree, fnum); fnum = smbcli_open(cli->tree, fname2, O_RDWR, DENY_NONE); memset(buf, 1, sizeof(buf)); smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)-1); smbcli_close(cli->tree, fnum); torture_all_info(cli->tree, fname1); torture_all_info(cli->tree, fname2); } io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION; status = smb_raw_rename(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); for (i=0; i<20000; i++) { io.ntrename.in.cluster_size = i; status = smb_raw_rename(cli->tree, &io); if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { torture_warning(tctx, "i=%d status=%s\n", i, nt_errstr(status)); } } #endif torture_comment(tctx, "Checking other flags\n"); for (i=0; i<0xFFF; i++) { if (i == RENAME_FLAG_RENAME || i == RENAME_FLAG_HARD_LINK || i == RENAME_FLAG_COPY) { continue; } io.ntrename.in.old_name = fname2; io.ntrename.in.new_name = fname1; io.ntrename.in.flags = i; io.ntrename.in.attrib = 0; io.ntrename.in.cluster_size = 0; status = smb_raw_rename(cli->tree, &io); if (TARGET_IS_WIN7(tctx)) { if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { torture_warning(tctx, "flags=0x%x status=%s\n", i, nt_errstr(status)); } } else { if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { torture_warning(tctx, "flags=0x%x status=%s\n", i, nt_errstr(status)); } } } done: smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); return ret; }
/* test offline file handling */ bool torture_test_offline(struct torture_context *torture) { bool ret = true; TALLOC_CTX *mem_ctx = talloc_new(torture); int i; int timelimit = torture_setting_int(torture, "timelimit", 10); struct timeval tv; struct offline_state *state; struct smbcli_state *cli; bool progress; progress = torture_setting_bool(torture, "progress", true); nconnections = torture_setting_int(torture, "nprocs", 4); numstates = nconnections * torture_entries; state = talloc_zero_array(mem_ctx, struct offline_state, numstates); printf("Opening %d connections with %d simultaneous operations and %u files\n", nconnections, numstates, torture_numops); for (i=0;i<nconnections;i++) { state[i].tctx = torture; state[i].mem_ctx = talloc_new(state); state[i].ev = torture->ev; if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) { return false; } state[i].tree = cli->tree; state[i].client = i; /* allow more time for offline files */ state[i].tree->session->transport->options.request_timeout = 200; } /* the others are repeats on the earlier connections */ for (i=nconnections;i<numstates;i++) { state[i].tctx = torture; state[i].mem_ctx = talloc_new(state); state[i].ev = torture->ev; state[i].tree = state[i % nconnections].tree; state[i].client = i; } num_connected = i; if (!torture_setup_dir(cli, BASEDIR)) { goto failed; } /* pre-create files */ printf("Pre-creating %u files ....\n", torture_numops); for (i=0;i<torture_numops;i++) { int fnum; char *fname = filename(mem_ctx, i); char buf[FILE_SIZE]; NTSTATUS status; memset(buf, 1+(i % 255), sizeof(buf)); fnum = smbcli_open(state[0].tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { printf("Failed to open %s on connection %d\n", fname, i); goto failed; } if (smbcli_write(state[0].tree, fnum, 0, buf, 0, sizeof(buf)) != sizeof(buf)) { printf("Failed to write file of size %u\n", FILE_SIZE); goto failed; } status = smbcli_close(state[0].tree, fnum); if (!NT_STATUS_IS_OK(status)) { printf("Close failed - %s\n", nt_errstr(status)); goto failed; } talloc_free(fname); } /* start the async ops */ for (i=0;i<numstates;i++) { state[i].tv_start = timeval_current(); test_offline(&state[i]); } tv = timeval_current(); if (progress) { event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state); } printf("Running for %d seconds\n", timelimit); while (timeval_elapsed(&tv) < timelimit) { event_loop_once(torture->ev); if (test_failed) { DEBUG(0,("test failed\n")); goto failed; } } printf("\nWaiting for completion\n"); test_finished = true; for (i=0;i<numstates;i++) { while (state[i].loadfile || state[i].savefile || state[i].req) { event_loop_once(torture->ev); } } printf("worst latencies: set_lat=%.1f get_lat=%.1f save_lat=%.1f load_lat=%.1f\n", worst_latencies[OP_SETOFFLINE], worst_latencies[OP_GETOFFLINE], worst_latencies[OP_SAVEFILE], worst_latencies[OP_LOADFILE]); smbcli_deltree(state[0].tree, BASEDIR); talloc_free(mem_ctx); printf("\n"); return ret; failed: talloc_free(mem_ctx); return false; }
bool torture_casetable(struct torture_context *tctx, struct smbcli_state *cli) { char *fname; int fnum; int c, i; #define MAX_EQUIVALENCE 8 codepoint_t equiv[0x10000][MAX_EQUIVALENCE]; torture_comment(tctx, "Determining upper/lower case table\n"); memset(equiv, 0, sizeof(equiv)); torture_assert(tctx, torture_setup_dir(cli, "\\utable"), "Error setting up dir \\utable"); for (c=1; c < 0x10000; c++) { size_t size; if (c == '.' || c == '\\') continue; torture_comment(tctx, "%04x (%c)\n", c, isprint(c)?c:'.'); fname = form_name(lp_iconv_convenience(tctx->lp_ctx), c); fnum = smbcli_nt_create_full(cli->tree, fname, 0, #if 0 SEC_RIGHT_MAXIMUM_ALLOWED, #else SEC_RIGHTS_FILE_ALL, #endif FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0); torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "Failed to create file with char %04x\n", c)); size = 0; if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, NULL, NULL, NULL, NULL, NULL))) continue; if (size > 0) { /* found a character equivalence! */ int c2[MAX_EQUIVALENCE]; if (size/sizeof(int) >= MAX_EQUIVALENCE) { torture_comment(tctx, "too many chars match?? size=%d c=0x%04x\n", (int)size, c); smbcli_close(cli->tree, fnum); return false; } smbcli_read(cli->tree, fnum, c2, 0, size); torture_comment(tctx, "%04x: ", c); equiv[c][0] = c; for (i=0; i<size/sizeof(int); i++) { torture_comment(tctx, "%04x ", c2[i]); equiv[c][i+1] = c2[i]; } torture_comment(tctx, "\n"); } smbcli_write(cli->tree, fnum, 0, &c, size, sizeof(c)); smbcli_close(cli->tree, fnum); } smbcli_unlink(cli->tree, "\\utable\\*"); smbcli_rmdir(cli->tree, "\\utable"); return true; }
static bool rw_torture(struct torture_context *tctx, struct smbcli_state *c) { const char *lockfname = "\\torture.lck"; char *fname; int fnum; int fnum2; pid_t pid2, pid = getpid(); int i, j; uint8_t buf[1024]; bool correct = true; fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE); if (fnum2 == -1) fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE); if (fnum2 == -1) { torture_comment(tctx, "open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree)); return false; } generate_random_buffer(buf, sizeof(buf)); for (i=0;i<torture_numops;i++) { uint_t n = (uint_t)random()%10; if (i % 10 == 0) { if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "%d\r", i); fflush(stdout); } } asprintf(&fname, "\\torture.%u", n); if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) { return false; } fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL); if (fnum == -1) { torture_comment(tctx, "open failed (%s)\n", smbcli_errstr(c->tree)); correct = false; break; } if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) { torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } for (j=0;j<50;j++) { if (smbcli_write(c->tree, fnum, 0, buf, sizeof(pid)+(j*sizeof(buf)), sizeof(buf)) != sizeof(buf)) { torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } } pid2 = 0; if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) { torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } if (pid2 != pid) { torture_comment(tctx, "data corruption!\n"); correct = false; } if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) { torture_comment(tctx, "close failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) { torture_comment(tctx, "unlink failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) { torture_comment(tctx, "unlock failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } free(fname); } smbcli_close(c->tree, fnum2); smbcli_unlink(c->tree, lockfname); torture_comment(tctx, "%d\n", i); return correct; }
/* test read ops */ static BOOL test_read(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { union smb_read io; NTSTATUS status; BOOL ret = True; int fnum; uint8_t *buf; const int maxsize = 90000; const char *fname = BASEDIR "\\test.txt"; const char *test_data = "TEST DATA"; uint_t seed = time(NULL); buf = talloc_zero_size(mem_ctx, maxsize); if (!torture_setup_dir(cli, BASEDIR)) { return False; } printf("Testing RAW_READ_READ\n"); io.generic.level = RAW_READ_READ; fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)); ret = False; goto done; } printf("Trying empty file read\n"); io.read.in.file.fnum = fnum; io.read.in.count = 1; io.read.in.offset = 0; io.read.in.remaining = 0; io.read.out.data = buf; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.read.out.nread, 0); printf("Trying zero file read\n"); io.read.in.count = 0; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.read.out.nread, 0); printf("Trying bad fnum\n"); io.read.in.file.fnum = fnum+1; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); io.read.in.file.fnum = fnum; smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data)); printf("Trying small read\n"); io.read.in.file.fnum = fnum; io.read.in.offset = 0; io.read.in.remaining = 0; io.read.in.count = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.read.out.nread, strlen(test_data)); if (memcmp(buf, test_data, strlen(test_data)) != 0) { ret = False; printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf); goto done; } printf("Trying short read\n"); io.read.in.offset = 1; io.read.in.count = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.read.out.nread, strlen(test_data)-1); if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) { ret = False; printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf); goto done; } if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) { printf("Trying max offset\n"); io.read.in.offset = ~0; io.read.in.count = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.read.out.nread, 0); } setup_buffer(buf, seed, maxsize); smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize); memset(buf, 0, maxsize); printf("Trying large read\n"); io.read.in.offset = 0; io.read.in.count = ~0; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_BUFFER(buf, seed, io.read.out.nread); printf("Trying locked region\n"); cli->session->pid++; if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) { printf("Failed to lock file at %d\n", __LINE__); ret = False; goto done; } cli->session->pid--; memset(buf, 0, maxsize); io.read.in.offset = 0; io.read.in.count = ~0; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); done: smbcli_close(cli->tree, fnum); smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); return ret; }
/* test readx ops */ static BOOL test_readx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { union smb_read io; NTSTATUS status; BOOL ret = True; int fnum; uint8_t *buf; const int maxsize = 90000; const char *fname = BASEDIR "\\test.txt"; const char *test_data = "TEST DATA"; uint_t seed = time(NULL); buf = talloc_zero_size(mem_ctx, maxsize); if (!torture_setup_dir(cli, BASEDIR)) { return False; } printf("Testing RAW_READ_READX\n"); fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)); ret = False; goto done; } printf("Trying empty file read\n"); io.generic.level = RAW_READ_READX; io.readx.in.file.fnum = fnum; io.readx.in.mincnt = 1; io.readx.in.maxcnt = 1; io.readx.in.offset = 0; io.readx.in.remaining = 0; io.readx.in.read_for_execute = False; io.readx.out.data = buf; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); printf("Trying zero file read\n"); io.readx.in.mincnt = 0; io.readx.in.maxcnt = 0; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); printf("Trying bad fnum\n"); io.readx.in.file.fnum = fnum+1; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); io.readx.in.file.fnum = fnum; smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data)); printf("Trying small read\n"); io.readx.in.file.fnum = fnum; io.readx.in.offset = 0; io.readx.in.remaining = 0; io.readx.in.read_for_execute = False; io.readx.in.mincnt = strlen(test_data); io.readx.in.maxcnt = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, strlen(test_data)); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); if (memcmp(buf, test_data, strlen(test_data)) != 0) { ret = False; printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf); goto done; } printf("Trying short read\n"); io.readx.in.offset = 1; io.readx.in.mincnt = strlen(test_data); io.readx.in.maxcnt = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, strlen(test_data)-1); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) { ret = False; printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf); goto done; } if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) { printf("Trying max offset\n"); io.readx.in.offset = 0xffffffff; io.readx.in.mincnt = strlen(test_data); io.readx.in.maxcnt = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); } setup_buffer(buf, seed, maxsize); smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize); memset(buf, 0, maxsize); printf("Trying large read\n"); io.readx.in.offset = 0; io.readx.in.mincnt = 0xFFFF; io.readx.in.maxcnt = 0xFFFF; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt); CHECK_BUFFER(buf, seed, io.readx.out.nread); printf("Trying extra large read\n"); io.readx.in.offset = 0; io.readx.in.mincnt = 100; io.readx.in.maxcnt = 80000; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); if (lp_parm_bool(-1, "torture", "samba3", False)) { printf("SAMBA3: large read extension\n"); CHECK_VALUE(io.readx.out.nread, 80000); } else { CHECK_VALUE(io.readx.out.nread, 0); } CHECK_BUFFER(buf, seed, io.readx.out.nread); printf("Trying mincnt > maxcnt\n"); memset(buf, 0, maxsize); io.readx.in.offset = 0; io.readx.in.mincnt = 30000; io.readx.in.maxcnt = 20000; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt); CHECK_BUFFER(buf, seed, io.readx.out.nread); printf("Trying mincnt < maxcnt\n"); memset(buf, 0, maxsize); io.readx.in.offset = 0; io.readx.in.mincnt = 20000; io.readx.in.maxcnt = 30000; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt); CHECK_BUFFER(buf, seed, io.readx.out.nread); if (cli->transport->negotiate.capabilities & CAP_LARGE_READX) { printf("Trying large readx\n"); io.readx.in.offset = 0; io.readx.in.mincnt = 0; io.readx.in.maxcnt = 0x10000 - 1; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0xFFFF); io.readx.in.maxcnt = 0x10000; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); if (lp_parm_bool(-1, "torture", "samba3", False)) { printf("SAMBA3: large read extension\n"); CHECK_VALUE(io.readx.out.nread, 0x10000); } else { CHECK_VALUE(io.readx.out.nread, 0); } io.readx.in.maxcnt = 0x10001; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); if (lp_parm_bool(-1, "torture", "samba3", False)) { printf("SAMBA3: large read extension\n"); CHECK_VALUE(io.readx.out.nread, 0x10001); } else { CHECK_VALUE(io.readx.out.nread, 0); } } printf("Trying locked region\n"); cli->session->pid++; if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) { printf("Failed to lock file at %d\n", __LINE__); ret = False; goto done; } cli->session->pid--; memset(buf, 0, maxsize); io.readx.in.offset = 0; io.readx.in.mincnt = 100; io.readx.in.maxcnt = 200; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) { printf("skipping large file tests - CAP_LARGE_FILES not set\n"); goto done; } printf("Trying large offset read\n"); io.readx.in.offset = ((uint64_t)0x2) << 32; io.readx.in.mincnt = 10; io.readx.in.maxcnt = 10; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); if (NT_STATUS_IS_ERR(smbcli_lock64(cli->tree, fnum, io.readx.in.offset, 1, 0, WRITE_LOCK))) { printf("Failed to lock file at %d\n", __LINE__); ret = False; goto done; } status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); done: smbcli_close(cli->tree, fnum); smbcli_deltree(cli->tree, BASEDIR); return ret; }
static bool torture_locktest7(struct torture_context *tctx, struct smbcli_state *cli1) { const char *fname = BASEDIR "\\lockt7.lck"; int fnum1; int fnum2 = -1; size_t size; uint8_t buf[200]; bool correct = false; torture_assert(tctx, torture_setup_dir(cli1, BASEDIR), talloc_asprintf(tctx, "Unable to set up %s", BASEDIR)); fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); memset(buf, 0, sizeof(buf)); torture_assert(tctx, smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) == sizeof(buf), "Failed to create file"); cli1->session->pid = 1; torture_assert_ntstatus_ok(tctx, smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK), talloc_asprintf(tctx, "Unable to apply read lock on range 130:4, error was %s", smbcli_errstr(cli1->tree))); torture_comment(tctx, "pid1 successfully locked range 130:4 for READ\n"); torture_assert(tctx, smbcli_read(cli1->tree, fnum1, buf, 130, 4) == 4, talloc_asprintf(tctx, "pid1 unable to read the range 130:4, error was %s)", smbcli_errstr(cli1->tree))); torture_comment(tctx, "pid1 successfully read the range 130:4\n"); if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) { torture_comment(tctx, "pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree)); torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT, "Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)"); } else { torture_fail(tctx, "pid1 successfully wrote to the range 130:4 (should be denied)"); } cli1->session->pid = 2; if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) { torture_comment(tctx, "pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree)); } else { torture_comment(tctx, "pid2 successfully read the range 130:4\n"); } if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) { torture_comment(tctx, "pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree)); torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT, "Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)"); } else { torture_fail(tctx, "pid2 successfully wrote to the range 130:4 (should be denied)"); } cli1->session->pid = 1; smbcli_unlock(cli1->tree, fnum1, 130, 4); torture_assert_ntstatus_ok(tctx, smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK), talloc_asprintf(tctx, "Unable to apply write lock on range 130:4, error was %s", smbcli_errstr(cli1->tree))); torture_comment(tctx, "pid1 successfully locked range 130:4 for WRITE\n"); torture_assert(tctx, smbcli_read(cli1->tree, fnum1, buf, 130, 4) == 4, talloc_asprintf(tctx, "pid1 unable to read the range 130:4, error was %s", smbcli_errstr(cli1->tree))); torture_comment(tctx, "pid1 successfully read the range 130:4\n"); torture_assert(tctx, smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) == 4, talloc_asprintf(tctx, "pid1 unable to write to the range 130:4, error was %s", smbcli_errstr(cli1->tree))); torture_comment(tctx, "pid1 successfully wrote to the range 130:4\n"); cli1->session->pid = 2; if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) { torture_comment(tctx, "pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree)); torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT, "Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)"); } else { torture_fail(tctx, "pid2 successfully read the range 130:4 (should be denied)"); } if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) { torture_comment(tctx, "pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree)); if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) { torture_comment(tctx, "Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n", __location__); goto fail; } } else { torture_comment(tctx, "pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n", __location__); goto fail; } torture_comment(tctx, "Testing truncate of locked file.\n"); fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE); torture_assert(tctx, fnum2 != -1, "Unable to truncate locked file"); torture_comment(tctx, "Truncated locked file.\n"); torture_assert_ntstatus_ok(tctx, smbcli_getatr(cli1->tree, fname, NULL, &size, NULL), talloc_asprintf(tctx, "getatr failed (%s)", smbcli_errstr(cli1->tree))); torture_assert(tctx, size == 0, talloc_asprintf(tctx, "Unable to truncate locked file. Size was %u", (unsigned)size)); cli1->session->pid = 1; smbcli_unlock(cli1->tree, fnum1, 130, 4); correct = true; fail: smbcli_close(cli1->tree, fnum1); smbcli_close(cli1->tree, fnum2); smbcli_unlink(cli1->tree, fname); return correct; }
/* looks at lock upgrade/downgrade. */ static bool torture_locktest5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2) { const char *fname = BASEDIR "\\lockt5.lck"; int fnum1, fnum2, fnum3; bool ret; uint8_t buf[1000]; bool correct = true; if (!torture_setup_dir(cli1, BASEDIR)) { return false; } fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE); fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE); memset(buf, 0, sizeof(buf)); torture_assert(tctx, smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) == sizeof(buf), "Failed to create file"); /* Check for NT bug... */ ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK)); smbcli_close(cli1->tree, fnum1); fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "this server %s the NT locking bug\n", ret ? "doesn't have" : "has"); smbcli_close(cli1->tree, fnum1); fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE); smbcli_unlock(cli1->tree, fnum3, 0, 1); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "the same process %s overlay a write with a read lock\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK)); EXPECTED(ret, false); torture_comment(tctx, "a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot"); /* Unlock the process 2 lock. */ smbcli_unlock(cli2->tree, fnum2, 0, 4); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK)); EXPECTED(ret, false); torture_comment(tctx, "the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot"); /* Unlock the process 1 fnum3 lock. */ smbcli_unlock(cli1->tree, fnum3, 0, 4); /* Stack 2 more locks here. */ ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "the same process %s stack read locks\n", ret?"can":"cannot"); /* Unlock the first process lock, then check this was the WRITE lock that was removed. */ ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) && NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "the first unlock removes the %s lock\n", ret?"WRITE":"READ"); /* Unlock the process 2 lock. */ smbcli_unlock(cli2->tree, fnum2, 0, 4); /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */ ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)); EXPECTED(ret, true); torture_comment(tctx, "the same process %s unlock the stack of 3 locks\n", ret?"can":"cannot"); /* Ensure the next unlock fails. */ ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)); EXPECTED(ret, false); torture_comment(tctx, "the same process %s count the lock stack\n", !ret?"can":"cannot"); /* Ensure connection 2 can get a write lock. */ ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot"); torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), talloc_asprintf(tctx, "close1 failed (%s)", smbcli_errstr(cli1->tree))); torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2), talloc_asprintf(tctx, "close2 failed (%s)", smbcli_errstr(cli2->tree))); torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum3), talloc_asprintf(tctx, "close2 failed (%s)", smbcli_errstr(cli2->tree))); torture_assert_ntstatus_ok(tctx, smbcli_unlink(cli1->tree, fname), talloc_asprintf(tctx, "unlink failed (%s)", smbcli_errstr(cli1->tree))); return correct; }
/* looks at overlapping locks */ static bool torture_locktest4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2) { const char *fname = BASEDIR "\\lockt4.lck"; int fnum1, fnum2, f; bool ret; uint8_t buf[1000]; bool correct = true; if (!torture_setup_dir(cli1, BASEDIR)) { return false; } fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE); memset(buf, 0, sizeof(buf)); if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) { torture_comment(tctx, "Failed to create file\n"); correct = false; goto fail; } ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK)); EXPECTED(ret, false); torture_comment(tctx, "the same process %s set overlapping write locks\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "the same process %s set overlapping read locks\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK)); EXPECTED(ret, false); torture_comment(tctx, "a different connection %s set overlapping write locks\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "a different connection %s set overlapping read locks\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) && NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK))); EXPECTED(ret, false); torture_comment(tctx, "a different pid %s set overlapping write locks\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) && NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK))); EXPECTED(ret, true); torture_comment(tctx, "a different pid %s set overlapping read locks\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "the same process %s set the same read lock twice\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)); EXPECTED(ret, false); torture_comment(tctx, "the same process %s set the same write lock twice\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK)); EXPECTED(ret, false); torture_comment(tctx, "the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK)); EXPECTED(ret, true); torture_comment(tctx, "the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) && NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK))); EXPECTED(ret, false); torture_comment(tctx, "a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6)); EXPECTED(ret, false); torture_comment(tctx, "the same process %s coalesce read locks\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) && (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4); EXPECTED(ret, false); torture_comment(tctx, "this server %s strict write locking\n", ret?"doesn't do":"does"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) && (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4); EXPECTED(ret, false); torture_comment(tctx, "this server %s strict read locking\n", ret?"doesn't do":"does"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)); EXPECTED(ret, true); torture_comment(tctx, "this server %s do recursive read locking\n", ret?"does":"doesn't"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) && (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) && !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)); EXPECTED(ret, true); torture_comment(tctx, "this server %s do recursive lock overlays\n", ret?"does":"doesn't"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) && (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) && (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4); EXPECTED(ret, true); torture_comment(tctx, "the same process %s remove a read lock using write locking\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) && (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) && (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4); EXPECTED(ret, true); torture_comment(tctx, "the same process %s remove a write lock using read locking\n", ret?"can":"cannot"); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) && !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) && (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4); EXPECTED(ret, true); torture_comment(tctx, "the same process %s remove the first lock first\n", ret?"does":"doesn't"); smbcli_close(cli1->tree, fnum1); smbcli_close(cli2->tree, fnum2); fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE); f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE); ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) && NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) && ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) && NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK)); smbcli_close(cli1->tree, f); smbcli_close(cli1->tree, fnum1); EXPECTED(ret, true); torture_comment(tctx, "the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't"); fail: smbcli_close(cli1->tree, fnum1); smbcli_close(cli2->tree, fnum2); smbcli_unlink(cli1->tree, fname); return correct; }
static bool test_session_reauth2(struct torture_context *tctx, struct smbcli_state *cli) { char *random_string; char *fname; union smb_open io_open; struct smb_composite_sesssetup io_sesssetup; union smb_fileinfo io_qsecdesc; struct smbcli_request *req; struct cli_credentials *anon_creds; NTSTATUS status; uint16_t fnum; ssize_t nwritten; uint16_t vuid1 = cli->session->vuid; random_string = generate_random_str(tctx, 8); torture_assert(tctx, (random_string != NULL), "memory allocation failed"); fname = talloc_asprintf(tctx, "raw_session_reauth2_%s.dat", random_string); talloc_free(random_string); torture_assert(tctx, (fname != NULL), "memory allocation failed"); smbcli_unlink(cli->tree, fname); smbcli_oplock_handler(cli->transport, test_session_reauth2_oplock_timeout, cli->tree); /* base ntcreatex parms */ ZERO_STRUCT(io_open); io_open.generic.level = RAW_OPEN_NTCREATEX; io_open.ntcreatex.in.root_fid.fnum = 0; io_open.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE; io_open.ntcreatex.in.alloc_size = 0; io_open.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io_open.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; io_open.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; io_open.ntcreatex.in.create_options = 0; io_open.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io_open.ntcreatex.in.security_flags = 0; io_open.ntcreatex.in.fname = fname; torture_comment(tctx, "open with batch oplock\n"); io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; status = smb_raw_open(cli->tree, tctx, &io_open); torture_assert_ntstatus_ok(tctx, status, "smb_raw_open failed"); fnum = io_open.ntcreatex.out.file.fnum; torture_assert( tctx, (io_open.ntcreatex.out.oplock_level == BATCH_OPLOCK_RETURN), "did not get batch oplock"); io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; req = smb_raw_open_send(cli->tree, &io_open); torture_assert(tctx, (req != NULL), "memory allocation failed"); /* * Make sure the open went through */ status = smbcli_chkpath(cli->tree, "\\"); torture_assert_ntstatus_ok(tctx, status, "smb_chkpath failed"); status = smbcli_nt_delete_on_close(cli->tree, fnum, true); torture_assert_ntstatus_ok(tctx, status, "could not set delete on " "close"); anon_creds = cli_credentials_init_anon(tctx); torture_assert(tctx, (anon_creds != NULL), "memory allocation failed"); ZERO_STRUCT(io_sesssetup); io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey; io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities; io_sesssetup.in.credentials = anon_creds; io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx); io_sesssetup.in.gensec_settings = lpcfg_gensec_settings( tctx, tctx->lp_ctx); status = smb_composite_sesssetup(cli->session, &io_sesssetup); torture_assert_ntstatus_ok(tctx, status, "setup2 failed"); torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2"); status = smbcli_close(cli->tree, fnum); torture_assert_ntstatus_ok(tctx, status, "close failed"); status = smb_raw_open_recv(req, tctx, &io_open); torture_assert_ntstatus_ok(tctx, status, "2nd open failed"); fnum = io_open.ntcreatex.out.file.fnum; nwritten = smbcli_write(cli->tree, fnum, 0, fname, 0, strlen(fname)); torture_assert(tctx, (nwritten == strlen(fname)), "smbcli_write failed"); ZERO_STRUCT(io_qsecdesc); io_qsecdesc.query_secdesc.level = RAW_FILEINFO_SEC_DESC; io_qsecdesc.query_secdesc.in.file.fnum = fnum; io_qsecdesc.query_secdesc.in.secinfo_flags = SECINFO_OWNER; status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc); torture_assert_ntstatus_equal( tctx, status, NT_STATUS_ACCESS_DENIED, "anon qsecdesc did not return ACCESS_DENIED"); ZERO_STRUCT(io_sesssetup); io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey; io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities; io_sesssetup.in.credentials = cmdline_credentials; io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx); io_sesssetup.in.gensec_settings = lpcfg_gensec_settings( tctx, tctx->lp_ctx); status = smb_composite_sesssetup(cli->session, &io_sesssetup); torture_assert_ntstatus_ok(tctx, status, "setup3 failed"); torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2"); status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc); torture_assert_ntstatus_ok(tctx, status, "2nd qsecdesc failed"); status = smbcli_nt_delete_on_close(cli->tree, fnum, true); torture_assert_ntstatus_ok(tctx, status, "could not set delete on " "close"); status = smbcli_close(cli->tree, fnum); torture_assert_ntstatus_ok(tctx, status, "close failed"); return true; }
static NTSTATUS push_recursive (struct gp_context *gp_ctx, const char *local_path, const char *remote_path, int depth) { DIR *dir; struct dirent *dirent; char *entry_local_path; char *entry_remote_path; int local_fd, remote_fd; int buf[1024]; int nread, total_read; struct stat s; dir = opendir(local_path); while ((dirent = readdir(dir)) != NULL) { if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) { continue; } entry_local_path = talloc_asprintf(gp_ctx, "%s/%s", local_path, dirent->d_name); NT_STATUS_HAVE_NO_MEMORY(entry_local_path); entry_remote_path = talloc_asprintf(gp_ctx, "%s\\%s", remote_path, dirent->d_name); NT_STATUS_HAVE_NO_MEMORY(entry_remote_path); if (stat(dirent->d_name, &s) != 0) { return NT_STATUS_UNSUCCESSFUL; } if (s.st_mode & S_IFDIR) { DEBUG(6, ("Pushing directory %s to %s on sysvol\n", entry_local_path, entry_remote_path)); smbcli_mkdir(gp_ctx->cli->tree, entry_remote_path); if (depth < GP_MAX_DEPTH) { push_recursive(gp_ctx, entry_local_path, entry_remote_path, depth+1); } } else { DEBUG(6, ("Pushing file %s to %s on sysvol\n", entry_local_path, entry_remote_path)); remote_fd = smbcli_open(gp_ctx->cli->tree, entry_remote_path, O_WRONLY | O_CREAT, 0); if (remote_fd < 0) { talloc_free(entry_local_path); talloc_free(entry_remote_path); DEBUG(0, ("Failed to create remote file: %s\n", entry_remote_path)); return NT_STATUS_UNSUCCESSFUL; } local_fd = open(entry_local_path, O_RDONLY); if (local_fd < 0) { talloc_free(entry_local_path); talloc_free(entry_remote_path); DEBUG(0, ("Failed to open local file: %s\n", entry_local_path)); return NT_STATUS_UNSUCCESSFUL; } total_read = 0; while ((nread = read(local_fd, &buf, sizeof(buf)))) { smbcli_write(gp_ctx->cli->tree, remote_fd, 0, &buf, total_read, nread); total_read += nread; } close(local_fd); smbcli_close(gp_ctx->cli->tree, remote_fd); } talloc_free(entry_local_path); talloc_free(entry_remote_path); } closedir(dir); return NT_STATUS_OK; }
/* test basic io on streams */ static BOOL test_stream_io(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { NTSTATUS status; union smb_open io; const char *fname = BASEDIR "\\stream.txt"; const char *sname1, *sname2; BOOL ret = True; int fnum = -1; ssize_t retsize; sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One"); sname2 = talloc_asprintf(mem_ctx, "%s:%s:$DaTa", fname, "Second Stream"); printf("opening non-existant directory stream\n"); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid = 0; io.ntcreatex.in.flags = 0; io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA; io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = 0; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = sname1; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY); printf("creating a stream on a non-existant file\n"); io.ntcreatex.in.create_options = 0; io.ntcreatex.in.fname = sname1; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; ret &= check_stream(cli, mem_ctx, fname, "Stream One", NULL); printf("check that open of base file is allowed\n"); io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; io.ntcreatex.in.fname = fname; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); printf("writing to stream\n"); retsize = smbcli_write(cli->tree, fnum, 0, "test data", 0, 9); CHECK_VALUE(retsize, 9); smbcli_close(cli->tree, fnum); ret &= check_stream(cli, mem_ctx, fname, "Stream One", "test data"); io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; io.ntcreatex.in.fname = sname1; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; printf("modifying stream\n"); retsize = smbcli_write(cli->tree, fnum, 0, "MORE DATA ", 5, 10); CHECK_VALUE(retsize, 10); smbcli_close(cli->tree, fnum); ret &= check_stream(cli, mem_ctx, fname, "Stream One:$FOO", NULL); printf("creating a stream2 on a existing file\n"); io.ntcreatex.in.fname = sname2; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; printf("modifying stream\n"); retsize = smbcli_write(cli->tree, fnum, 0, "SECOND STREAM", 0, 13); CHECK_VALUE(retsize, 13); smbcli_close(cli->tree, fnum); ret &= check_stream(cli, mem_ctx, fname, "Stream One", "test MORE DATA "); ret &= check_stream(cli, mem_ctx, fname, "Stream One:$DATA", "test MORE DATA "); ret &= check_stream(cli, mem_ctx, fname, "Stream One:", NULL); ret &= check_stream(cli, mem_ctx, fname, "Second Stream", "SECOND STREAM"); ret &= check_stream(cli, mem_ctx, fname, "Second Stream:$DATA", "SECOND STREAM"); ret &= check_stream(cli, mem_ctx, fname, "Second Stream:", NULL); ret &= check_stream(cli, mem_ctx, fname, "Second Stream:$FOO", NULL); printf("deleting stream\n"); status = smbcli_unlink(cli->tree, sname1); CHECK_STATUS(status, NT_STATUS_OK); printf("delete a stream via delete-on-close\n"); io.ntcreatex.in.fname = sname2; io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; smbcli_close(cli->tree, fnum); status = smbcli_unlink(cli->tree, sname2); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); printf("deleting file\n"); status = smbcli_unlink(cli->tree, fname); CHECK_STATUS(status, NT_STATUS_OK); done: smbcli_close(cli->tree, fnum); return ret; }