📄 fileio.c
字号:
p++; } if (!lose) {#ifdef VMS if (index (nm, '/')) return build_string (sys_translate_unix (nm));#endif /* VMS */ if (nm == XSTRING (name)->data) return name; return build_string (nm); } } /* Now determine directory to start with and put it in NEWDIR. */ newdir = 0; if (nm[0] == '~') { if (nm[1] == '/'#ifdef VMS || nm[1] == ':'#endif /* VMS */ || nm[1] == 0) { /* Handle ~ on its own. */ newdir = (unsigned char *) egetenv ("HOME"); } else { /* Handle ~ followed by user name. */ unsigned char *user = nm + 1; /* Find end of name. */ unsigned char *ptr = (unsigned char *) index (user, '/'); int len = ptr ? ptr - user : strlen (user);#ifdef VMS unsigned char *ptr1 = index (user, ':'); if (ptr1 != 0 && ptr1 - user < len) len = ptr1 - user;#endif /* VMS */ /* Copy the user name into temp storage. */ o = (unsigned char *) alloca (len + 1); bcopy ((char *) user, o, len); o[len] = 0; /* Look up the user name. */ pw = (struct passwd *) getpwnam (o); if (!pw) error ("User \"%s\" is not known", o); newdir = (unsigned char *) pw->pw_dir; /* Discard the user name from NM. */ nm += len; } /* Discard the ~ from NM. */ nm++;#ifdef VMS if (*nm != 0) nm++; /* Don't leave the slash in nm. */#endif /* VMS */ if (newdir == 0) newdir = (unsigned char *) ""; } if (nm[0] != '/'#ifdef VMS && !index (nm, ':')#endif /* not VMS */ && !newdir) { if (NULL (defalt)) defalt = current_buffer->directory; CHECK_STRING (defalt, 1); newdir = XSTRING (defalt)->data; } /* Now concatenate the directory and name to new space in the stack frame */ tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1; target = (unsigned char *) alloca (tlen); *target = 0; if (newdir) {#ifndef VMS if (nm[0] == 0 || nm[0] == '/') strcpy (target, newdir); else#endif file_name_as_directory (target, newdir); } strcat (target, nm);#ifdef VMS if (index (target, '/')) strcpy (target, sys_translate_unix (target));#endif /* VMS */ /* Now canonicalize by removing /. and /foo/.. if they appear */ p = target; o = target; while (*p) {#ifdef VMS if (*p != ']' && *p != '>' && *p != '-') { if (*p == '\\') p++; *o++ = *p++; } else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2) /* brackets are offset from each other by 2 */ { p += 2; if (*p != '.' && *p != '-' && o[-1] != '.') /* convert [foo][bar] to [bar] */ while (o[-1] != '[' && o[-1] != '<') o--; else if (*p == '-' && *o != '.') *--p = '.'; } else if (p[0] == '-' && o[-1] == '.' && (p[1] == '.' || p[1] == ']' || p[1] == '>')) /* flush .foo.- ; leave - if stopped by '[' or '<' */ { do o--; while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<'); if (p[1] == '.') /* foo.-.bar ==> bar*/ p += 2; else if (o[-1] == '.') /* '.foo.-]' ==> ']' */ p++, o--; /* else [foo.-] ==> [-] */ } else {#ifndef VMS4_4 if (*p == '-' && o[-1] != '[' && o[-1] != '<' && o[-1] != '.' && p[1] != ']' && p[1] != '>' && p[1] != '.') *p = '_';#endif /* VMS4_4 */ *o++ = *p++; }#else /* not VMS */ if (*p != '/') { *o++ = *p++; } else if (!strncmp (p, "//", 2)#ifdef APOLLO /* // at start of filename is meaningful in Apollo system */ && o != target#endif /* APOLLO */ ) { o = target; p++; } else if (p[0] == '/' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) p += 2; else if (!strncmp (p, "/..", 3) /* `/../' is the "superroot" on certain file systems. */ && o != target && (p[3] == '/' || p[3] == 0)) { while (o != target && *--o != '/') ;#ifdef APOLLO if (o == target + 1 && o[-1] == '/' && o[0] == '/') ++o; else#endif APOLLO if (o == target && *o == '/') ++o; p += 3; } else { *o++ = *p++; }#endif /* not VMS */ } return make_string (target, o - target);}DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name, Ssubstitute_in_file_name, 1, 1, 0, "Substitute environment variables referred to in STRING.\n\A $ begins a request to substitute; the env variable name is the alphanumeric\n\characters and underscores after the $, or is surrounded by braces.\n\If a ~ appears following a /, everything through that / is discarded.\n\On VMS, $ substitution is not done; this function does little and only\n\duplicates what expand-file-name does.") (string) Lisp_Object string;{ unsigned char *nm; register unsigned char *s, *p, *o, *x, *endp; unsigned char *target; int total = 0; int substituted = 0; unsigned char *xnm; CHECK_STRING (string, 0); nm = XSTRING (string)->data; endp = nm + XSTRING (string)->size; /* If /~ or // appears, discard everything through first slash. */ for (p = nm; p != endp; p++) { if ((p[0] == '~' ||#ifdef APOLLO /* // at start of file name is meaningful in Apollo system */ (p[0] == '/' && p - 1 != nm)#else /* not APOLLO */ p[0] == '/'#endif /* not APOLLO */ ) && p != nm &&#ifdef VMS (p[-1] == ':' || p[-1] == ']' || p[-1] == '>' ||#endif /* VMS */ p[-1] == '/')#ifdef VMS )#endif /* VMS */ { nm = p; substituted = 1; } }#ifdef VMS return build_string (nm);#else /* See if any variables are substituted into the string and find the total length of their values in `total' */ for (p = nm; p != endp;) if (*p != '$') p++; else { p++; if (p == endp) goto badsubst; else if (*p == '$') { /* "$$" means a single "$" */ p++; total -= 1; substituted = 1; continue; } else if (*p == '{') { o = ++p; while (p != endp && *p != '}') p++; if (*p != '}') goto missingclose; s = p; } else { o = p; while (p != endp && (isalnum (*p) || *p == '_')) p++; s = p; } /* Copy out the variable name */ target = (unsigned char *) alloca (s - o + 1); strncpy (target, o, s - o); target[s - o] = 0; /* Get variable value */ o = (unsigned char *) egetenv (target);/* The presence of this code makes vax 5.0 crash, for reasons yet unknown */#if 0#ifdef USG if (!o && !strcmp (target, "USER")) o = egetenv ("LOGNAME");#endif /* USG */#endif /* 0 */ if (!o) goto badvar; total += strlen (o); substituted = 1; } if (!substituted) return string; /* If substitution required, recopy the string and do it */ /* Make space in stack frame for the new copy */ xnm = (unsigned char *) alloca (XSTRING (string)->size + total + 1); x = xnm; /* Copy the rest of the name through, replacing $ constructs with values */ for (p = nm; *p;) if (*p != '$') *x++ = *p++; else { p++; if (p == endp) goto badsubst; else if (*p == '$') { *x++ = *p++; continue; } else if (*p == '{') { o = ++p; while (p != endp && *p != '}') p++; if (*p != '}') goto missingclose; s = p++; } else { o = p; while (p != endp && (isalnum (*p) || *p == '_')) p++; s = p; } /* Copy out the variable name */ target = (unsigned char *) alloca (s - o + 1); strncpy (target, o, s - o); target[s - o] = 0; /* Get variable value */ o = (unsigned char *) egetenv (target);/* The presence of this code makes vax 5.0 crash, for reasons yet unknown */#if 0#ifdef USG if (!o && !strcmp (target, "USER")) o = egetenv ("LOGNAME");#endif /* USG */#endif /* 0 */ if (!o) goto badvar; strcpy (x, o); x += strlen (o); } *x = 0; /* If /~ or // appears, discard everything through first slash. */ for (p = xnm; p != x; p++) if ((p[0] == '~' ||#ifdef APOLLO /* // at start of file name is meaningful in Apollo system */ (p[0] == '/' && p - 1 != xnm)#else /* not APOLLO */ p[0] == '/'#endif /* not APOLLO */ ) && p != nm && p[-1] == '/') xnm = p; return make_string (xnm, x - xnm); badsubst: error ("Bad format environment-variable substitution"); missingclose: error ("Missing \"}\" in environment-variable substitution"); badvar: error ("Substituting nonexistent environment variable \"%s\"", target); /* NOTREACHED */#endif /* not VMS */}Lisp_Objectexpand_and_dir_to_file (filename, defdir) Lisp_Object filename, defdir;{ register Lisp_Object abspath; abspath = Fexpand_file_name (filename, defdir);#ifdef VMS { register int c = XSTRING (abspath)->data[XSTRING (abspath)->size - 1]; if (c == ':' || c == ']' || c == '>') abspath = Fdirectory_file_name (abspath); }#else /* Remove final slash, if any (unless path is root). stat behaves differently depending! */ if (XSTRING (abspath)->size > 1 && XSTRING (abspath)->data[XSTRING (abspath)->size - 1] == '/') { if (EQ (abspath, filename)) abspath = Fcopy_sequence (abspath); XSTRING (abspath)->data[XSTRING (abspath)->size - 1] = 0; }#endif return abspath;}barf_or_query_if_file_exists (absname, querystring, interactive) Lisp_Object absname; unsigned char *querystring; int interactive;{ register Lisp_Object tem; struct gcpro gcpro1; if (access (XSTRING (absname)->data, 4) >= 0) { if (! interactive) Fsignal (Qfile_already_exists, Fcons (build_string ("File already exists"), Fcons (absname, Qnil))); GCPRO1 (absname); tem = Fyes_or_no_p (format1 ("File %s already exists; %s anyway? ", XSTRING (absname)->data, querystring)); UNGCPRO; if (NULL (tem)) Fsignal (Qfile_already_exists, Fcons (build_string ("File already exists"), Fcons (absname, Qnil))); } return;}DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4, "fCopy file: \nFCopy %s to file: \np", "Copy FILE to NEWNAME. Both args strings.\n\Signals a file-already-exists error if NEWNAME already exists,\n\unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\A number as third arg means request confirmation if NEWNAME already exists.\n\This is what happens in interactive use with M-x.\n\Fourth arg non-nil means give the new file the same last-modified time\n\that the old one has. (This works on only some systems.)") (filename, newname, ok_if_already_exists, keep_date) Lisp_Object filename, newname, ok_if_already_exists, keep_date;{ int ifd, ofd, n; char buf[16 * 1024]; struct stat st; struct gcpro gcpro1, gcpro2; GCPRO2 (filename, newname); CHECK_STRING (filename, 0); CHECK_STRING (newname, 1); filename = Fexpand_file_name (filename, Qnil); newname = Fexpand_file_name (newname, Qnil); if (NULL (ok_if_already_exists) || XTYPE (ok_if_already_exists) == Lisp_Int) barf_or_query_if_file_exists (newname, "copy to it", XTYPE (ok_if_already_exists) == Lisp_Int); ifd = open (XSTRING (filename)->data, 0); if (ifd < 0) report_file_error ("Opening input file", Fcons (filename, Qnil));#ifdef VMS /* Create the copy file with the same record format as the input file */ ofd = sys_creat (XSTRING (newname)->data, 0666, ifd);#else ofd = creat (XSTRING (newname)->data, 0666);#endif /* VMS */ if (ofd < 0) { close (ifd); report_file_error ("Opening output file", Fcons (newname, Qnil)); } while ((n = read (ifd, buf, sizeof buf)) > 0) if (write (ofd, buf, n) != n) { close (ifd); close (ofd); report_file_error ("I/O error", Fcons (newname, Qnil)); } if (fstat (ifd, &st) >= 0) {#ifdef HAVE_TIMEVAL if (!NULL (keep_date)) {#ifdef USE_UTIME/* AIX has utimes() in compatibility package, but it dies. So use good old utime interface instead. */ struct { time_t atime; time_t mtime; } tv; tv.atime = st.st_atime; tv.mtime = st.st_mtime; utime (XSTRING (newname)->data, &tv);#else /* not USE_UTIME */ struct timeval timevals[2]; timevals[0].tv_sec = st.st_atime; timevals[1].tv_sec = st.st_mtime; timevals[0].tv_usec = timevals[1].tv_usec = 0; utimes (XSTRING (newname)->data, timevals);#endif /* not USE_UTIME */ }#endif /* HAVE_TIMEVALS */#ifdef APOLLO if (!egetenv ("USE_DOMAIN_ACLS"))#endif chmod (XSTRING (newname)->data, st.st_mode & 07777); } close (ifd); if (close (ofd) < 0) report_file_error ("I/O error", Fcons (newname, Qnil)); UNGCPRO; return Qnil;}DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ", "Delete specified file. One argument, a file name string.\n\If file has multiple names, it continues to exist with the other names.") (filename) Lisp_Object filename;{ CHECK_STRING (filename, 0); filename = Fexpand_file_name (filename, Qnil); if (0 > unlink (XSTRING (filename)->data)) report_file_error ("Removing old name", Flist (1, &filename)); return Qnil;}DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, "fRename file: \nFRename %s to file: \np", "Rename FILE as NEWNAME. Both args strings.\n\If file has names other than FILE, it continues to have those names.\n\Signals a file-already-exists error if NEWNAME already exists\n\unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\A number as third arg means request confirmation if NEWNAME already exists.\n\This is what happens in interactive use with M-x.") (filename, newname, ok_if_already_exists) Lisp_Object filename, newname, ok_if_already_exists;{#ifdef NO_ARG_ARRAY Lisp_Object args[2];#endif struct gcpro gcpro1, gcpro2; GCPRO2 (filename, newname); CHECK_STRING (filename, 0); CHECK_STRING (newname, 1); filename = Fexpand_file_name (filename, Qnil); newname = Fexpand_file_name (newname, Qnil); if (NULL (ok_if_already_exists) || XTYPE (ok_if_already_exists) == Lisp_Int) barf_or_query_if_file_exists (newname, "rename to it", XTYPE (ok_if_already_exists) == Lisp_Int);#ifndef BSD4_1 if (0 > rename (XSTRING (filename)->data, XSTRING (newname)->data))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -