/*
 * exercise bug at line 7663/7664 of v6 namei.
 * Robert Morris <rtm@csail.mit.edu>
 * http://pdos.csail.mit.edu/6.828/2005/inode-thing.c
 *
 * first, mkdir d
 *
 * one process keeps creating d/a over and over, writing "d/a" into it.
 * the other process keeps deleting d/a and creating a different file,
 * containing "d/XXXX" (for some number XXXX).
 * so if the first process ever reads d/a but sees anything other than 
 * "d/a" in the file, the bug occured.
 *
 * I think this output is evidence of the problem:
 * # cc x.c
 * # ./a.out
 * starting
 * read d/a failed, ret 0, errno 0
 * done
 */

extern errno;
char junk[20*512];

cr(s)
     char *s;
{
  int fd, n;

  fd = creat(s, 0666);
  if(fd < 0){
    printf("creat %s failed\n", s);
    exit(1);
  }
  if(write(fd, s, strlen(s)) != strlen(s)){
    printf("small write %s failed\n", s);
    exit(1);
  }
  close(fd);
}

main()
{
  int pid, fd, n, i;
  char name[10];

  for(i = 0; i < 1000; i++){
    name[0] = 'd';
    name[1] = '/';
    name[2] = '0' + (i / 1000) % 10;
    name[3] = '0' + (i / 100) % 10;
    name[4] = '0' + (i / 10) % 10;
    name[5] = '0' + (i / 1) % 10;
    name[6] = '\0';
    unlink(name);
  }

  printf("starting\n");

  pid = fork();
  if(pid < 0){
    perror("fork");
    exit(1);
  }

  if(pid == 0){
    while(1){
      cr("d/a");

      fd = open("d/a", 2);
      if(fd >= 0){
        errno = 0;
        n = read(fd, junk, sizeof(junk));
        if(n < 3){
          printf("read d/a failed, ret %d, errno %d\n",
                 n, errno);
          sleep(2);
          errno = 0;
          if((n = write(fd, "deadbeef\n", 9)) < 0){
            printf("write haha to bad d/a, ret %d, errno %d\n",
                   n, errno);
          }
          exit(1);
        }
        if(junk[2] != 'a'){
          printf("read %d, did not start with a\n", n);
          exit(1);
        }
        close(fd);
      }
    }
  } else {
    for(i = 0; i < 1000; i++){
      unlink("d/a");
    name[0] = 'd';
    name[1] = '/';
    name[2] = '0' + (i / 1000) % 10;
    name[3] = '0' + (i / 100) % 10;
    name[4] = '0' + (i / 10) % 10;
    name[5] = '0' + (i / 1) % 10;
    name[6] = '\0';
      cr(name);
    }
    printf("done\n");
    kill(pid, 9);
  }
}

