Subject: Re: Vi still can't remove its own vi-recover files from NFS /var/tmp
To: NetBSD-current Discussion List <current-users@NetBSD.org>
From: Greg A. Woods <woods@weird.com>
List: netbsd-users
Date: 01/24/2004 17:00:55
[ On Saturday, January 24, 2004 at 20:56:37 (+0100), Christian Biere wrote: ]
> Subject: Re: Vi still can't remove its own vi-recover files from NFS /var/tmp
>
> Greg A. Woods wrote:
> > Remember this was an ordinary file (/etc/nsswitch.conf, to be exact):
>  
> > 	http://mail-index.netbsd.org/current-users/2002/01/22/0008.html
> 
> Can you still reproduce this?

which part to you mean?

> How was vi invoked?

With or without an filename parameter for an existing file.  All that
matters is that text be modified.

> I don't see how this
> would happen with file descriptor 6 with the current sources of vi.
> vi uses isatty() only with STDIN_FILENO and STDOUT_FILENO. Thus, you
> would only see something if you invoked it with `-se' but not for
> file descriptor 6.

Ah, you mean the ioctl(TIOCGETA) thing, not the main subject.  Yes:

  4497 vi       CALL  __stat13(0x8d4b0,0xefffd2f0)
  4497 vi       NAMI  "/etc/nsswitch.conf"
  4497 vi       RET   __stat13 0
  4497 vi       CALL  open(0x8d4b0,0,0x1b6)
  4497 vi       NAMI  "/etc/nsswitch.conf"
  4497 vi       RET   open 7
  4497 vi       CALL  ioctl(0x7,TIOCGETA,0xefffd0a8)
  4497 vi       RET   ioctl -1 errno 25 Inappropriate ioctl for device
  4497 vi       CALL  __fstat13(0x7,0xefffcf98)
  4497 vi       RET   __fstat13 0

Note the file in question is (and was) "/etc/nsswitch.conf".

As far as I can tell from the code nsdispatch(3) is just using fopen()
and (since it uses lex & yacc), fread().

However as the stdio code would suggest I cannot reproduce the
ioct(TIOCGETA) with a test program that uses only fopen() and fread():

16:22 [286] $ cat tfread.c
#include <stdio.h>

main(argc, argv)
        int argc;
        char *argv[];
{
        FILE *fp;
        char buf[BUFSIZ];

        if ((fp = fopen(argv[1], "r")) < 0) {
                perror(argv[1]);
                exit(1);
        }

        while (fread(buf, 1, 1, fp) > 0) {
                ;
        }

        exit(0);
}
16:22 [287] $ cc -O2 -static -o tfread tfread.c 
16:22 [288] $ ktrace ./tfread tfread.c
16:22 [289] $ kdump
  9374 ktrace   EMUL  "netbsd"
  9374 ktrace   CALL  execve(0xbfbfd0d7,0xbfbfcf40,0xbfbfcf4c)
  9374 ktrace   NAMI  "./tfread"
  9374 tfread   EMUL  "netbsd"
  9374 tfread   RET   execve JUSTRETURN
  9374 tfread   CALL  open(0xbfbfd0e1,0,0x1b6)
  9374 tfread   NAMI  "tfread.c"
  9374 tfread   RET   open 3
  9374 tfread   CALL  __fstat13(0x3,0xbfbfc998)
  9374 tfread   RET   __fstat13 0
  9374 tfread   CALL  __sysctl(0xbfbfc920,0x2,0xbfbfc918,0xbfbfc91c,0,0)
  9374 tfread   RET   __sysctl 0
  9374 tfread   CALL  readlink(0x804aee0,0xbfbfc978,0x3f)
  9374 tfread   NAMI  "/etc/malloc.conf"
  9374 tfread   RET   readlink -1 errno 2 No such file or directory
  9374 tfread   CALL  mmap(0,0x1000,0x3,0x1002,0xffffffff,0,0,0)
  9374 tfread   RET   mmap 1208270848/0x4804c000
  9374 tfread   CALL  break(0x804e058)
  9374 tfread   RET   break 0
  9374 tfread   CALL  break(0x804f058)
  9374 tfread   RET   break 0
  9374 tfread   CALL  break(0x8050000)
  9374 tfread   RET   break 0
  9374 tfread   CALL  break(0x8054000)
  9374 tfread   RET   break 0
  9374 tfread   CALL  read(0x3,0x8050000,0x4000)
  9374 tfread   GIO   fd 3 read 225 bytes
       "#include <stdio.h>
        
        main(argc, argv)
                int argc;
                char *argv[];
        {
                FILE *fp;
                char buf[BUFSIZ];
        
                if ((fp = fopen(argv[1], "r")) < 0) {
                        perror(argv[1]);
                        exit(1);
                }
        
                while (fread(buf, 1, 1, fp) > 0) {
                        ;
                }
        
                exit(0);
        }
       "
  9374 tfread   RET   read 225/0xe1
  9374 tfread   CALL  read(0x3,0x8050000,0x4000)
  9374 tfread   RET   read 0
  9374 tfread   CALL  exit(0)


As for reproducing the main subject issue, yes that still happens too:

  4446 vi       CALL  unlink(0xa61e0)
  4446 vi       NAMI  "/var/tmp/vi.recover/vi.04446b"
  4446 vi       RET   unlink 0
  4446 vi       CALL  unlink(0xad440)
  4446 vi       NAMI  "/var/tmp/vi.recover/recover.04446d"
  4446 vi       RET   unlink -1 errno 13 Permission denied

as before the recover.* file can be removed after 'vi' has exited....

-- 
						Greg A. Woods

+1 416 218-0098                  VE3TCP            RoboHack <woods@robohack.ca>
Planix, Inc. <woods@planix.com>          Secrets of the Weird <woods@weird.com>