Quellcode durchsuchen

tar2qfile: use read_all() instead of read()

read() syscall do not guarantee to read as much data as requested. This
is especially important when reading from pipe - remote end can produce
data slower than we are reading them. Use read_all() helper to always
get requested amount of data.
Marek Marczykowski-Górecki vor 10 Jahren
Ursprung
Commit
3c92cdba22
1 geänderte Dateien mit 48 neuen und 54 gelöschten Zeilen
  1. 48 54
      qubes-rpc/tar2qfile.c

+ 48 - 54
qubes-rpc/tar2qfile.c

@@ -819,11 +819,12 @@ ustar_rd (int fd, struct file_header * untrusted_hdr, char *buf, struct stat * s
 #ifdef DEBUG
 	fprintf(stderr,"Need to remove pad:%lld %lld\n",untrusted_hdr->filelen,BLKMULT-(untrusted_hdr->filelen%BLKMULT));
 #endif
-	if (untrusted_hdr->filelen%BLKMULT > 0)
-		ret = read(fd, buf, BLKMULT-(untrusted_hdr->filelen%BLKMULT));
-#ifdef DEBUG
-	fprintf(stderr,"Removed %d bytes of padding\n",ret);
-#endif
+	if (untrusted_hdr->filelen%BLKMULT > 0) {
+		if (!read_all(fd, buf, BLKMULT-(untrusted_hdr->filelen%BLKMULT))) {
+			wait_for_result();
+			exit(1);
+		}
+	}
 
 	// Resync trailing headers in order to find next file chunck in the tar file
 	return NEED_SYNC_TRAIL;
@@ -866,71 +867,64 @@ void tar_file_processor(int fd, struct filters *filters)
 	struct stat sb;			/* stat buffer see stat(2) */
 
 	char buf[BLKMULT+1];
-	size_t size;
 
 	i=0;
 	current = NEED_READ;
 	size_t to_skip = 0;
 	int sync_count = 0;
-	while ((size = read(fd, &buf, BLKMULT))) {
-		if (size != -1) {
+	while (read_all(fd, buf, BLKMULT)) {
+		ret = 0;
+		if (current==NEED_SYNC_TRAIL) {
+			ret = tar_trail (buf, 1, &sync_count);
 #ifdef DEBUG
-			fprintf(stderr,"Read %ld bytes\n",size);
+			fprintf(stderr,"Synchronizing trail: %d %d\n", ret, sync_count);
 #endif
-			ret = 0;
-			if (current==NEED_SYNC_TRAIL) {
-				ret = tar_trail (buf, 1, &sync_count);
-#ifdef DEBUG
-				fprintf(stderr,"Synchronizing trail: %d %d\n",ret,sync_count);
-#endif
-				if (ret != 1) {
-					current = NEED_READ;
-				}
+			if (ret != 1) {
+				current = NEED_READ;
+				sync_count = 0;
 			}
-			if (current==NEED_READ) {
-				current = ustar_rd(fd, &hdr, buf, &sb, filters);
+		}
+		if (current==NEED_READ) {
+			current = ustar_rd(fd, &hdr, buf, &sb, filters);
 #ifdef DEBUG
-				fprintf(stderr,"Return %d\n",ret);
+			fprintf(stderr,"Return %d\n", current);
 #endif
+		}
+		if (current==NEED_SKIP || current==NEED_SKIP_FILE) {
+			if (current==NEED_SKIP_FILE &&
+				filters->filters_count > 0 &&
+				filters->filters_count == filters->matched_filters) {
+				// This assume that either:
+				//  a) files are sorted (using full path as sort key)
+				//  b) all the directory content is in
+				//     consecutive block and only directories
+				//      are given as filters
+				// This is true for backups prepared by qvm-backup
+#ifdef DEBUG
+				fprintf(stderr, "All filters matched at least once - assuming end of requested data\n");
+#endif
+				return;
 			}
-			if (current==NEED_SKIP || current==NEED_SKIP_FILE) {
-				if (current==NEED_SKIP_FILE &&
-					filters->filters_count > 0 &&
-					filters->filters_count == filters->matched_filters) {
-				    // This assume that either:
-				    //  a) files are sorted (using full path as sort key)
-				    //  b) all the directory content is in
-				    //     consecutive block and only directories
-				    //      are given as filters
-				    // This is true for backups prepared by qvm-backup
-#ifdef DEBUG
-				    fprintf(stderr, "All filters matched at least once - assuming end of requested data\n");
-#endif
-				    return;
-				}
-#ifdef DEBUG
-				fprintf(stderr,"Need to skip %lld bytes (matched filters %d < %d)\n",
-					hdr.filelen, filters->matched_filters, filters->filters_count);
-#endif
-				to_skip = hdr.filelen;
-				while (to_skip > 0) {
-					to_skip -= read(fd, &buf, MIN(to_skip,BLKMULT));
-				}
-	
-				// Extract extra padding
+			to_skip = hdr.filelen;
 #ifdef DEBUG
-				fprintf(stderr,"Need to remove pad:%ld %lld %lld\n",to_skip,hdr.filelen,BLKMULT-(hdr.filelen%BLKMULT));
-#endif
-				if (hdr.filelen%BLKMULT > 0) {
-					ret = read(fd, &buf, BLKMULT-(hdr.filelen%BLKMULT));
-#ifdef DEBUG
-					fprintf(stderr,"Removed %d bytes of padding\n",ret);
+			fprintf(stderr,"Need to skip %lld bytes (matched filters %d < %d)\n",
+				hdr.filelen, filters->matched_filters, filters->filters_count);
+			fprintf(stderr,"Need to remove pad:%ld %lld %lld\n",to_skip,hdr.filelen,BLKMULT-(hdr.filelen%BLKMULT));
 #endif
+			if (to_skip%BLKMULT > 0) {
+				to_skip += BLKMULT-(to_skip%BLKMULT);
+			}
+			while (to_skip > 0) {
+				ret = read_all(fd, &buf, MIN(to_skip,BLKMULT));
+				if (ret <= 0) {
+					exit(1);
 				}
-				current = NEED_SYNC_TRAIL;
+				to_skip -= MIN(to_skip,BLKMULT);
 			}
-			i++;
+
+			current = NEED_SYNC_TRAIL;
 		}
+		i++;
 		//if (i >= 10)
 		//	exit(0);
 	}