#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
+/* Encode the file name NAME using the specified coding system
+ for file names, if any. */
+#define ENCODE_FILE(name) \
+ (! NILP (Vfile_name_coding_system) \
+ && XFASTINT (Vfile_name_coding_system) != 0 \
+ ? Fencode_coding_string (name, Vfile_name_coding_system, Qt) \
+ : name)
+
/* Nonzero during writing of auto-save files */
int auto_saving;
a new file with the same mode as the original */
int auto_save_mode_bits;
+/* Coding system for file names, or nil if none. */
+Lisp_Object Vfile_name_coding_system;
+
/* Alist of elements (REGEXP . HANDLER) for file names
whose I/O is done with a special handler. */
Lisp_Object Vfile_name_handler_alist;
char buf[16 * 1024];
struct stat st, out_st;
Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
int count = specpdl_ptr - specpdl;
int input_file_statable_p;
+ Lisp_Object encoded_file, encoded_newname;
- GCPRO2 (file, newname);
+ encoded_file = encoded_newname = Qnil;
+ GCPRO4 (file, newname, encoded_file, encoded_newname);
CHECK_STRING (file, 0);
CHECK_STRING (newname, 1);
+
file = Fexpand_file_name (file, Qnil);
newname = Fexpand_file_name (newname, Qnil);
RETURN_UNGCPRO (call5 (handler, Qcopy_file, file, newname,
ok_if_already_exists, keep_date));
+ encoded_file = ENCODE_FILE (file);
+ encoded_newname = ENCODE_FILE (newname);
+
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
- barf_or_query_if_file_exists (newname, "copy to it",
+ barf_or_query_if_file_exists (encoded_newname, "copy to it",
INTEGERP (ok_if_already_exists), &out_st);
- else if (stat (XSTRING (newname)->data, &out_st) < 0)
+ else if (stat (XSTRING (encoded_newname)->data, &out_st) < 0)
out_st.st_mode = 0;
- ifd = open (XSTRING (file)->data, O_RDONLY);
+ ifd = open (XSTRING (encoded_file)->data, O_RDONLY);
if (ifd < 0)
report_file_error ("Opening input file", Fcons (file, Qnil));
#ifdef VMS
/* Create the copy file with the same record format as the input file */
- ofd = sys_creat (XSTRING (newname)->data, 0666, ifd);
+ ofd = sys_creat (XSTRING (encoded_newname)->data, 0666, ifd);
#else
#ifdef MSDOS
/* System's default file type was set to binary by _fmode in emacs.c. */
- ofd = creat (XSTRING (newname)->data, S_IREAD | S_IWRITE);
+ ofd = creat (XSTRING (encoded_newname)->data, S_IREAD | S_IWRITE);
#else /* not MSDOS */
- ofd = creat (XSTRING (newname)->data, 0666);
+ ofd = creat (XSTRING (encoded_newname)->data, 0666);
#endif /* not MSDOS */
#endif /* VMS */
if (ofd < 0)
EMACS_TIME atime, mtime;
EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
- if (set_file_times (XSTRING (newname)->data, atime, mtime))
+ if (set_file_times (XSTRING (encoded_newname)->data,
+ atime, mtime))
Fsignal (Qfile_date_error,
Fcons (build_string ("Cannot set file date"),
Fcons (newname, Qnil)));
}
#ifndef MSDOS
- chmod (XSTRING (newname)->data, st.st_mode & 07777);
+ chmod (XSTRING (encoded_newname)->data, st.st_mode & 07777);
#else /* MSDOS */
#if defined (__DJGPP__) && __DJGPP__ > 1
/* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
get only the READ bit, which will make the copied file read-only,
so it's better not to chmod at all. */
if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
- chmod (XSTRING (newname)->data, st.st_mode & 07777);
+ chmod (XSTRING (encoded_newname)->data, st.st_mode & 07777);
#endif /* DJGPP version 2 or newer */
#endif /* MSDOS */
}
{
unsigned char *dir;
Lisp_Object handler;
+ Lisp_Object encoded_dir;
CHECK_STRING (directory, 0);
directory = Fexpand_file_name (directory, Qnil);
if (!NILP (handler))
return call2 (handler, Qmake_directory_internal, directory);
- dir = XSTRING (directory)->data;
+ encoded_dir = ENCODE_FILE (directory);
+
+ dir = XSTRING (encoded_dir)->data;
#ifdef WINDOWSNT
if (mkdir (dir) != 0)
{
unsigned char *dir;
Lisp_Object handler;
+ Lisp_Object encoded_dir;
CHECK_STRING (directory, 0);
directory = Fdirectory_file_name (Fexpand_file_name (directory, Qnil));
- dir = XSTRING (directory)->data;
handler = Ffind_file_name_handler (directory, Qdelete_directory);
if (!NILP (handler))
return call2 (handler, Qdelete_directory, directory);
+ encoded_dir = ENCODE_FILE (directory);
+
+ dir = XSTRING (encoded_dir)->data;
+
if (rmdir (dir) != 0)
report_file_error ("Removing directory", Flist (1, &directory));
Lisp_Object filename;
{
Lisp_Object handler;
+ Lisp_Object encoded_file;
+
CHECK_STRING (filename, 0);
filename = Fexpand_file_name (filename, Qnil);
if (!NILP (handler))
return call2 (handler, Qdelete_file, filename);
- if (0 > unlink (XSTRING (filename)->data))
+ encoded_file = ENCODE_FILE (filename);
+
+ if (0 > unlink (XSTRING (encoded_file)->data))
report_file_error ("Removing old name", Flist (1, &filename));
return Qnil;
}
Lisp_Object args[2];
#endif
Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+ Lisp_Object encoded_file, encoded_newname;
- GCPRO2 (file, newname);
+ encoded_file = encoded_newname = Qnil;
+ GCPRO4 (file, newname, encoded_file, encoded_newname);
CHECK_STRING (file, 0);
CHECK_STRING (newname, 1);
file = Fexpand_file_name (file, Qnil);
RETURN_UNGCPRO (call4 (handler, Qrename_file,
file, newname, ok_if_already_exists));
+ encoded_file = ENCODE_FILE (file);
+ encoded_newname = ENCODE_FILE (newname);
+
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
- barf_or_query_if_file_exists (newname, "rename to it",
+ barf_or_query_if_file_exists (encoded_newname, "rename to it",
INTEGERP (ok_if_already_exists), 0);
#ifndef BSD4_1
- if (0 > rename (XSTRING (file)->data, XSTRING (newname)->data))
+ if (0 > rename (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
#else
- if (0 > link (XSTRING (file)->data, XSTRING (newname)->data)
- || 0 > unlink (XSTRING (file)->data))
+ if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data)
+ || 0 > unlink (XSTRING (encoded_file)->data))
#endif
{
if (errno == EXDEV)
Lisp_Object args[2];
#endif
Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
+ Lisp_Object encoded_file, encoded_newname;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- GCPRO2 (file, newname);
+ GCPRO4 (file, newname, encoded_file, encoded_newname);
+ encoded_file = encoded_newname = Qnil;
CHECK_STRING (file, 0);
CHECK_STRING (newname, 1);
file = Fexpand_file_name (file, Qnil);
RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
newname, ok_if_already_exists));
+ encoded_file = ENCODE_FILE (file);
+ encoded_newname = ENCODE_FILE (newname);
+
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
- barf_or_query_if_file_exists (newname, "make it a new name",
+ barf_or_query_if_file_exists (encoded_newname, "make it a new name",
INTEGERP (ok_if_already_exists), 0);
unlink (XSTRING (newname)->data);
- if (0 > link (XSTRING (file)->data, XSTRING (newname)->data))
+ if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
{
#ifdef NO_ARG_ARRAY
args[0] = file;
Lisp_Object args[2];
#endif
Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
+ Lisp_Object encoded_filename, encoded_linkname;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- GCPRO2 (filename, linkname);
+ GCPRO4 (filename, linkname, encoded_filename, encoded_linkname);
+ encoded_filename = encoded_linkname = Qnil;
CHECK_STRING (filename, 0);
CHECK_STRING (linkname, 1);
/* If the link target has a ~, we must expand it to get
RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
linkname, ok_if_already_exists));
+ encoded_filename = ENCODE_FILE (filename);
+ encoded_linkname = ENCODE_FILE (linkname);
+
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
- barf_or_query_if_file_exists (linkname, "make it a link",
+ barf_or_query_if_file_exists (encoded_linkname, "make it a link",
INTEGERP (ok_if_already_exists), 0);
- if (0 > symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
+ if (0 > symlink (XSTRING (encoded_filename)->data,
+ XSTRING (encoded_linkname)->data))
{
/* If we didn't complain already, silently delete existing file. */
if (errno == EEXIST)
{
- unlink (XSTRING (linkname)->data);
- if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
+ unlink (XSTRING (encoded_linkname)->data);
+ if (0 <= symlink (XSTRING (encoded_filename)->data,
+ XSTRING (encoded_linkname)->data))
{
UNGCPRO;
return Qnil;
if (!NILP (handler))
return call2 (handler, Qfile_exists_p, absname);
+ absname = ENCODE_FILE (absname);
+
return (stat (XSTRING (absname)->data, &statbuf) >= 0) ? Qt : Qnil;
}
if (!NILP (handler))
return call2 (handler, Qfile_executable_p, absname);
+ absname = ENCODE_FILE (absname);
+
return (check_executable (XSTRING (absname)->data) ? Qt : Qnil);
}
if (!NILP (handler))
return call2 (handler, Qfile_readable_p, absname);
+ absname = ENCODE_FILE (absname);
+
#ifdef DOS_NT
/* Under MS-DOS and Windows, open does not work for directories. */
if (access (XSTRING (absname)->data, 0) == 0)
(filename)
Lisp_Object filename;
{
- Lisp_Object absname, dir;
+ Lisp_Object absname, dir, encoded;
Lisp_Object handler;
struct stat statbuf;
if (!NILP (handler))
return call2 (handler, Qfile_writable_p, absname);
- if (stat (XSTRING (absname)->data, &statbuf) >= 0)
- return (check_writable (XSTRING (absname)->data)
+ encoded = ENCODE_FILE (absname);
+ if (stat (XSTRING (encoded)->data, &statbuf) >= 0)
+ return (check_writable (XSTRING (encoded)->data)
? Qt : Qnil);
+
dir = Ffile_name_directory (absname);
#ifdef VMS
if (!NILP (dir))
if (!NILP (dir))
dir = Fdirectory_file_name (dir);
#endif /* MSDOS */
+
+ dir = ENCODE_FILE (dir);
return (check_writable (!NILP (dir) ? (char *) XSTRING (dir)->data : "")
? Qt : Qnil);
}
(filename, string)
Lisp_Object filename, string;
{
- Lisp_Object handler;
+ Lisp_Object handler, encoded_filename;
int fd;
CHECK_STRING (filename, 0);
if (!NILP (handler))
return call3 (handler, Qaccess_file, filename, string);
- fd = open (XSTRING (filename)->data, O_RDONLY);
+ encoded_filename = ENCODE_FILE (filename);
+
+ fd = open (XSTRING (encoded_filename)->data, O_RDONLY);
if (fd < 0)
report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
close (fd);
if (!NILP (handler))
return call2 (handler, Qfile_symlink_p, filename);
+ filename = ENCODE_FILE (filename);
+
bufsize = 100;
while (1)
{
}
val = make_string (buf, valsize);
xfree (buf);
- return val;
+ return Fdecode_coding_string (val, Vfile_name_coding_system, Qt);
#else /* not S_IFLNK */
return Qnil;
#endif /* not S_IFLNK */
if (!NILP (handler))
return call2 (handler, Qfile_directory_p, absname);
+ absname = ENCODE_FILE (absname);
+
if (stat (XSTRING (absname)->data, &st) < 0)
return Qnil;
return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
if (!NILP (handler))
return call2 (handler, Qfile_regular_p, absname);
+ absname = ENCODE_FILE (absname);
+
if (stat (XSTRING (absname)->data, &st) < 0)
return Qnil;
return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
if (!NILP (handler))
return call2 (handler, Qfile_modes, absname);
+ absname = ENCODE_FILE (absname);
+
if (stat (XSTRING (absname)->data, &st) < 0)
return Qnil;
#if defined (MSDOS) && __DJGPP__ < 2
(filename, mode)
Lisp_Object filename, mode;
{
- Lisp_Object absname;
+ Lisp_Object absname, encoded_absname;
Lisp_Object handler;
absname = Fexpand_file_name (filename, current_buffer->directory);
if (!NILP (handler))
return call3 (handler, Qset_file_modes, absname, mode);
- if (chmod (XSTRING (absname)->data, XINT (mode)) < 0)
+ encoded_absname = ENCODE_FILE (absname);
+
+ if (chmod (XSTRING (encoded_absname)->data, XINT (mode)) < 0)
report_file_error ("Doing chmod", Fcons (absname, Qnil));
return Qnil;
if (!NILP (handler))
return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
+ GCPRO2 (absname1, absname2);
+ absname1 = ENCODE_FILE (absname1);
+ absname2 = ENCODE_FILE (absname2);
+ UNGCPRO;
+
if (stat (XSTRING (absname1)->data, &st) < 0)
return Qnil;
register int how_much;
register int unprocessed;
int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object handler, val, insval;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+ Lisp_Object handler, val, insval, orig_filename;
Lisp_Object p;
int total;
int not_regular = 0;
val = Qnil;
p = Qnil;
+ orig_filename = Qnil;
- GCPRO3 (filename, val, p);
+ GCPRO4 (filename, val, p, orig_filename);
CHECK_STRING (filename, 0);
filename = Fexpand_file_name (filename, Qnil);
goto handled;
}
+ orig_filename = filename;
+ filename = ENCODE_FILE (filename);
+
fd = -1;
#ifndef APOLLO
if (fd >= 0) close (fd);
badopen:
if (NILP (visit))
- report_file_error ("Opening input file", Fcons (filename, Qnil));
+ report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
st.st_mtime = -1;
how_much = 0;
goto notfound;
if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
Fsignal (Qfile_error,
Fcons (build_string ("not a regular file"),
- Fcons (filename, Qnil)));
+ Fcons (orig_filename, Qnil)));
}
#endif
{
if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
report_file_error ("Setting file position",
- Fcons (filename, Qnil));
+ Fcons (orig_filename, Qnil));
nread += read (fd, read_buf + nread, 1024 * 3);
}
}
if (nread < 0)
error ("IO error reading %s: %s",
- XSTRING (filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, strerror (errno));
else if (nread > 0)
{
val = call1 (Vset_auto_coding_function,
/* Rewind the file for the actual read done later. */
if (lseek (fd, 0, 0) < 0)
report_file_error ("Setting file position",
- Fcons (filename, Qnil));
+ Fcons (orig_filename, Qnil));
}
}
if (NILP (val))
{
Lisp_Object args[6], coding_systems;
- args[0] = Qinsert_file_contents, args[1] = filename,
+ args[0] = Qinsert_file_contents, args[1] = orig_filename,
args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
coding_systems = Ffind_operation_coding_system (6, args);
if (CONSP (coding_systems)) val = XCONS (coding_systems)->car;
{
if (lseek (fd, XINT (beg), 0) < 0)
report_file_error ("Setting file position",
- Fcons (filename, Qnil));
+ Fcons (orig_filename, Qnil));
}
immediate_quit = 1;
nread = read (fd, buffer, sizeof buffer);
if (nread < 0)
error ("IO error reading %s: %s",
- XSTRING (filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, strerror (errno));
else if (nread == 0)
break;
trial = min (curpos, sizeof buffer);
if (lseek (fd, curpos - trial, 0) < 0)
report_file_error ("Setting file position",
- Fcons (filename, Qnil));
+ Fcons (orig_filename, Qnil));
total_read = 0;
while (total_read < trial)
nread = read (fd, buffer + total_read, trial - total_read);
if (nread <= 0)
error ("IO error reading %s: %s",
- XSTRING (filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, strerror (errno));
total_read += nread;
}
/* Scan this bufferful from the end, comparing with
{
free (conversion_buffer);
report_file_error ("Setting file position",
- Fcons (filename, Qnil));
+ Fcons (orig_filename, Qnil));
}
total = st.st_size; /* Total bytes in the file. */
if (how_much == -1)
error ("IO error reading %s: %s",
- XSTRING (filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, strerror (errno));
else if (how_much == -2)
error ("maximum buffer size exceeded");
}
if (XINT (beg) != 0 || !NILP (replace))
{
if (lseek (fd, XINT (beg), 0) < 0)
- report_file_error ("Setting file position", Fcons (filename, Qnil));
+ report_file_error ("Setting file position",
+ Fcons (orig_filename, Qnil));
}
/* In the following loop, HOW_MUCH contains the total bytes read so
is deemed to be a text file. */
{
current_buffer->buffer_file_type
- = call1 (Qfind_buffer_file_type, filename);
+ = call1 (Qfind_buffer_file_type, orig_filename);
if (NILP (current_buffer->buffer_file_type))
{
int reduced_size
if (how_much == -1)
error ("IO error reading %s: %s",
- XSTRING (filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, strerror (errno));
else if (how_much == -2)
error ("maximum buffer size exceeded");
if (NILP (handler))
{
current_buffer->modtime = st.st_mtime;
- current_buffer->filename = filename;
+ current_buffer->filename = orig_filename;
}
SAVE_MODIFF = MODIFF;
if (not_regular)
Fsignal (Qfile_error,
Fcons (build_string ("not a regular file"),
- Fcons (filename, Qnil)));
+ Fcons (orig_filename, Qnil)));
/* If visiting nonexistent file, return nil. */
if (current_buffer->modtime == -1)
- report_file_error ("Opening input file", Fcons (filename, Qnil));
+ report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
}
/* Decode file format */
}
if (NILP (val))
- val = Fcons (filename,
+ val = Fcons (orig_filename,
Fcons (make_number (inserted),
Qnil));
Lisp_Object handler;
Lisp_Object visit_file;
Lisp_Object annotations;
+ Lisp_Object encoded_filename;
int visiting, quietly;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
struct buffer *given_buffer;
GCPRO4 (start, filename, visit, lockname);
- /* Decide the coding-system to be encoded to. */
+ /* Decide the coding-system to encode the data with. */
{
Lisp_Object val;
}
#endif /* CLASH_DETECTION */
- fn = XSTRING (filename)->data;
+ encoded_filename = ENCODE_FILE (filename);
+
+ fn = XSTRING (encoded_filename)->data;
desc = -1;
if (!NILP (append))
#ifdef DOS_NT
desc = open (fn, O_WRONLY);
#endif /* not DOS_NT */
- if (desc < 0 && (NILP (append) || errno == ENOENT) )
+ if (desc < 0 && (NILP (append) || errno == ENOENT))
#ifdef VMS
if (auto_saving) /* Overwrite any previous version of autosave file */
{
current_buffer->modtime = st.st_mtime;
if (failure)
- error ("IO error writing %s: %s", fn, strerror (save_errno));
+ error ("IO error writing %s: %s", XSTRING (filename)->data,
+ strerror (save_errno));
if (visiting)
{
struct buffer *b;
struct stat st;
Lisp_Object handler;
+ Lisp_Object filename;
CHECK_BUFFER (buf, 0);
b = XBUFFER (buf);
if (!NILP (handler))
return call2 (handler, Qverify_visited_file_modtime, buf);
- if (stat (XSTRING (b->filename)->data, &st) < 0)
+ filename = ENCODE_FILE (b->filename);
+
+ if (stat (XSTRING (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 (!NILP (handler))
/* The handler can find the file name the same way we did. */
return call2 (handler, Qset_visited_file_modtime, Qnil);
- else if (stat (XSTRING (filename)->data, &st) >= 0)
+
+ filename = ENCODE_FILE (filename);
+
+ if (stat (XSTRING (filename)->data, &st) >= 0)
current_buffer->modtime = st.st_mtime;
}
staticpro (&Qfind_buffer_file_type);
#endif /* DOS_NT */
+ DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system,
+ "*Coding system for encoding file names.");
+ Vfile_name_coding_system = Qnil;
+
DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
"*Format in which to write auto-save files.\n\
Should be a list of symbols naming formats that are defined in `format-alist'.\n\