Parcourir la source

dpkg-split: Do not slurp the entire part into memory when splitting

The current code is slurping the entire part into memory, which works
fine when the partsize is small but might be unbearable when the
partsize is too big. Use fd_fd_copy() via dpkg_ar_member_put_file()
instead, which will guarantee small constant memory usage.
Guillem Jover il y a 15 ans
Parent
commit
506dd27b56
1 fichiers modifiés avec 9 ajouts et 12 suppressions
  1. 9 12
      dpkg-split/split.c

+ 9 - 12
dpkg-split/split.c

@@ -119,11 +119,11 @@ mksplit(const char *file_src, const char *prefix, size_t maxpartsize,
 	char *package, *version;
 	char *package, *version;
 	int nparts, curpart;
 	int nparts, curpart;
 	off_t partsize;
 	off_t partsize;
+	off_t last_partsize;
 	char *prefixdir = NULL, *msdos_prefix = NULL;
 	char *prefixdir = NULL, *msdos_prefix = NULL;
 	struct varbuf file_dst = VARBUF_INIT;
 	struct varbuf file_dst = VARBUF_INIT;
 	struct varbuf partmagic = VARBUF_INIT;
 	struct varbuf partmagic = VARBUF_INIT;
 	struct varbuf partname = VARBUF_INIT;
 	struct varbuf partname = VARBUF_INIT;
-	char *partdata;
 
 
 	fd_src = open(file_src, O_RDONLY);
 	fd_src = open(file_src, O_RDONLY);
 	if (fd_src < 0)
 	if (fd_src < 0)
@@ -141,6 +141,9 @@ mksplit(const char *file_src, const char *prefix, size_t maxpartsize,
 	version = deb_field(file_src, "Version");
 	version = deb_field(file_src, "Version");
 
 
 	partsize = maxpartsize - HEADERALLOWANCE;
 	partsize = maxpartsize - HEADERALLOWANCE;
+	last_partsize = st.st_size % partsize;
+	if (last_partsize == 0)
+		last_partsize = partsize;
 	nparts = (st.st_size + partsize - 1) / partsize;
 	nparts = (st.st_size + partsize - 1) / partsize;
 
 
 	setvbuf(stdout, NULL, _IONBF, 0);
 	setvbuf(stdout, NULL, _IONBF, 0);
@@ -163,11 +166,8 @@ mksplit(const char *file_src, const char *prefix, size_t maxpartsize,
 		prefix = clean_msdos_filename(msdos_prefix);
 		prefix = clean_msdos_filename(msdos_prefix);
 	}
 	}
 
 
-	partdata = m_malloc(partsize);
-
 	for (curpart = 1; curpart <= nparts; curpart++) {
 	for (curpart = 1; curpart <= nparts; curpart++) {
 		int fd_dst;
 		int fd_dst;
-		ssize_t partrealsize;
 
 
 		varbufreset(&file_dst);
 		varbufreset(&file_dst);
 		/* Generate output filename. */
 		/* Generate output filename. */
@@ -186,12 +186,10 @@ mksplit(const char *file_src, const char *prefix, size_t maxpartsize,
 			             prefix, curpart, nparts);
 			             prefix, curpart, nparts);
 		}
 		}
 
 
-		/* Read data from the original package. */
-		partrealsize = read(fd_src, partdata, partsize);
-		if (partrealsize < 0)
-			ohshite("mksplit: read");
+		if (curpart == nparts)
+			partsize = last_partsize;
 
 
-		if ((size_t)partrealsize > maxpartsize) {
+		if ((size_t)partsize > maxpartsize) {
 			ohshit(_("Header is too long, making part too long. "
 			ohshit(_("Header is too long, making part too long. "
 			       "Your package name or version\n"
 			       "Your package name or version\n"
 			       "numbers must be extraordinarily long, "
 			       "numbers must be extraordinarily long, "
@@ -216,8 +214,8 @@ mksplit(const char *file_src, const char *prefix, size_t maxpartsize,
 
 
 		/* Write the data part. */
 		/* Write the data part. */
 		varbufprintf(&partname, "data.%d", curpart);
 		varbufprintf(&partname, "data.%d", curpart);
-		dpkg_ar_member_put_mem(file_dst.buf, fd_dst, partname.buf,
-		                       partdata, (size_t)partrealsize);
+		dpkg_ar_member_put_file(file_dst.buf, fd_dst, partname.buf,
+		                        fd_src, partsize);
 		varbufreset(&partname);
 		varbufreset(&partname);
 
 
 		close(fd_dst);
 		close(fd_dst);
@@ -228,7 +226,6 @@ mksplit(const char *file_src, const char *prefix, size_t maxpartsize,
 	varbuf_destroy(&file_dst);
 	varbuf_destroy(&file_dst);
 	varbuf_destroy(&partname);
 	varbuf_destroy(&partname);
 	varbuf_destroy(&partmagic);
 	varbuf_destroy(&partmagic);
-	free(partdata);
 
 
 	free(prefixdir);
 	free(prefixdir);
 	free(msdos_prefix);
 	free(msdos_prefix);