#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int fd;
static int
rdok(unsigned long long a, unsigned char *b, int len){
  ssize_t n = pread(fd, b, len, (off_t)a);
  return n == len;
}
int main(void){
  fd=open("/dev/kmem",O_RDONLY);
  unsigned long long start=0xfffff80040000000ULL, end=0xfffff80080000000ULL;
  unsigned long long win=2ULL<<20;
  unsigned char *p=malloc(win);
  unsigned char magic[4]={0xAE,0x0A,0xE4,0xF7};
  int hits=0;
  unsigned long long a=start;
  while(a<end){
    ssize_t n=pread(fd,p,win,(off_t)a);
    if(n>4096){
      unsigned char *q=p;
      while((q=memmem(q,(p+n)-(q),magic,4))){
        if(q+0xA8<p+n && q[0x10]==5 && !memcmp(q+0x11,"ZFILE",5)){
          unsigned long long addr=a+(q-p);
          unsigned char ext[8];
          /* live hpfsnode (not the 512B fnode buffer copy): h_flag at
           * h_fn+560-... struct hpfsnode: h_fn@off, then h_vp..h_flag;
           * h_flag sits 40 bytes past the 520-byte h_fn */
          if(rdok(addr+560, ext, 4)){
            unsigned int fl; memcpy(&fl,ext,4);
            if((fl & 0xA)==0xA){ printf("HPFN %llx flag=%x\n",addr,fl); hits++; }
            else printf("SKIP %llx (flag=%x, fnode-buffer copy?)\n",addr,fl);
          }
        }
        q+=4;
      }
      a+=win;
    } else {
      for(unsigned long long b=a;b<a+win && b<end;b+=4096){
        ssize_t m=pread(fd,p,4096,(off_t)b);
        if(m<4096) continue;
        unsigned char *q=p;
        while((q=memmem(q,(p+m)-(q),magic,4))){
          if(q+0xA8<p+m && q[0x10]==5 && !memcmp(q+0x11,"ZFILE",5)){
            unsigned long long addr=b+(q-p);
            unsigned char ext[8];
            if(rdok(addr+560, ext, 4)){
              unsigned int fl; memcpy(&fl,ext,4);
              if((fl & 0xA)==0xA){ printf("HPFN %llx flag=%x\n",addr,fl); hits++; }
              else printf("SKIP %llx (flag=%x)\n",addr,fl);
            }
          }
          q+=4;
        }
      }
      a+=win;
    }
  }
  printf("HSCAN_DONE hits=%d\n",hits);
  return 0;}
