/*
 * nasd_edrfs_common.c
 *
 * Common utility functions for NASD/EDRFS file system prototype.
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1996,1997,1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#include <nasd/nasd_options.h>
#include <nasd/nasd_types.h>
#include <nasd/nasd_edrfs_types.h>
#include <nasd/nasd_edrfs_rpc.h>
#include <nasd/nasd_marshall.h>
#include <nasd/nasd_edrfs_pipe.h>
#include <nasd/nasd_general.h>

/* possible debugging */

/* external utility routines */
extern char* nasd_error_string(nasd_status_t error);

void nasd_edrfs_print_attribute (nasd_attribute_t *attribute)
{
  if (attribute) {
    nasd_edrfs_attributes_t *edrfs_specific =
      (nasd_edrfs_attributes_t *)(attribute->fs_specific);

    nasd_printf("\n");
    nasd_printf("{blk_prealloc(%" NASD_64u_FMT ")",attribute->block_preallocation);
    nasd_printf(",blks_used(%" NASD_64u_FMT ")",attribute->blocks_used);
    nasd_printf(",blksiz(%u)",attribute->block_size);
    nasd_printf(",obj_len(%" NASD_64u_FMT ")",attribute->object_len);
    nasd_printf("\n");
    nasd_printf(",amtime(%d,%d)",
	    attribute->attr_modify_time.ts_sec,
	    attribute->attr_modify_time.ts_nsec);
    nasd_printf(",omtime(%d,%d)",
	    attribute->object_modify_time.ts_sec,
	    attribute->object_modify_time.ts_nsec);
    nasd_printf("\n");
    nasd_printf(",fsamtime(%d,%d)",
	    attribute->fs_attr_modify_time.ts_sec,
	    attribute->fs_attr_modify_time.ts_nsec);
    nasd_printf(",fsomtime(%d,%d)",
	    attribute->fs_object_modify_time.ts_sec,
	    attribute->fs_object_modify_time.ts_nsec);
    nasd_printf("\n");
    nasd_printf(",crtime(%d,%d)",
	    attribute->object_create_time.ts_sec,
	    attribute->object_create_time.ts_nsec);

    nasd_printf(",av(%d)",attribute->av);

    nasd_printf("\n");
    nasd_printf(",fs{");
    nasd_printf("type(%x)",edrfs_specific->type);
    nasd_printf(",mode(%o)",edrfs_specific->mode);
    nasd_printf(",nlink(%d)",edrfs_specific->nlink);
    nasd_printf(",uid(%d)",edrfs_specific->uid);
    nasd_printf(",gid(%d)",edrfs_specific->gid);
    nasd_printf("}");
    nasd_printf("\n");
  }    
}

/*
 * colocation pipes -- now used by the client (for kernel colocation)
 * and by the server (for userspace colocation).
 */

nasd_status_t
nasd_copipe_readdir_push(
  void        *state_arg,
  void        *buf,
  nasd_len_t   in_len,
  nasd_byte_t *ign1,
  nasd_byte_t *ign2,
  int	      *ign3)
{
  nasd_edrfs_readdir_pipe_state_t *state;
  nasd_len_t remain;
  nasd_byte_t *b;
  int nl, off, c;
  char *pb;

  state = (nasd_edrfs_readdir_pipe_state_t *)state_arg;

  if (state->dir_buf_ents_filled >= state->dir_buf_ents)
    return(NASD_NO_MEM);

  pb = (char *)buf;
  off = 0;
  remain = in_len;

  if (state->partial_buf_offset) {
    /*
     * This should never happen in the implementation at the
     * time this is written. I'm adding the code for
     * completeness. I will not test it. --jimz
     */
    nl = NASD_EDRFS_DIRENT_T_MAX - state->partial_buf_offset;
    NASD_ASSERT(nl > 0);
    c = NASD_MIN(nl, off);
    bcopy(&pb[off], (char *)&state->partial_buf[state->partial_buf_offset], c);
    state->partial_buf_offset += c;
    off += c;
    remain -= c;
    if (state->partial_buf_offset == NASD_EDRFS_DIRENT_T_MAX) {
      state->partial_buf_offset = 0;
      nasd_edrfs_dirent_t_unmarshall(state->partial_buf,
        &state->dir_buf[state->dir_buf_ents_filled]);
      state->dir_buf_ents_filled++;
    }
  }

  while(remain >= NASD_EDRFS_DIRENT_T_MAX) {
    b = (nasd_byte_t *)&pb[off];
    nasd_edrfs_dirent_t_unmarshall((nasd_otw_base_t *)b,
      &state->dir_buf[state->dir_buf_ents_filled]);
    off += NASD_EDRFS_DIRENT_T_MAX;
    remain -= NASD_EDRFS_DIRENT_T_MAX;
    state->dir_buf_ents_filled++;
  }

  if (remain) {
    NASD_ASSERT(remain < NASD_EDRFS_DIRENT_T_MAX);
    NASD_ASSERT(state->partial_buf_offset == 0);
    bcopy(&((char *)buf)[off], (char *)&state->partial_buf[0], remain);
    state->partial_buf_offset = remain;
  }

  return(NASD_SUCCESS);
}
