⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 remote_access.c

📁 一个用在mips体系结构中的操作系统
💻 C
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * *//* * remote_access.c - Routines to provide remote access to SimOS files. */#include "sim.h"#include <stdio.h>#include <sys/types.h>#ifndef __alpha#ifndef i386#include <sys/unistd.h>#include <sys/ioccom.h>#include <sys/filio.h>#endif#endif#include <sys/mman.h>#include <sys/file.h>#include <sys/signal.h>#include <sys/time.h>#include <sys/uio.h>#include <unistd.h>#ifndef linux#include <sys/socket.h>#include <netinet/in.h>#endif#include <sys/param.h>#include <errno.h>#include <netdb.h>#include <string.h>#include "remote_access.h"#include "sim_error.h"#include "simutil.h"#include "rmtaccess.h"extern char *MemFileDir;#define RMT_MAXHOSTNAMELEN 64#define RMT_MAXCONN 64enum {RMT_DISK = 0, RMT_CPT, RMT_END};static char server[RMT_END][RMT_MAXHOSTNAMELEN];static struct sockaddr_in rmt_addr[RMT_END];static char cpt_rootname[MAX_PATH_LENGTH];/* --------------------------------------- */static int StartRequest(struct sockaddr_in *rmtsrv, int cmd, char *arg, int argsize);static int ReadForSure(int fd, byte *buf, int size);static int CopyFile(int infd, int outfd);/* * Simrmt_init -Initialized access to a remote checkpoint.  *    returns < 0 on error, 1 if sucessful. */intSimrmt_cptinit(char *fullname, char *rootname){   int port;   struct hostent *host;    /*     * We assume that the root pathname encodes the host and port as follows:     *    hostname:port:masterlog_root     */    if (sscanf(fullname, "%[^:]:%d:%s", server[RMT_CPT], &port, rootname) != 3) {       Sim_Warning("Simrmt_init: Bad remote checkpoint name <%s>\n", fullname);       return -1;    }    /*     * Fill in the internet address to be used in later calls.      */    strcpy(cpt_rootname, rootname);    host = gethostbyname(server[RMT_CPT]);    if (!host) {        perror( "Simrmt_init:gethostbyname bad host");	Sim_Warning("Bad hostname %s\n", server[RMT_CPT]);	return -1;    }    rmt_addr[RMT_CPT].sin_family = host->h_addrtype;    bcopy(host->h_addr, (char *) &rmt_addr[RMT_CPT].sin_addr, host->h_length);    rmt_addr[RMT_CPT].sin_port = htons((short)port);        return 1;}/* * Simrmt_diskinit - Initialize remote disk for access. *      Return the open file descriptor. */int Simrmt_diskinit(char *remoteName){    int port;    struct hostent *host;    /* If no remote name is given, then we are using the remote       checkpoint server as a remote disk server as well */    if (remoteName == NULL) {      return StartRequest(&(rmt_addr[RMT_CPT]), SIMRMT_DISKINIT, (char *) NULL, 0);    }    else {    /*     * We assume that the remote name encodes the host and port as follows:     *    $hostname:port     */      if (sscanf(remoteName, "$%[^:]:%d", server[RMT_DISK], &port) != 2) {        Sim_Warning("Simrmt_diskinit: Bad remote disk name <%s>\n", remoteName);        return -1;      }      /*       * Fill in the internet address to be used in later calls.        */      host = gethostbyname(server[RMT_DISK]);      if (!host) {        perror( "Simrmt_diskinit:gethostbyname bad host");	Sim_Warning("Bad hostname %s\n", server[RMT_DISK]);	return -1;      }      rmt_addr[RMT_DISK].sin_family = host->h_addrtype;      bcopy(host->h_addr, (char *) &rmt_addr[RMT_DISK].sin_addr, host->h_length);      rmt_addr[RMT_DISK].sin_port = htons((short)port);      return StartRequest(&(rmt_addr[RMT_DISK]), SIMRMT_DISKINIT, (char *) NULL, 0);    }}/* * Simrmt_access - See if a remote file is readable *     Returns: TRUE if file exists and is readable, FALSE otherwise */boolSimrmt_access(char *pathname){  int fd = StartRequest(&(rmt_addr[RMT_CPT]), SIMRMT_ACCESS, pathname, strlen(pathname));  if (fd == -1) return FALSE;  close(fd);  return TRUE;}/* * Simrmt_fopen - Open a remote file. *     Returns: NULL on error, otherwise the open file pointer */FILE *Simrmt_fopen(char *pathname){  int fd = StartRequest(&(rmt_addr[RMT_CPT]), SIMRMT_OPEN, pathname, strlen(pathname));  if (fd < 0) return NULL;  else return fdopen(fd, "r");}/* * Simrmt_diskcmd - Send a remote disk command. */int64Simrmt_diskcmd(int diskfd, int op,	       int node, int ctrl, int unit,	       int64 sectorNum,int64 sizeInBytes,                byte *buffer) {     NetDiskHdr	hdr, rhdr;     int  size;    static 	int reqnum;         reqnum++;            bzero((char *) &hdr, sizeof(hdr));    hdr.op = (DiskOp)op;    hdr.node = node;    hdr.ctrl = ctrl;    hdr.unit = unit;    hdr.sectorNum = sectorNum;    hdr.sizeInBytes = sizeInBytes;    hdr.reqnum = reqnum;        if( write(diskfd, &hdr,sizeof(hdr))!=sizeof(hdr) ) {        CPUError("write to rmtaccess server failed\n");    };    if( (op == NETDISK_WRITE) || (op == NETDISK_ATTACH) ) {       if( write(diskfd,buffer,sizeInBytes)!=sizeInBytes) {           CPUError("write to rmtaccess server failed\n");       }    }         size = ReadForSure(diskfd, (byte *)&rhdr, sizeof(rhdr));    if (size != sizeof(rhdr)) {        perror("simckpt_netdisk:read");        rhdr.retVal = EIO;        return rhdr.retVal; 	    }    if (rhdr.reqnum != hdr.reqnum) {        Sim_Warning("Simnetdisk: Bad reqnum (%d)\n", rhdr.reqnum);    }    if (((op == NETDISK_READ) || (op == NETDISK_ATTACH)) && (rhdr.retVal > 0)) {       size = ReadForSure(diskfd, buffer, rhdr.retVal);       if (size != rhdr.retVal) {          Sim_Warning("Simnetdisk: Reply packet too small (%d)\n", size);          rhdr.retVal = EIO;       }     }    return rhdr.retVal;}/* * ReadForSure - just like the read() system call execpt it keeps trying *               if not enough data was returned by the read or it was interrupted *               by a signal. */static intReadForSure(int fd, byte *buf, int size){    int a;    for(a = 0; a < size;) {		int ret = read(fd, buf + a, size-a);	if (ret < 0) {	   if (errno == EINTR)	      continue;	   return -1;	}	a += ret;    }    return size;}/* * StartRequest - * Establish a connection with the remote server and exchange the specified command * with it.  * Returns the open connection to the server. < 0 if the connection * fails or the command encountes an errors.  */static intStartRequest(struct sockaddr_in *rmtsrv, int cmd, char *arg, int argsize){    int fd, err;    RmtAccessStartRequest  req;    byte ack[8];    /*     * Create the TCP socket and send command, returning socket     * blocks to and from the net disk server.     */     fd = socket(rmtsrv->sin_family, SOCK_STREAM, IPPROTO_TCP);    if (fd < 0) {            perror("Simrmt:StartRequest:socket");	    return -1;    }    if (connect(fd, (struct sockaddr *)rmtsrv, sizeof (*rmtsrv)) < 0) {            perror("Simrmt:StartRequest:connect");	    close(fd);	    return -1;    }     /*     * format and send the request over the connection.     */    req.magic = RMTACCESS_MAGIC;    req.cmd = (Rmtaccess_op)cmd;    req.arglen = argsize;        err = write(fd, (char *) &req, sizeof(req));    if (err != sizeof(req)) {       perror("Simrmt:StartRequest:write");       close(fd);       goto error;    }    if (req.arglen > 0) {        err = write(fd, arg, req.arglen);       if (err != req.arglen) {	  perror("Simrmt:StartRequest:write2");	 goto error;       }    }    /*     * Get error code for command: OK\n or Enn      */    err = ReadForSure(fd, ack, 3);    if (err < 0) {       perror("Simrmt:StartRequest:ReadForSure ack");       goto error;    }    if ((ack[0] == 'O') && (ack[1] == 'K')) {       return fd;    } error:    close(fd);    return -1;}static intCopyFile(int infd, int outfd){    char buf[8192];    int cnt, cnt2;    while(1) {        cnt = read(infd, buf, sizeof(buf));        if (cnt == 0)             break;        if (cnt < 0) {            perror("CopyFile -- read");            exit(1);        }        cnt2 = write(outfd, buf, cnt);        if (cnt2 != cnt) {            perror("CopyFile -- write");            exit(1);        }    }    return 0;}/*  * Open a file across a remote server and return the FILE ptr * The client must close the FILE ptr when done.  */FILE* Simrmt_RemoteFileOpen(char *pathName) {   struct hostent *host;   char hostName[RMT_MAXHOSTNAMELEN];   int port;   char fileName[RMT_MAXHOSTNAMELEN];   int fd;   struct sockaddr_in rmtsrv;   if (sscanf(pathName, "%[^:]:%d:%s", hostName, &port, fileName) != 3) {      Sim_Warning("Simrmt_RemoteFileOpen: Bad remote file name <%s>",                  pathName);      return NULL;   }   host = gethostbyname(hostName);   if (!host) {      perror( "Simrmt_RemoteFileOpen: gethostbyname bad host");      Sim_Warning("Bad host name %s\n", hostName);      return NULL;   }   bzero((char *) &rmtsrv, sizeof(rmtsrv));   rmtsrv.sin_family = host->h_addrtype;   bcopy(host->h_addr, (char *) &(rmtsrv.sin_addr), host->h_length);   rmtsrv.sin_port = htons((short) port);      fd = StartRequest(&rmtsrv, SIMRMT_OPEN, fileName, strlen(fileName));  if (fd < 0) {     return NULL;  } else {     return fdopen(fd, "r");  }}/* * This routine implements an mmap of a remote file. Currently we do the  * dumb thing, which is to copy the file to a temporary local file * and then mmaps it. The parameters to the call are exactly the same as * for the mmap call, except that you pass a remoteserver filepath instead of * of a file descriptor. */void *Simrmt_mmap(void *addr, size_t len, int prot, int flags, char* pathName, off_t off){   struct stat statbuf;   struct hostent *host;   char hostName[RMT_MAXHOSTNAMELEN];   int port;   char fileName[RMT_MAXHOSTNAMELEN];   int fd, tmpfd;   struct sockaddr_in rmtsrv;   void *maddr;   if (sscanf(pathName, "%[^:]:%d:%s", hostName, &port, fileName) != 3) {      Sim_Warning("Simrmt_mmap: Bad remote file name <%s>",                  pathName);      return NULL;   }   host = gethostbyname(hostName);   if (!host) {      perror( "Simrmt_mmap: gethostbyname bad host");      Sim_Warning("Bad host name %s\n", hostName);      return NULL;   }      rmtsrv.sin_family = host->h_addrtype;   bcopy(host->h_addr, (char *) &(rmtsrv.sin_addr), host->h_length);   rmtsrv.sin_port = htons((short) port);       fd = StartRequest(&rmtsrv, SIMRMT_OPEN, fileName, strlen(fileName));   if (fd < 0) {      return NULL;   }       tmpfd = MakeFile(MemFileDir, NULL, 0, 1);   CopyFile(fd, tmpfd);   close(fd);      if (len == 0) {      /* this means we want to map to the end of file */      if (fstat(tmpfd, &statbuf) < 0) {         perror("Simrmt_mmap fstat");         exit(1);      }      len = statbuf.st_size - off;   }   if((maddr = mmap(addr, len, prot, flags, tmpfd, off)) == (void *)-1) {      perror("Simrmt_mmap");      exit(1);   }   close(tmpfd);   return maddr;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -