Line data Source code
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 it and/or modify it
7 : * 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 : /* Check whether the files NAME1 and NAME2 are identical. This is for
53 : example achieved by comparing the inode numbers of the files. */
54 : int
55 0 : same_file_p (const char *name1, const char *name2)
56 : {
57 : int yes;
58 :
59 : /* First try a shortcut. */
60 0 : if (!compare_filenames (name1, name2))
61 0 : yes = 1;
62 : else
63 : {
64 : #ifdef HAVE_W32_SYSTEM
65 : HANDLE file1, file2;
66 : BY_HANDLE_FILE_INFORMATION info1, info2;
67 :
68 : #ifdef HAVE_W32CE_SYSTEM
69 : {
70 : wchar_t *wname = utf8_to_wchar (name1);
71 : if (wname)
72 : file1 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
73 : else
74 : file1 = INVALID_HANDLE_VALUE;
75 : xfree (wname);
76 : }
77 : #else
78 : file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
79 : #endif
80 : if (file1 == INVALID_HANDLE_VALUE)
81 : yes = 0; /* If we can't open the file, it is not the same. */
82 : else
83 : {
84 : #ifdef HAVE_W32CE_SYSTEM
85 : {
86 : wchar_t *wname = utf8_to_wchar (name2);
87 : if (wname)
88 : file2 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
89 : else
90 : file2 = INVALID_HANDLE_VALUE;
91 : xfree (wname);
92 : }
93 : #else
94 : file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
95 : #endif
96 : if (file2 == INVALID_HANDLE_VALUE)
97 : yes = 0; /* If we can't open the file, it is not the same. */
98 : else
99 : {
100 : yes = (GetFileInformationByHandle (file1, &info1)
101 : && GetFileInformationByHandle (file2, &info2)
102 : && info1.dwVolumeSerialNumber==info2.dwVolumeSerialNumber
103 : && info1.nFileIndexHigh == info2.nFileIndexHigh
104 : && info1.nFileIndexLow == info2.nFileIndexLow);
105 : CloseHandle (file2);
106 : }
107 : CloseHandle (file1);
108 : }
109 : #else /*!HAVE_W32_SYSTEM*/
110 : struct stat info1, info2;
111 :
112 0 : yes = (!stat (name1, &info1) && !stat (name2, &info2)
113 0 : && info1.st_dev == info2.st_dev && info1.st_ino == info2.st_ino);
114 : #endif /*!HAVE_W32_SYSTEM*/
115 : }
116 0 : return yes;
117 : }
118 :
119 :
120 : /*
121 : timegm() is a GNU function that might not be available everywhere.
122 : It's basically the inverse of gmtime() - you give it a struct tm,
123 : and get back a time_t. It differs from mktime() in that it handles
124 : the case where the struct tm is UTC and the local environment isn't.
125 :
126 : Note, that this replacement implementation might not be thread-safe!
127 :
128 : Some BSDs don't handle the putenv("foo") case properly, so we use
129 : unsetenv if the platform has it to remove environment variables.
130 : */
131 : #ifndef HAVE_TIMEGM
132 : time_t
133 : timegm (struct tm *tm)
134 : {
135 : #ifdef HAVE_W32_SYSTEM
136 : /* This one is thread safe. */
137 : SYSTEMTIME st;
138 : FILETIME ft;
139 : unsigned long long cnsecs;
140 :
141 : st.wYear = tm->tm_year + 1900;
142 : st.wMonth = tm->tm_mon + 1;
143 : st.wDay = tm->tm_mday;
144 : st.wHour = tm->tm_hour;
145 : st.wMinute = tm->tm_min;
146 : st.wSecond = tm->tm_sec;
147 : st.wMilliseconds = 0; /* Not available. */
148 : st.wDayOfWeek = 0; /* Ignored. */
149 :
150 : /* System time is UTC thus the conversion is pretty easy. */
151 : if (!SystemTimeToFileTime (&st, &ft))
152 : {
153 : gpg_err_set_errno (EINVAL);
154 : return (time_t)(-1);
155 : }
156 :
157 : cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
158 : | ft.dwLowDateTime);
159 : cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01. */
160 : return (time_t)(cnsecs / 10000000ULL);
161 :
162 : #else /* (Non thread safe implementation!) */
163 :
164 : time_t answer;
165 : char *zone;
166 :
167 : zone=getenv("TZ");
168 : putenv("TZ=UTC");
169 : tzset();
170 : answer=mktime(tm);
171 : if(zone)
172 : {
173 : static char *old_zone;
174 :
175 : if (!old_zone)
176 : {
177 : old_zone = malloc(3+strlen(zone)+1);
178 : if (old_zone)
179 : {
180 : strcpy(old_zone,"TZ=");
181 : strcat(old_zone,zone);
182 : }
183 : }
184 : if (old_zone)
185 : putenv (old_zone);
186 : }
187 : else
188 : gnupg_unsetenv("TZ");
189 :
190 : tzset();
191 : return answer;
192 : #endif
193 : }
194 : #endif /*!HAVE_TIMEGM*/
|