示例#1
0
int nb_writex(int handle, int offset, int size, int ret_size)
{
    int     i;
    ssize_t status;
    char    FileName[128];
    char    temp[512];
    unsigned char magic = (unsigned char)getpid();

    sprintf(FileName, "Thread_%05d.log", ProcessNumber);

    if (IoBuffer[0] != magic ||
        IoBuffer[1] != magic ||
        IoBuffer[2] != magic ||
        IoBuffer[3] != magic)
        memset(IoBuffer, magic, BufferSize);

    if ((i = FindHandle(handle)) == -1)
        return(-1);
    StartFirstTimer();
    status = nb_write(ftable[i].fd, IoBuffer, offset, size);
    if (status != ret_size) 
    {
        EndFirstTimer(CMD_WRITEX, 0);
		LeaveThread(0, "", CMD_WRITEX);
        if (status == 0)
            sprintf(temp, "File: %s. wrote %d bytes, got %d bytes\n", ftable[i].name, size, status);
        if (status == -1)
            sprintf(temp, "File: %s. On write, cannot set file pointer\n", ftable[i].name);
        if (verbose)
            printf("%s", temp);
        nb_close(handle);
        if (verbose)
            printf("%s", temp);
        LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
        return(-1);
	}
    EndFirstTimer(CMD_WRITEX, 1);

    ftable[i].writes++;
    return(0);
}
示例#2
0
/*
 * Broker a CGI process child.
 * Return zero on failure and non-zero on success.
 */
