[Crash-utility] [PATCH 1/7] Add NIL mode to remote.

Don Slutz dslutz at verizon.com
Tue Nov 19 11:46:40 UTC 2013


From: Don Slutz <dslutz at verizon.com>

Signed-off-by: Don Slutz <dslutz at verizon.com>
---
 defs.h   |   1 +
 remote.c | 241 +++++++++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 173 insertions(+), 69 deletions(-)

diff --git a/defs.h b/defs.h
index a5299cc..108ffc1 100755
--- a/defs.h
+++ b/defs.h
@@ -504,6 +504,7 @@ struct program_context {
 #define GET_LOG       (0x200ULL)
 #define VMCOREINFO    (0x400ULL)
 #define ALLOW_FP      (0x800ULL)
+#define REMOTE_NIL   (0x1000ULL)
 	char *cleanup;
 	char *namelist_orig;
 	char *namelist_debug_orig;
diff --git a/remote.c b/remote.c
index fca08a1..e64f2bd 100755
--- a/remote.c
+++ b/remote.c
@@ -1808,6 +1808,10 @@ static int remote_file_type(char *);
 static int remote_lkcd_dump_init(void);
 static int remote_s390_dump_init(void);
 static int remote_netdump_init(void);
+static int remote_tcp_read(int, const char *, size_t);
+static int remote_tcp_read_string(int, const char *, size_t, int);
+static int remote_tcp_write(int, const void *, size_t);
+static int remote_tcp_write_string(int, const char *);
 
 /*
  *  Parse, verify and establish a connection with the network daemon
@@ -1921,6 +1925,16 @@ is_remote_daemon(char *dp)
 
 	remote_socket_options(pc->sockfd);
 
+	/*
+	 * Try and use NIL mode.
+	 */
+	BZERO(sendbuf, BUFSIZE);
+	BZERO(recvbuf, BUFSIZE);
+	sprintf(sendbuf, "NIL");
+	remote_tcp_write_string(pc->sockfd, sendbuf);
+	remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+	if (!strstr(recvbuf, "<FAIL>"))
+		pc->flags2 |= REMOTE_NIL;
         /*
          *  Get the remote machine type and verify a match.  The daemon pid
          *  is also used as a live system initial context.
@@ -1928,8 +1942,8 @@ is_remote_daemon(char *dp)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "MACHINE_PID");
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         p1 = strtok(recvbuf, " ");  /* MACHINE */
         p1 = strtok(NULL, " ");     /* machine type */
 	if (CRASHDEBUG(1))
@@ -2032,8 +2046,8 @@ remote_file_type(char *file)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "TYPE %s", file);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
 
         if (strstr(recvbuf, "<FAIL>"))
                 error(FATAL, "invalid remote file name: %s\n", file);
@@ -2112,6 +2126,84 @@ remote_socket_options(int sockfd)
 }
 
 /*
+ * Wrapper around recv to read full length packet.
+ */
+static int
+remote_tcp_read(int sock, const char *pv_buffer, size_t cb_buffer)
+{
+	size_t cb_total = 0;
+
+	do
+	{
+		ssize_t cb_read = recv(sock, (void*)pv_buffer, cb_buffer, MSG_NOSIGNAL);
+
+		if (cb_read <= 0)
+			return cb_read;
+		cb_total += cb_read;
+		cb_buffer -= cb_read;
+		pv_buffer = (char *)pv_buffer + cb_read;
+	} while (cb_buffer);
+
+	return cb_total;
+}
+
+/*
+ * Wrapper around recv to read full string packet.
+ */
+static int
+remote_tcp_read_string(int sock, const char *pv_buffer, size_t cb_buffer, int nil_mode)
+{
+	size_t cb_total = 0;
+
+	do
+	{
+		ssize_t cb_read = recv(sock, (void*)pv_buffer, cb_buffer, MSG_NOSIGNAL);
+
+		if (cb_read <= 0)
+			return cb_read;
+		cb_total += cb_read;
+		if (!nil_mode && cb_total >= 4)
+			return cb_total;
+		if (!pv_buffer[cb_read - 1])
+			return cb_total;
+		cb_buffer -= cb_read;
+		pv_buffer = (char *)pv_buffer + cb_read;
+	} while (cb_buffer);
+
+	return cb_total;
+}
+
+/*
+ * Wrapper around send to send full packet.
+ */
+static int
+remote_tcp_write(int sock, const void *pv_buffer, size_t cb_buffer)
+{
+	do
+	{
+		size_t cb_now = cb_buffer;
+		ssize_t cb_written = send(sock, (const char *)pv_buffer, cb_now, MSG_NOSIGNAL);
+
+		if (cb_written < 0)
+			return 1;
+		cb_buffer -= cb_written;
+		pv_buffer = (char *)pv_buffer + cb_written;
+	} while (cb_buffer);
+
+	return 0;
+}
+
+/*
+ * Wrapper around tcp_write to send a string
+ */
+static int
+remote_tcp_write_string(int sock, const char *pv_buffer)
+{
+	return remote_tcp_write(sock, pv_buffer, strlen(pv_buffer) + 1);
+}
+
+
+/*
  *  Request that the daemon open a file.
  */
 static int
