# SPDX-FileCopyrightText: 2003 Renaud Deraison
# Some text descriptions might be excerpted from (a) referenced
# source(s), and are Copyright (C) by the respective right holder(s).
#
# SPDX-License-Identifier: GPL-2.0-only

# mount(soc, share)     - Mounts an NFS share and returns a file handle
#                         (soc is a socket opened to the mount daemon)
#
# readdir(soc, fid)     - Returns the content of the directory pointed by
#                         <fid>. (soc is a socket opened to the NFS daemon)
#
# cwd(soc, fid, dir)    - Changes the working directory to <dir>. Returns
#                         a new fid
#
# umount(soc, share)    - Tells the remote NFS server we don't need its services
#                         any more (soc is a socket opened to the mount daemon)

function padsz(len)
{
 if(len % 4)
  return 4 - len % 4;
 else
  return 0;
}

function rpclong(val)
{
 local_var ret;

 ret = raw_string(val / (256*256*256),
                  val / (256*256),
                  val / 256,
                  val % 256);
 return ret;
}


function str2long(val, idx)
{
 local_var ret;
 ret = ord(val[idx]) * 256 * 256 * 256 +
       ord(val[idx+1]) * 256 * 256 +
       ord(val[idx+2]) * 256 +
       ord(val[idx+3]);

  return int(ret);
}



function rpcpad(pad)
{
 return crap(length:pad, data:raw_string(0));
}




function mount(soc, share)
{
  local_var pad, req, len, r, ret, i;

  pad = padsz(len:strlen(this_host_name()));
  len = 52 + strlen(this_host_name()) + pad;

  req =            rpclong(val:rand()) +
                   rpclong(val:0) +
                   rpclong(val:2) +
                   rpclong(val:100005) +
                   rpclong(val:1) +
                   rpclong(val:1) +
                   rpclong(val:1) +
                   rpclong(val:len) +
                   rpclong(val:rand()) +
                   rpclong(val:strlen(this_host_name())) +
                   this_host_name() +
                   rpcpad(pad:pad) +
                   rpclong(val:0)  +
                   rpclong(val:0)  +
                   rpclong(val:7)  +
                   rpclong(val:0)  +
                   rpclong(val:2)  +
                   rpclong(val:3)  +
                   rpclong(val:4)  +
                   rpclong(val:5)  +
                   rpclong(val:20) +
                   rpclong(val:31) +
                   rpclong(val:0)  +
                   rpclong(val:0)  +
                   rpclong(val:0)  +

                   rpclong(val:strlen(share)) +
                   share +
                   rpcpad(pad:padsz(len:strlen(share)));

  send(socket:soc, data:req);
  r = recv(socket:soc, length:4096);
  if(strlen(r) < 24)
   return NULL;
  else
   {
    if(str2long(val:r, idx:24) != 0)
      return NULL;

    ret = "";
    for(i=28;i<60;i++)ret += r[i];
    return ret;
   }
}

function readdir(soc, fid)
{
 local_var req, r, i, dir, ret;

 req =          rpclong(val:rand()) +
                rpclong(val:0)      +
                rpclong(val:2)      +
                rpclong(val:100003) +
                rpclong(val:2)      +
                rpclong(val:16)     +
                rpclong(val:1)      +
                rpclong(val:48)     +
                rpclong(val:0)          +
                rpclong(val:0)          +
                rpclong(val:0)          +
                rpclong(val:0)      +
                rpclong(val:7)      +
                rpclong(val:0)      +
                rpclong(val:2)      +
                rpclong(val:3)      +
                rpclong(val:4)      +
                rpclong(val:5)          +
                rpclong(val:20)         +
                rpclong(val:31)     +

                rpclong(val:0)      +
                rpclong(val:0)      +
                fid                 +
                rpclong(val:0)      +
                rpclong(val:8192);

 send(socket:soc, data:req);
 r = recv(socket:soc, length:8192);
 if(strlen(r) <= 24) return NULL;
 if(str2long(val:r, idx:24) != 0) return NULL; # Could not read dir

 i = 28;
 ret = make_list();
 while(str2long(val:r, idx:i) == 1)
 {
  if ( i > strlen(r)) break;
  i += 4;
  i += 4; # File ID - don't care
  len = str2long(val:r, idx:i);
  i+=4;
  dir = substr(r, i, i + len - 1);
  i += len;
  i += padsz(len:len);
  i += 4;
  ret = make_list(ret, dir);
 }
 return ret;
}


function cwd(soc, dir, fid)
{
 local_var req, ret, i;


 req = rpclong(val:rand()) +
       rpclong(val:0)     +
       rpclong(val:2)     +
       rpclong(val:100003) +
       rpclong(val:2)     +
       rpclong(val:4)     +
       rpclong(val:1)     +
       rpclong(val:48)    +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:7)      +
       rpclong(val:0)      +
       rpclong(val:2)      +
       rpclong(val:3)      +
       rpclong(val:4)      +
       rpclong(val:5)      +
       rpclong(val:20)     +
       rpclong(val:31)     +
       rpclong(val:0)      +
       rpclong(val:0)      +
       fid +
       rpclong(val:strlen(dir)) +
       dir +
       rpcpad(pad:padsz(len:strlen(dir)));

   send(socket:soc, data:req);
   r = recv(socket:soc, length:8192);
   if(strlen(r) < 24)
    return NULL;

  if(strlen(r) < 24)
    return NULL;
   else
   {
    if(str2long(val:r, idx:24) != 0)
      return NULL;

    ret = "";
    for(i=28;i<56;i++)ret += r[i];
    ret += rpclong(val:0);
    return ret;
   }
}






function open(soc, file, fid)
{
 local_var req, ret, i;


 req = rpclong(val:rand()) +
       rpclong(val:0)     +
       rpclong(val:2)     +
       rpclong(val:100003) +
       rpclong(val:2)     +
       rpclong(val:4)     +
       rpclong(val:1)     +
       rpclong(val:48)    +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:7)      +
       rpclong(val:0)      +
       rpclong(val:2)      +
       rpclong(val:3)      +
       rpclong(val:3)      +
       rpclong(val:5)      +
       rpclong(val:20)     +
       rpclong(val:31)     +
       rpclong(val:0)      +
       rpclong(val:0)      +
       fid +
       rpclong(val:strlen(file)) +
       file +
       rpcpad(pad:padsz(len:strlen(file)));

   send(socket:soc, data:req);
   r = recv(socket:soc, length:8192);
   if(strlen(r) < 24)
    return NULL;

  if(strlen(r) < 24)
    return NULL;
   else
   {
    if(str2long(val:r, idx:24) != 0)
      return NULL;

    ret = "";
    for(i=28;i<56;i++)ret += r[i];
    ret += rpclong(val:0);
    return ret;
   }
}

function read(soc, fid, length, off)
{
 local_var req, ret, i, len;


 req = rpclong(val:rand()) +
       rpclong(val:0)     +
       rpclong(val:2)     +
       rpclong(val:100003) +
       rpclong(val:2)     +
       rpclong(val:6)     +
       rpclong(val:1)     +
       rpclong(val:48)    +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:0)      +
       rpclong(val:7)      +
       rpclong(val:0)      +
       rpclong(val:2)      +
       rpclong(val:3)      +
       rpclong(val:4)      +
       rpclong(val:5)      +
       rpclong(val:20)     +
       rpclong(val:31)     +
       rpclong(val:0)      +
       rpclong(val:0)      +
       fid +
       rpclong(val:off) +
       rpclong(val:length) +
       rpclong(val:0);

   send(socket:soc, data:req);
   r = recv(socket:soc, length:length + 33);
   if(strlen(r) <= 32)
    return NULL;

   return substr(r, 32, strlen(r) - 1);
}


function umount(soc, share)
{
 local_var pad, req, len, r, ret, i;

  pad = padsz(len:strlen(this_host_name()));
  len = 52 + strlen(this_host_name()) + pad;

 req =  rpclong(val:rand()) +
                   rpclong(val:0) +
                   rpclong(val:2) +
                   rpclong(val:100005) +
                   rpclong(val:1) +
                   rpclong(val:3) +
                   rpclong(val:1) +
                   rpclong(val:len) +
                   rpclong(val:rand()) +
                   rpclong(val:strlen(this_host_name())) +
                   this_host_name() +
                   rpcpad(pad:pad) +
                   rpclong(val:0)  +
                   rpclong(val:0)  +
                   rpclong(val:7)  +
                   rpclong(val:0)  +
                   rpclong(val:2)  +
                   rpclong(val:3)  +
                   rpclong(val:4)  +
                   rpclong(val:5)  +
                   rpclong(val:20) +
                   rpclong(val:31) +
                   rpclong(val:0)  +
                   rpclong(val:0)  +
                   rpclong(val:0)  +

                   rpclong(val:strlen(share)) +
                   share +
                   rpcpad(pad:padsz(len:strlen(share)));

  send(socket:soc, data:req);
  r = recv(socket:soc, length:8192);
}