static int
dochild_cgi(kcgi_regress_server child, void *carg)
{
	int		 in, fd[2], rc;
	const char	*msg;
	pid_t		 pid;
	char		*vec, *end, *start, *cp, *ovec;
	size_t		 vecsz, headsz;
	void		*pp;
	char		 buf[BUFSIZ];
	ssize_t		 ssz;

	if (-1 == (in = dochild_prepare())) 
		return(0);

	/*
	 * We need to do some filtering from the CGI script's output
	 * (just its Status message), so create a socketpair which we'll
	 * use to scrub its output.
	 * This is because the CGI protocol is stupid: it would have
	 * been a lot easier to just require an HTTP status message, but
	 * I guess the intent was to make the web server worry about
	 * formatting for various versions of HTTP.
	 * Whatever.
	 */

	if (-1 == socketpair(PF_LOCAL, SOCK_STREAM, 0, fd)) {
		perror("socketpair");
		close(in);
		return(0);
	} 

	/* Launch the actual CGI process. */

	if (-1 == (pid = fork())) {
		perror("fork");
		close(fd[0]);
		close(fd[1]);
		close(in);
		return(0);
	} else if (0 == pid) {
		close(fd[1]);
		/*
		 * First, we suck down the HTTP headeres into our CGI
		 * environment and run the child.
		 * Next, re-assign our stdin to be the server's file
		 * descriptor "in".
		 * Then assign our stdout to be fd[0].
		 */

		if ( ! dochild_params(in, NULL, NULL, 
		    dochild_params_cgi)) {
			close(in);
			close(fd[0]);
			return(0);
		}

		if (STDIN_FILENO != dup2(in, STDIN_FILENO)) {
			perror("dup2");
			close(in);
			close(fd[0]);
			_exit(EXIT_FAILURE);
		} 
		close(in);

		if (STDOUT_FILENO != dup2(fd[0], STDOUT_FILENO)) {
			perror("dup2");
			close(fd[0]);
			return(0);
		} 
		close(fd[0]);

		child(carg);
		_exit(in ? EXIT_SUCCESS : EXIT_FAILURE);
	}

	/*
	 * We're in the parent.
	 * Read and buffer the output of the CGI process until we get
	 * its Status value.
	 * Do so by copying through a static buffer into a growable
	 * vector that we'll scan for the Status message to re-write.
	 * Of course, if the CGI process is ill-designed, we'll consume
	 * all of our memory and die.
	 */

	close(fd[0]);
	vecsz = 0;
	vec = end = NULL;
	rc = 0;

	while ((ssz = read(fd[1], buf, sizeof(buf))) > 0) {
		pp = realloc(vec, vecsz + ssz);
		if (NULL == pp) {
			perror("realloc");
			goto out;
		}
		vec = pp;
		memcpy(vec + vecsz, buf, ssz);
		vecsz += ssz;
		end = memmem(vec, vecsz, "\r\n\r\n", 4);
		if (NULL != end)
			break;
	}

	if (ssz < 0) {
		perror("read");
		goto out;
	}

	/*
	 * Now all our headers are in vec plus extra; of if it's NULL,
	 * we reached the end of input without getting headers.
	 * Now we start to scan for the status line or dump.
	 */

	if (NULL != end) {
		/* Look for the status field. */

		headsz = (size_t)(end - vec);
		start = memmem(vec, headsz, "Status:", 7);
		if (NULL == start) {
			/*
			 * No status field.
			 * This is Ok (according to CGI).
			 * However, we do not provide a valid status, so
			 * do what others do and 200 it.
			 */

			msg = "HTTP/1.1 200 OK\r\n";
			if ( ! nb_write(in, msg, strlen(msg)))
				goto out;
			fprintf(stderr, "CGI script did "
				"not specify status\n");
			ovec = vec;
		} else {
			/*
			 * We found the status.
			 * Print it out now, then everything that came
			 * before it.
			 */

			msg = "HTTP/1.1";
			if ( ! nb_write(in, msg, strlen(msg)))
				goto out;
			cp = start + 7;
			while (cp < end) {
				if ( ! nb_write(in, cp, 1))
					goto out;
				cp++;
				if ('\n' == cp[-1])
					break;
			}
			if ( ! nb_write(in, vec, (size_t)(start - vec)))
				goto out;
			vecsz -= (cp - vec);
			ovec = cp;
		}

		/*
		 * Print everything else in our vector array, then poll
		 * on the CGI script til its dry.
		 */

		if ( ! nb_write(in, ovec, vecsz))
			goto out;

		while ((ssz = read(fd[1], buf, sizeof(buf))) > 0)
			if ( ! nb_write(in, buf, ssz))
				goto out;

		if (ssz < 0) {
			perror("read");
			goto out;
		}
	} else {
		if ( ! nb_write(in, vec, vecsz))
			goto out;
		fprintf(stderr, "CGI script did "
			"not terminate headers\n");
	} 

	rc = 1;
out:
	if (-1 == waitpid(pid, NULL, 0))
		perror("waitpid");

	free(vec);
	close(in);
	close(fd[1]);
	return(rc);
}
示例#3
0
文件: nbench.c 项目: gojdic/samba
/* run a test that simulates an approximate netbench client load */
static bool run_netbench(struct torture_context *tctx, struct smbcli_state *cli, int client)
{
	int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
	int i;
	char line[1024];
	char *cname;
	FILE *f;
	bool correct = true;
	double target_rate = torture_setting_double(tctx, "targetrate", 0);	
	int n;

	if (target_rate != 0 && client == 0) {
		printf("Targetting %.4f MByte/sec\n", target_rate);
	}

	nb_setup(cli, client);

	if (torture_nprocs == 1) {
		if (!read_only) {
			NB_RETRY(torture_setup_dir(cli, "\\clients"));
		}
	}

	asprintf(&cname, "client%d", client+1);

	f = fopen(loadfile, "r");

	if (!f) {
		perror(loadfile);
		return false;
	}

again:
	nbio_time_reset();

	while (fgets(line, sizeof(line)-1, f)) {
		NTSTATUS status;
		const char **params0, **params;

		nbench_line_count++;

		line[strlen(line)-1] = 0;

		all_string_sub(line,"client1", cname, sizeof(line));
		
		params = params0 = str_list_make_shell(NULL, line, " ");
		i = str_list_length(params);

		if (i > 0 && isdigit(params[0][0])) {
			double targett = strtod(params[0], NULL);
			if (target_rate != 0) {
				nbio_target_rate(target_rate);
			} else {
				nbio_time_delay(targett);
			}
			params++;
			i--;
		} else if (target_rate != 0) {
			nbio_target_rate(target_rate);
		}

		if (i < 2 || params[0][0] == '#') continue;

		if (!strncmp(params[0],"SMB", 3)) {
			printf("ERROR: You are using a dbench 1 load file\n");
			nb_exit(1);
		}

		if (strncmp(params[i-1], "NT_STATUS_", 10) != 0 &&
		    strncmp(params[i-1], "0x", 2) != 0) {
			printf("Badly formed status at line %d\n", nbench_line_count);
			talloc_free(params);
			continue;
		}

		/* accept numeric or string status codes */
		if (strncmp(params[i-1], "0x", 2) == 0) {
			status = NT_STATUS(strtoul(params[i-1], NULL, 16));
		} else {
			status = nt_status_string_to_code(params[i-1]);
		}

		DEBUG(9,("run_netbench(%d): %s %s\n", client, params[0], params[1]));

		if (!strcmp(params[0],"NTCreateX")) {
			NB_RETRY(nb_createx(params[1], ival(params[2]), ival(params[3]), 
					    ival(params[4]), status));
		} else if (!strcmp(params[0],"Close")) {
			NB_RETRY(nb_close(ival(params[1]), status));
		} else if (!read_only && !strcmp(params[0],"Rename")) {
			NB_RETRY(nb_rename(params[1], params[2], status, n>0));
		} else if (!read_only && !strcmp(params[0],"Unlink")) {
			NB_RETRY(nb_unlink(params[1], ival(params[2]), status, n>0));
		} else if (!read_only && !strcmp(params[0],"Deltree")) {
			NB_RETRY(nb_deltree(params[1], n>0));
		} else if (!read_only && !strcmp(params[0],"Rmdir")) {
			NB_RETRY(nb_rmdir(params[1], status, n>0));
		} else if (!read_only && !strcmp(params[0],"Mkdir")) {
			NB_RETRY(nb_mkdir(params[1], status, n>0));
		} else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
			NB_RETRY(nb_qpathinfo(params[1], ival(params[2]), status));
		} else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
			NB_RETRY(nb_qfileinfo(ival(params[1]), ival(params[2]), status));
		} else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
			NB_RETRY(nb_qfsinfo(ival(params[1]), status));
		} else if (!read_only && !strcmp(params[0],"SET_FILE_INFORMATION")) {
			NB_RETRY(nb_sfileinfo(ival(params[1]), ival(params[2]), status));
		} else if (!strcmp(params[0],"FIND_FIRST")) {
			NB_RETRY(nb_findfirst(params[1], ival(params[2]), 
					      ival(params[3]), ival(params[4]), status));
		} else if (!read_only && !strcmp(params[0],"WriteX")) {
			NB_RETRY(nb_writex(ival(params[1]), 
					   ival(params[2]), ival(params[3]), ival(params[4]),
					   status));
		} else if (!read_only && !strcmp(params[0],"Write")) {
			NB_RETRY(nb_write(ival(params[1]), 
					  ival(params[2]), ival(params[3]), ival(params[4]),
					  status));
		} else if (!strcmp(params[0],"LockX")) {
			NB_RETRY(nb_lockx(ival(params[1]), 
					  ival(params[2]), ival(params[3]), status));
		} else if (!strcmp(params[0],"UnlockX")) {
			NB_RETRY(nb_unlockx(ival(params[1]), 
					    ival(params[2]), ival(params[3]), status));
		} else if (!strcmp(params[0],"ReadX")) {
			NB_RETRY(nb_readx(ival(params[1]), 
					  ival(params[2]), ival(params[3]), ival(params[4]),
					  status));
		} else if (!strcmp(params[0],"Flush")) {
			NB_RETRY(nb_flush(ival(params[1]), status));
		} else if (!strcmp(params[0],"Sleep")) {
			nb_sleep(ival(params[1]), status);
		} else {
			printf("[%d] Unknown operation %s\n", nbench_line_count, params[0]);
		}

		if (n > nb_max_retries) {
			printf("Maximum reconnect retries reached for op '%s'\n", params[0]);
			nb_exit(1);
		}

		talloc_free(params0);
		
		if (nb_tick()) goto done;
	}

	rewind(f);
	goto again;

