Browse code

blob fixes

git-svn: trunk@3729

aCaB authored on 2008/03/21 06:02:17
Showing 3 changed files
... ...
@@ -1,3 +1,8 @@
1
+Thu Mar 20 21:06:30 CET 2008 (acab)
2
+-----------------------------------
3
+ * libclamav/blob.[ch]: Fix for "bad file descriptor" under win32, properly
4
+			 generate tempfiles, huge cleanup
5
+
1 6
 Thu Mar 20 20:55:37 CET 2008 (acab)
2 7
 -----------------------------------
3 8
   * libclamav: Remove fsync()'s. Win32 ports should greatly benefit from it
... ...
@@ -494,8 +494,7 @@ fileblobDestroy(fileblob *fb)
494 494
 void
495 495
 fileblobSetFilename(fileblob *fb, const char *dir, const char *filename)
496 496
 {
497
-	int fd;
498
-	char fullname[NAME_MAX + 1];
497
+	char *fullname;
499 498
 
500 499
 	if(fb->b.name)
501 500
 		return;
... ...
@@ -512,78 +511,17 @@ fileblobSetFilename(fileblob *fb, const char *dir, const char *filename)
512 512
 	filename = blobGetFilename(&fb->b);
513 513
 
514 514
 	assert(filename != NULL);
515
+	
516
+	if (cli_gentempfd(dir, &fullname, &fb->fd)!=CL_SUCCESS) return;
515 517
 
516
-#ifdef	C_QNX6
517
-	/*
518
-	 * QNX6 support from mikep@kaluga.org to fix bug where mkstemp
519
-	 * can return ETOOLONG even when the file name isn't too long
520
-	 */
521
-	snprintf(fullname, sizeof(fullname), "%s/clamavtmpXXXXXXXXXXXXX", dir);
522
-#elif	defined(C_WINDOWS)
523
-	sprintf_s(fullname, sizeof(fullname) - 1, "%s\\%.*sXXXXXX", dir,
524
-		(int)(sizeof(fullname) - 9 - strlen(dir)), filename);
525
-#else
526
-	sprintf(fullname, "%s/%.*sXXXXXX", dir,
527
-		(int)(sizeof(fullname) - 9 - strlen(dir)), filename);
528
-#endif
529
-
530
-#if	defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) || defined(C_CYGWIN) || defined(C_QNX6)
531
-	cli_dbgmsg("fileblobSetFilename: mkstemp(%s)\n", fullname);
532
-	/*
533
-	 * On older Cygwin, mkstemp opened in O_TEXT mode, rather than
534
-	 *	O_BINARY. I understand this is now fixed, but I don't know in
535
-	 *	what version
536
-	 * See http://cygwin.com/ml/cygwin-patches/2006-q2/msg00014.html
537
-	 */
538
-	fd = mkstemp(fullname);
539
-	if((fd < 0) && (errno == EINVAL)) {
540
-		/*
541
-		 * This happens with some Linux flavours when (mis)handling
542
-		 * filenames with foreign characters
543
-		 */
544
-		snprintf(fullname, sizeof(fullname), "%s/clamavtmpXXXXXXXXXXXXX", dir);
545
-		cli_dbgmsg("fileblobSetFilename: retry as mkstemp(%s)\n", fullname);
546
-		fd = mkstemp(fullname);
547
-	}
548
-#elif	defined(C_WINDOWS)
549
-	cli_dbgmsg("fileblobSetFilename: _mktemp_s(%s)\n", fullname);
550
-	if(_mktemp_s(fullname, strlen(fullname) + 1) != 0) {
551
-		char *name;
552
-
553
-		/* _mktemp_s only allows 26 files */
554
-		cli_dbgmsg("fileblobSetFilename: _mktemp_s(%s) failed: %s\n", fullname, strerror(errno));
555
-		name = cli_gentemp(dir);
556
-		if(name == NULL)
557
-			return;
558
-		fd = open(name, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
559
-		if(fd >= 0)
560
-			strncpy(fullname, name, sizeof(fullname) - 1);
561
-		free(name);
562
-	} else
563
-		fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
564
-#else
565
-	cli_dbgmsg("fileblobSetFilename: mktemp(%s)\n", fullname);
566
-	(void)mktemp(fullname);
567
-	fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
568
-#endif
569
-
570
-	if(fd < 0) {
571
-		cli_errmsg("Can't create temporary file %s: %s\n", fullname, strerror(errno));
572
-		cli_dbgmsg("%lu %lu\n", (unsigned long)sizeof(fullname),
573
-			(unsigned long)strlen(fullname));
574
-		return;
575
-	}
518
+	cli_dbgmsg("fileblobSetFilename: file %s saved to %s\n", filename, fullname);
576 519
 
577
-	cli_dbgmsg("Creating %s\n", fullname);
578
-
579
-	fb->fp = fdopen(fd, "wb");
520
+	fb->fp = fdopen(fb->fd, "wb");
580 521
 
581 522
 	if(fb->fp == NULL) {
582
-		cli_errmsg("Can't create file %s: %s\n", fullname, strerror(errno));
583
-		cli_dbgmsg("%lu %lu\n", (unsigned long)sizeof(fullname),
584
-			(unsigned long)strlen(fullname));
585
-		close(fd);
586
-
523
+		cli_errmsg("fileblobSetFilename: fdopen failed (%s)\n", strerror(errno));
524
+		close(fb->fd);
525
+		free(fullname);
587 526
 		return;
588 527
 	}
589 528
 	if(fb->b.data)
... ...
@@ -593,13 +531,7 @@ fileblobSetFilename(fileblob *fb, const char *dir, const char *filename)
593 593
 			fb->b.len = fb->b.size = 0;
594 594
 			fb->isNotEmpty = 1;
595 595
 		}
596
-
597
-	/*
598
-	 * If this strdup fails, then if the file is empty it won't be removed
599
-	 * until later. Since this is only a trivial issue, there is no need
600
-	 * to error if it fails to allocate
601
-	 */
602
-	fb->fullname = cli_strdup(fullname);
596
+	fb->fullname = fullname;
603 597
 }
