Fix copyright years in new cygw32 files.
[bpt/emacs.git] / src / cygw32.c
1 /* Cygwin support routines.
2 Copyright (C) 2011-2012 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18
19
20 #include "cygw32.h"
21 #include "character.h"
22 #include "buffer.h"
23 #include <unistd.h>
24 #include <fcntl.h>
25 static Lisp_Object Qutf_16_le;
26
27 static Lisp_Object
28 fchdir_unwind (Lisp_Object dir_fd)
29 {
30 (void) fchdir (XFASTINT (dir_fd));
31 (void) close (XFASTINT (dir_fd));
32 return Qnil;
33 }
34
35 static void
36 chdir_to_default_directory ()
37 {
38 Lisp_Object new_cwd;
39 int old_cwd_fd = open (".", O_RDONLY | O_DIRECTORY);
40
41 if (old_cwd_fd == -1)
42 error ("could not open current directory: %s", strerror (errno));
43
44 record_unwind_protect (fchdir_unwind, make_number (old_cwd_fd));
45
46 new_cwd = Funhandled_file_name_directory (
47 Fexpand_file_name (build_string ("."), Qnil));
48 if (!STRINGP (new_cwd))
49 new_cwd = build_string ("/");
50
51 if (chdir (SDATA (ENCODE_FILE (new_cwd))))
52 error ("could not chdir: %s", strerror (errno));
53 }
54
55 static Lisp_Object
56 conv_filename_to_w32_unicode (Lisp_Object in, int absolute_p)
57 {
58 ssize_t converted_len;
59 Lisp_Object converted;
60 unsigned flags;
61 int count = SPECPDL_INDEX ();
62
63 chdir_to_default_directory ();
64
65 flags = CCP_POSIX_TO_WIN_W;
66 if (!absolute_p) {
67 flags |= CCP_RELATIVE;
68 }
69
70 in = ENCODE_FILE (in);
71
72 converted_len = cygwin_conv_path (flags, SDATA (in), NULL, 0);
73 if (converted_len < 2)
74 error ("cygwin_conv_path: %s", strerror (errno));
75
76 converted = make_uninit_string (converted_len - 1);
77 if (cygwin_conv_path (flags, SDATA (in),
78 SDATA (converted), converted_len))
79 error ("cygwin_conv_path: %s", strerror (errno));
80
81 return unbind_to (count, converted);
82 }
83
84 static Lisp_Object
85 conv_filename_from_w32_unicode (const wchar_t* in, int absolute_p)
86 {
87 ssize_t converted_len;
88 Lisp_Object converted;
89 unsigned flags;
90 int count = SPECPDL_INDEX ();
91
92 chdir_to_default_directory ();
93
94 flags = CCP_WIN_W_TO_POSIX;
95 if (!absolute_p) {
96 flags |= CCP_RELATIVE;
97 }
98
99 converted_len = cygwin_conv_path (flags, in, NULL, 0);
100 if (converted_len < 1)
101 error ("cygwin_conv_path: %s", strerror (errno));
102
103 converted = make_uninit_string (converted_len - 1 /*subtract terminator*/);
104 if (cygwin_conv_path (flags, in, SDATA (converted), converted_len))
105 error ("cygwin_conv_path: %s", strerror (errno));
106
107 return unbind_to (count, DECODE_FILE (converted));
108 }
109
110 Lisp_Object
111 from_unicode (Lisp_Object str)
112 {
113 CHECK_STRING (str);
114 if (!STRING_MULTIBYTE (str) &&
115 SBYTES (str) & 1)
116 {
117 str = Fsubstring (str, make_number (0), make_number (-1));
118 }
119
120 return code_convert_string_norecord (str, Qutf_16_le, 0);
121 }
122
123 wchar_t *
124 to_unicode (Lisp_Object str, Lisp_Object *buf)
125 {
126 *buf = code_convert_string_norecord (str, Qutf_16_le, 1);
127 /* We need to make a another copy (in addition to the one made by
128 code_convert_string_norecord) to ensure that the final string is
129 _doubly_ zero terminated --- that is, that the string is
130 terminated by two zero bytes and one utf-16le null character.
131 Because strings are already terminated with a single zero byte,
132 we just add one additional zero. */
133 str = make_uninit_string (SBYTES (*buf) + 1);
134 memcpy (SDATA (str), SDATA (*buf), SBYTES (*buf));
135 SDATA (str) [SBYTES (*buf)] = '\0';
136 *buf = str;
137 return WCSDATA (*buf);
138 }
139
140 DEFUN ("cygwin-convert-path-to-windows",
141 Fcygwin_convert_path_to_windows, Scygwin_convert_path_to_windows,
142 1, 2, 0,
143 doc: /* Convert PATH to a Windows path. If ABSOLUTE-P if
144 non-nil, return an absolute path.*/)
145 (Lisp_Object path, Lisp_Object absolute_p)
146 {
147 return from_unicode (
148 conv_filename_to_w32_unicode (path, absolute_p == Qnil ? 0 : 1));
149 }
150
151 DEFUN ("cygwin-convert-path-from-windows",
152 Fcygwin_convert_path_from_windows, Scygwin_convert_path_from_windows,
153 1, 2, 0,
154 doc: /* Convert a Windows path to a Cygwin path. If ABSOLUTE-P
155 if non-nil, return an absolute path.*/)
156 (Lisp_Object path, Lisp_Object absolute_p)
157 {
158 return conv_filename_from_w32_unicode (to_unicode (path, &path),
159 absolute_p == Qnil ? 0 : 1);
160 }
161
162 void
163 syms_of_cygw32 (void)
164 {
165 /* No, not utf-16-le: that one has a BOM. */
166 DEFSYM (Qutf_16_le, "utf-16le");
167 defsubr (&Scygwin_convert_path_from_windows);
168 defsubr (&Scygwin_convert_path_to_windows);
169 }