Exemple #1
0
int
net_mountroot(void)
{
	int error;

#ifdef DEBUG
	printf("net_mountroot\n");
#endif

	/*
	 * Get info for NFS boot: our IP address, our hostname,
	 * server IP address, and our root path on the server.
	 * There are two ways to do this:  The old, Sun way,
	 * and the more modern, BOOTP way. (RFC951, RFC1048)
	 */

	/* Historically, we've used BOOTPARAMS, so try that first */
	error = net_mountroot_bootparams();
	if (error != 0)
		/* Next, try BOOTP */
		error = net_mountroot_bootp();
	if (error != 0)
		return (error);

	printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath);

	/* Get the NFS file handle (mount). */
	if (nfs_mount(netdev_sock, rootip, rootpath) != 0)
		return (errno);

	return (0);
}
Exemple #2
0
int main(int argc, char *argv[])
{
	struct nfs_context *nfs;
	struct nfs_url *url;
        uint64_t length;
	struct nfs_stat_64 st;

	if (argc != 5) {
		usage();
	}

        length = strtol(argv[4], NULL, 10);

	nfs = nfs_init_context();
	if (nfs == NULL) {
		printf("failed to init context\n");
		exit(1);
	}

	url = nfs_parse_url_full(nfs, argv[1]);
	if (url == NULL) {
		fprintf(stderr, "%s\n", nfs_get_error(nfs));
		exit(1);
	}

	if (nfs_mount(nfs, url->server, url->path) != 0) {
 		fprintf(stderr, "Failed to mount nfs share : %s\n",
			nfs_get_error(nfs));
		exit(1);
	}

	if (nfs_chdir(nfs, argv[2]) != 0) {
 		fprintf(stderr, "Failed to chdir to \"%s\" : %s\n",
			argv[2], nfs_get_error(nfs));
                exit(1);
	}

	if (nfs_truncate(nfs, argv[3], length)) {
 		fprintf(stderr, "Failed to truncate file : %s\n",
			nfs_get_error(nfs));
		exit(1);
	}

	if (nfs_stat64(nfs, argv[3], &st)) {
 		fprintf(stderr, "Failed to stat file : %s\n",
			nfs_get_error(nfs));
                exit(1);
	}

        if (st.nfs_size != length) {
 		fprintf(stderr, "Unexpected file size. Expected %d got %d\n",
                        (int)length, (int)st.nfs_size);
                exit(1);
        }
        
	nfs_destroy_url(url);
	nfs_destroy_context(nfs);

	return 0;
}
Exemple #3
0
static struct file_context *
open_file(const char *url, int flags)
{
	struct file_context *file_context;

	file_context = malloc(sizeof(struct file_context));
	if (file_context == NULL) {
		fprintf(stderr, "Failed to malloc file_context\n");
		return NULL;
	}
	file_context->fd     = -1;
	file_context->nfs    = NULL;
	file_context->nfsfh  = NULL;
	file_context->url    = NULL;
	
	file_context->nfs = nfs_init_context();
	if (file_context->nfs == NULL) {
		fprintf(stderr, "failed to init context\n");
		free_file_context(file_context);
		return NULL;
	}

	file_context->url = nfs_parse_url_full(file_context->nfs, url);
	if (file_context->url == NULL) {
		fprintf(stderr, "%s\n", nfs_get_error(file_context->nfs));
		free_file_context(file_context);
		return NULL;
	}

	if (nfs_mount(file_context->nfs, file_context->url->server,
				file_context->url->path) != 0) {
		fprintf(stderr, "Failed to mount nfs share : %s\n",
			       nfs_get_error(file_context->nfs));
		free_file_context(file_context);
		return NULL;
	}

	if (flags == O_RDONLY) {
		if (nfs_open(file_context->nfs, file_context->url->file, flags,
				&file_context->nfsfh) != 0) {
 			fprintf(stderr, "Failed to open file %s: %s\n",
				       file_context->url->file,
				       nfs_get_error(file_context->nfs));
			free_file_context(file_context);
			return NULL;
		}
	} else {
		if (nfs_creat(file_context->nfs, file_context->url->file, 0660,
				&file_context->nfsfh) != 0) {
 			fprintf(stderr, "Failed to creat file %s: %s\n",
				       file_context->url->file,
				       nfs_get_error(file_context->nfs));
			free_file_context(file_context);
			return NULL;
		}
	}
	return file_context;
}
Exemple #4
0
int
net_mountroot(void)
{

#ifdef DEBUG
	printf("net_mountroot\n");
#endif

	/*
	 * Get info for NFS boot: our IP address, our hostname,
	 * server IP address, and our root path on the server.
	 * There are two ways to do this:  The old, Sun way,
	 * and the more modern, BOOTP way. (RFC951, RFC1048)
	 */

#ifdef	SUN_BOOTPARAMS
	/* Get boot info using RARP and Sun bootparams. */

	/* Get our IP address.  (rarp.c) */
	if (rarp_getipaddress(netdev_sock) == -1)
		return errno;

	printf("boot: client IP address: %s\n", inet_ntoa(myip));

	/* Get our hostname, server IP address. */
	if (bp_whoami(netdev_sock))
		return (errno);

	printf("boot: client name: %s\n", hostname);

	/* Get the root pathname. */
	if (bp_getfile(netdev_sock, "root", &rootip, rootpath))
		return (errno);

#else

	/* Get boot info using BOOTP way. (RFC951, RFC1048) */
	bootp(netdev_sock);

	printf("Using IP address: %s\n", inet_ntoa(myip));

	printf("myip: %s (%s)", hostname, inet_ntoa(myip));
	if (gateip)
		printf(", gateip: %s", inet_ntoa(gateip));
	if (netmask)
		printf(", netmask: %s", intoa(netmask));
	printf("\n");

#endif

	printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath);

	/* Get the NFS file handle (mount). */
	if (nfs_mount(netdev_sock, rootip, rootpath) != 0)
		return (errno);
	return 0;
}
Exemple #5
0
/*
 * NFS mount the kernel directory, and perform a lookup on the
 * kernel file.
 *
 * Places the directory filehandle in global "dirfh"
 * Places the kernel filehandle in global filefh
 *
 * returns 0 on success, nonzero on failure
 */
int
fileinit(struct in_addr ip, char *dirname, char *filename)
{
	int			mount_port;
	char			*readahead_option;
	int			err;
	
	readahead_option = getenv("readahead");
	if (readahead_option)
		kimg_readahead = atoi(readahead_option);
	if (kimg_readahead < 0)
		dprintf("NFS using whole-file readahead\n");
	else if (kimg_readahead > 0)
		dprintf("NFS using %dkb readahead\n", kimg_readahead);

	rpc_init();

	/*
	 * Lookup NFS/MOUNTD ports for ROOT using PORTMAP.
	 */
	nfs_port = rpc_lookup(ip, PROG_NFS, 2);
	mount_port = rpc_lookup(ip, PROG_MOUNT, 1);
	if (nfs_port == -1 || mount_port == -1) {
		printf("Can't get root NFS/MOUNT ports.\n");
		return 1;
	}
	dprintf("fileinit: NFS port = %d, MOUNT port = %d\n",
		nfs_port, mount_port);

	/*
	 * NFS mount the directory.
	 */
	dprintf("Mounting %s ... ", dirname);
	err = nfs_mount(ip, mount_port, dirname, dirfh);
	if (err) {
		printf("Can't mount filesystem: %s.\n", nfs_strerror(err));
		return 1;
	}
	dprintf("done\n");

	/*
	 * Lookup the file.
	 */
	dprintf("Looking up %s ... ", filename);
	err = nfs_lookup(ip, nfs_port, dirfh, filename, filefh);
	if (err) {
		printf("Can't lookup %s: %s.\n", filename, nfs_strerror(err));
		return 1;
	}
	dprintf("done\n");

	/* Stash ipaddr for subsequent calls */
	ipaddr.s_addr = ip.s_addr;

	return 0;
}
Exemple #6
0
/*
 * Called by devopen after it sets f->f_dev to our devsw entry.
 * This opens the low-level device and sets f->f_devdata.
 * This is declared with variable arguments...
 */
int
net_open(struct open_file *f, ...)
{
	va_list ap;
	char *devname;		/* Device part of file name (or NULL). */
	int error = 0;

	va_start(ap, f);
	devname = va_arg(ap, char*);
	va_end(ap);

#ifdef	NETIF_DEBUG
	if (debug)
		printf("net_open: %s\n", devname);
#endif

	/* On first open, do netif open, mount, etc. */
	if (netdev_opens == 0) {
		/* Find network interface. */
		if (netdev_sock < 0) {
			netdev_sock = netif_open(devname);
			if (netdev_sock < 0) {
				printf("net_open: netif_open() failed\n");
				return (ENXIO);
			}
			if (debug)
				printf("net_open: netif_open() succeeded\n");
		}
		if (rootip.s_addr == 0) {
			/* Get root IP address, and path, etc. */
			error = net_getparams(netdev_sock);
			if (error) {
				/* getparams makes its own noise */
				goto fail;
			}
			/* Get the NFS file handle (mountd). */
			error = nfs_mount(netdev_sock, rootip, rootpath);
			if (error) {
				error = errno;
				printf("net_open: NFS mount error=%d\n", error);
				rootip.s_addr = 0;
			fail:
				netif_close(netdev_sock);
				netdev_sock = -1;
				return (error);
			}
			if (debug)
				printf("net_open: NFS mount succeeded\n");
		}
	}
	netdev_opens++;
	f->f_devdata = nfs_root_node;
	return (error);
}
Exemple #7
0
int main(int argc, char *argv[])
{
	struct nfs_context *nfs = NULL;
	struct nfs_url *url = NULL;
	int ret = 0;
        int mode;

	if (argc != 5) {
		usage();
	}

        mode = strtol(argv[4], NULL, 8);
        
	nfs = nfs_init_context();
	if (nfs == NULL) {
		printf("failed to init context\n");
		exit(1);
	}

	url = nfs_parse_url_full(nfs, argv[1]);
	if (url == NULL) {
		fprintf(stderr, "%s\n", nfs_get_error(nfs));
		exit(1);
	}

	if (nfs_mount(nfs, url->server, url->path) != 0) {
 		fprintf(stderr, "Failed to mount nfs share : %s\n",
			nfs_get_error(nfs));
		ret = 1;
		goto finished;
	}

	if (nfs_chdir(nfs, argv[2]) != 0) {
 		fprintf(stderr, "Failed to chdir to \"%s\" : %s\n",
			argv[2], nfs_get_error(nfs));
		ret = 1;
		goto finished;
	}

	if (nfs_lchmod(nfs, argv[3], mode)) {
 		fprintf(stderr, "Failed to lchmod(): %s\n",
			nfs_get_error(nfs));
		ret = 1;
		goto finished;
	}
        
finished:
	nfs_destroy_url(url);
	nfs_destroy_context(nfs);

	return ret;
}
Exemple #8
0
bool CNFSConnection::Connect(VFSURL* url, std::string& relativePath)
{
  PLATFORM::CLockObject lock(*this);
  bool ret = false;
  int nfsRet = 0;
  std::string exportPath;

  resolveHost(url->hostname);
  ret = splitUrlIntoExportAndPath(url->hostname, url->filename, exportPath, relativePath);
  
  if( (ret && (exportPath != m_exportPath  || 
      m_hostName != url->hostname))    ||
      (PLATFORM::GetTimeMs() - m_lastAccessedTime) > CONTEXT_TIMEOUT )
  {
    int contextRet = getContextForExport(std::string(url->hostname) + exportPath);
    
    if(contextRet == CONTEXT_INVALID)//we need a new context because sharename or hostname has changed
    {
      return false;
    }
    
    if(contextRet == CONTEXT_NEW) //new context was created - we need to mount it
    {
      //we connect to the directory of the path. This will be the "root" path of this connection then.
      //So all fileoperations are relative to this mountpoint...
      nfsRet = nfs_mount(m_pNfsContext, m_resolvedHostName.c_str(), exportPath.c_str());

      if(nfsRet != 0) 
      {
        XBMC->Log(ADDON::LOG_ERROR,"NFS: Failed to mount nfs share: %s %s (%s)\n", m_resolvedHostName.c_str(), exportPath.c_str(), nfs_get_error(m_pNfsContext));
        destroyContext(std::string(url->hostname) + exportPath);
        return false;
      }
      XBMC->Log(ADDON::LOG_DEBUG,"NFS: Connected to server %s and export %s\n", url->hostname, exportPath.c_str());
    }
    m_exportPath = exportPath;
    m_hostName = url->hostname;
    //read chunksize only works after mount
    m_readChunkSize = nfs_get_readmax(m_pNfsContext);
    m_writeChunkSize =nfs_get_writemax(m_pNfsContext);

    if(contextRet == CONTEXT_NEW)
    {
      XBMC->Log(ADDON::LOG_DEBUG,"NFS: chunks: r/w %i/%i\n", (int)m_readChunkSize,(int)m_writeChunkSize);
    }
  }
  return ret; 
}
Exemple #9
0
/*
 *  Get a file handle from the server for the directory which is to be
 *  mounted.
 */
