/*  The actual code behind mountd

    ©1998,1999 Joseph Walton

    This software is distributed under the terms of the GNU General Public
    License; either version 2 of the License, or (at your option) any
    later version.
*/

/*
    This is a *very* simple mountd implementation - some would call
     it deficient.
*/

/*
    30-Nov-1999 - Changes to support new RPC code.
*/

#include "mount.h"
#include "nfsd.h"

#include "handle_list.h"
#include "config.h"
#include "auth.h"
#include "util.h"

#include <stdio.h>
#include <string.h>

/* Give out a handle to a mountpoint */
nfsstat mountproc_mnt(struct Call *call, STRPTR dirpath, int32 *fh)
{
    struct ConfigEntry *ce;

    /* A mount is an important operation. We always log it. */
    print_auth_once(call);
    printf("Mounting '%s'\n", dirpath);

    /* Authentication is quite important here, but not critical.
        Checks are made on each use - knowing a handle does not
        itself grant privilege.
     */

    /* We traverse the list, and stop at the first match.
        If we may export this, we do so. Otherwise we
        return an error. We will not search for further matches.

     A linear search isn't terribly elegant, but neither is
        this a frequent operation */

    ce = global.config.lh_Head;

    while (ce->ce_Node.mln_Succ) {
        if (0 == stricmp(dirpath, ce->ce_ExportAs)) {
            struct LocalFile *lf;

            /* Let's check that they're allowed to mount that..
               Remember, ce_ExportAs is what they ask for, but
                we give them ce_Path */

            nfsstat stat = does_mount_permit(call, ce->ce_Path, ALLOW_READ);

            if (stat != NFS_OK) {
                printf("Mount failed - %s\n", reason(stat));
                return stat;
            }

            /* The mountpoint does not necessarily exist, but since
                it's in the configuration file the user clearly wants
                it to be mountable
            */

            lf = get_namedlocalfile(ce->ce_Path);

            /* Copy the new file handle into the response */
            if (lf) {
                fh_copy(lf, fh);

                lf->lf_IsMount = TRUE; /* So it won't be flushed */

                lf->lf_ForcedUID = ce->ce_UID;
                lf->lf_ForcedGID = ce->ce_GID;
                lf->lf_ForcedProtection = ce->ce_Protection;

                release_lf(lf);
                /* It will be given an inode when it's asked
                    for its attributes */

                return NFS_OK;
            } else
                return NFSERR_IO; /* Out of memory, I guess... */
        }
        ce = ce->ce_Node.mln_Succ;
    }
        
    puts("Mount failed - path not exported");

    /* If we fall through to here, we have failed */
    return NFSERR_ACCES;
}


/* Just log what happened - no action is taken */
void mountproc_umnt(struct Call *call, STRPTR dirpath)
{
    print_auth_once(call);
    printf("Unmounting '%s'\n", dirpath);
}
