wks: Allow reading of --install-key arguments from stdin.
[gnupg.git] / common / mischelp.c
1 /* mischelp.c - Miscellaneous helper functions
2  * Copyright (C) 1998, 2000, 2001, 2006, 2007 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute and/or modify this
7  * part of GnuPG under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * GnuPG is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * General Public License for more details.
25  *
26  * You should have received a copies of the GNU General Public License
27  * and the GNU Lesser General Public License along with this program;
28  * if not, see <https://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35 #ifdef HAVE_W32_SYSTEM
36 # define WIN32_LEAN_AND_MEAN
37 # include <windows.h>
38 #else /*!HAVE_W32_SYSTEM*/
39 # include <sys/types.h>
40 # include <sys/stat.h>
41 # include <unistd.h>
42 #endif /*!HAVE_W32_SYSTEM*/
43 #include <errno.h>
44
45 #include "util.h"
46 #include "common-defs.h"
47 #include "stringhelp.h"
48 #include "utf8conv.h"
49 #include "mischelp.h"
50
51
52 void
53 wipememory (void *ptr, size_t len)
54 {
55 #if defined(HAVE_W32_SYSTEM) && defined(SecureZeroMemory)
56   SecureZeroMemory (ptr, len);
57 #elif defined(HAVE_EXPLICIT_BZERO)
58   explicit_bzero (ptr, len);
59 #else
60   /* Prevent compiler from optimizing away the call to memset by accessing
61      memset through volatile pointer. */
62   static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
63   memset_ptr (ptr, 0, len);
64 #endif
65 }
66
67
68 /* Check whether the files NAME1 and NAME2 are identical.  This is for
69    example achieved by comparing the inode numbers of the files.  */
70 int
71 same_file_p (const char *name1, const char *name2)
72 {
73   int yes;
74
75   /* First try a shortcut.  */
76   if (!compare_filenames (name1, name2))
77     yes = 1;
78   else
79     {
80 #ifdef HAVE_W32_SYSTEM
81       HANDLE file1, file2;
82       BY_HANDLE_FILE_INFORMATION info1, info2;
83
84 #ifdef HAVE_W32CE_SYSTEM
85       {
86         wchar_t *wname = utf8_to_wchar (name1);
87         if (wname)
88           file1 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
89         else
90           file1 = INVALID_HANDLE_VALUE;
91         xfree (wname);
92       }
93 #else
94       file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
95 #endif
96       if (file1 == INVALID_HANDLE_VALUE)
97         yes = 0; /* If we can't open the file, it is not the same.  */
98       else
99         {
100 #ifdef HAVE_W32CE_SYSTEM
101           {
102             wchar_t *wname = utf8_to_wchar (name2);
103             if (wname)
104               file2 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
105             else
106               file2 = INVALID_HANDLE_VALUE;
107             xfree (wname);
108           }
109 #else
110           file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
111 #endif
112           if (file2 == INVALID_HANDLE_VALUE)
113             yes = 0; /* If we can't open the file, it is not the same.  */
114           else
115             {
116               yes = (GetFileInformationByHandle (file1, &info1)
117                      && GetFileInformationByHandle (file2, &info2)
118                      && info1.dwVolumeSerialNumber==info2.dwVolumeSerialNumber
119                      && info1.nFileIndexHigh == info2.nFileIndexHigh
120                      && info1.nFileIndexLow == info2.nFileIndexLow);
121               CloseHandle (file2);
122             }
123           CloseHandle (file1);
124         }
125 #else /*!HAVE_W32_SYSTEM*/
126       struct stat info1, info2;
127
128       yes = (!stat (name1, &info1) && !stat (name2, &info2)
129              && info1.st_dev == info2.st_dev && info1.st_ino == info2.st_ino);
130 #endif /*!HAVE_W32_SYSTEM*/
131     }
132   return yes;
133 }
134
135
136 /*
137   timegm() is a GNU function that might not be available everywhere.
138   It's basically the inverse of gmtime() - you give it a struct tm,
139   and get back a time_t.  It differs from mktime() in that it handles
140   the case where the struct tm is UTC and the local environment isn't.
141
142   Note, that this replacement implementation might not be thread-safe!
143
144   Some BSDs don't handle the putenv("foo") case properly, so we use
145   unsetenv if the platform has it to remove environment variables.
146 */
147 #ifndef HAVE_TIMEGM
148 time_t
149 timegm (struct tm *tm)
150 {
151 #ifdef HAVE_W32_SYSTEM
152   /* This one is thread safe.  */
153   SYSTEMTIME st;
154   FILETIME ft;
155   unsigned long long cnsecs;
156
157   st.wYear   = tm->tm_year + 1900;
158   st.wMonth  = tm->tm_mon  + 1;
159   st.wDay    = tm->tm_mday;
160   st.wHour   = tm->tm_hour;
161   st.wMinute = tm->tm_min;
162   st.wSecond = tm->tm_sec;
163   st.wMilliseconds = 0; /* Not available.  */
164   st.wDayOfWeek = 0;    /* Ignored.  */
165
166   /* System time is UTC thus the conversion is pretty easy.  */
167   if (!SystemTimeToFileTime (&st, &ft))
168     {
169       gpg_err_set_errno (EINVAL);
170       return (time_t)(-1);
171     }
172
173   cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
174             | ft.dwLowDateTime);
175   cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
176   return (time_t)(cnsecs / 10000000ULL);
177
178 #else /* (Non thread safe implementation!) */
179
180   time_t answer;
181   char *zone;
182
183   zone=getenv("TZ");
184   putenv("TZ=UTC");
185   tzset();
186   answer=mktime(tm);
187   if(zone)
188     {
189       static char *old_zone;
190
191       if (!old_zone)
192         {
193           old_zone = malloc(3+strlen(zone)+1);
194           if (old_zone)
195             {
196               strcpy(old_zone,"TZ=");
197               strcat(old_zone,zone);
198             }
199         }
200       if (old_zone)
201         putenv (old_zone);
202     }
203   else
204     gnupg_unsetenv("TZ");
205
206   tzset();
207   return answer;
208 #endif
209 }
210 #endif /*!HAVE_TIMEGM*/