static int __init root_nfs_get_handle(void)
{
	struct sockaddr_in sin;
	unsigned int auth_flav_len = 0;
	struct nfs_mount_request request = {
		.sap		= (struct sockaddr *)&sin,
		.salen		= sizeof(sin),
		.dirpath	= nfs_export_path,
		.version	= (nfs_data.flags & NFS_MOUNT_VER3) ?
					NFS_MNT3_VERSION : NFS_MNT_VERSION,
		.protocol	= (nfs_data.flags & NFS_MOUNT_TCP) ?
					XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
		.auth_flav_len	= &auth_flav_len,
	};
	int status = -ENOMEM;

	request.fh = nfs_alloc_fhandle();
	if (!request.fh)
		goto out;
	set_sockaddr(&sin, servaddr, htons(mount_port));
	status = nfs_mount(&request);
	if (status < 0)
		printk(KERN_ERR "Root-NFS: Server returned error %d "
				"while mounting %s\n", status, nfs_export_path);
	else {
		nfs_data.root.size = request.fh->size;
		memcpy(&nfs_data.root.data, request.fh->data, request.fh->size);
	}
	nfs_free_fhandle(request.fh);
out:
	return status;
}

/*
 *  Get the NFS port numbers and file handle, and return the prepared 'data'
 *  argument for mount() if everything went OK. Return NULL otherwise.
 */
void * __init nfs_root_data(void)
{
	if (root_nfs_init() < 0
	 || root_nfs_ports() < 0
	 || root_nfs_get_handle() < 0)
		return NULL;
	set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port));
	return (void*)&nfs_data;
}
Exemple #10
0
int
net_mountroot()
{

#ifdef	DEBUG
	printf("net_mountroot\n");
#endif

	/*
	 * Get info for NFS boot: our IP address, out hostname,
	 * server IP address, and our root path on the server.
	 * We use BOOTP (RFC951, RFC1532) exclusively as mandated
	 * by PowerPC Reference Platform Specification I.4.2
	 */

	bootp(netdev_sock);

	if (myip.s_addr == 0)
		return ETIMEDOUT;

	printf("Using IP address: %s\n", inet_ntoa(myip));

#ifdef	DEBUG
	printf("myip: %s (%s)", hostname, inet_ntoa(myip));
	if (gateip.s_addr)
		printf(", gateip: %s", inet_ntoa(gateip));
	if (netmask)
		printf(", netmask: %s", intoa(netmask));
	printf("\n");
#endif
	printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath);

	/*
	 * Get the NFS file handle (mount).
	 */
	if (nfs_mount(netdev_sock, rootip, rootpath) < 0)
		return errno;
	return 0;
}
Exemple #11
0
err_t http_cache_init(struct ip_addr server, const char *path,
                     void (*callback)(void))
{
    struct timer *cache_timer;      /* timer for triggering cache timeouts */
    init_callback = callback;

    /* FIXME: Start the trace */
#if ENABLE_WEB_TRACING
    printf("Starting tracing\n");

    errval_t err = trace_control(TRACE_EVENT(TRACE_SUBSYS_NET,
                                    TRACE_EVENT_NET_START, 0),
                        TRACE_EVENT(TRACE_SUBSYS_NET,
                                    TRACE_EVENT_NET_STOP, 0), 0);
    if(err_is_fail(err)) {
        USER_PANIC_ERR(err, "trace_control failed");
    }
    trace_event(TRACE_SUBSYS_NET, TRACE_EVENT_NET_START, 0);
#else // ENABLE_WEB_TRACING
    printf("Tracing not enabled\n");
#endif // ENABLE_WEB_TRACING

    my_nfs_client = nfs_mount(server, path, mount_callback, NULL);
    assert(my_nfs_client != NULL);
    /* creating the empty cache */
    cache_table = NULL;
    create_404_page_cache();

    cache_timer = timer_create(MAX_STALENESS, true, cache_timeout_event,
            cache_table);
    assert (cache_timer != NULL);
    if (cache_timer == NULL) {
        printf ("http_cache_init failed in timer_create\n");
        return ERR_MEM;
    }
    timer_start(cache_timer);
    DEBUGPRINT ("http_cache_init done\n");
    return ERR_OK;
} /* end function: http_cache_init */
Exemple #12
0
/*
 *  Get a file handle from the server for the directory which is to be
 *  mounted.
 */
static int __init root_nfs_get_handle(void)
{
	struct nfs_fh fh;
	struct sockaddr_in sin;
	int status;
	int protocol = (nfs_data.flags & NFS_MOUNT_TCP) ?
					XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP;
	int version = (nfs_data.flags & NFS_MOUNT_VER3) ?
					NFS_MNT3_VERSION : NFS_MNT_VERSION;

	set_sockaddr(&sin, servaddr, htons(mount_port));
	status = nfs_mount((struct sockaddr *) &sin, sizeof(sin), NULL,
			   nfs_path, version, protocol, &fh, nfs_data.mount_prog);
	if (status < 0)
		printk(KERN_ERR "Root-NFS: Server returned error %d "
				"while mounting %s\n", status, nfs_path);
	else {
		nfs_data.root.size = fh.size;
		memcpy(nfs_data.root.data, fh.data, fh.size);
	}

	return status;
}
Exemple #13
0
int CNFSConnection::stat(VFSURL* url, struct stat *statbuff)
{
  PLATFORM::CLockObject lock(*this);
  int nfsRet = 0;
  std::string exportPath;
  std::string relativePath;
  struct nfs_context *pTmpContext = NULL;
  
  resolveHost(url->hostname);
  
  if(splitUrlIntoExportAndPath(url->hostname, url->filename, exportPath, relativePath))
  {    
    pTmpContext = nfs_init_context();
    
    if(pTmpContext)
    {  
      //we connect to the directory of the path. This will be the "root" path of this connection then.
      //So all fileoperations are relative to this mountpoint...
      nfsRet = nfs_mount(pTmpContext, m_resolvedHostName.c_str(), exportPath.c_str());
      
      if(nfsRet == 0) 
      {
        nfsRet = nfs_stat(pTmpContext, relativePath.c_str(), statbuff);      
      }
      else
      {
        XBMC->Log(ADDON::LOG_ERROR,"NFS: Failed to mount nfs share: %s (%s)\n", exportPath.c_str(), nfs_get_error(m_pNfsContext));
      }
      
      nfs_destroy_context(pTmpContext);
      XBMC->Log(ADDON::LOG_DEBUG,"NFS: Connected to server %s and export %s in tmpContext\n", url->hostname, exportPath.c_str());
    }
  }

  return nfsRet;
}
Exemple #14
0
static struct file_context *
open_file(const char *url, int flags)
{
	struct file_context *file_context;
	char *server = NULL, *path = NULL, *file = NULL, *strp;

	file_context = malloc(sizeof(struct file_context));
	if (file_context == NULL) {
		fprintf(stderr, "Failed to malloc file_context\n");
		return NULL;
	}
	file_context->is_nfs = 0;
	file_context->fd     = -1;
	file_context->nfs    = NULL;
	file_context->nfsfh  = NULL;
	

	if (strncmp(url, "nfs://", 6)) {
		file_context->is_nfs = 0;
		file_context->fd = open(url, flags, 0660);
		if (file_context->fd == -1) {		
			fprintf(stderr, "Failed to open %s\n", url);
			free_file_context(file_context);
			return NULL;
		}
		return file_context;
	}

	file_context->is_nfs = 1;

	file_context->nfs = nfs_init_context();
	if (file_context->nfs == NULL) {
		fprintf(stderr, "failed to init context\n");
		free_file_context(file_context);
		return NULL;
	}

	server = strdup(url + 6);
	if (server == NULL) {
		fprintf(stderr, "Failed to strdup server string\n");
		free_file_context(file_context);
		return NULL;
	}
	if (server[0] == '/' || server[0] == '\0') {
		fprintf(stderr, "Invalid server string.\n");
		free(server);
		free_file_context(file_context);
		return NULL;
	}
	strp = strchr(server, '/');
	path = strdup(strp);
	*strp = 0;
	if (path == NULL) {
		fprintf(stderr, "Invalid URL specified.\n");
		free(server);
		free_file_context(file_context);
		return NULL;
	}

	strp = strrchr(path, '/');
	if (strp == NULL) {
		fprintf(stderr, "Invalid URL specified.\n");
		free(path);
		free(server);
		free_file_context(file_context);
		return NULL;
	}
	file = strdup(strp);
	*strp = 0;

	if (nfs_mount(file_context->nfs, server, path) != 0) {
 		fprintf(stderr, "Failed to mount nfs share : %s\n",
			       nfs_get_error(file_context->nfs));
		free(file);
		free(path);
		free(server);
		free_file_context(file_context);
		return NULL;
	}

	if (flags == O_RDONLY) {
		if (nfs_open(file_context->nfs, file, flags,
				&file_context->nfsfh) != 0) {
 			fprintf(stderr, "Failed to open file : %s\n",
				       nfs_get_error(file_context->nfs));
			free(file);
			free(path);
			free(server);
			free_file_context(file_context);
			return NULL;
		}
	} else {
		if (nfs_creat(file_context->nfs, file, 0660,
				&file_context->nfsfh) != 0) {
 			fprintf(stderr, "Failed to creat file %s  %s\n", file,
				       nfs_get_error(file_context->nfs));
			free(file);
			free(path);
			free(server);
			free_file_context(file_context);
			return NULL;
		}
	}

	free(file);
	free(path);
	free(server);

	return file_context;
}
Exemple #15
0
int dup2(int oldfd, int newfd)
{
	close(newfd);

	if (nfs_fd_list[oldfd].is_nfs == 1) {
		struct nfs_context *nfs;
		struct nfs_url *url;
		struct nfsfh *fh = NULL;
		int ret, fd;

		LD_NFS_DPRINTF(9, "dup2(%s:%d, %d)", nfs_fd_list[oldfd].path,
			oldfd, newfd);
		nfs = nfs_init_context();
		if (nfs == NULL) {
			LD_NFS_DPRINTF(1, "Failed to create context");
			errno = ENOMEM;
			return -1;
		}

		url = nfs_parse_url_full(nfs, nfs_fd_list[oldfd].path);
		if (url == NULL) {
			LD_NFS_DPRINTF(1, "Failed to parse URL: %s\n",
				nfs_get_error(nfs));
			nfs_destroy_context(nfs);
			errno = EINVAL;
			return -1;
		}

		if (nfs_mount(nfs, url->server, url->path) != 0) {
			LD_NFS_DPRINTF(1, "Failed to mount nfs share : %s\n",
			       nfs_get_error(nfs));
			nfs_destroy_url(url);
			nfs_destroy_context(nfs);
			errno = EINVAL;
			return -1;
		}

		if ((ret = nfs_open(nfs, url->file, nfs_fd_list[oldfd].mode,
				&fh)) != 0) {
			LD_NFS_DPRINTF(1, "Failed to open nfs file : %s\n",
			       nfs_get_error(nfs));
			nfs_destroy_url(url);
			nfs_destroy_context(nfs);
			errno = -ret;
			return -1;
		}

		/* We could actually end on the right descriptor by chance */
		if (nfs_get_fd(nfs) != newfd) {
			if (real_dup2(nfs_get_fd(nfs), newfd) < 0) {
				LD_NFS_DPRINTF(1, "Failed to dup2 file : %d",
					errno);
				return -1;
			}

			close(rpc_get_fd(nfs_get_rpc_context(nfs)));
			rpc_set_fd(nfs_get_rpc_context(nfs), newfd);
		}

		fd = nfs_get_fd(nfs);
		if (fd >= NFS_MAX_FD) {
			LD_NFS_DPRINTF(1, "Too many files open");
			nfs_destroy_url(url);
			nfs_destroy_context(nfs);
			errno = ENFILE;
			return -1;
		}		

		nfs_fd_list[fd].is_nfs     = 1;
		nfs_fd_list[fd].nfs        = nfs;
		nfs_fd_list[fd].fh         = fh;
		nfs_fd_list[fd].path       = strdup(nfs_fd_list[oldfd].path);
		nfs_fd_list[fd].flags      = nfs_fd_list[oldfd].flags;
		nfs_fd_list[fd].mode       = nfs_fd_list[oldfd].mode;

		nfs_destroy_url(url);

		LD_NFS_DPRINTF(9, "dup2(%s) successful",
			nfs_fd_list[oldfd].path);
		return fd;
	}

	return real_dup2(oldfd, newfd);
}
Exemple #16
0
int
netmountroot(struct open_file *f, char *devname)
{
	int error;
	struct iodesc *d;

#ifdef DEBUG
	printf("netmountroot: %s\n", devname);
#endif

	if (netio_ask) {
 get_my_ip:
		printf("My IP address? ");
		bzero(input_line, sizeof(input_line));
		gets(input_line);
		if ((myip.s_addr = inet_addr(input_line)) ==
		    htonl(INADDR_NONE)) {
			printf("invalid IP address: %s\n", input_line);
			goto get_my_ip;
		}

 get_my_netmask:
		printf("My netmask? ");
		bzero(input_line, sizeof(input_line));
		gets(input_line);
		if ((netmask = inet_addr(input_line)) ==
		    htonl(INADDR_NONE)) {
			printf("invalid netmask: %s\n", input_line);
			goto get_my_netmask;
		}

 get_my_gateway:
		printf("My gateway? ");
		bzero(input_line, sizeof(input_line));
		gets(input_line);
		if ((gateip.s_addr = inet_addr(input_line)) ==
		    htonl(INADDR_NONE)) {
			printf("invalid IP address: %s\n", input_line);
			goto get_my_gateway;
		}

 get_server_ip:
		printf("Server IP address? ");
		bzero(input_line, sizeof(input_line));
		gets(input_line);
		if ((rootip.s_addr = inet_addr(input_line)) ==
		    htonl(INADDR_NONE)) {
			printf("invalid IP address: %s\n", input_line);
			goto get_server_ip;
		}

 get_server_path:
		printf("Server path? ");
		bzero(rootpath, sizeof(rootpath));
		gets(rootpath);
		if (rootpath[0] == '\0' || rootpath[0] == '\n')
			goto get_server_path;

		if ((d = socktodesc(netdev_sock)) == NULL)
			return (EMFILE);

		d->myip = myip;

		goto do_nfs_mount;
	}

	/*
	 * Get info for NFS boot: our IP address, our hostname,
	 * server IP address, and our root path on the server.
	 * There are two ways to do this:  The old, Sun way,
	 * and the more modern, BOOTP way. (RFC951, RFC1048)
	 */

#ifdef	SUN_BOOTPARAMS
	/* Get boot info using RARP and Sun bootparams. */

	/* Get our IP address.  (rarp.c) */
	if (rarp_getipaddress(netdev_sock) == -1)
		return (errno);

	printf("boot: client IP address: %s\n", inet_ntoa(myip));

	/* Get our hostname, server IP address. */
	if (bp_whoami(netdev_sock))
		return (errno);

	printf("boot: client name: %s\n", hostname);

	/* Get the root pathname. */
	if (bp_getfile(netdev_sock, "root", &rootip, rootpath))
		return (errno);

#else

	/* Get boot info using BOOTP way. (RFC951, RFC1048) */
	bootp(netdev_sock);

	printf("Using IP address: %s\n", inet_ntoa(myip));

	printf("myip: %s (%s)", hostname, inet_ntoa(myip));
	if (gateip)
		printf(", gateip: %s", inet_ntoa(gateip));
	if (mask)
		printf(", mask: %s", intoa(netmask));
	printf("\n");

#endif /* SUN_BOOTPARAMS */

	printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath);

 do_nfs_mount:
	/* Get the NFS file handle (mount). */
	error = nfs_mount(netdev_sock, rootip, rootpath);

	return (error);
}
Exemple #17
0
int open(const char *path, int flags, mode_t mode)
{
	if (!strncmp(path, "nfs:", 4)) {
		struct nfs_context *nfs;
		struct nfs_url *url;
		struct nfsfh *fh = NULL;
		int ret, fd;

		LD_NFS_DPRINTF(9, "open(%s, %x, %o)", path, flags, mode);
		nfs = nfs_init_context();
		if (nfs == NULL) {
			LD_NFS_DPRINTF(1, "Failed to create context");
			errno = ENOMEM;
			return -1;
		}

		url = nfs_parse_url_full(nfs, path);
		if (url == NULL) {
			LD_NFS_DPRINTF(1, "Failed to parse URL: %s\n",
				nfs_get_error(nfs));
			nfs_destroy_context(nfs);
			errno = EINVAL;
			return -1;
		}

		if (nfs_mount(nfs, url->server, url->path) != 0) {
			LD_NFS_DPRINTF(1, "Failed to mount nfs share : %s\n",
			       nfs_get_error(nfs));
			nfs_destroy_url(url);
			nfs_destroy_context(nfs);
			errno = EINVAL;
			return -1;
		}

		if (flags & O_CREAT) {
			if ((ret = nfs_creat(nfs, url->file, mode, &fh)) != 0) {
				LD_NFS_DPRINTF(1, "Failed to creat nfs file : "
					"%s\n", nfs_get_error(nfs));
				nfs_destroy_url(url);
				nfs_destroy_context(nfs);
				errno = -ret;
				return -1;
			}
		} else {
			if ((ret = nfs_open(nfs, url->file, flags, &fh)) != 0) {
				LD_NFS_DPRINTF(1, "Failed to open nfs file : "
					"%s\n", nfs_get_error(nfs));
				nfs_destroy_url(url);
				nfs_destroy_context(nfs);
				errno = -ret;
				return -1;
			}
		}

		fd = nfs_get_fd(nfs);
		if (fd >= NFS_MAX_FD) {
			LD_NFS_DPRINTF(1, "Too many files open");
			nfs_destroy_url(url);
			nfs_destroy_context(nfs);
			errno = ENFILE;
			return -1;
		}		

		nfs_fd_list[fd].is_nfs     = 1;
		nfs_fd_list[fd].nfs        = nfs;
		nfs_fd_list[fd].fh         = fh;
		nfs_fd_list[fd].path       = strdup(path);
		nfs_fd_list[fd].flags      = flags;
		nfs_fd_list[fd].mode       = mode;

		nfs_destroy_url(url);

		LD_NFS_DPRINTF(9, "open(%s) == %d", path, fd);
		return fd;
	}

	return real_open(path, flags, mode);
}
Exemple #18
0
int
net_devinit(struct open_file *f, struct netif_driver *drv, u_char *eaddr) {
	static struct netif best_if;
	struct iodesc *s;
	int r;

	if (inited)
		return 0;
	/* find a free socket */
	s = &desc;

	memset(s, 0, sizeof(*s));
	best_if.nif_driver = drv;
	s->io_netif = &best_if;
	memcpy(s->myea, eaddr, 6);

	/*
	 * Get info for NFS boot: our IP address, our hostname,
	 * server IP address, and our root path on the server.
	 * There are two ways to do this:  The old, Sun way,
	 * and the more modern, BOOTP way. (RFC951, RFC1048)
	 */

#ifdef SUPPORT_BOOTP

	/* Get boot info using BOOTP way. (RFC951, RFC1048) */
	printf("Trying BOOTP\n");
	bootp(0);

	if (myip.s_addr) {
		printf("Using IP address: %s\n", inet_ntoa(myip));

		printf("myip: %s (%s)\n", hostname, inet_ntoa(myip));
	} else

#endif /* SUPPORT_BOOTP */
	{
#ifdef	SUPPORT_BOOTPARAMS
		/* Get boot info using RARP and Sun bootparams. */

		printf("Trying BOOTPARAMS\n");
		/* Get our IP address.	(rarp.c) */
		if (rarp_getipaddress(0) == -1)
			return (errno);

		printf("boot: client IP address: %s\n", inet_ntoa(myip));

		/* Get our hostname, server IP address. */
		if (bp_whoami(0))
			return (errno);

		printf("boot: client name: %s\n", hostname);

		/* Get the root pathname. */
		if (bp_getfile(0, "root", &rootip, rootpath))
			return (errno);
#endif
	}
	printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath);
	f->f_devdata = s;

	/* Get the NFS file handle (mount). */
	r = nfs_mount(0, rootip, rootpath);
	if (r)
		return r;

	inited = 1;
	return 0;
}
Exemple #19
0
/**************************************************************************
LOAD - Try to get booted
**************************************************************************/
load()
{
	char	*p,*q;
	char	cfg[64];
	int	root_mount_port;
	int	swap_nfs_port;
	int	swap_mount_port;
	char	cmd_line[80];
	int	err, read_size, i;
	long	addr, broadcast;
	int	swsize;
	unsigned long pad;

	config_buffer[0]='\0'; /* clear; bootp might fill this up */
/* Initialize this early on */

        nfsdiskless.root_args.rsize = 8192;
        nfsdiskless.root_args.wsize = 8192;
        nfsdiskless.swap_args.rsize = 8192;
        nfsdiskless.swap_args.wsize = 8192;
        nfsdiskless.root_args.sotype = SOCK_DGRAM;
        nfsdiskless.root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | 
				       NFSMNT_RESVPORT);
        nfsdiskless.swap_args.sotype = SOCK_DGRAM;
        nfsdiskless.swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | 
				       NFSMNT_RESVPORT);


		/* Find a server to get BOOTP reply from */
	if (!arptable[ARP_CLIENT].ipaddr || !arptable[ARP_SERVER].ipaddr) {
		printf("\nSearching for server...\n");
		if (!bootp()) {
			printf("No Server found.\n");
			longjmp(jmp_bootmenu,1);
		}
	}
	printf("My IP %I, Server IP %I, GW IP %I\n",
		arptable[ARP_CLIENT].ipaddr,
		arptable[ARP_SERVER].ipaddr,
		arptable[ARP_GATEWAY].ipaddr);

#ifdef MDEBUG
	printf("\n=>>"); getchar();
#endif

	/*** check if have got info from bootp ***/
	if (config_buffer[0])
		goto cfg_done;
#ifndef NO_TFTP
	/* Now use TFTP to load configuration file */
	sprintf(cfg,"/tftpboot/freebsd.%I",arptable[ARP_CLIENT].ipaddr);
	if (tftp(cfg) || tftp(cfg+10))
		goto cfg_done;
	cfg[17]='\0';
	if (tftp(cfg) || tftp(cfg+10))
		goto cfg_done;
	sprintf(cfg,"/tftpboot/cfg.%I",arptable[ARP_CLIENT].ipaddr);
	if (tftp(cfg) || tftp(cfg+10))
		goto cfg_done;
#endif
	/* not found; using default values... */
	sprintf(config_buffer,"rootfs %I:/usr/diskless_root",
		arptable[ARP_SERVER].ipaddr);
	printf("Unable to load config file, guessing:\n\t%s\n",
		config_buffer);

cfg_done:
#ifdef MDEBUG
	printf("\n=>>"); getchar();
#endif

	p = config_buffer;
	while(*p) {
		q = cmd_line;
		while ((*p != '\n') && (*p)) *(q++) = *(p++);
		*q = 0;
		printf("%s\n",cmd_line);
		execute(cmd_line);
		if (*p) p++;
	}

