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

📄 fileio.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	    if (desc < 0)	      {		/* If we can't open the temporary file, try creating a new		   version of the original file.  VMS "creat" creates a		   new version rather than truncating an existing file. */		fn = fname;		fname = 0;		desc = creat (fn, 0666);		if (desc < 0)		  {		    /* We can't make a new version;		       try to truncate and rewrite existing version if any.  */		    vms_truncate (fn);		    desc = open (fn, O_RDWR);		  }	      }	  }	else	  desc = creat (fn, 0666);      }#else /* not VMS */  desc = creat (fn, 0666);#endif /* not VMS */  if (desc < 0)    {#ifdef CLASH_DETECTION      save_errno = errno;      if (!auto_saving) unlock_file (filename);      errno = save_errno;#endif /* CLASH_DETECTION */      report_file_error ("Opening output file", Fcons (filename, Qnil));    }  record_unwind_protect (close_file_unwind, make_number (desc));  if (!NULL (append))    if (lseek (desc, (off_t) 0, 2) < 0)      {#ifdef CLASH_DETECTION	if (!auto_saving) unlock_file (filename);#endif /* CLASH_DETECTION */	report_file_error ("Lseek error", Fcons (filename, Qnil));      }#ifdef VMS/* * Kludge Warning: The VMS C RTL likes to insert carriage returns * if we do writes that don't end with a carriage return. Furthermore * it cannot handle writes of more then 16K. The modified * version of "sys_write" in SYSDEP.C (see comment there) copes with * this EXCEPT for the last record (iff it doesn't end with a carriage * return). This implies that if your buffer doesn't end with a carriage * return, you get one free... tough. However it also means that if * we make two calls to sys_write (a la the following code) you can * get one at the gap as well. The easiest way to fix this (honest) * is to move the gap to the next newline (or the end of the buffer). * Thus this change. * * Yech! */  if (GPT > BEG && GPT_ADDR[-1] != '\n')    move_gap (find_next_newline (GPT, 1));#endif  failure = 0;  if (XINT (start) != XINT (end))    {      if (XINT (start) < GPT)	{	  register int end1 = XINT (end);	  tem = XINT (start);	  failure = 0 > e_write (desc, &FETCH_CHAR (tem),				 min (GPT, end1) - tem);	  save_errno = errno;	}      if (XINT (end) > GPT && !failure)	{	  tem = XINT (start);	  tem = max (tem, GPT);	  failure = 0 > e_write (desc, &FETCH_CHAR (tem), XINT (end) - tem);	  save_errno = errno;	}    }#ifndef USG#ifndef VMS#ifndef BSD4_1#ifndef alliant /* trinkle@cs.purdue.edu says fsync can return EBUSY		   on alliant, for no visible reason.  */  /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).     Disk full in NFS may be reported here.  */  if (fsync (desc) < 0)    failure = 1, save_errno = errno;#endif#endif#endif#endif#if 0  /* Spurious "file has changed on disk" warnings have been      observed on Sun 3 as well.  Maybe close changes the modtime     with nfs as well.  */  /* On VMS and APOLLO, must do the stat after the close     since closing changes the modtime.  */#ifndef VMS#ifndef APOLLO  /* Recall that #if defined does not work on VMS.  */#define FOO  fstat (desc, &st);#endif#endif#endif /* 0 */  /* NFS can report a write failure now.  */  if (close (desc) < 0)    failure = 1, save_errno = errno;#ifdef VMS  /* If we wrote to a temporary name and had no errors, rename to real name. */  if (fname)    {      if (!failure)	failure = (rename (fn, fname) != 0), save_errno = errno;      fn = fname;    }#endif /* VMS */#ifndef FOO  stat (fn, &st);#endif  /* Discard the unwind protect */  specpdl_ptr = specpdl + count;#ifdef CLASH_DETECTION  if (!auto_saving)    unlock_file (filename);#endif /* CLASH_DETECTION */  /* Do this before reporting IO error     to avoid a "file has changed on disk" warning on     next attempt to save.  */  if (EQ (visit, Qt))    current_buffer->modtime = st.st_mtime;  if (failure)    error ("IO error writing %s: %s", fn, err_str (save_errno));  if (EQ (visit, Qt))    {      current_buffer->save_modified = MODIFF;      XFASTINT (current_buffer->save_length) = Z - BEG;      current_buffer->filename = filename;    }  else if (!NULL (visit))    return Qnil;  if (!auto_saving)    message ("Wrote %s", fn);  return Qnil;}inte_write (desc, addr, len)     int desc;     register char *addr;     register int len;{  char buf[16 * 1024];  register char *p, *end;  if (!EQ (current_buffer->selective_display, Qt))    return write (desc, addr, len) - len;  else    {      p = buf;      end = p + sizeof buf;      while (len--)	{	  if (p == end)	    {	      if (write (desc, buf, sizeof buf) != sizeof buf)		return -1;	      p = buf;	    }	  *p = *addr++;	  if (*p++ == '\015')	    p[-1] = '\n';	}      if (p != buf)	if (write (desc, buf, p - buf) != p - buf)	  return -1;    }  return 0;}DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,  Sverify_visited_file_modtime, 1, 1, 0,  "Return t if last mod time of BUF's visited file matches what BUF records.\n\This means that the file has not been changed since it was visited or saved.")  (buf)     Lisp_Object buf;{  struct buffer *b;  struct stat st;  CHECK_BUFFER (buf, 0);  b = XBUFFER (buf);  if (XTYPE (b->filename) != Lisp_String) return Qt;  if (b->modtime == 0) return Qt;  if (stat (XSTRING (b->filename)->data, &st) < 0)    {      /* If the file doesn't exist now and didn't exist before,	 we say that it isn't modified, provided the error is a tame one.  */      if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)	st.st_mtime = -1;      else	st.st_mtime = 0;    }  if (st.st_mtime == b->modtime      /* If both are positive, accept them if they are off by one second.  */      || (st.st_mtime > 0 && b->modtime > 0	  && (st.st_mtime == b->modtime + 1	      || st.st_mtime == b->modtime - 1)))    return Qt;  return Qnil;}DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,  Sclear_visited_file_modtime, 0, 0, 0,  "Clear out records of last mod time of visited file.\n\Next attempt to save will certainly not complain of a discrepancy.")  (){  current_buffer->modtime = 0;  return Qnil;}Lisp_Objectauto_save_error (){  unsigned char *name = XSTRING (current_buffer->name)->data;  bell ();  message ("Autosaving...error for %s", name);  Fsleep_for (make_number (1));  message ("Autosaving...error!for %s", name);  Fsleep_for (make_number (1));  message ("Autosaving...error for %s", name);  Fsleep_for (make_number (1));  return Qnil;}Lisp_Objectauto_save_1 (){  return    Fwrite_region (Qnil, Qnil,		   current_buffer->auto_save_file_name,		   Qnil, Qlambda);}DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 1, "",  "Auto-save all buffers that need it.\n\This is all buffers that have auto-saving enabled\n\and are changed since last auto-saved.\n\Auto-saving writes the buffer into a file\n\so that your editing is not lost if the system crashes.\n\This file is not the file you visited; that changes only when you save.\n\n\Non-nil argument means do not print any message if successful.")  (nomsg)     Lisp_Object nomsg;{  struct buffer *old = current_buffer, *b;  Lisp_Object tail, buf;  int auto_saved = 0;  int tried = 0;  char *omessage = echo_area_contents;  /* No GCPRO needed, because (when it matters) all Lisp_Object variables     point to non-strings reached from Vbuffer_alist.  */  auto_saving = 1;  if (minibuf_level)    nomsg = Qt;  for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;       tail = XCONS (tail)->cdr)    {      buf = XCONS (XCONS (tail)->car)->cdr;      b = XBUFFER (buf);      /* Check for auto save enabled	 and file changed since last auto save	 and file changed since last real save.  */      if (XTYPE (b->auto_save_file_name) == Lisp_String	  && b->save_modified < BUF_MODIFF (b)	  && b->auto_save_modified < BUF_MODIFF (b))	{	  /* If we at least consider a buffer for auto-saving,	     don't try again for a suitable time.  */	  tried++;	  if ((XFASTINT (b->save_length) * 10	       > (BUF_Z (b) - BUF_BEG (b)) * 13)	      /* A short file is likely to change a large fraction;		 spare the user annoying messages.  */	      && XFASTINT (b->save_length) > 5000	      /* These messages are frequent and annoying for `*mail*'.  */	      && !EQ (b->filename, Qnil))	    {	      /* It has shrunk too much; don't checkpoint. */	      message ("Buffer %s has shrunk a lot; not autosaving it",		       XSTRING (b->name)->data);	      Fsleep_for (make_number (1));	      continue;	    }	  set_buffer_internal (b);	  if (!auto_saved && NULL (nomsg))	    message1 ("Auto-saving...");	  internal_condition_case (auto_save_1, Qt, auto_save_error);	  auto_saved++;	  b->auto_save_modified = BUF_MODIFF (b);	  XFASTINT (current_buffer->save_length) = Z - BEG;	  set_buffer_internal (old);	}    }  if (tried)    record_auto_save ();  if (auto_saved && NULL (nomsg))    message1 (omessage ? omessage : "Auto-saving...done");  auto_saving = 0;  return Qnil;}DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,  Sset_buffer_auto_saved, 0, 0, 0,  "Mark current buffer as auto-saved with its current text.\n\No auto-save file will be written until the buffer changes again.")  (){  current_buffer->auto_save_modified = MODIFF;  XFASTINT (current_buffer->save_length) = Z - BEG;  return Qnil;}DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,  0, 0, 0,  "Return t if buffer has been auto-saved since last read in or saved.")  (){  return (current_buffer->save_modified < current_buffer->auto_save_modified) ? Qt : Qnil;}/* Reading and completing file names */extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,  3, 3, 0,  "Internal subroutine for read-file-name.  Do not call this.")  (string, dir, action)     Lisp_Object string, dir, action;  /* action is nil for complete, t for return list of completions,     lambda for verify final value */{  Lisp_Object name, specdir, realdir, val;  if (XSTRING (string)->size == 0)    {      name = string;      realdir = dir;      if (EQ (action, Qlambda))	return Qnil;    }  else    {      string = Fsubstitute_in_file_name (string);      name = Ffile_name_nondirectory (string);      realdir = Ffile_name_directory (string);      if (NULL (realdir))	realdir = dir;      else	realdir = Fexpand_file_name (realdir, dir);    }  if (NULL (action))    {      specdir = Ffile_name_directory (string);      val = Ffile_name_completion (name, realdir);      if (XTYPE (val) != Lisp_String)	return (val);      if (!NULL (specdir))	val = concat2 (specdir, val);#ifndef VMS      {	register unsigned char *old, *new;	register int n;	int osize, count;	osize = XSTRING (val)->size;	/* Quote "$" as "$$" to get it past substitute-in-file-name */	for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)	  if (*old++ == '$') count++;	if (count > 0)	  {	    old = XSTRING (val)->data;	    val = Fmake_string (make_number (osize + count), make_number (0));	    new = XSTRING (val)->data;	    for (n = osize; n > 0; n--)	      if (*old != '$')		*new++ = *old++;	      else		{		  *new++ = '$';		  *new++ = '$';		  old++;		}	  }      }#endif /* Not VMS */      return (val);    }  if (EQ (action, Qt))    return Ffile_name_all_completions (name, realdir);  /* Only other case actually used is ACTION = lambda */#ifdef VMS  /* Supposedly this helps commands such as `cd' that read directory names,     but can someone explain how it helps them? -- RMS */  if (XSTRING (name)->size == 0)    return Qt;#endif /* VMS */  return Ffile_exists_p (string);}DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 4, 0,  "Read file name, prompting with PROMPT and completing in directory DIR.\n\Value is not expanded!  You must call expand-file-name yourself.\n\Default name to DEFAULT if user enters a null string.\n\Fourth arg MUSTMATCH non-nil means require existing file's name.\n\ Non-nil and non-t means also require confirmation after completion.\n\DIR defaults to current buffer's directory default.")  (prompt, dir, defalt, mustmatch)     Lisp_Object prompt, dir, defalt, mustmatch;{  Lisp_Object val, insdef, tem;  struct gcpro gcpro1, gcpro2;  register char *homedir;  int count;  if (NULL (dir))    dir = current_buffer->directory;  if (NULL (defalt))    defalt = current_buffer->filename;  /* If dir starts with user's homedir, change that to ~. */  homedir = (char *) egetenv ("HOME");  if (homedir != 0      && XTYPE (dir) == Lisp_String      && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))      && XSTRING (dir)->data[strlen (homedir)] == '/')    {      dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,			 XSTRING (dir)->size - strlen (homedir) + 1);      XSTRING (dir)->data[0] = '~';    }  if (insert_default_directory)    insdef = dir;  else    insdef = build_string ("");#ifdef VMS  count = specpdl_ptr - specpdl;  specbind (intern ("completion-ignore-case"), Qt);#endif  GCPRO2 (insdef, defalt);  val = Fcompleting_read (prompt, intern ("read-file-name-internal"),			  dir, mustmatch,			  insert_default_directory ? insdef : Qnil);#ifdef VMS  unbind_to (count);#endif  UNGCPRO;  if (NULL (val))    error ("No file name specified");  tem = Fstring_equal (val, insdef);  if (!NULL (tem) && !NULL (defalt))    return defalt;  return Fsubstitute_in_file_name (val);}syms_of_fileio (){  Qfile_error = intern ("file-error");  staticpro (&Qfile_error);  Qfile_already_exists = intern("file-already-exists");  staticpro (&Qfile_already_exists);  Fput (Qfile_error, Qerror_conditions,	Fcons (Qfile_error, Fcons (Qerror, Qnil)));  Fput (Qfile_error, Qerror_message,	build_string ("File error"));  Fput (Qfile_already_exists, Qerror_conditions,	Fcons (Qfile_already_exists,	       Fcons (Qfile_error, Fcons (Qerror, Qnil))));  Fput (Qfile_already_exists, Qerror_message,	build_string ("File already exists"));  DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,    "*Non-nil means when reading a filename start with default dir in minibuffer.");  insert_default_directory = 1;  DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,    "*Non-nil means write new files with record format `stmlf'.\n\nil means use format `var'.  This variable is meaningful only on VMS.");  vms_stmlf_recfm = 0;  defsubr (&Sfile_name_directory);  defsubr (&Sfile_name_nondirectory);  defsubr (&Sfile_name_as_directory);  defsubr (&Sdirectory_file_name);  defsubr (&Smake_temp_name);  defsubr (&Sexpand_file_name);  defsubr (&Ssubstitute_in_file_name);  defsubr (&Scopy_file);  defsubr (&Sdelete_file);  defsubr (&Srename_file);  defsubr (&Sadd_name_to_file);#ifdef S_IFLNK  defsubr (&Smake_symbolic_link);#endif /* S_IFLNK */#ifdef VMS  defsubr (&Sdefine_logical_name);#endif /* VMS */#ifdef HPUX_NET  defsubr (&Ssysnetunam);#endif /* HPUX_NET */  defsubr (&Sfile_name_absolute_p);  defsubr (&Sfile_exists_p);  defsubr (&Sfile_readable_p);  defsubr (&Sfile_writable_p);  defsubr (&Sfile_symlink_p);  defsubr (&Sfile_directory_p);  defsubr (&Sfile_modes);  defsubr (&Sset_file_modes);  defsubr (&Sfile_newer_than_file_p);  defsubr (&Sinsert_file_contents);  defsubr (&Swrite_region);  defsubr (&Sverify_visited_file_modtime);  defsubr (&Sclear_visited_file_modtime);  defsubr (&Sdo_auto_save);  defsubr (&Sset_buffer_auto_saved);  defsubr (&Srecent_auto_save_p);  defsubr (&Sread_file_name_internal);  defsubr (&Sread_file_name);}

⌨️ 快捷键说明

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