Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Feb 1997 12:56:54 -0700
From:      "Aaron D. Gifford" <agifford@infowest.com>
To:        freebsd-stable@freebsd.org
Subject:   2.1.7 and Tripwire ftruncate() fun (MORE INFO)
Message-ID:  <3.0.1.32.19970224125654.00d5f0a0@infowest.com>

next in thread | raw e-mail | index | archive | help
Hi,

First the questions:

  Is anyone successfully running Tripwire on FreeBSD 2.1.7?

  If so, how did you overcome the problem with ftruncate()?

  Is the problem with ftruncate() in Tripwire an OS bug?  Is it a compiler
bug?

Now for the background:
  I downloaded Tripwire 1.2 from
ftp://coast.cs.purdue.edu/pub/Purdue/Tripwire/tripwire-1.2.tar.Z and
compiled it.  I followed the instructions in the README file included in
the tarball and the compile and install went smoothly.  I then created my
own custom config file for tripwire.  Last, I ran tripwire to create the
initial database.  Here's what happened:

  bash# ./tripwire -initialize
  ### Phase 1:   Reading configuration file
  ### Phase 2:   Generating file list
  ### Phase 3:   Creating file information database
  truncate(): Invalid argument
  bash#

I then went back to the source files for tripwire and grep'd for truncate.
I found the only occurence was a call to "ftruncate()" in the file
"dbase.build.c" in the subroutine "database_record_write()" and nowhere
else.  Looking at the code some more, I noticed that the file which was to
be truncated with ftruncate() was opened the very first time
database_record_write() was called by a call to fd_tempfilename_generate()
in utils.c, a subroutine that opens a temporary file for reading and
writing in /tmp then unlinks it and returns the file descriptor number to
the caller.  Just so I could see what was happening, I commented out the
"unlink()" call in fd_tempfilename_generate() in utils.c so that the
temporary file would stick around.  In database_record_write() in
dbase.build.c I then added some code around the call to ftruncate:

  /* Added code begins: */
  fprintf(stderr, "fdsymlink = %d\n", fdsymlink);
  if ((err = write(fdsymlink, "Before...\n", 10)) != 10) {
      fprintf(stderr, "BEFORE: write() returned %d\n", err);
  } else {
      fprintf(stderr, "BEFORE: write() succeeded!\n");
  }
  /* End of first chunk of added code */
  
  /* The line below was altered.  The original line WAS:
     if (ftruncate(fdsymlink, 0) < 0) {
  */
  if ((err=ftruncate(fdsymlink, 0)) < 0) {
      /* More added code below: */
      fprintf(stderr, "ftruncate() failed, returning %d -- fdsymlink=%d "
              "and errno=%d \"%s\"\n", err, fdsymlink, errno,
              strerror(errno));
      if ((err = write(fdsymlink, "After...\n", 9)) != 9) {
          fprintf(stderr, "AFTER: write() returned %d\n", err);
      } else {
          fprintf(stderr, "AFTER: write() succeeded!\n");
      }
      /* End of added code chunk #2 */
      die_with_err("truncate()", NULL);
  }

After adding the stuff above I recompiled and this is what I saw:

  bash# ./tripwire -initialize
  ### Phase 1:   Reading configuration file
  ### Phase 2:   Generating file list
  ### Phase 3:   Creating file information database
  BEFORE: write() succeeded!
  ftruncate() failed, returning -1 -- fdsymlink=4 and errno=22 "Invalid
argument"
  AFTER: write() succeeded!
  truncate(): Invalid argument
  bash# ls -l /tmp
  total 2
  -rw-------  1 root  bin  19 Feb 24 12:42 twz006363
  bash# cat /tmp/twz006363
  Before...
  After...
  bash# 

I must say I was (and I still am) very puzzled.  A quick 'man errno'
informed me:
  22 EINVAL Invalid argument. Some invalid argument was supplied. (For ex-
          ample, specifying an undefined signal to a signal or kill func-
          tion).
Then a quick 'man ftruncate' returned:
  Ftruncate() succeeds unless:
  [EBADF]    The fd is not a valid descriptor.
  [EINVAL]   The fd references a socket, not a file.
  [EINVAL]   The fd is not open for writing.

>From my test code and from looking at the tripwire source, the fd is a FILE
(not a socket) and is open for WRITING, so why is ftruncate() returning
EINVAL?  I cannot understand it.  From looking at the contents of the temp
file after my code additions, I see that when the ftruncate() call occurs,
the temp file is length 10 (from the "Before...\n"), the call failes with
EINVAL then the very same file descriptor is successfully written to again
("After...\n").

So, what's going on?  The tripwire source looks like it SHOULD work.  Any
ideas?

I searched the archive at freebsd.org for "tripwire" and "truncate" and saw
a few messages from about a year ago.  Unfortunately, none of the messages
was of any use (most just reported the bug).

Thanks in advance for any and all information.  I would really like to get
tripwire working.

Puzzled,
Aaron Gifford






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3.0.1.32.19970224125654.00d5f0a0>