#ifdef MDEBUG
	printf("\n=>>"); getchar();
#endif

		/* Check to make sure we've got a rootfs */
	if (!arptable[ARP_ROOTSERVER].ipaddr) {
		printf("No ROOT filesystem server!\n");
		longjmp(jmp_bootmenu,1);
	}

		/* Fill in nfsdiskless.myif */
	sprintf(&nfsdiskless.myif.ifra_name,eth_driver);
        nfsdiskless.myif.ifra_addr.sa_len = sizeof(struct sockaddr);
        nfsdiskless.myif.ifra_addr.sa_family = AF_INET;
	addr = htonl(arptable[ARP_CLIENT].ipaddr);
	bcopy(&addr, &nfsdiskless.myif.ifra_addr.sa_data[2], 4);
	broadcast = (addr & netmask) | ~netmask;
	nfsdiskless.myif.ifra_broadaddr.sa_len = sizeof(struct sockaddr);
	nfsdiskless.myif.ifra_broadaddr.sa_family = AF_INET;
	bcopy(&broadcast, &nfsdiskless.myif.ifra_broadaddr.sa_data[2], 4);
	addr = htonl(arptable[ARP_GATEWAY].ipaddr);
	if (addr) {
		nfsdiskless.mygateway.sin_len = sizeof(struct sockaddr);
		nfsdiskless.mygateway.sin_family = AF_INET;
		bcopy(&addr, &nfsdiskless.mygateway.sin_addr, 4);
	} else {
		nfsdiskless.mygateway.sin_len = 0;
	}
	nfsdiskless.myif.ifra_mask.sa_len = sizeof(struct sockaddr);
	nfsdiskless.myif.ifra_mask.sa_family = AF_UNSPEC;
	bcopy(&netmask, &nfsdiskless.myif.ifra_mask.sa_data[2], 4);

	rpc_id = currticks();

		/* Lookup NFS/MOUNTD ports for SWAP using PORTMAP */
	if (arptable[ARP_SWAPSERVER].ipaddr) {
		char swapfs_fh[32], swapfile[32];
		swap_nfs_port = rpclookup(ARP_SWAPSERVER, PROG_NFS, 2);
		swap_mount_port = rpclookup(ARP_SWAPSERVER, PROG_MOUNT, 1);
		if ((swap_nfs_port == -1) || (swap_mount_port == -1)) {
			printf("Unable to get SWAP NFS/MOUNT ports\n");
			longjmp(jmp_bootmenu,1);
		}
		if (err = nfs_mount(ARP_SWAPSERVER, swap_mount_port,
			nfsdiskless.swap_hostnam, &swapfs_fh)) {
			printf("Unable to mount SWAP filesystem: ");
			nfs_err(err);
			longjmp(jmp_bootmenu,1);
		}
		sprintf(swapfile,"swap.%I",arptable[ARP_CLIENT].ipaddr);
		if (err = nfs_lookup(ARP_SWAPSERVER, swap_nfs_port,
			&swapfs_fh, swapfile, &nfsdiskless.swap_fh, &swsize)) {
			printf("Unable to open %s: ",swapfile);
			nfs_err(err);
			longjmp(jmp_bootmenu,1);
		}
		if (!nfsdiskless.swap_nblks) {
		  nfsdiskless.swap_nblks = swsize / 1024;
		  printf("Swap size is: %d blocks\n",nfsdiskless.swap_nblks);
		}
		nfsdiskless.swap_saddr.sin_len = sizeof(struct sockaddr_in);
		nfsdiskless.swap_saddr.sin_family = AF_INET;
		nfsdiskless.swap_saddr.sin_port = htons(swap_nfs_port);
		nfsdiskless.swap_saddr.sin_addr.s_addr =
			htonl(arptable[ARP_SWAPSERVER].ipaddr);
        	nfsdiskless.swap_args.timeo = 10;
        	nfsdiskless.swap_args.retrans = 100;
	}

		/* Lookup NFS/MOUNTD ports for ROOT using PORTMAP */
	root_nfs_port = rpclookup(ARP_ROOTSERVER, PROG_NFS, 2);
	root_mount_port = rpclookup(ARP_ROOTSERVER, PROG_MOUNT, 1);
	if ((root_nfs_port == -1) || (root_mount_port == -1)) {
		printf("Unable to get ROOT NFS/MOUNT ports\n");
		longjmp(jmp_bootmenu,1);
	}
	if (err = nfs_mount(ARP_ROOTSERVER, root_mount_port,
		nfsdiskless.root_hostnam, &nfsdiskless.root_fh)) {
		printf("Unable to mount ROOT filesystem: ");
		nfs_err(err);
		longjmp(jmp_bootmenu,1);
	}
	nfsdiskless.root_saddr.sin_len = sizeof(struct sockaddr_in);
	nfsdiskless.root_saddr.sin_family = AF_INET;
	nfsdiskless.root_saddr.sin_port = htons(root_nfs_port);
	nfsdiskless.root_saddr.sin_addr.s_addr =
		htonl(arptable[ARP_ROOTSERVER].ipaddr);
        nfsdiskless.root_args.timeo = 10;
        nfsdiskless.root_args.retrans = 100;
	nfsdiskless.root_time = 0;

	if (err = nfs_lookup(ARP_ROOTSERVER, root_nfs_port,
		&nfsdiskless.root_fh, *kernel == '/' ? kernel+1 : kernel,
		&kernel_handle, NULL)) {
		printf("Unable to open %s: ",kernel);
		nfs_err(err);
		longjmp(jmp_bootmenu,1);
	}

		/* Load the kernel using NFS */
	printf("Loading %s...\n",kernel);
	if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, &kernel_handle, 0,
		sizeof(struct exec), &head)) < 0) {
		printf("Unable to read %s: ",kernel);
		nfs_err(err);
		longjmp(jmp_bootmenu,1);
	}
	if (N_BADMAG(head)) {
		printf("Bad executable format!\n");
		longjmp(jmp_bootmenu, 1);
	}
	loadpoint = (char *)(head.a_entry & 0x00FFFFFF);
	offset = N_TXTOFF(head);
	printf("text=0x%X, ",head.a_text);
