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