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

📄 fileio.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* File IO for GNU Emacs.   Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.This file is part of GNU Emacs.GNU Emacs is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU Emacs is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Emacs; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */#include <sys/types.h>#ifdef hpux/* needed by <pwd.h> */#include <stdio.h>#undef NULL#endif#include <sys/stat.h>#include <pwd.h>#include <ctype.h>#include <sys/dir.h>#include <errno.h>#ifndef VMSextern int errno;extern char *sys_errlist[];extern int sys_nerr;#endif#define err_str(a) ((a) < sys_nerr ? sys_errlist[a] : "unknown error")#ifdef APOLLO#include <sys/time.h>#endif#ifdef NULL#undef NULL#endif#include "config.h"#include "lisp.h"#include "buffer.h"#include "window.h"#ifdef VMS#include <perror.h>#include <file.h>#include <rmsdef.h>#include <fab.h>#include <nam.h>#endif#ifdef HAVE_TIMEVAL#ifdef HPUX#include <time.h>#else#include <sys/time.h>#endif#endif#ifdef HPUX#include <netio.h>#include <errnet.h>#endif#ifndef O_WRONLY#define O_WRONLY 1#endif#define min(a, b) ((a) < (b) ? (a) : (b))#define max(a, b) ((a) > (b) ? (a) : (b))/* Nonzero during writing of auto-save files */int auto_saving;/* Nonzero means, when reading a filename in the minibuffer, start out by inserting the default directory into the minibuffer. */int insert_default_directory;/* On VMS, nonzero means write new files with record format stmlf.   Zero means use var format.  */int vms_stmlf_recfm;Lisp_Object Qfile_error, Qfile_already_exists;report_file_error (string, data)     char *string;     Lisp_Object data;{  Lisp_Object errstring;  if (errno >= 0 && errno < sys_nerr)    errstring = build_string (sys_errlist[errno]);  else    errstring = build_string ("undocumented error code");  /* System error messages are capitalized.  Downcase the initial. */  XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);  while (1)    Fsignal (Qfile_error,	     Fcons (build_string (string), Fcons (errstring, data)));}DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,  1, 1, 0,  "Return the directory component in file name NAME.\n\Return nil if NAME does not include a directory.\n\Otherwise returns a directory spec.\n\Given a Unix syntax file name, returns a string ending in slash;\n\on VMS, perhaps instead a string ending in :, ] or >.")  (file)     Lisp_Object file;{  register unsigned char *beg;  register unsigned char *p;  CHECK_STRING (file, 0);  beg = XSTRING (file)->data;  p = beg + XSTRING (file)->size;  while (p != beg && p[-1] != '/'#ifdef VMS	 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'#endif /* VMS */	 ) p--;  if (p == beg)    return Qnil;  return make_string (beg, p - beg);}DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, Sfile_name_nondirectory,  1, 1, 0,  "Return file name NAME sans its directory.\n\For example, in a Unix-syntax file name,\n\this is everything after the last slash,\n\or the entire name if it contains no slash.")  (file)     Lisp_Object file;{  register unsigned char *beg, *p, *end;  CHECK_STRING (file, 0);  beg = XSTRING (file)->data;  end = p = beg + XSTRING (file)->size;  while (p != beg && p[-1] != '/'#ifdef VMS	 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'#endif /* VMS */	 ) p--;  return make_string (p, end - p);}char *file_name_as_directory (out, in)     char *out, *in;{  int size = strlen (in) - 1;  strcpy (out, in);#ifdef VMS  /* Is it already a directory string? */  if (in[size] == ':' || in[size] == ']' || in[size] == '>')    return out;  /* Is it a VMS directory file name?  If so, hack VMS syntax.  */  else if (! index (in, '/')	   && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))	       || (size > 3 && ! strcmp (&in[size - 3], ".dir"))	       || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)				|| ! strncmp (&in[size - 5], ".dir", 4))		   && (in[size - 1] == '.' || in[size - 1] == ';')		   && in[size] == '1')))    {      register char *p, *dot;      char brack;      /* x.dir -> [.x]	 dir:x.dir --> dir:[x]	 dir:[x]y.dir --> dir:[x.y] */      p = in + size;      while (p != in && *p != ':' && *p != '>' && *p != ']') p--;      if (p != in)	{	  strncpy (out, in, p - in);	  out[p - in] = '\0';	  if (*p == ':')	    {	      brack = ']';	      strcat (out, ":[");	    }	  else	    {	      brack = *p;	      strcat (out, ".");	    }	  p++;	}      else	{	  brack = ']';	  strcpy (out, "[.");	}      if (dot = index (p, '.'))	{	  /* blindly remove any extension */	  size = strlen (out) + (dot - p);	  strncat (out, p, dot - p);	}      else	{	  strcat (out, p);	  size = strlen (out);	}      out[size++] = brack;      out[size] = '\0';    }#else /* not VMS */  /* For Unix syntax, Append a slash if necessary */  if (out[size] != '/')    strcat (out, "/");#endif /* not VMS */  return out;}DEFUN ("file-name-as-directory", Ffile_name_as_directory,       Sfile_name_as_directory, 1, 1, 0,  "Return a string representing file FILENAME interpreted as a directory.\n\This string can be used as the value of default-directory\n\or passed as second argument to expand-file-name.\n\For a Unix-syntax file name, just appends a slash.\n\On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")  (file)     Lisp_Object file;{  char *buf;  CHECK_STRING (file, 0);  if (NULL (file))    return Qnil;  buf = (char *) alloca (XSTRING (file)->size + 10);  return build_string (file_name_as_directory (buf, XSTRING (file)->data));}/* * Convert from directory name to filename. * On VMS: *       xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1 *       xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1 * On UNIX, it's simple: just make sure there is a terminating / * Value is nonzero if the string output is different from the input. */directory_file_name (src, dst)     char *src, *dst;{  long slen;#ifdef VMS  long rlen;  char * ptr, * rptr;  char bracket;  struct FAB fab = cc$rms_fab;  struct NAM nam = cc$rms_nam;  char esa[NAM$C_MAXRSS];#endif /* VMS */  slen = strlen (src) - 1;#ifdef VMS  if (! index (src, '/')      && (src[slen] == ']' || src[slen] == ':' || src[slen] == '>'))    {      /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */      fab.fab$l_fna = src;      fab.fab$b_fns = slen + 1;      fab.fab$l_nam = &nam;      fab.fab$l_fop = FAB$M_NAM;      nam.nam$l_esa = esa;      nam.nam$b_ess = sizeof esa;      nam.nam$b_nop |= NAM$M_SYNCHK;      /* We call SYS$PARSE to handle such things as [--] for us. */      if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)	{	  slen = nam.nam$b_esl - 1;	  if (esa[slen] == ';' && esa[slen - 1] == '.')	    slen -= 2;	  esa[slen + 1] = '\0';	  src = esa;	}      if (src[slen] != ']' && src[slen] != '>')	{	  /* what about when we have logical_name:???? */	  if (src[slen] == ':')	    {			/* Xlate logical name and see what we get */	      ptr = strcpy (dst, src); /* upper case for getenv */	      while (*ptr)		{		  if ('a' <= *ptr && *ptr <= 'z')		    *ptr -= 040;		  ptr++;		}	      dst[slen] = 0;	/* remove colon */	      if (!(src = egetenv (dst)))		return 0;	      /* should we jump to the beginning of this procedure?		 Good points: allows us to use logical names that xlate		 to Unix names,		 Bad points: can be a problem if we just translated to a device		 name...		 For now, I'll punt and always expect VMS names, and hope for		 the best! */	      slen = strlen (src) - 1;	      if (src[slen] != ']' && src[slen] != '>')		{ /* no recursion here! */		  strcpy (dst, src);		  return 0;		}	    }	  else	    {		/* not a directory spec */	      strcpy (dst, src);	      return 0;	    }	}      bracket = src[slen];      if (!(ptr = index (src, bracket - 2)))	{ /* no opening bracket */	  strcpy (dst, src);	  return 0;	}      if (!(rptr = rindex (src, '.')))	rptr = ptr;      slen = rptr - src;      strncpy (dst, src, slen);      dst[slen] = '\0';      if (*rptr == '.')	{	  dst[slen++] = bracket;	  dst[slen] = '\0';	}      else	{	  /* If we have the top-level of a rooted directory (i.e. xx:[000000]),	     then translate the device and recurse. */	  if (dst[slen - 1] == ':'	      && dst[slen - 2] != ':'	/* skip decnet nodes */	      && strcmp(src + slen, "[000000]") == 0)	    {	      dst[slen - 1] = '\0';	      if ((ptr = egetenv (dst))		  && (rlen = strlen (ptr) - 1) > 0		  && (ptr[rlen] == ']' || ptr[rlen] == '>')		  && ptr[rlen - 1] == '.')		{		  ptr[rlen - 1] = ']';		  ptr[rlen] = '\0';		  return directory_file_name (ptr, dst);		}	      else		dst[slen - 1] = ':';	    }	  strcat (dst, "[000000]");	  slen += 8;	}      rptr++;      rlen = strlen (rptr) - 1;      strncat (dst, rptr, rlen);      dst[slen + rlen] = '\0';      strcat (dst, ".DIR.1");      return 1;    }#endif /* VMS */  /* Process as Unix format: just remove any final slash.     But leave "/" unchanged; do not change it to "".  */  strcpy (dst, src);  if (dst[slen] == '/' && slen > 1)    dst[slen] = 0;  return 1;}DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,  1, 1, 0,  "Returns the file name of the directory named DIR.\n\This is the name of the file that holds the data for the directory DIR.\n\In Unix-syntax, this just removes the final slash.\n\On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\returns a file name such as \"[X]Y.DIR.1\".")  (directory)     Lisp_Object directory;{  char *buf;  CHECK_STRING (directory, 0);  if (NULL (directory))    return Qnil;#ifdef VMS  /* 20 extra chars is insufficient for VMS, since we might perform a     logical name translation. an equivalence string can be up to 255     chars long, so grab that much extra space...  - sss */  buf = (char *) alloca (XSTRING (directory)->size + 20 + 255);#else  buf = (char *) alloca (XSTRING (directory)->size + 20);#endif  directory_file_name (XSTRING (directory)->data, buf);  return build_string (buf);}DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,  "Generate temporary name (string) starting with PREFIX (a string).")  (prefix)     Lisp_Object prefix;{  Lisp_Object val;  val = concat2 (prefix, build_string ("XXXXXX"));  mktemp (XSTRING (val)->data);  return val;}DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,  "Convert FILENAME to absolute, and canonicalize it.\n\Second arg DEFAULT is directory to start with if FILENAME is relative\n\ (does not start with slash); if DEFAULT is nil or missing,\n\the current buffer's value of default-directory is used.\n\Filenames containing . or .. as components are simplified;\n\initial ~ is expanded.  See also the function  substitute-in-file-name.")     (name, defalt)     Lisp_Object name, defalt;{  unsigned char *nm;    register unsigned char *newdir, *p, *o;  int tlen;  unsigned char *target;  struct passwd *pw;  int lose;#ifdef VMS  unsigned char * colon = 0;  unsigned char * close = 0;  unsigned char * slash = 0;  unsigned char * brack = 0;  int lbrack = 0, rbrack = 0;  int dots = 0;#endif /* VMS */    CHECK_STRING (name, 0);#ifdef VMS  /* Filenames on VMS are always upper case.  */  name = Fupcase (name);#endif  nm = XSTRING (name)->data;    /* If nm is absolute, flush ...// and detect /./ and /../.     If no /./ or /../ we can return right away. */  if (      nm[0] == '/'#ifdef VMS      || index (nm, ':')#endif /* VMS */      )    {      p = nm;      lose = 0;      while (*p)	{	  if (p[0] == '/' && p[1] == '/'#ifdef APOLLO	      /* // at start of filename is meaningful on Apollo system */	      && nm != p#endif /* APOLLO */	      )	    nm = p + 1;	  if (p[0] == '/' && p[1] == '~')	    nm = p + 1, lose = 1;	  if (p[0] == '/' && p[1] == '.'	      && (p[2] == '/' || p[2] == 0		  || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))	    lose = 1;#ifdef VMS	  if (p[0] == '\\')	    lose = 1;	  if (p[0] == '/') {	    /* if dev:[dir]/, move nm to / */	    if (!slash && p > nm && (brack || colon)) {	      nm = (brack ? brack + 1 : colon + 1);	      lbrack = rbrack = 0;	      brack = 0;	      colon = 0;	    }	    slash = p;	  }	  if (p[0] == '-')#ifndef VMS4_4	    /* VMS pre V4.4,convert '-'s in filenames. */	    if (lbrack == rbrack)	      {		if (dots < 2)	/* this is to allow negative version numbers */		  p[0] = '_';	      }	    else#endif /* VMS4_4 */	      if (lbrack > rbrack &&		  ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&		   (p[1] == '.' || p[1] == ']' || p[1] == '>')))		lose = 1;#ifndef VMS4_4	      else		p[0] = '_';#endif /* VMS4_4 */	  /* count open brackets, reset close bracket pointer */	  if (p[0] == '[' || p[0] == '<')	    lbrack++, brack = 0;	  /* count close brackets, set close bracket pointer */	  if (p[0] == ']' || p[0] == '>')	    rbrack++, brack = p;	  /* detect ][ or >< */	  if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))	    lose = 1;	  if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')	    nm = p + 1, lose = 1;	  if (p[0] == ':' && (colon || slash))	    /* if dev1:[dir]dev2:, move nm to dev2: */	    if (brack)	      {		nm = brack + 1;		brack = 0;	      }	    /* if /pathname/dev:, move nm to dev: */	    else if (slash)	      nm = slash + 1;	    /* if node::dev:, move colon following dev */	    else if (colon && colon[-1] == ':')	      colon = p;	    /* if dev1:dev2:, move nm to dev2: */	    else if (colon && colon[-1] != ':')	      {		nm = colon + 1;		colon = 0;	      }	  if (p[0] == ':' && !colon)	    {	      if (p[1] == ':')		p++;	      colon = p;	    }	  if (lbrack == rbrack)	    if (p[0] == ';')	      dots = 2;	    else if (p[0] == '.')	      dots++;#endif /* VMS */

⌨️ 快捷键说明

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