#ifdef	PC98
	set_twiddle_max(8);
#endif
	nfsload(head.a_text);
	while (((int)loadpoint) & PAGE_MASK)
		*(loadpoint++) = 0;

	printf("data=0x%X, ",head.a_data);
	nfsload(head.a_data);

	printf("bss=0x%X, ",head.a_bss);
	while(head.a_bss--) *(loadpoint++) = 0;

	while (((int)loadpoint) & PAGE_MASK)
		*(loadpoint++) = 0;

	bootinfo.bi_symtab = (int) loadpoint;

	p = (char*)&head.a_syms;
	for (i=0;i<sizeof(head.a_syms);i++)
		*loadpoint++ = *p++;

	printf("symbols=[+0x%x+0x%x", sizeof(head.a_syms), head.a_syms);
	
	nfsload(head.a_syms);
	i = sizeof(int);
	p = loadpoint;
	nfsload(i);
	i = *(int*)p;
	printf("+0x%x]\n", i);
	i -= sizeof(int);
	nfsload(i);
	bootinfo.bi_esymtab = (int) loadpoint;

	printf("entry=0x%X.\n",head.a_entry);

		/* Jump to kernel */
	bootinfo.bi_version = BOOTINFO_VERSION;
	bootinfo.bi_kernelname = kernel;
	bootinfo.bi_nfs_diskless = &nfsdiskless;
	bootinfo.bi_size = sizeof bootinfo;
	kernelentry = (void *)(head.a_entry & 0x00FFFFFF);
	(*kernelentry)(howto|RB_BOOTINFO,NODEV,0,0,0,&bootinfo,0,0,0);
	printf("*** %s execute failure ***\n",kernel);
}
Exemple #20
0
int main(int argc, char *argv[])
{
	int ret = 1;
	struct nfs_context *nfs = NULL;
	struct nfsfh *nfsfh = NULL;
	struct nfs_url *url = NULL;

#ifdef WIN32
	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
		printf("Failed to start Winsock2\n");
		exit(10);
	}
#endif

#ifdef AROS
	aros_init_socket();
#endif

	if (argc < 3) {
		fprintf(stderr, "No URL specified.\n");
		goto finished;
	}

	nfs = nfs_init_context();
	if (nfs == NULL) {
		printf("failed to init context\n");
		goto finished;
	}

	url = nfs_parse_url_full(nfs, argv[argc - 1]);
	if (url == NULL) {
		fprintf(stderr, "%s\n", nfs_get_error(nfs));
		goto finished;
	}

	if (nfs_mount(nfs, url->server, url->path) != 0) {
 		fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs));
		goto finished;
	}

	if (!strncmp(argv[1], "creat", 5)) {
		ret = nfs_creat(nfs, url->file, 0600, &nfsfh);
	} else if (!strncmp(argv[1], "unlink", 6)) {
		ret = nfs_unlink(nfs, url->file);
	} else if (!strncmp(argv[1], "mkdir", 5)) {
		ret = nfs_mkdir(nfs, url->file);
	} else if (!strncmp(argv[1], "rmdir", 5)) {
		ret = nfs_rmdir(nfs, url->file);
	} else if (!strncmp(argv[1], "stat", 4)) {
		struct nfs_stat_64 st;
		ret = nfs_stat64(nfs, url->file, &st);
		if (!ret) {
			switch (st.nfs_mode & S_IFMT) {
	#ifndef WIN32
			case S_IFLNK:
				printf("l");
				break;
	#endif
			case S_IFREG:
				printf("-");
				break;
			case S_IFDIR:
				printf("d");
				break;
			case S_IFCHR:
				printf("c");
				break;
			case S_IFBLK:
				printf("b");
				break;
			}
			printf("%c%c%c",
			       "-r"[!!(st.nfs_mode & S_IRUSR)],
			       "-w"[!!(st.nfs_mode & S_IWUSR)],
			       "-x"[!!(st.nfs_mode & S_IXUSR)]
			);
			printf("%c%c%c",
			       "-r"[!!(st.nfs_mode & S_IRGRP)],
			       "-w"[!!(st.nfs_mode & S_IWGRP)],
			       "-x"[!!(st.nfs_mode & S_IXGRP)]
			);
			printf("%c%c%c",
			       "-r"[!!(st.nfs_mode & S_IROTH)],
			       "-w"[!!(st.nfs_mode & S_IWOTH)],
			       "-x"[!!(st.nfs_mode & S_IXOTH)]
			);
			printf(" %2d", (int)st.nfs_nlink);
			printf(" %5d", (int)st.nfs_uid);
			printf(" %5d", (int)st.nfs_gid);
			printf(" %12" PRId64, st.nfs_size);
			printf("\n");
		}
	} else {
		goto finished;
	}
	
	if (ret) {
		fprintf(stderr, "ERROR: %s\n", nfs_get_error(nfs));
	}

finished:
	if (ret > 0) {
		print_usage();
	}
	nfs_destroy_url(url);
	if (nfs != NULL) {		
		if (nfsfh) {
			nfs_close(nfs, nfsfh);
		}
		nfs_destroy_context(nfs);
	}
	return !!ret;
}
Exemple #21
0
/**************************************************************************
NFS - Download extended BOOTP data, or kernel image from NFS server
**************************************************************************/
int nfs(const char *name, int (*fnc)(unsigned char *, unsigned int, unsigned int, int))
{
	static int recursion = 0;
	int sport;
	int err, namelen = strlen(name);
	char dirname[300], *fname;
	char dirfh[NFS_FHSIZE];		/* file handle of directory */
	char filefh[NFS_FHSIZE];	/* file handle of kernel image */
	unsigned int block;
	int rlen, size, offs, len;
	struct rpc_t *rpc;

	rx_qdrain();

	sport = oport++;
	if (oport > START_OPORT+OPORT_SWEEP) {
		oport = START_OPORT;
	}
	if ( name != dirname ) {
		memcpy(dirname, name, namelen + 1);
	}
	recursion = 0;
nfssymlink:
	if ( recursion > NFS_MAXLINKDEPTH ) {
		printf ( "\nRecursion: More than %d symlinks followed. Abort.\n", NFS_MAXLINKDEPTH );
		return	0;
	}
	recursion++;
	fname = dirname + (namelen - 1);
	while (fname >= dirname) {
		if (*fname == '/') {
			*fname = '\0';
			fname++;
			break;
		}
		fname--;
	}
	if (fname < dirname) {
		printf("can't parse file name %s\n", name);
		return 0;
	}

	if (mount_port == -1) {
		mount_port = rpc_lookup(ARP_SERVER, PROG_MOUNT, 1, sport);
	}
	if (nfs_port == -1) {
		nfs_port = rpc_lookup(ARP_SERVER, PROG_NFS, 2, sport);
	}
	if (nfs_port == -1 || mount_port == -1) {
		printf("can't get nfs/mount ports from portmapper\n");
		return 0;
	}


	err = nfs_mount(ARP_SERVER, mount_port, dirname, dirfh, sport);
	if (err) {
		printf("mounting %s: ", dirname);
		nfs_printerror(err);
		/* just to be sure... */
		nfs_umountall(ARP_SERVER);
		return 0;
	}

	err = nfs_lookup(ARP_SERVER, nfs_port, dirfh, fname, filefh, sport);
	if (err) {
		printf("looking up %s: ", fname);
		nfs_printerror(err);
		nfs_umountall(ARP_SERVER);
		return 0;
	}

	offs = 0;
	block = 1;	/* blocks are numbered starting from 1 */
	size = -1;	/* will be set properly with the first reply */
	len = NFS_READ_SIZE;	/* first request is always full size */
	do {
		err = nfs_read(ARP_SERVER, nfs_port, filefh, offs, len, sport);
                if ((err <= -NFSERR_ISDIR)&&(err >= -NFSERR_INVAL) && (offs == 0)) {
			// An error occured. NFS servers tend to sending
			// errors 21 / 22 when symlink instead of real file
			// is requested. So check if it's a symlink!
			block = nfs_readlink(ARP_SERVER, nfs_port, dirfh, dirname,
			                filefh, sport);
			if ( 0 == block ) {
				printf("\nLoading symlink:%s ..",dirname);
				goto nfssymlink;
			}
			nfs_printerror(err);
			nfs_umountall(ARP_SERVER);
			return 0;
		}
		if (err) {
			printf("reading at offset %d: ", offs);
			nfs_printerror(err);
			nfs_umountall(ARP_SERVER);
			return 0;
		}

		rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];

		/* size must be found out early to allow EOF detection */
		if (size == -1) {
			size = ntohl(rpc->u.reply.data[6]);
		}
		rlen = ntohl(rpc->u.reply.data[18]);
		if (rlen > len) {
			rlen = len;	/* shouldn't happen...  */
		}

		err = fnc((char *)&rpc->u.reply.data[19], block, rlen,
			(offs+rlen == size));
		if (err <= 0) {
			nfs_umountall(ARP_SERVER);
			return err;
		}

		block++;
		offs += rlen;
		/* last request is done with matching requested read size */
		if (size-offs < NFS_READ_SIZE) {
			len = size-offs;
		}
	} while (len != 0);
	/* len == 0 means that all the file has been read */
	return 1;
}