@@ -2124,8 +2216,8 @@ remote_file_open(struct remote_file *rfp)
 	BZERO(sendbuf, BUFSIZE);
 	BZERO(recvbuf, BUFSIZE);
        	sprintf(sendbuf, "OPEN %s", rfp->filename);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
 
         if (CRASHDEBUG(1))
                 fprintf(fp, "remote_file_open: [%s]\n", recvbuf);
@@ -2159,8 +2251,8 @@ remote_file_close(struct remote_file *rfp)
 	BZERO(sendbuf, BUFSIZE);
 	BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "CLOSE %d", rfp->fd);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
 
 	return (strstr(recvbuf, "OK") ? TRUE : FALSE);
 }
@@ -2177,8 +2269,8 @@ remote_proc_version(char *buf)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "PROC_VERSION");
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         if (STREQ(recvbuf, "<FAIL>"))
                 return FALSE;
         strcpy(buf, recvbuf);
@@ -2359,8 +2451,8 @@ copy_to_local_namelist(struct remote_file *rfp)
         	BZERO(sendbuf, BUFSIZE);
         	BZERO(recvbuf, BUFSIZE);
         	sprintf(sendbuf, "DEBUGGING_SYMBOLS %s", rfp->filename);
-        	send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        	recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        	remote_tcp_write_string(pc->sockfd, sendbuf);
+        	remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
 		if (strstr(recvbuf, "NO_DEBUG")) {
 			sprintf(readbuf, "%s@%s", rfp->filename, pc->server);
 			pc->namelist = readbuf;
@@ -2472,8 +2564,8 @@ identical_namelist(char *file, struct remote_file *rfp)
         BZERO(readbuf, BUFSIZE);
 
         sprintf(sendbuf, "LINUX_VERSION %s", rfp->filename);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         if (strstr(recvbuf, "<FAIL>")) 
 		return FALSE;
 
@@ -2515,8 +2607,8 @@ remote_file_checksum(struct remote_file *rfp)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "SUM %s", rfp->filename);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         if (strstr(recvbuf, "<FAIL>")) {
                 error(INFO, "%s: does not exist on server %s\n",
                         rfp->filename, pc->server);
@@ -2785,8 +2877,8 @@ remote_find_booted_kernel(struct remote_file *rfp)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "FIND_BOOTED_KERNEL");
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         strtok(recvbuf, " ");           /* FIND_BOOTED_KERNEL */
         p1 = strtok(NULL, " ");         /* filename */
         if (STREQ(p1, "<FAIL>"))
@@ -2806,8 +2898,8 @@ remote_lkcd_dump_init(void)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "LKCD_DUMP_INIT %d %s", pc->rmfd, pc->server_memsrc);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         if (strstr(recvbuf, "<FAIL>"))
                 return FALSE;
 
@@ -2844,8 +2936,8 @@ remote_s390_dump_init(void)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "S390_DUMP_INIT %d %s", pc->rmfd, pc->server_memsrc);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         if (strstr(recvbuf, "<FAIL>"))
                 return FALSE;
 
@@ -2880,8 +2972,8 @@ remote_netdump_init(void)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "NETDUMP_INIT %d %s", pc->rmfd, pc->server_memsrc);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         if (strstr(recvbuf, "<FAIL>"))
                 return FALSE;
 
@@ -2925,8 +3017,8 @@ remote_page_size(void)
                 error(FATAL, 
 		 "cannot determine remote page size (unknown memory source)\n");
 
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         if (strstr(recvbuf, "FAIL"))
                 error(FATAL, "cannot determine remote page size\n");
         strtok(recvbuf, " ");           /* PAGESIZE */
@@ -2968,7 +3060,7 @@ copy_remote_file(struct remote_file *rfp, int fd, char *file, char *ttystr)
 		
 		BZERO(sendbuf, BUFSIZE);
         	sprintf(sendbuf, "READ %d %lx %ld", rfp->fd, offset, size);
-        	bytes = write(pc->sockfd, sendbuf, strlen(sendbuf));
+        	bytes = write(pc->sockfd, sendbuf, strlen(sendbuf) + 1);
 
         	bzero(readbuf, READBUFSIZE);
 
@@ -3059,7 +3151,7 @@ copy_remote_gzip_file(struct remote_file *rfp, char *file, char *ttystr)
 
         BZERO(sendbuf, BUFSIZE);
         sprintf(sendbuf, "READ_GZIP %ld %s", pc->rcvbufsize, rfp->filename);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
 
        	bzero(readbuf, READBUFSIZE);
 
@@ -3170,8 +3262,8 @@ find_remote_module_objfile(struct load_module *lm, char *module, char *retbuf)
 	        BZERO(recvbuf, BUFSIZE);
 	        sprintf(sendbuf, "FIND_MODULE %s %s",
 	                kt->utsname.release, module);
-	        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-	        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+	        remote_tcp_write_string(pc->sockfd, sendbuf);
+	        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
 	        if (strstr(recvbuf, "<FAIL>")) {
 			fprintf(fp, "find_remote_module_objfile: [%s]\n", 
 				recvbuf);
@@ -3231,8 +3323,8 @@ remote_free_memory(void)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "MEMORY FREE %s", type);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         p1 = strtok(recvbuf, " ");      /* MEMORY */
         p1 = strtok(NULL, " ");         /* FREE */
         p1 = strtok(NULL, " ");         /* MCLXCD, LKCD etc. */
@@ -3267,8 +3359,8 @@ remote_memory_used(void)
         BZERO(sendbuf, BUFSIZE);
         BZERO(recvbuf, BUFSIZE);
         sprintf(sendbuf, "MEMORY USED %s", type);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-        recv(pc->sockfd, recvbuf, BUFSIZE-1, 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
+        remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
         p1 = strtok(recvbuf, " ");          /* MEMORY */
         p1 = strtok(NULL, " ");             /* FREE */
         p1 = strtok(NULL, " ");             /* MCLXCD, LKCD, etc. */
@@ -3308,7 +3400,7 @@ remote_memory_dump(int verbose)
         BZERO(sendbuf, BUFSIZE);
         sprintf(sendbuf, "MEMORY_DUMP %ld %s%s", pc->rcvbufsize, type,
 		verbose ? "_VERBOSE" : "");
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
 
        	bzero(readbuf, READBUFSIZE);
 	done = total = 0;
@@ -3371,10 +3463,9 @@ int
 remote_memory_read(int rfd, char *buffer, int cnt, physaddr_t address)
 {
         char sendbuf[BUFSIZE];
-        char readbuf[READBUFSIZE];
 	char datahdr[DATA_HDRSIZE];
-        char *bufptr, *p1;
-	int ret, req, tot;
+	char *p1;
+	int ret, tot;
 	ulong addr;
 
 	addr = (ulong)address;  /* may be virtual */
@@ -3391,48 +3482,49 @@ remote_memory_read(int rfd, char *buffer, int cnt, physaddr_t address)
         else
                 sprintf(sendbuf, "READ_LIVE %d %lx %d", rfd, addr, cnt);
 
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
-
-       	bzero(readbuf, READBUFSIZE);
+	if (remote_tcp_write_string(pc->sockfd, sendbuf))
+		return -1;
 
 	/*
 	 *  Read request will come back with a singular header 
 	 *  followed by the data.
          */
-	req = cnt+DATA_HDRSIZE;
-	tot = 0;
-	errno = 0;
-	bufptr = readbuf;
-
-        while (req) {
-                if ((ret = recv(pc->sockfd, bufptr, req, 0)) == -1) 
-			return -1;
-                req -= ret;
-                bufptr += ret;
-		tot += ret;
-		if ((tot >= DATA_HDRSIZE) && STRNEQ(readbuf, FAILMSG)) {
-                       	p1 = strtok(readbuf, " ");   /* FAIL */
-                       	p1 = strtok(NULL, " ");      /* errno */
-			errno = atoi(p1);
-			return -1;
-		}
+        BZERO(datahdr, DATA_HDRSIZE);
+	ret = remote_tcp_read_string(pc->sockfd, datahdr, DATA_HDRSIZE, 1);
+	if (ret <= 0)
+		return -1;
+	if (CRASHDEBUG(3))
+		fprintf(fp, "remote_memory_read: [%s]\n", datahdr);
+	if (STRNEQ(datahdr, FAILMSG)) {
+		p1 = strtok(datahdr, " ");  /* FAIL  */
+		p1 = strtok(NULL, " ");     /* errno */
+		errno = atoi(p1);
+		return -1;
 	}
-        
 
-	if (!STRNEQ(readbuf, DONEMSG) && !STRNEQ(readbuf, DATAMSG)) {
+	if (!STRNEQ(datahdr, DONEMSG) && !STRNEQ(datahdr, DATAMSG)) {
 		error(INFO, "out of sync with remote memory source\n");
 		return -1;
 	}
 
-	strncpy(datahdr, readbuf, DATA_HDRSIZE);
-	if (CRASHDEBUG(3))
-		fprintf(fp, "remote_memory_read: [%s]\n", datahdr);
-        p1 = strtok(datahdr, " ");  /* DONE */
-        p1 = strtok(NULL, " ");     /* count */
+	p1 = strtok(datahdr, " ");  /* DONE */
+	p1 = strtok(NULL, " ");     /* count */
 	tot = atol(p1);
 
-	BCOPY(readbuf+DATA_HDRSIZE, buffer, tot);
+	if (cnt != tot) {
+		error(FATAL,
+		      "requested %d bytes remote memory return %d bytes\n",
+		      cnt, tot);
+		return -1;
+	}
 
+	ret = remote_tcp_read(pc->sockfd, buffer, tot);
+	if (ret != tot) {
+		error(FATAL,
+		      "requested %d bytes remote memory return %d bytes\n",
+		      ret, tot);
+		return -1;
+	}
 	return tot;
 }
 
@@ -3492,7 +3584,7 @@ remote_execute(void)
 
         BZERO(sendbuf, BUFSIZE);
         sprintf(sendbuf, "EXECUTE %ld %s", pc->rcvbufsize, command);
-        send(pc->sockfd, sendbuf, strlen(sendbuf), 0);
+        remote_tcp_write_string(pc->sockfd, sendbuf);
 
        	bzero(readbuf, READBUFSIZE);
 	done = total = 0;
@@ -3561,12 +3653,23 @@ remote_exit(void)
 
         BZERO(buf, BUFSIZE);
         sprintf(buf, "EXIT");
-        send(pc->sockfd, buf, strlen(buf), 0);
+        remote_tcp_write_string(pc->sockfd, buf);
 	/* 
 	 *  Read but ignore the return status -- we don't really care... 
 	 */
-        recv(pc->sockfd, buf, BUFSIZE-1, 0);
+        remote_tcp_read_string(pc->sockfd, buf, BUFSIZE-1, pc->flags2 & REMOTE_NIL);
 
 }
 #endif /* !DAEMON */
 
+/*
+ * Specify Emacs local variables so the formating
+ * of the code stays the same.
+ *
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 8
+ * indent-tabs-mode: t
+ * End:
+ */
-- 
1.8.4




More information about the Crash-utility mailing list