/* Support for Non-ASCII Path Name Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the 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 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* 94.3.9 modified for Mule Ver.1.1 by T.Emami The last arg of encode() should be a pointer to a real Lisp_Object. */ /* 94.6.22 modified for Mule Ver.2.0 by K.Handa CONV_BUF_SIZE -> ENCODE_BUF_SIZE/DECODE_BUF_SIZE. Macro definition of ITNCODE and AUTOCONV switched. */ #define MCPATH_SOURCE #include #include #include #include #ifdef MSDOS /* 94.8.9 by K.Fujii */ #include #include #endif /* mcpath.h should be included in config.h */ #include "config.h" #ifdef MCPATH_ASSERT /* for debugging */ #include #endif #undef NILP #include "lisp.h" #include "buffer.h" #include "charset.h" #include "coding.h" Lisp_Object Qpathname_coding_system = 0; /* this function should be lisp function. */ DEFUN ("set-pathname-coding-system", Fset_pathname_coding_system, Sset_pathname_coding_system, 1, 1, 0, "Set the pathname-coding-system to CODING_SYSTEM.") (coding_system) register Lisp_Object coding_system; { Fcheck_code (coding_system); Fset (Qpathname_coding_system, coding_system); } static void mcpath_encode_code (cp) coding_type *cp; { Lisp_Object coding_system; coding_system = Fsymbol_value (Qpathname_coding_system); encode_code (coding_system, cp); CODE_CNTL (cp) |= CC_END; /* 94.6.22 by K.Handa */ } static int encode_path_1 (src, srcsize, dst, dstsize) unsigned char *src, *dst; unsigned int srcsize, dstsize; { coding_type code; mcpath_encode_code (&code); if (CODE_TYPE (&code) > AUTOCONV) { unsigned char *buf; /* get_conversion_buffer () is not */ /* re-entrant. */ buf = (unsigned char *) alloca (ENCODE_BUF_SIZE (srcsize, &code)); if (buf) { int len; Lisp_Object dummy = Qnil; /* 94.3.9 by T.Enami */ len = encode (&code, src, buf, srcsize, &dummy); if (!CODE_CHAR (&code) && len <= dstsize) { bcopy (buf, dst, len); return len; } } } return -1; /* use original */ } static unsigned char *decode_path_1 (src, dst, dstsize) unsigned char *src, *dst; unsigned int dstsize; { coding_type code; mcpath_encode_code (&code); if (CODE_TYPE (&code) > AUTOCONV) { int len; unsigned char *buf; len = strlen (src) + 1; /* + 1 for '\0' */ /* get_conversion_buffer () is not */ /* re-entrant. */ buf = (unsigned char *) alloca (DECODE_BUF_SIZE (len, &code)); if (buf) { CODE_CNTL (&code) |= CC_END; len = decode (&code, src, buf, len); if (!CODE_CHAR (&code) && len <= dstsize) { bcopy (buf, dst, len); /* len should include '\0' */ return dst; } } } return src; } static unsigned char *decode_path (path, ext_path) unsigned char *path, ext_path[MC_MAXPATHLEN]; { return (Qpathname_coding_system ? decode_path_1 (path, ext_path, MC_MAXPATHLEN) : path); /* in case of before initialization */ } /* patch 94.8.9 by K.Fujii */ unsigned char *encode_path (path, encode_buffer, size) unsigned char *path; unsigned char *encode_buffer; unsigned int size; { int len; /* encode up to '\0', the end of string. */ len = encode_path_1 (path, strlen (path) + 1, encode_buffer, size); if (len > 0) path = encode_buffer; #ifdef MSDOS /* convert the MSDOS style path delimiter to the UNIX style. Note that now the code is *internal*, so we can simply compare each character with '\\'. And this operation will alter the contents of Lisp Object, PATH. */ { unsigned char *p = path; while (*p) { if (*p == '\\') *p = '/'; p++; } } #endif /* MSDOS */ return path; } /* end of patch */ /* patch 94.9.4 by K.Fujii */ DEFUN ("encode-path", Fencode_path, Sencode_path, 1, 1, 0, "encode the PATH from external code to internal code.\n\ If the system type is MSDOS, path delimter of PATH will be altered.") (path) Lisp_Object path; { unsigned char encode_buffer[MC_MAXPATHLEN]; unsigned char *tmp; CHECK_STRING (path, 0); tmp = encode_path (XSTRING (path)->data, encode_buffer, sizeof (encode_buffer)); if (XSTRING (path)->data != tmp) path = build_string (tmp); return path; } /* end of patch */ int mc_creat (path, mode) unsigned char *path; int mode; { unsigned char buffer[MC_MAXPATHLEN]; return creat (decode_path (path, buffer), mode); } #if defined (INTERRUPTABLE_OPEN) || defined (INTERRUPTIBLE_OPEN) #define open sys_open /* call open in sysdep.c */ #endif int mc_open (path, flag, mode) unsigned char *path; int flag, mode; { unsigned char buffer[MC_MAXPATHLEN]; return open (decode_path (path, buffer), flag, mode); } int mc_access (path, mode) unsigned char *path; int mode; { unsigned char buffer[MC_MAXPATHLEN]; return access (decode_path (path, buffer), mode); } int mc_chmod (path, mode) unsigned char *path; int mode; { unsigned char buffer[MC_MAXPATHLEN]; return chmod (decode_path (path, buffer), mode); } /* if system does not have symbolic links, it does not have lstat. In that case, use ordinary stat instead. */ #ifdef S_IFLNK int mc_lstat (path, st_addr) unsigned char *path; struct stat *st_addr; { unsigned char buffer[MC_MAXPATHLEN]; return lstat (decode_path (path, buffer), st_addr); } int mc_readlink (path, buf, size) unsigned char *path, *buf; int size; { unsigned char buffer[MC_MAXPATHLEN], buffer2[MAXPATHLEN]; int nread; /* decode given `path' into buffer, and get the link contents into buffer2. */ nread = readlink (decode_path (path, buffer), buffer2, MAXPATHLEN); if (nread > 0) { int len; unsigned char *result; len = encode_path_1 (buffer2, nread, buffer, sizeof (buffer)); /* if the conversion success and the result fits to `buf', use it. */ if (0 <= len && len <= size) { nread = len; result = buffer; } else /* use original one. */ result = buffer2; bcopy (result, buf, nread); } return nread; } #endif #ifndef nec_ews_svr4 /* hir, 1993.10.22 */ int mc_stat (path, st_addr) #else int mc_xstat (v, path, st_addr) int v; #endif unsigned char *path; struct stat *st_addr; { unsigned char buffer[MC_MAXPATHLEN]; #ifndef nec_ews_svr4 /* hir, 1993.10.22 */ return stat (decode_path (path, buffer), st_addr); #else return _xstat (v, decode_path (path, buffer), st_addr); #endif } int mc_unlink (path) unsigned char *path; { unsigned char buffer[MC_MAXPATHLEN]; return unlink (decode_path (path, buffer)); } #ifdef HAVE_RENAME int mc_rename (path, newpath) unsigned char *path, *newpath; { unsigned char buffer[MC_MAXPATHLEN], buffer2[MC_MAXPATHLEN]; return rename (decode_path (path, buffer), decode_path (newpath, buffer2)); } #endif int mc_link (path, newpath) unsigned char *path, *newpath; { unsigned char buffer[MC_MAXPATHLEN], buffer2[MC_MAXPATHLEN]; return link (decode_path (path, buffer), decode_path (newpath, buffer2)); } #ifndef MSDOS /* 94.8.9 by K.Fujii */ int mc_symlink (path, newpath) unsigned char *path, *newpath; { unsigned char buffer[MC_MAXPATHLEN], buffer2[MC_MAXPATHLEN]; return symlink (decode_path (path, buffer), decode_path (newpath, buffer2)); } #endif int mc_chdir (path) unsigned char *path; { unsigned char buffer[MC_MAXPATHLEN]; path = decode_path (path, buffer); #ifdef MSDOS /* 94.8.9 by K.Fujii */ if ((path[0] != 0) && (path[1] == ':')) { int drive = (tolower (path[0]) - 'a'); if (getdisk () != drive) setdisk (drive); } /* If path != "/" and path != "a:/" and path ends with slash, remove it. */ { int len = strlen (path); if (strcmp (path + 1, ":/") && (len > 1) && (path[len - 1] == '/')) { if (path != buffer) /* It is not good to modify original path. */ { bcopy (path, buffer, len - 1); /* no need to copy last /. */ path = buffer; } path[len - 1] = 0; } } #endif /* MSDOS */ return chdir (path); } #ifdef MSDOS #ifndef HAVE_GETWD unsigned char *mc_getcwd (null, size) unsigned char *null; /* in sysdep.c, always 0. */ size_t size; { unsigned char buffer[MAXPATHLEN]; unsigned char *path; path = (unsigned char *) getcwd ((char *)buffer, MAXPATHLEN); if (path) { /* here, shoule be (path == buffer). */ path = (unsigned char *) malloc (MC_MAXPATHLEN); /* MSDOS */ if (path) { int len; int buffer_length = strlen (buffer) + 1; len = encode_path_1 (buffer, buffer_length, path, MC_MAXPATHLEN); if (len < 0) { /* conversion failed. use value that is returned from system. */ bcopy (buffer, path, buffer_length); } } } return path; } #else /* HAVE_GETWD */ unsigned char *mc_getwd (path) unsigned char path[]; { unsigned char *p; p = getwd (path); if (p) { unsigned char buffer[MC_MAXPATHLEN]; int len; len = encode_path_1 (path, strlen (path) + 1, buffer, sizeof buffer); if (len > 0) { bcopy (buffer, path, len); } } return p; } #endif /* HAVE_GETWD */ #endif /* MSDOS */ /* In callproc.c, execvp() is called like this: * execvp (new_argv[0], new_argv); * following implement depends this. */ #ifndef NO_MC_EXECVP void mc_execvp (path, argv) unsigned char *path, *argv[]; { unsigned char buffer[MC_MAXPATHLEN]; argv[0] = path = decode_path (path, buffer); execvp (path, argv); } #endif /* !NO_MC_EXECVP */ DIR *mc_opendir (path) unsigned char *path; { unsigned char buffer[MC_MAXPATHLEN]; return opendir (decode_path (path, buffer)); } static DIRENTRY mcpath_directory_entry; DIRENTRY *mc_readdir (d) DIR *d; { SYSTEM_DIRENTRY *sp; DIRENTRY *dp = &mcpath_directory_entry; sp = readdir (d); if (!sp) return 0; #ifndef MSDOS dp->d_ino = sp->d_ino; #endif /* MSDOS */ { /* copy d_name with conversion. */ int len; len = encode_path_1 (sp->d_name, NAMLEN (sp), dp->d_name, sizeof (dp->d_name) - 1); if (len < 0) { len = NAMLEN (sp); #ifdef MCPATH_ASSERT assert (len < sizeof (dp->d_name)); #endif bcopy (sp->d_name, dp->d_name, len); } dp->d_name[len] = 0; } return dp; } #ifdef HAVE_MKDIR /* hir, 1994.8.12 */ int mc_mkdir (path, mode) unsigned char *path; int mode; { unsigned char buffer[MC_MAXPATHLEN]; return mkdir (decode_path (path, buffer), mode); } #endif #ifdef HAVE_RMDIR /* hir, 1994.8.12 */ int mc_rmdir (path) unsigned char *path; { unsigned char buffer[MC_MAXPATHLEN]; return rmdir (decode_path (path, buffer)); } #endif syms_of_mcpath () { Qpathname_coding_system = intern ("pathname-coding-system"); Fset_pathname_coding_system (Qnil); defsubr (&Sset_pathname_coding_system); /* patch 94.9.4 by K.Fujii */ defsubr (&Sencode_path); /* end of patch */ }