604 598
 
605 599
 int
... ...
@@ -669,14 +601,12 @@ fileblobSetCTX(fileblob *fb, cli_ctx *ctx)
669 669
 int
670 670
 fileblobScan(const fileblob *fb)
671 671
 {
672
-#ifndef	C_WINDOWS
673
-	int rc, fd;
672
+	int rc;
674 673
 	cli_file_t ftype;
675
-#endif
676 674
 
677 675
 	if(fb->isInfected)
678 676
 		return CL_VIRUS;
679
-	if(fb->fullname == NULL) {
677
+	if(fb->fp == NULL || fb->fullname == NULL) {
680 678
 		/* shouldn't happen, scan called before fileblobSetFilename */
681 679
 		cli_warnmsg("fileblobScan, fullname == NULL\n");
682 680
 		return CL_ENULLARG;	/* there is no CL_UNKNOWN */
... ...
@@ -686,49 +616,26 @@ fileblobScan(const fileblob *fb)
686 686
 		cli_dbgmsg("fileblobScan, ctx == NULL\n");
687 687
 		return CL_CLEAN;	/* there is no CL_UNKNOWN */
688 688
 	}
689
-#ifndef	C_WINDOWS
690
-	/*
691
-	 * FIXME: On Windows, cli_readn gives "bad file descriptor" when called
692
-	 * by cli_check_mydoom_log from the call to cli_magic_scandesc here
693
-	 * which implies that the file descriptor is getting closed somewhere,
694
-	 * but I can't see where.
695
-	 * One possible fix would be to duplicate cli_scanfile here.
696
-	 */
697
-	fflush(fb->fp);
698
-	fd = dup(fileno(fb->fp));
699
-	if(fd == -1) {
700
-		cli_warnmsg("%s: dup failed\n", fb->fullname);
701
-		return CL_CLEAN;
702
-	}
703
-	/* cli_scanfile is static :-( */
704
-	/*if(cli_scanfile(fb->fullname, fb->ctx) == CL_VIRUS) {
705
-		cli_dbgmsg("%s is infected\n", fb->fullname);
706
-		return CL_VIRUS;
707
-	}*/
708 689
 
709
-	rc = cli_magic_scandesc(fd, fb->ctx);
690
+	fflush(fb->fp);
691
+	lseek(fb->fd, 0, SEEK_SET);
692
+	rc = cli_magic_scandesc(fb->fd, fb->ctx);
710 693
 
711 694
 	if(rc == CL_CLEAN) {
712
-		lseek(fd, 0, SEEK_SET);
713
-		ftype = cli_filetype2(fd, fb->ctx->engine);
695
+		lseek(fb->fd, 0, SEEK_SET);
696
+		ftype = cli_filetype2(fb->fd, fb->ctx->engine);
714 697
 		if(ftype >= CL_TYPE_TEXT_ASCII && ftype <= CL_TYPE_TEXT_UTF16BE) {
715
-			lseek(fd, 0, SEEK_SET);
716
-			rc = cli_scandesc(fd, fb->ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR);
698
+			lseek(fb->fd, 0, SEEK_SET);
699
+			rc = cli_scandesc(fb->fd, fb->ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR);
717 700
 		}
718 701
 	}
719 702
 
720
-	close(fd);
721
-
722 703
 	if(rc == CL_VIRUS) {
723 704
 		cli_dbgmsg("%s is infected\n", fb->fullname);
724 705
 		return CL_VIRUS;
725 706
 	}
726 707
 	cli_dbgmsg("%s is clean\n", fb->fullname);
727 708
 	return CL_BREAK;
728
-#else	/*C_WINDOWS*/
729
-	/* Ensure that the file is saved and scanned */
730
-	return CL_CLEAN;	/* there is no CL_UNKNOWN :-( */
731
-#endif	/*C_WINDOWS*/
732 709
 }
733 710
 
734 711
 /*
... ...
@@ -51,6 +51,7 @@ int	blobGrow(blob *b, size_t len);
51 51
  */
52 52
 typedef	struct fileblob {
53 53
 	FILE	*fp;
54
+	int	fd;
54 55
 	blob	b;	/*
55 56
 			 * b.name is the name of the attachment as stored in the
56 57
 			 * email, not the full path name of the temporary file