done:
	fclose(f);

	if (!read_only && torture_nprocs == 1) {
		smbcli_deltree(cli->tree, "\\clients");
	}
	if (!torture_close_connection(cli)) {
		correct = false;
	}
	
	return correct;
}
示例#4
0
/*
 * Broker a FastCGI process child.
 * Return zero on failure and non-zero on success.
 */
static int
dochild_fcgi(kcgi_regress_server child, void *carg)
{
	int			 in, rc, fd;
	size_t			 sz, len;
	pid_t			 pid;
	struct sockaddr_un	 sun;
	struct sockaddr		*ss;
	ssize_t			 ssz;
	extern char		*__progname;
	char			 sfn[22];
	char			 buf[BUFSIZ];
	struct fcgi_hdr		 hdr;
	mode_t		  	 mode;

	/* 
	 * Create a temporary file, close it, then unlink it.
	 * The child will recreate this as a socket.
	 */

	strlcpy(sfn, "/tmp/kfcgi.XXXXXXXXXX", sizeof(sfn));

	/* This shuts up Coverity. */

	mode = umask(S_IXUSR | S_IRWXG | S_IRWXO);
	if (-1 == (fd = mkstemp(sfn))) {
		perror(sfn);
		return(0);
	} else if (-1 == close(fd) || -1 == unlink(sfn)) {
		perror(sfn);
		return(0);
	}
	umask(mode);

	/* Do the usual dance to set up UNIX sockets. */

	ss = (struct sockaddr *)&sun;
	memset(&sun, 0, sizeof(sun));
	sun.sun_family = AF_UNIX;
	sz = strlcpy(sun.sun_path, sfn, sizeof(sun.sun_path));
	if (sz >= sizeof(sun.sun_path)) {
		fprintf(stderr, "socket path to long\n");
		return(0);
	}
#ifndef __linux__
	sun.sun_len = sz;
#endif

	if (-1 == (fd = socket(AF_UNIX, SOCK_STREAM, 0))) {
		perror("socket");
		return(0);
	} else if (-1 == bind(fd, ss, sizeof(sun))) {
		perror(sfn);
		close(fd);
		return(0);
	} else if (-1 == listen(fd, 5)) {
		perror(sfn);
		close(fd);
		return(0);
	}

	/*
	 * Now fork the FastCGI process.
	 * We need to use a separate process because we're going to
	 * package the request as a FastCGI request and ship it into the
	 * UNIX socket.
	 */

	if (-1 == (pid = fork())) {
		perror("fork");
		unlink(sfn);
		close(fd);
		return(0);
	} else if (0 == pid) {
		if (-1 == dup2(fd, STDIN_FILENO))
			_exit(EXIT_FAILURE);
		close(fd);
		return(child(carg));
	}

	/* 
	 * Close the socket, as we're going to connect to it.
	 * The child has a reference to the object (via its dup2), so
	 * we're not going to totally remove the file.
	 */

	close(fd);
	fd = in = -1;
	rc = 0;

	/* Get the next incoming connection and FILE-ise it. */

	if (-1 == (in = dochild_prepare())) 
		goto out;

	/*
	 * Open a new socket to the FastCGI object and connect to it,
	 * reusing the prior socket address.
	 * Then remove the object, as nobody needs it any more.
	 */

	if (-1 == (fd = socket(AF_UNIX, SOCK_STREAM, 0))) {
		perror(sfn);
		goto out;
	} else if (-1 == connect(fd, ss, sizeof(sun))) {
		perror(sfn);
		goto out;
	} else if (-1 == unlink(sfn)) {
		perror(sfn);
		goto out;
	} 
	sfn[0] = '\0';

	/* Write the request, its parameters, and all data. */

	if ( ! fcgi_begin_write(fd))
		goto out;
	else if ( ! dochild_params(in, &fd, &len, dochild_params_fcgi))
		goto out;

	/*
	 * We might not have any data to read from the server, so
	 * remember whether a Content-Type was stipulated and only
	 * download data if it was.
	 * This is required because we'll just sit here waiting for data
	 * otherwise.
	 * Note: "in" is non-blocking, so be respectful.
	 */

	while (len > 0) {
		ssz = nb_read(in, buf, 
			len < sizeof(buf) ? len : sizeof(buf));
		if (ssz < 0) {
			perror("read");
			goto out;
		} else if (0 == ssz)
			break;

		if ( ! fcgi_data_write(fd, buf, ssz)) {
			fprintf(stderr, "%s: stdout\n", __func__);
			goto out;
		}
		len -= ssz;
	}

	/* Indicate end of input. */

	if ( ! fcgi_data_write(fd, NULL, 0)) {
		fprintf(stderr, "%s: stdout (FIN)\n", __func__);
		goto out;
	}

	/*
	 * Now we read the response, funneling it to the output.
	 * Stop reading on error or when we receive the end of data
	 * token from the FastCGI client.
	 */

	while (fcgi_hdr_read(fd, &hdr)) {
		if (3 == hdr.type) {
			/* End of message. */
			if ( ! fcgi_end_read(fd, &rc)) {
				fprintf(stderr, "%s: bad fin\n", __func__);
				goto out;
			}
			break;
		} else if (6 != hdr.type) {
			fprintf(stderr, "%s: bad type: %" 
				PRIu8 "\n", __func__, hdr.type);
			goto out;
		}

		/* Echo using a temporary buffer. */

		while (hdr.contentLength > 0) {
			sz = hdr.contentLength > BUFSIZ ? 
				BUFSIZ : hdr.contentLength;
			if (fcgi_read(fd, buf, sz)) {
				if ( ! nb_write(in, buf, sz))
					goto out;
				hdr.contentLength -= sz;
				continue;
			} else
				fprintf(stderr, "%s: bad read\n", __func__);
			goto out;
		}
		if (0 == fcgi_ignore(fd, hdr.paddingLength)) {
			fprintf(stderr, "%s: bad ignore\n", __func__);
			goto out;
		} 
	}
out:
	/* 
	 * Begin by asking the child to exit.
	 * Then close all of our comm channels.
	 */

	kill(pid, SIGTERM);
	if (-1 != in)
		close(in);
	if ('\0' != sfn[0])
		unlink(sfn);
	if (-1 != fd)
		close(fd);

	/*
	 * Now mandate that the child dies and reap its resources.
	 * FIXME: we might kill the process before it's done actually
	 * terminating, which is unfair and will raise spurious
	 * warnings elsewhere.
	 */

	if (-1 == waitpid(pid, NULL, 0))
		perror("waitpid");
	return(rc);
}