diff options
Diffstat (limited to 'src/fileio.c')
| -rw-r--r-- | src/fileio.c | 212 |
1 files changed, 155 insertions, 57 deletions
diff --git a/src/fileio.c b/src/fileio.c index f1cfe0eb625..5e9b36ee44a 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1,6 +1,6 @@ /* File IO for GNU Emacs. -Copyright (C) 1985-1988, 1993-2012 Free Software Foundation, Inc. +Copyright (C) 1985-1988, 1993-2013 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -379,12 +379,26 @@ Given a Unix syntax file name, returns a string ending in slash. */) strcat (res, "/"); beg = res; p = beg + strlen (beg); + dostounix_filename (beg); + tem_fn = make_specified_string (beg, -1, p - beg, + STRING_MULTIBYTE (filename)); } + else + tem_fn = make_specified_string (beg - 2, -1, p - beg + 2, + STRING_MULTIBYTE (filename)); + } + else if (STRING_MULTIBYTE (filename)) + { + tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 1)); + dostounix_filename (SSDATA (tem_fn)); + tem_fn = DECODE_FILE (tem_fn); + } + else + { + dostounix_filename (beg); + tem_fn = make_specified_string (beg, -1, p - beg, 0); } - tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, - STRING_MULTIBYTE (filename))); - dostounix_filename (SSDATA (tem_fn)); - return DECODE_FILE (tem_fn); + return tem_fn; #else /* DOS_NT */ return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename)); #endif /* DOS_NT */ @@ -459,12 +473,14 @@ get a current directory to run processes in. */) return Ffile_name_directory (filename); } -/* Convert from file name SRC of length SRCLEN to directory name - in DST. On UNIX, just make sure there is a terminating /. - Return the length of DST in bytes. */ +/* Convert from file name SRC of length SRCLEN to directory name in + DST. MULTIBYTE non-zero means the file name in SRC is a multibyte + string. On UNIX, just make sure there is a terminating /. Return + the length of DST in bytes. */ static ptrdiff_t -file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen) +file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen, + bool multibyte) { if (srclen == 0) { @@ -483,14 +499,17 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen) srclen++; } #ifdef DOS_NT - { - Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1); + if (multibyte) + { + Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1); - tem_fn = ENCODE_FILE (tem_fn); - dostounix_filename (SSDATA (tem_fn)); - tem_fn = DECODE_FILE (tem_fn); - memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1); - } + tem_fn = ENCODE_FILE (tem_fn); + dostounix_filename (SSDATA (tem_fn)); + tem_fn = DECODE_FILE (tem_fn); + memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1); + } + else + dostounix_filename (dst); #endif return srclen; } @@ -526,16 +545,18 @@ For a Unix-syntax file name, just appends a slash. */) } buf = alloca (SBYTES (file) + 10); - length = file_name_as_directory (buf, SSDATA (file), SBYTES (file)); + length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), + STRING_MULTIBYTE (file)); return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); } -/* Convert from directory name SRC of length SRCLEN to - file name in DST. On UNIX, just make sure there isn't - a terminating /. Return the length of DST in bytes. */ +/* Convert from directory name SRC of length SRCLEN to file name in + DST. MULTIBYTE non-zero means the file name in SRC is a multibyte + string. On UNIX, just make sure there isn't a terminating /. + Return the length of DST in bytes. */ static ptrdiff_t -directory_file_name (char *dst, char *src, ptrdiff_t srclen) +directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) { /* Process as Unix format: just remove any final slash. But leave "/" unchanged; do not change it to "". */ @@ -551,14 +572,17 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen) srclen--; } #ifdef DOS_NT - { - Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1); + if (multibyte) + { + Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1); - tem_fn = ENCODE_FILE (tem_fn); - dostounix_filename (SSDATA (tem_fn)); - tem_fn = DECODE_FILE (tem_fn); - memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1); - } + tem_fn = ENCODE_FILE (tem_fn); + dostounix_filename (SSDATA (tem_fn)); + tem_fn = DECODE_FILE (tem_fn); + memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1); + } + else + dostounix_filename (dst); #endif return srclen; } @@ -594,7 +618,8 @@ In Unix-syntax, this function just removes the final slash. */) } buf = alloca (SBYTES (directory) + 20); - length = directory_file_name (buf, SSDATA (directory), SBYTES (directory)); + length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), + STRING_MULTIBYTE (directory)); return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); } @@ -1044,7 +1069,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) /* `egetenv' may return a unibyte string, which will bite us since we expect the directory to be multibyte. */ tem = build_string (newdir); - if (!STRING_MULTIBYTE (tem)) + if (multibyte && !STRING_MULTIBYTE (tem)) { hdir = DECODE_FILE (tem); newdir = SSDATA (hdir); @@ -1066,7 +1091,18 @@ filesystem tree, not (expand-file-name ".." dirname). */) unblock_input (); if (pw) { + Lisp_Object tem; + newdir = pw->pw_dir; + /* `getpwnam' may return a unibyte string, which will + bite us since we expect the directory to be + multibyte. */ + tem = build_string (newdir); + if (multibyte && !STRING_MULTIBYTE (tem)) + { + hdir = DECODE_FILE (tem); + newdir = SSDATA (hdir); + } nm = p; #ifdef DOS_NT collapse_newdir = 0; @@ -1090,6 +1126,13 @@ filesystem tree, not (expand-file-name ".." dirname). */) adir = alloca (MAXPATHLEN + 1); if (!getdefdir (c_toupper (drive) - 'A' + 1, adir)) adir = NULL; + else if (multibyte) + { + Lisp_Object tem = build_string (adir); + + tem = DECODE_FILE (tem); + memcpy (adir, SSDATA (tem), SBYTES (tem) + 1); + } } if (!adir) { @@ -1148,6 +1191,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) indirectly by prepending newdir to nm if necessary, and using cwd (or the wd of newdir's drive) as the new newdir. */ char *adir; + if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1])) { drive = (unsigned char) newdir[0]; @@ -1157,7 +1201,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) { ptrdiff_t newlen = strlen (newdir); char *tmp = alloca (newlen + strlen (nm) + 2); - file_name_as_directory (tmp, newdir, newlen); + file_name_as_directory (tmp, newdir, newlen, multibyte); strcat (tmp, nm); nm = tmp; } @@ -1165,10 +1209,17 @@ filesystem tree, not (expand-file-name ".." dirname). */) if (drive) { if (!getdefdir (c_toupper (drive) - 'A' + 1, adir)) - newdir = "/"; + strcpy (adir, "/"); } else getcwd (adir, MAXPATHLEN + 1); + if (multibyte) + { + Lisp_Object tem = build_string (adir); + + tem = DECODE_FILE (tem); + memcpy (adir, SSDATA (tem), SBYTES (tem) + 1); + } newdir = adir; } @@ -1255,7 +1306,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) strcpy (target, newdir); } else - file_name_as_directory (target, newdir, length); + file_name_as_directory (target, newdir, length, multibyte); } strcat (target, nm); @@ -1341,9 +1392,14 @@ filesystem tree, not (expand-file-name ".." dirname). */) target[1] = ':'; } result = make_specified_string (target, -1, o - target, multibyte); - result = ENCODE_FILE (result); - dostounix_filename (SSDATA (result)); - result = DECODE_FILE (result); + if (multibyte) + { + result = ENCODE_FILE (result); + dostounix_filename (SSDATA (result)); + result = DECODE_FILE (result); + } + else + dostounix_filename (SSDATA (result)); #else /* !DOS_NT */ result = make_specified_string (target, -1, o - target, multibyte); #endif /* !DOS_NT */ @@ -1625,18 +1681,24 @@ those `/' is discarded. */) memcpy (nm, SDATA (filename), SBYTES (filename) + 1); #ifdef DOS_NT - { - Lisp_Object encoded_filename = ENCODE_FILE (filename); - Lisp_Object tem_fn; - - dostounix_filename (SDATA (encoded_filename)); - tem_fn = DECODE_FILE (encoded_filename); - nm = alloca (SBYTES (tem_fn) + 1); - memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1); - substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); - if (substituted) - filename = tem_fn; - } + if (multibyte) + { + Lisp_Object encoded_filename = ENCODE_FILE (filename); + Lisp_Object tem_fn; + + dostounix_filename (SDATA (encoded_filename)); + tem_fn = DECODE_FILE (encoded_filename); + nm = alloca (SBYTES (tem_fn) + 1); + memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1); + substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); + if (substituted) + filename = tem_fn; + } + else + { + dostounix_filename (nm); + substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); + } #endif endp = nm + SBYTES (filename); @@ -1956,10 +2018,26 @@ entries (depending on how Emacs was built). */) out_st.st_mode = 0; #ifdef WINDOWSNT + if (!NILP (preserve_extended_attributes)) + { +#ifdef HAVE_POSIX_ACL + acl = acl_get_file (SDATA (encoded_file), ACL_TYPE_ACCESS); + if (acl == NULL && errno != ENOTSUP) + report_file_error ("Getting ACL", Fcons (file, Qnil)); +#endif + } if (!CopyFile (SDATA (encoded_file), SDATA (encoded_newname), FALSE)) - report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil))); + { + /* CopyFile doesn't set errno when it fails. By far the most + "popular" reason is that the target is read-only. */ + if (GetLastError () == 5) + errno = EACCES; + else + errno = EPERM; + report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil))); + } /* CopyFile retains the timestamp by default. */ else if (NILP (keep_time)) { @@ -1983,6 +2061,17 @@ entries (depending on how Emacs was built). */) /* Restore original attributes. */ SetFileAttributes (filename, attributes); } +#ifdef HAVE_POSIX_ACL + if (acl != NULL) + { + bool fail = + acl_set_file (SDATA (encoded_newname), ACL_TYPE_ACCESS, acl) != 0; + if (fail && errno != ENOTSUP) + report_file_error ("Setting ACL", Fcons (newname, Qnil)); + + acl_free (acl); + } +#endif #else /* not WINDOWSNT */ immediate_quit = 1; ifd = emacs_open (SSDATA (encoded_file), O_RDONLY, 0); @@ -2915,8 +3004,10 @@ DEFUN ("set-file-selinux-context", Fset_file_selinux_context, CONTEXT should be a list (USER ROLE TYPE RANGE), where the list elements are strings naming the components of a SELinux context. -This function does nothing if SELinux is disabled, or if Emacs was not -compiled with SELinux support. */) +Value is t if setting of SELinux context was successful, nil otherwise. + +This function does nothing and returns nil if SELinux is disabled, +or if Emacs was not compiled with SELinux support. */) (Lisp_Object filename, Lisp_Object context) { Lisp_Object absname; @@ -2982,6 +3073,7 @@ compiled with SELinux support. */) context_free (parsed_con); freecon (con); + return fail ? Qnil : Qt; } else report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil)); @@ -2992,11 +3084,11 @@ compiled with SELinux support. */) } DEFUN ("file-acl", Ffile_acl, Sfile_acl, 1, 1, 0, - doc: /* Return ACL entries of file named FILENAME, as a string. + doc: /* Return ACL entries of file named FILENAME. +The entries are returned in a format suitable for use in `set-file-acl' +but is otherwise undocumented and subject to change. Return nil if file does not exist or is not accessible, or if Emacs -was unable to determine the ACL entries. The latter can happen for -local files if Emacs was not compiled with ACL support, or for remote -files if the file handler returns nil for the file's ACL entries. */) +was unable to determine the ACL entries. */) (Lisp_Object filename) { Lisp_Object absname; @@ -3046,6 +3138,8 @@ DEFUN ("set-file-acl", Fset_file_acl, Sset_file_acl, ACL-STRING should contain the textual representation of the ACL entries in a format suitable for the platform. +Value is t if setting of ACL was successful, nil otherwise. + Setting ACL for local files requires Emacs to be built with ACL support. */) (Lisp_Object filename, Lisp_Object acl_string) @@ -3085,6 +3179,7 @@ support. */) report_file_error ("Setting ACL", Fcons (absname, Qnil)); acl_free (acl); + return fail ? Qnil : Qt; } #endif @@ -3398,7 +3493,10 @@ the number of characters that replace previous buffer contents. This function does code conversion according to the value of `coding-system-for-read' or `file-coding-system-alist', and sets the -variable `last-coding-system-used' to the coding system actually used. */) +variable `last-coding-system-used' to the coding system actually used. + +In addition, this function decodes the inserted text from known formats +by calling `format-decode', which see. */) (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace) { struct stat st; @@ -4112,7 +4210,7 @@ variable `last-coding-system-used' to the coding system actually used. */) prepare_to_modify_buffer (GPT, GPT, NULL); } - move_gap (PT); + move_gap_both (PT, PT_BYTE); if (GAP_SIZE < total) make_gap (total - GAP_SIZE); |
