⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 delaywrite.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* One more test to do. We should read the filetime via findfirst on the	   second connection to ensure it's the same. This is very easy for a Windows	   server but a bastard to get right on a POSIX server. JRA. */	if (fnum1 != -1)		smbcli_close(cli->tree, fnum1);	smbcli_unlink(cli->tree, fname);	smbcli_deltree(cli->tree, BASEDIR);	return ret;}/* Windows does obviously not update the stat info during a write call. I * *think* this is the problem causing a spurious Excel 2003 on XP error * message when saving a file. Excel does a setfileinfo, writes, and then does * a getpath(!)info. Or so... For Samba sometimes it displays an error message * that the file might have been changed in between. What i've been able to * trace down is that this happens if the getpathinfo after the write shows a * different last write time than the setfileinfo showed. This is really * nasty.... */static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_state *cli, 								   struct smbcli_state *cli2){	union smb_fileinfo finfo1, finfo2;	const char *fname = BASEDIR "\\torture_file.txt";	NTSTATUS status;	int fnum1 = -1;	int fnum2;	bool ret = true;	ssize_t written;	int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);	int normal_delay = 2000000;	double sec = ((double)used_delay) / ((double)normal_delay);	int msec = 1000 * sec;	if (!torture_setup_dir(cli, BASEDIR)) {		return false;	}	fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);	if (fnum1 == -1) {		ret = false;		torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);		goto done;	}	finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;	finfo1.basic_info.in.file.fnum = fnum1;	status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);	if (!NT_STATUS_IS_OK(status)) {		ret = false;		torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", nt_errstr(status));		goto done;	}	msleep(1 * msec);	written =  smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);	if (written != 1) {		torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);		ret = false;		goto done;	}	fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);	if (fnum2 == -1) {		torture_result(tctx, TORTURE_FAIL, __location__": failed to open 2nd time - %s", 		       smbcli_errstr(cli2->tree));		ret = false;		goto done;	}		written =  smbcli_write(cli2->tree, fnum2, 0, "x", 0, 1);		if (written != 1) {		torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", 		       (int)written);		ret = false;		goto done;	}		finfo2.basic_info.level = RAW_FILEINFO_BASIC_INFO;	finfo2.basic_info.in.file.path = fname;		status = smb_raw_pathinfo(cli2->tree, tctx, &finfo2);		if (!NT_STATUS_IS_OK(status)) {		torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", 			  nt_errstr(status));		ret = false;		goto done;	}		if (finfo1.basic_info.out.create_time !=	    finfo2.basic_info.out.create_time) {		torture_result(tctx, TORTURE_FAIL, __location__": create_time changed");		ret = false;		goto done;	}		if (finfo1.basic_info.out.access_time !=	    finfo2.basic_info.out.access_time) {		torture_result(tctx, TORTURE_FAIL, __location__": access_time changed");		ret = false;		goto done;	}		if (finfo1.basic_info.out.write_time !=	    finfo2.basic_info.out.write_time) {		torture_result(tctx, TORTURE_FAIL, __location__": write_time changed:\n"					   "write time conn 1 = %s, conn 2 = %s", 		       nt_time_string(tctx, finfo1.basic_info.out.write_time),		       nt_time_string(tctx, finfo2.basic_info.out.write_time));		ret = false;		goto done;	}		if (finfo1.basic_info.out.change_time !=	    finfo2.basic_info.out.change_time) {		torture_result(tctx, TORTURE_FAIL, __location__": change_time changed");		ret = false;		goto done;	}		/* One of the two following calls updates the qpathinfo. */		/* If you had skipped the smbcli_write on fnum2, it would	 * *not* have updated the stat on disk */		smbcli_close(cli2->tree, fnum2);	cli2 = NULL;	/* This call is only for the people looking at ethereal :-) */	finfo2.basic_info.level = RAW_FILEINFO_BASIC_INFO;	finfo2.basic_info.in.file.path = fname;	status = smb_raw_pathinfo(cli->tree, tctx, &finfo2);	if (!NT_STATUS_IS_OK(status)) {		torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", nt_errstr(status));		ret = false;		goto done;	} done:	if (fnum1 != -1)		smbcli_close(cli->tree, fnum1);	smbcli_unlink(cli->tree, fname);	smbcli_deltree(cli->tree, BASEDIR);	return ret;}#define COMPARE_WRITE_TIME_CMP(given, correct, cmp) do { \	uint64_t r = 10*1000*1000; \	NTTIME g = (given).basic_info.out.write_time; \	NTTIME gr = (g / r) * r; \	NTTIME c = (correct).basic_info.out.write_time; \	NTTIME cr = (c / r) * r; \	bool strict = torture_setting_bool(tctx, "strict mode", false); \	bool err = false; \	if (strict && (g cmp c)) { \		err = true; \	} else if (gr cmp cr) { \		/* handle filesystem without high resolution timestamps */ \		err = true; \	} \	if (err) { \		torture_result(tctx, TORTURE_FAIL, __location__": wrong write_time (%s)%s(%llu) %s (%s)%s(%llu)", \				#given, nt_time_string(tctx, g), (unsigned long long)g, \				#cmp, #correct, nt_time_string(tctx, c), (unsigned long long)c); \		ret = false; \		goto done; \	} \} while (0)#define COMPARE_WRITE_TIME_EQUAL(given,correct) \	COMPARE_WRITE_TIME_CMP(given,correct,!=)#define COMPARE_WRITE_TIME_GREATER(given,correct) \	COMPARE_WRITE_TIME_CMP(given,correct,<=)#define COMPARE_WRITE_TIME_LESS(given,correct) \	COMPARE_WRITE_TIME_CMP(given,correct,>=)#define COMPARE_ACCESS_TIME_CMP(given, correct, cmp) do { \	NTTIME g = (given).basic_info.out.access_time; \	NTTIME c = (correct).basic_info.out.access_time; \	if (g cmp c) { \		torture_result(tctx, TORTURE_FAIL, __location__": wrong access_time (%s)%s %s (%s)%s", \				#given, nt_time_string(tctx, g), \				#cmp, #correct, nt_time_string(tctx, c)); \		ret = false; \		goto done; \	} \} while (0)#define COMPARE_ACCESS_TIME_EQUAL(given,correct) \	COMPARE_ACCESS_TIME_CMP(given,correct,!=)#define COMPARE_ACCESS_TIME_GREATER(given,correct) \	COMPARE_ACCESS_TIME_CMP(given,correct,<=)#define COMPARE_ACCESS_TIME_LESS(given,correct) \	COMPARE_ACCESS_TIME_CMP(given,correct,>=)#define COMPARE_BOTH_TIMES_EQUAL(given,correct) do { \	COMPARE_ACCESS_TIME_EQUAL(given,correct); \	COMPARE_WRITE_TIME_EQUAL(given,correct); \} while (0)#define COMPARE_BOTH_TIMES_GEATER(given,correct) do { \	COMPARE_ACCESS_TIME_GREATER(given,correct); \	COMPARE_WRITE_TIME_GREATER(given,correct); \} while (0)#define COMPARE_BOTH_TIMES_LESS(given,correct) do { \	COMPARE_ACCESS_TIME_LESS(given,correct); \	COMPARE_WRITE_TIME_LESS(given,correct); \} while (0)#define GET_INFO_FILE(finfo) do { \	NTSTATUS _status; \	_status = smb_raw_fileinfo(cli->tree, tctx, &finfo); \	if (!NT_STATUS_IS_OK(_status)) { \		ret = false; \		torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", \			       nt_errstr(_status)); \		goto done; \	} \	torture_comment(tctx, "fileinfo: Access(%s) Write(%s)\n", \			nt_time_string(tctx, finfo.basic_info.out.access_time), \			nt_time_string(tctx, finfo.basic_info.out.write_time)); \} while (0)#define GET_INFO_PATH(pinfo) do { \	NTSTATUS _status; \	_status = smb_raw_pathinfo(cli2->tree, tctx, &pinfo); \	if (!NT_STATUS_IS_OK(_status)) { \		torture_result(tctx, TORTURE_FAIL, __location__": pathinfo failed: %s", \			       nt_errstr(_status)); \		ret = false; \		goto done; \	} \	torture_comment(tctx, "pathinfo: Access(%s) Write(%s)\n", \			nt_time_string(tctx, pinfo.basic_info.out.access_time), \			nt_time_string(tctx, pinfo.basic_info.out.write_time)); \} while (0)#define GET_INFO_BOTH(finfo,pinfo) do { \	GET_INFO_FILE(finfo); \	GET_INFO_PATH(pinfo); \	COMPARE_BOTH_TIMES_EQUAL(finfo,pinfo); \} while (0)#define SET_INFO_FILE_EX(finfo, wrtime, tree, tfnum) do { \	NTSTATUS _status; \	union smb_setfileinfo sfinfo; \	sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFO; \	sfinfo.basic_info.in.file.fnum = tfnum; \	sfinfo.basic_info.in.create_time = 0; \	sfinfo.basic_info.in.access_time = 0; \	unix_to_nt_time(&sfinfo.basic_info.in.write_time, (wrtime)); \	sfinfo.basic_info.in.change_time = 0; \	sfinfo.basic_info.in.attrib = finfo1.basic_info.out.attrib; \	_status = smb_raw_setfileinfo(tree, &sfinfo); \	if (!NT_STATUS_IS_OK(_status)) { \		torture_result(tctx, TORTURE_FAIL, __location__": setfileinfo failed: %s", \			       nt_errstr(_status)); \		ret = false; \		goto done; \	} \} while (0)#define SET_INFO_FILE(finfo, wrtime) \	SET_INFO_FILE_EX(finfo, wrtime, cli->tree, fnum1)static bool test_delayed_write_update3(struct torture_context *tctx,				       struct smbcli_state *cli,				       struct smbcli_state *cli2){	union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;	union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;	const char *fname = BASEDIR "\\torture_file.txt";	int fnum1 = -1;	bool ret = true;	ssize_t written;	struct timeval start;	struct timeval end;	int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);	int normal_delay = 2000000;	double sec = ((double)used_delay) / ((double)normal_delay);	int msec = 1000 * sec;	if (!torture_setup_dir(cli, BASEDIR)) {		return false;	}	torture_comment(tctx, "Open the file handle\n");	fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);	if (fnum1 == -1) {		ret = false;		torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);		goto done;	}	finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;	finfo0.basic_info.in.file.fnum = fnum1;	finfo1 = finfo0;	finfo2 = finfo0;	finfo3 = finfo0;	finfo4 = finfo0;	pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;	pinfo0.basic_info.in.file.path = fname;	pinfo1 = pinfo0;	pinfo2 = pinfo0;	pinfo3 = pinfo0;	pinfo4 = pinfo0;	pinfo5 = pinfo0;	/* get the initial times */	GET_INFO_BOTH(finfo0,pinfo0);	/*	 * make sure the write time is updated 2 seconds later	 * calcuated from the first write	 * (but expect upto 5 seconds extra time for a busy server)	 */	start = timeval_current();	end = timeval_add(&start, 7 * sec, 0);	while (!timeval_expired(&end)) {		/* do a write */		torture_comment(tctx, "Do a write on the file handle\n");		written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);		if (written != 1) {			torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);			ret = false;			goto done;		}		/* get the times after the write */		GET_INFO_FILE(finfo1);		if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {			double diff = timeval_elapsed(&start);			if (diff < (2 * sec * 0.75)) { /* 0.75 to cope with vmware timing */				torture_comment(tctx, "Server updated write_time after %.2f seconds "						"(1sec == %.2f) (wrong!)\n",						diff, sec);				ret = false;				break;			}			torture_comment(tctx, "Server updated write_time after %.2f seconds "					"(1sec == %.2f) (correct)\n",					diff, sec);			break;		}		msleep(0.5 * msec);	}	GET_INFO_BOTH(finfo1,pinfo1);	/* sure any further write doesn't update the write time */	start = timeval_current();	end = timeval_add(&start, 15 * sec, 0);	while (!timeval_expired(&end)) {		/* do a write */		torture_comment(tctx, "Do a write on the file handle\n");		written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);		if (written != 1) {			torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);			ret = false;			goto done;		}		/* get the times after the write */		GET_INFO_BOTH(finfo2,pinfo2);		if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {			double diff = timeval_elapsed(&start);			torture_comment(tctx, "Server updated write_time after %.2f seconds "					"(1sec == %.2f) (wrong!)\n",					diff, sec);			ret = false;			break;		}		msleep(2 * msec);	}	GET_INFO_BOTH(finfo2,pinfo2);	COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);	if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {		torture_comment(tctx, "Server did not update write_time (correct)\n");	}	/* sleep */	msleep(5 * msec);	GET_INFO_BOTH(finfo3,pinfo3);	COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);	/*	 * the close updates the write time to the time of the close	 * and not to the time of the last write!	 */	torture_comment(tctx, "Close the file handle\n");	smbcli_close(cli->tree, fnum1);	fnum1 = -1;	GET_INFO_PATH(pinfo4);	COMPARE_WRITE_TIME_GREATER(pinfo4, pinfo3);	if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {		torture_comment(tctx, "Server updated the write_time on close (correct)\n");	} done:	if (fnum1 != -1)		smbcli_close(cli->tree, fnum1);	smbcli_unlink(cli->tree, fname);	smbcli_deltree(cli->tree, BASEDIR);	return ret;}static bool test_delayed_write_update4(struct torture_context *tctx,				       struct smbcli_state *cli,				       struct smbcli_state *cli2){	union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;	union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;	const char *fname = BASEDIR "\\torture_file.txt";	int fnum1 = -1;	bool ret = true;	ssize_t written;	struct timeval start;	struct timeval end;	int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);	int normal_delay = 2000000;	double sec = ((double)used_delay) / ((double)normal_delay);	int msec = 1000 * sec;	if (!torture_setup_dir(cli, BASEDIR)) {		return false;	}	torture_comment(tctx, "Open the file handle\n");	fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);	if (fnum1 == -1) {		ret = false;		torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);		goto done;	}	finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;	finfo0.basic_info.in.file.fnum = fnum1;	finfo1 = finfo0;	finfo2 = finfo0;	finfo3 = finfo0;	finfo4 = finfo0;	pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;	pinfo0.basic_info.in.file.path = fname;	pinfo1 = pinfo0;	pinfo2 = pinfo0;	pinfo3 = pinfo0;	pinfo4 = pinfo0;	pinfo5 = pinfo0;	/* get the initial times */	GET_INFO_BOTH(finfo0,pinfo0);	/* sleep a bit */	msleep(5 * msec);	/* do a write */	torture_comment(tctx, "Do a write on the file handle\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -