libgaim/win32/libc_interface.c

branch
gaim
changeset 20470
77693555855f
parent 12749
704b51d5007a
parent 14974
8180f0f2e20c
child 20471
1966704b3e42
equal deleted inserted replaced
13071:b98e72d4089a 20470:77693555855f
1 /*
2 * gaim
3 *
4 * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
5 *
6 * This program 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 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21 #include <winsock2.h>
22 #include <ws2tcpip.h>
23 #include <io.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <sys/timeb.h>
28 #include <sys/stat.h>
29 #include <time.h>
30 #include <glib.h>
31 #include "debug.h"
32 #include "libc_internal.h"
33 #if GLIB_CHECK_VERSION(2,6,0)
34 # include <glib/gstdio.h>
35 #else
36 #define g_remove remove
37 #define g_rename rename
38 #define g_stat stat
39 #endif
40
41 static char errbuf[1024];
42
43 /* helpers */
44 static int wgaim_is_socket( int fd ) {
45 int optval;
46 unsigned int optlen = sizeof(int);
47
48 if( (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&optval, &optlen)) == SOCKET_ERROR ) {
49 int error = WSAGetLastError();
50 if( error == WSAENOTSOCK )
51 return FALSE;
52 else {
53 gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "wgaim_is_socket: getsockopt returned error: %d\n", error);
54 return FALSE;
55 }
56 }
57 return TRUE;
58 }
59
60 /* socket.h */
61 int wgaim_socket (int namespace, int style, int protocol) {
62 int ret;
63
64 ret = socket( namespace, style, protocol );
65
66 if( ret == INVALID_SOCKET ) {
67 errno = WSAGetLastError();
68 return -1;
69 }
70 return ret;
71 }
72
73 int wgaim_connect(int socket, struct sockaddr *addr, u_long length) {
74 int ret;
75
76 ret = connect( socket, addr, length );
77
78 if( ret == SOCKET_ERROR ) {
79 errno = WSAGetLastError();
80 if( errno == WSAEWOULDBLOCK )
81 errno = WSAEINPROGRESS;
82 return -1;
83 }
84 return 0;
85 }
86
87 int wgaim_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr) {
88 if(getsockopt(socket, level, optname, optval, optlenptr) == SOCKET_ERROR ) {
89 errno = WSAGetLastError();
90 return -1;
91 }
92 return 0;
93 }
94
95 int wgaim_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) {
96 if(setsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR ) {
97 errno = WSAGetLastError();
98 return -1;
99 }
100 return 0;
101 }
102
103 int wgaim_getsockname(int socket, struct sockaddr *addr, socklen_t *lenptr) {
104 if(getsockname(socket, addr, lenptr) == SOCKET_ERROR) {
105 errno = WSAGetLastError();
106 return -1;
107 }
108 return 0;
109 }
110
111 int wgaim_bind(int socket, struct sockaddr *addr, socklen_t length) {
112 if(bind(socket, addr, length) == SOCKET_ERROR) {
113 errno = WSAGetLastError();
114 return -1;
115 }
116 return 0;
117 }
118
119 int wgaim_listen(int socket, unsigned int n) {
120 if(listen(socket, n) == SOCKET_ERROR) {
121 errno = WSAGetLastError();
122 return -1;
123 }
124 return 0;
125 }
126
127 int wgaim_sendto(int socket, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) {
128 int ret;
129 if ((ret = sendto(socket, buf, len, flags, to, tolen)
130 ) == SOCKET_ERROR) {
131 errno = WSAGetLastError();
132 return -1;
133 }
134 return ret;
135 }
136
137 /* fcntl.h */
138 /* This is not a full implementation of fcntl. Update as needed.. */
139 int wgaim_fcntl(int socket, int command, int val) {
140 switch( command ) {
141 case F_SETFL:
142 {
143 int ret=0;
144
145 switch( val ) {
146 case O_NONBLOCK:
147 {
148 u_long imode=1;
149 ret = ioctlsocket(socket, FIONBIO, &imode);
150 break;
151 }
152 case 0:
153 {
154 u_long imode=0;
155 ret = ioctlsocket(socket, FIONBIO, &imode);
156 break;
157 }
158 default:
159 errno = EINVAL;
160 return -1;
161 }/*end switch*/
162 if( ret == SOCKET_ERROR ) {
163 errno = WSAGetLastError();
164 return -1;
165 }
166 return 0;
167 }
168 default:
169 gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "wgaim_fcntl: Unsupported command\n");
170 return -1;
171 }/*end switch*/
172 }
173
174 /* sys/ioctl.h */
175 int wgaim_ioctl(int fd, int command, void* val) {
176 switch( command ) {
177 case FIONBIO:
178 {
179 if (ioctlsocket(fd, FIONBIO, (unsigned long *)val) == SOCKET_ERROR) {
180 errno = WSAGetLastError();
181 return -1;
182 }
183 return 0;
184 }
185 case SIOCGIFCONF:
186 {
187 INTERFACE_INFO InterfaceList[20];
188 unsigned long nBytesReturned;
189 if (WSAIoctl(fd, SIO_GET_INTERFACE_LIST,
190 0, 0, &InterfaceList,
191 sizeof(InterfaceList), &nBytesReturned,
192 0, 0) == SOCKET_ERROR) {
193 errno = WSAGetLastError();
194 return -1;
195 } else {
196 int i;
197 struct ifconf *ifc = val;
198 char *tmp = ifc->ifc_buf;
199 int nNumInterfaces =
200 nBytesReturned / sizeof(INTERFACE_INFO);
201 for (i = 0; i < nNumInterfaces; i++) {
202 INTERFACE_INFO ii = InterfaceList[i];
203 struct ifreq *ifr = (struct ifreq *) tmp;
204 struct sockaddr_in *sa = (struct sockaddr_in *) &ifr->ifr_addr;
205
206 sa->sin_family = ii.iiAddress.AddressIn.sin_family;
207 sa->sin_port = ii.iiAddress.AddressIn.sin_port;
208 sa->sin_addr.s_addr = ii.iiAddress.AddressIn.sin_addr.s_addr;
209 tmp += sizeof(struct ifreq);
210
211 /* Make sure that we can fit in the original buffer */
212 if (tmp >= (ifc->ifc_buf + ifc->ifc_len + sizeof(struct ifreq))) {
213 break;
214 }
215 }
216 /* Replace the length with the actually used length */
217 ifc->ifc_len = ifc->ifc_len - (ifc->ifc_buf - tmp);
218 return 0;
219 }
220 }
221 default:
222 errno = EINVAL;
223 return -1;
224 }/*end switch*/
225 }
226
227 /* arpa/inet.h */
228 int wgaim_inet_aton(const char *name, struct in_addr *addr) {
229 if((addr->s_addr = inet_addr(name)) == INADDR_NONE)
230 return 0;
231 else
232 return 1;
233 }
234
235 /* Thanks to GNU wget for this inet_ntop() implementation */
236 const char *
237 wgaim_inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
238 {
239 /* struct sockaddr can't accomodate struct sockaddr_in6. */
240 union {
241 struct sockaddr_in6 sin6;
242 struct sockaddr_in sin;
243 } sa;
244 DWORD dstlen = cnt;
245 size_t srcsize;
246
247 ZeroMemory(&sa, sizeof(sa));
248 switch (af)
249 {
250 case AF_INET:
251 sa.sin.sin_family = AF_INET;
252 sa.sin.sin_addr = *(struct in_addr *) src;
253 srcsize = sizeof (sa.sin);
254 break;
255 case AF_INET6:
256 sa.sin6.sin6_family = AF_INET6;
257 sa.sin6.sin6_addr = *(struct in6_addr *) src;
258 srcsize = sizeof (sa.sin6);
259 break;
260 default:
261 abort ();
262 }
263
264 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
265 {
266 errno = WSAGetLastError();
267 return NULL;
268 }
269 return (const char *) dst;
270 }
271
272
273 /* netdb.h */
274 struct hostent* wgaim_gethostbyname(const char *name) {
275 struct hostent *hp;
276
277 if((hp = gethostbyname(name)) == NULL) {
278 errno = WSAGetLastError();
279 return NULL;
280 }
281 return hp;
282 }
283
284 /* string.h */
285 char* wgaim_strerror( int errornum ) {
286 if( errornum > WSABASEERR ) {
287 sprintf( errbuf, "Windows socket error #%d", errornum );
288 return errbuf;
289 }
290 else
291 return strerror( errornum );
292 }
293
294 /* unistd.h */
295
296 /*
297 * We need to figure out whether fd is a file or socket handle.
298 */
299 int wgaim_read(int fd, void *buf, unsigned int size) {
300 int ret;
301
302 if(wgaim_is_socket(fd)) {
303 if((ret = recv(fd, buf, size, 0)) == SOCKET_ERROR) {
304 errno = WSAGetLastError();
305 if(errno == WSAEWOULDBLOCK)
306 errno = EAGAIN;
307 return -1;
308 }
309 #if 0
310 else if( ret == 0 ) {
311 /* connection has been gracefully closed */
312 errno = WSAENOTCONN;
313 return -1;
314 }
315 #endif
316 else {
317 /* success reading socket */
318 return ret;
319 }
320 } else {
321 /* fd is not a socket handle.. pass it off to read */
322 return read(fd, buf, size);
323 }
324 }
325
326 int wgaim_send(int fd, const void *buf, unsigned int size, int flags) {
327 int ret;
328
329 ret = send(fd, buf, size, flags);
330
331 if (ret == SOCKET_ERROR) {
332 errno = WSAGetLastError();
333 if(errno == WSAEWOULDBLOCK)
334 errno = EAGAIN;
335 return -1;
336 }
337 return ret;
338 }
339
340 int wgaim_write(int fd, const void *buf, unsigned int size) {
341
342 if(wgaim_is_socket(fd))
343 return wgaim_send(fd, buf, size, 0);
344 else
345 return write(fd, buf, size);
346 }
347
348 int wgaim_recv(int fd, void *buf, size_t len, int flags) {
349 int ret;
350
351 if((ret = recv(fd, buf, len, flags)) == SOCKET_ERROR) {
352 errno = WSAGetLastError();
353 if(errno == WSAEWOULDBLOCK)
354 errno = EAGAIN;
355 return -1;
356 } else {
357 return ret;
358 }
359 }
360
361 int wgaim_close(int fd) {
362 int ret;
363
364 if( wgaim_is_socket(fd) ) {
365 if( (ret = closesocket(fd)) == SOCKET_ERROR ) {
366 errno = WSAGetLastError();
367 return -1;
368 }
369 else
370 return 0;
371 }
372 else
373 return close(fd);
374 }
375
376 int wgaim_gethostname(char *name, size_t size) {
377 if(gethostname(name, size) == SOCKET_ERROR) {
378 errno = WSAGetLastError();
379 return -1;
380 }
381 return 0;
382 }
383
384 /* sys/time.h */
385
386 int wgaim_gettimeofday(struct timeval *p, struct timezone *z) {
387 int res = 0;
388 struct _timeb timebuffer;
389
390 if (z != 0) {
391 _tzset();
392 z->tz_minuteswest = _timezone/60;
393 z->tz_dsttime = _daylight;
394 }
395
396 if (p != 0) {
397 _ftime(&timebuffer);
398 p->tv_sec = timebuffer.time; /* seconds since 1-1-1970 */
399 p->tv_usec = timebuffer.millitm*1000; /* microseconds */
400 }
401
402 return res;
403 }
404
405 /* stdio.h */
406
407 int wgaim_rename (const char *oldname, const char *newname) {
408 struct stat oldstat, newstat;
409
410 if(g_stat(oldname, &oldstat) == 0) {
411 /* newname exists */
412 if(g_stat(newname, &newstat) == 0) {
413 /* oldname is a dir */
414 if(_S_ISDIR(oldstat.st_mode)) {
415 if(!_S_ISDIR(newstat.st_mode)) {
416 return g_rename(oldname, newname);
417 }
418 /* newname is a dir */
419 else {
420 /* This is not quite right.. If newname is empty and
421 is not a sub dir of oldname, newname should be
422 deleted and oldname should be renamed.
423 */
424 gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "wgaim_rename does not behave here as it should\n");
425 return g_rename(oldname, newname);
426 }
427 }
428 /* oldname is not a dir */
429 else {
430 /* newname is a dir */
431 if(_S_ISDIR(newstat.st_mode)) {
432 errno = EISDIR;
433 return -1;
434 }
435 /* newname is not a dir */
436 else {
437 g_remove(newname);
438 return g_rename(oldname, newname);
439 }
440 }
441 }
442 /* newname doesn't exist */
443 else
444 return g_rename(oldname, newname);
445 }
446 else {
447 /* oldname doesn't exist */
448 errno = ENOENT;
449 return -1;
450 }
451
452 }
453
454 /* time.h */
455
456 struct tm * wgaim_localtime_r (const time_t *time, struct tm *resultp) {
457 struct tm* tmptm;
458
459 if(!time)
460 return NULL;
461 tmptm = localtime(time);
462 if(resultp && tmptm)
463 return memcpy(resultp, tmptm, sizeof(struct tm));
464 else
465 return NULL;
466 }
467
468 /*
469 * Used by gaim_utf8_strftime() by way of gaim_internal_strftime()
470 * in src/util.c
471 *
472 * Code derived from PostgreSQL src/timezone/pgtz.c:
473 * http://developer.postgresql.org/cvsweb.cgi/pgsql/src/timezone/pgtz.c
474 */
475
476 /*
477 PostgreSQL Database Management System
478 (formerly known as Postgres, then as Postgres95)
479
480 Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
481
482 Portions Copyright (c) 1994, The Regents of the University of California
483
484 Permission to use, copy, modify, and distribute this software and its
485 documentation for any purpose, without fee, and without a written agreement
486 is hereby granted, provided that the above copyright notice and this
487 paragraph and the following two paragraphs appear in all copies.
488
489 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
490 DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
491 LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
492 DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
493 POSSIBILITY OF SUCH DAMAGE.
494
495 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
496 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
497 AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
498 ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
499 PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
500
501 */
502 static struct
503 {
504 char *wstd; /* Windows name of standard timezone */
505 char *wdst; /* Windows name of daylight timezone */
506 char *ustd; /* Unix name of standard timezone */
507 char *udst; /* Unix name of daylight timezone */
508 } win32_tzmap[] =
509 {
510 {
511 "", "",
512 "", "",
513 },
514 /*
515 * This list was built from the contents of the registry at
516 * "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
517 * on Windows XP Professional SP1
518 */
519 {
520 "Afghanistan Standard Time", "Afghanistan Daylight Time",
521 "AFT", "AFT"
522 },
523 {
524 "Alaskan Standard Time", "Alaskan Daylight Time",
525 "AKST", "AKDT"
526 },
527 {
528 "Arab Standard Time", "Arab Daylight Time",
529 "AST", "AST"
530 },
531 {
532 "Arabian Standard Time", "Arabian Daylight Time",
533 "GST", "GST"
534 },
535 {
536 "Arabic Standard Time", "Arabic Daylight Time",
537 "AST", "ADT"
538 },
539 {
540 "Atlantic Standard Time", "Atlantic Daylight Time",
541 "AST", "ADT"
542 },
543 {
544 "AUS Central Standard Time", "AUS Central Daylight Time",
545 "CST", "CST"
546 },
547 {
548 "AUS Eastern Standard Time", "AUS Eastern Daylight Time",
549 "EST", "EST"
550 },
551 {
552 "Azores Standard Time", "Azores Daylight Time",
553 "AZOT", "AZOST"
554 },
555 {
556 "Canada Central Standard Time", "Canada Central Daylight Time",
557 "CST", "MDT"
558 },
559 {
560 "Cape Verde Standard Time", "Cape Verde Daylight Time",
561 "CVT", "CVST"
562 },
563 {
564 "Caucasus Standard Time", "Caucasus Daylight Time",
565 "AZT", "AZST"
566 },
567 {
568 "Cen. Australia Standard Time", "Cen. Australia Daylight Time",
569 "CST", "CST"
570 },
571 {
572 "Central America Standard Time", "Central America Daylight Time",
573 "CST", "CDT"
574 },
575 {
576 "Central Asia Standard Time", "Central Asia Daylight Time",
577 "BDT", "BDT"
578 },
579 {
580 "Central Europe Standard Time", "Central Europe Daylight Time",
581 "CET", "CEST"
582 },
583 {
584 "Central European Standard Time", "Central European Daylight Time",
585 "CET", "CEST"
586 },
587 {
588 "Central Pacific Standard Time", "Central Pacific Daylight Time",
589 "NCT", "NCST"
590 },
591 {
592 "Central Standard Time", "Central Daylight Time",
593 "CST", "CDT"
594 },
595 {
596 "China Standard Time", "China Daylight Time",
597 "HKT", "HKST"
598 },
599 {
600 "Dateline Standard Time", "Dateline Daylight Time",
601 "GMT+12", "GMT+12"
602 },
603 {
604 "E. Africa Standard Time", "E. Africa Daylight Time",
605 "EAT", "EAT"
606 },
607 {
608 "E. Australia Standard Time", "E. Australia Daylight Time",
609 "EST", "EST"
610 },
611 {
612 "E. Europe Standard Time", "E. Europe Daylight Time",
613 "EET", "EEST"
614 },
615 {
616 "E. South America Standard Time", "E. South America Daylight Time",
617 "BRT", "BRST"
618 },
619 {
620 "Eastern Standard Time", "Eastern Daylight Time",
621 "EST", "EDT"
622 },
623 {
624 "Egypt Standard Time", "Egypt Daylight Time",
625 "EET", "EEST"
626 },
627 {
628 "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time",
629 "YEKT", "YEKST"
630 },
631 {
632 "Fiji Standard Time", "Fiji Daylight Time",
633 "FJT", "FJST"
634 },
635 {
636 "FLE Standard Time", "FLE Daylight Time",
637 "EET", "EEST"
638 },
639 {
640 "GMT Standard Time", "GMT Daylight Time",
641 "GMT", "IST"
642 },
643 {
644 "Greenland Standard Time", "Greenland Daylight Time",
645 "WGT", "WGST"
646 },
647 {
648 "Greenwich Standard Time", "Greenwich Daylight Time",
649 "WET", "WEST"
650 },
651 {
652 "GTB Standard Time", "GTB Daylight Time",
653 "EET", "EEST"
654 },
655 {
656 "Hawaiian Standard Time", "Hawaiian Daylight Time",
657 "HST", "HPT"
658 },
659 {
660 "India Standard Time", "India Daylight Time",
661 "IST", "IST"
662 },
663 {
664 "Iran Standard Time", "Iran Daylight Time",
665 "IRST", "IRDT"
666 },
667 {
668 "Jerusalem Standard Time", "Jerusalem Daylight Time",
669 "IST", "IDT"
670 },
671 {
672 "Korea Standard Time", "Korea Daylight Time",
673 "KST", "KDT"
674 },
675 {
676 "Mexico Standard Time", "Mexico Daylight Time",
677 "CST", "CDT"
678 },
679 {
680 "Mexico Standard Time", "Mexico Daylight Time",
681 "BOT", "BOST"
682 },
683 {
684 "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time",
685 "GST", "GST"
686 },
687 {
688 "Mountain Standard Time", "Mountain Daylight Time",
689 "MST", "MDT"
690 },
691 {
692 "Myanmar Standard Time", "Myanmar Daylight Time",
693 "MMT", "MMT"
694 },
695 {
696 "N. Central Asia Standard Time", "N. Central Asia Daylight Time",
697 "ALMT", "ALMST"
698 },
699 {
700 "Nepal Standard Time", "Nepal Daylight Time",
701 "NPT", "NPT"
702 },
703 {
704 "New Zealand Standard Time", "New Zealand Daylight Time",
705 "NZST", "NZDT"
706 },
707 {
708 "Newfoundland Standard Time", "Newfoundland Daylight Time",
709 "NST", "NDT"
710 },
711 {
712 "North Asia East Standard Time", "North Asia East Daylight Time",
713 "IRKT", "IRKST"
714 },
715 {
716 "North Asia Standard Time", "North Asia Daylight Time",
717 "KRAT", "KRAST"
718 },
719 {
720 "Pacific SA Standard Time", "Pacific SA Daylight Time",
721 "CLT", "CLST"
722 },
723 {
724 "Pacific Standard Time", "Pacific Daylight Time",
725 "PST", "PDT"
726 },
727 {
728 "Romance Standard Time", "Romance Daylight Time",
729 "CET", "CEST"
730 },
731 {
732 "Russian Standard Time", "Russian Daylight Time",
733 "MSK", "MSD"
734 },
735 {
736 "SA Eastern Standard Time", "SA Eastern Daylight Time",
737 "ART", "ARST"
738 },
739 {
740 "SA Pacific Standard Time", "SA Pacific Daylight Time",
741 "COT", "COST"
742 },
743 {
744 "SA Western Standard Time", "SA Western Daylight Time",
745 "VET", "VET"
746 },
747 {
748 "Samoa Standard Time", "Samoa Daylight Time",
749 "SST", "NDT"
750 },
751 {
752 "SE Asia Standard Time", "SE Asia Daylight Time",
753 "ICT", "ICT"
754 },
755 {
756 "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time",
757 "MYT", "MALST"
758 },
759 {
760 "South Africa Standard Time", "South Africa Daylight Time",
761 "CAT", "CAT"
762 },
763 {
764 "Sri Lanka Standard Time", "Sri Lanka Daylight Time",
765 "LKT", "IST"
766 },
767 {
768 "Taipei Standard Time", "Taipei Daylight Time",
769 "CST", "CDT"
770 },
771 {
772 "Tasmania Standard Time", "Tasmania Daylight Time",
773 "EST", "EST"
774 },
775 {
776 "Tokyo Standard Time", "Tokyo Daylight Time",
777 "JST", "JDT"
778 },
779 {
780 "Tonga Standard Time", "Tonga Daylight Time",
781 "TOT", "TOST"
782 },
783 {
784 "US Eastern Standard Time", "US Eastern Daylight Time",
785 "EST", "EDT"
786 },
787 {
788 "US Mountain Standard Time", "US Mountain Daylight Time",
789 "MST", "MDT"
790 },
791 {
792 "Vladivostok Standard Time", "Vladivostok Daylight Time",
793 "VLAT", "VLAST"
794 },
795 {
796 "W. Australia Standard Time", "W. Australia Daylight Time",
797 "WST", "WST"
798 },
799
800 /* Not mapped in PostgreSQL.
801 *
802 * I mapped this based on the following information... -- rlaager
803 * $ cd /usr/share/zoneinfo/Africa
804 * $ for i in * ; do echo `TZ=Africa/$i date +"%z %Z"` $i ; done | grep +0100
805 * +0100 CET Algiers
806 * +0100 WAT Bangui
807 * +0100 WAT Brazzaville
808 * +0100 CET Ceuta
809 * +0100 WAT Douala
810 * +0100 WAT Kinshasa
811 * +0100 WAT Lagos
812 * +0100 WAT Libreville
813 * +0100 WAT Luanda
814 * +0100 WAT Malabo
815 * +0100 WAT Ndjamena
816 * +0100 WAT Niamey
817 * +0100 WAT Porto-Novo
818 * +0100 CET Tunis
819 **/
820 {
821 "W. Central Africa Standard Time", "W. Central Africa Daylight Time",
822 "WAT", "WAT"
823 },
824
825 {
826 "W. Europe Standard Time", "W. Europe Daylight Time",
827 "CET", "CEST"
828 },
829 {
830 "West Asia Standard Time", "West Asia Daylight Time",
831 "PKT", "PKST"
832 },
833 {
834 "West Pacific Standard Time", "West Pacific Daylight Time",
835 "ChST", "ChST"
836 },
837 {
838 "Yakutsk Standard Time", "Yakutsk Daylight Time",
839 "YAKT", "YAKST"
840 },
841 {
842 NULL, NULL,
843 NULL, NULL
844 }
845 };
846
847 const char *
848 wgaim_get_timezone_abbreviation(const struct tm *tm)
849 {
850 int i;
851 char tzname[128];
852 char localtzname[256];
853 HKEY rootKey;
854 int idx;
855
856 if (!tm)
857 {
858 gaim_debug_warning("wgaim", "could not determine current date/time: localtime failed\n");
859 return "";
860 }
861
862 if (strftime(tzname, sizeof(tzname) - 1, "%Z", tm) == 0)
863 {
864 gaim_debug_error("wgaim", "timezone name is too long for the buffer\n");
865 return "";
866 }
867
868 for (i = 0; win32_tzmap[i].wstd != NULL; i++)
869 {
870 if (strcmp(tzname, win32_tzmap[i].wstd) == 0)
871 {
872 #if 0
873 gaim_debug_info("wgaim", "TZ \"%s\" matches Windows timezone \"%s\"\n",
874 win32_tzmap[i].ustd, tzname);
875 #endif
876 /* Cache the Result */
877 if (i > 0) {
878 if (win32_tzmap[0].wstd[0] != '\0')
879 g_free(win32_tzmap[0].wstd);
880 win32_tzmap[0].wstd = g_strdup(tzname);
881 win32_tzmap[0].ustd = win32_tzmap[i].ustd;
882 }
883
884 return win32_tzmap[i].ustd;
885 }
886 if (strcmp(tzname, win32_tzmap[i].wdst) == 0)
887 {
888 #if 0
889 gaim_debug_info("wgaim", "TZ \"%s\" matches Windows timezone \"%s\"\n",
890 win32_tzmap[i].udst, tzname);
891 #endif
892 /* Cache the Result */
893 if (i > 0) {
894 if (win32_tzmap[0].wdst[0] != '\0')
895 g_free(win32_tzmap[0].wdst);
896 win32_tzmap[0].wdst = g_strdup(tzname);
897 win32_tzmap[0].udst = win32_tzmap[i].udst;
898 }
899
900 return win32_tzmap[i].udst;
901 }
902 }
903
904 /*
905 * Localized Windows versions return localized names for the timezone.
906 * Scan the registry to find the English name, and then try matching
907 * against our table again.
908 */
909 memset(localtzname, 0, sizeof(localtzname));
910 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
911 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
912 0,
913 KEY_READ,
914 &rootKey) != ERROR_SUCCESS)
915 {
916 gaim_debug_warning("wgaim", "could not open registry key to identify Windows timezone: %i\n", (int) GetLastError());
917 return "";
918 }
919
920 for (idx = 0;; idx++)
921 {
922 char keyname[256];
923 char zonename[256];
924 DWORD namesize;
925 FILETIME lastwrite;
926 HKEY key;
927 LONG r;
928
929 memset(keyname, 0, sizeof(keyname));
930 namesize = sizeof(keyname);
931 if ((r = RegEnumKeyEx(rootKey,
932 idx,
933 keyname,
934 &namesize,
935 NULL,
936 NULL,
937 NULL,
938 &lastwrite)) != ERROR_SUCCESS)
939 {
940 if (r == ERROR_NO_MORE_ITEMS)
941 break;
942 gaim_debug_warning("wgaim", "could not enumerate registry subkeys to identify Windows timezone: %i\n", (int) r);
943 break;
944 }
945
946 if ((r = RegOpenKeyEx(rootKey, keyname, 0, KEY_READ, &key)) != ERROR_SUCCESS)
947 {
948 gaim_debug_warning("wgaim", "could not open registry subkey to identify Windows timezone: %i\n", (int) r);
949 break;
950 }
951
952 memset(zonename, 0, sizeof(zonename));
953 namesize = sizeof(zonename);
954 if ((r = RegQueryValueEx(key, "Std", NULL, NULL, zonename, &namesize)) != ERROR_SUCCESS)
955 {
956 gaim_debug_warning("wgaim", "could not query value for 'std' to identify Windows timezone: %i\n", (int) r);
957 RegCloseKey(key);
958 break;
959 }
960 if (strcmp(tzname, zonename) == 0)
961 {
962 /* Matched zone */
963 strcpy(localtzname, keyname);
964 RegCloseKey(key);
965 break;
966 }
967 memset(zonename, 0, sizeof(zonename));
968 namesize = sizeof(zonename);
969 if ((r = RegQueryValueEx(key, "Dlt", NULL, NULL, zonename, &namesize)) != ERROR_SUCCESS)
970 {
971 gaim_debug_warning("wgaim", "could not query value for 'dlt' to identify Windows timezone: %i\n", (int) r);
972 RegCloseKey(key);
973 break;
974 }
975 if (strcmp(tzname, zonename) == 0)
976 {
977 /* Matched DST zone */
978 strcpy(localtzname, keyname);
979 RegCloseKey(key);
980 break;
981 }
982
983 RegCloseKey(key);
984 }
985
986 RegCloseKey(rootKey);
987
988 if (localtzname[0])
989 {
990 /* Found a localized name, so scan for that one too */
991 for (i = 0; win32_tzmap[i].wstd != NULL; i++)
992 {
993 if (strcmp(localtzname, win32_tzmap[i].wstd) == 0)
994 {
995 #if 0
996 gaim_debug_info("wgaim", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
997 win32_tzmap[i].ustd, tzname, localtzname);
998 #endif
999 /* Cache the Result */
1000 if (win32_tzmap[0].wstd[0] != '\0')
1001 g_free(win32_tzmap[0].wstd);
1002 win32_tzmap[0].wstd = g_strdup(tzname);
1003 win32_tzmap[0].ustd = win32_tzmap[i].ustd;
1004
1005 return win32_tzmap[i].ustd;
1006 }
1007 if (strcmp(localtzname, win32_tzmap[i].wdst) == 0)
1008 {
1009 #if 0
1010 gaim_debug_info("wgaim", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
1011 win32_tzmap[i].udst, tzname, localtzname);
1012 #endif
1013 /* Cache the Result */
1014 if (win32_tzmap[0].wdst[0] != '\0')
1015 g_free(win32_tzmap[0].wdst);
1016
1017 win32_tzmap[0].wdst = g_strdup(tzname);
1018 win32_tzmap[0].udst = win32_tzmap[i].udst;
1019
1020 return win32_tzmap[i].udst;
1021 }
1022 }
1023 }
1024
1025 gaim_debug_warning("wgaim", "could not find a match for Windows timezone \"%s\"\n", tzname);
1026 return "";
1027 }
1028
1029 #if !GLIB_CHECK_VERSION(2,8,0)
1030 /**
1031 * g_access:
1032 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
1033 * @mode: as in access()
1034 *
1035 * A wrapper for the POSIX access() function. This function is used to
1036 * test a pathname for one or several of read, write or execute
1037 * permissions, or just existence. On Windows, the underlying access()
1038 * function in the C library only checks the READONLY attribute, and
1039 * does not look at the ACL at all. Software that needs to handle file
1040 * permissions on Windows more exactly should use the Win32 API.
1041 *
1042 * See the C library manual for more details about access().
1043 *
1044 * Returns: zero if the pathname refers to an existing file system
1045 * object that has all the tested permissions, or -1 otherwise or on
1046 * error.
1047 *
1048 * Since: 2.8
1049 */
1050 int
1051 wgaim_g_access (const gchar *filename,
1052 int mode)
1053 {
1054 if (G_WIN32_HAVE_WIDECHAR_API ())
1055 {
1056 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1057 int retval;
1058 int save_errno;
1059
1060 if (wfilename == NULL)
1061 {
1062 errno = EINVAL;
1063 return -1;
1064 }
1065
1066 retval = _waccess (wfilename, mode);
1067 save_errno = errno;
1068
1069 g_free (wfilename);
1070
1071 errno = save_errno;
1072 return retval;
1073 }
1074 else
1075 {
1076 gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
1077 int retval;
1078 int save_errno;
1079
1080 if (cp_filename == NULL)
1081 {
1082 errno = EINVAL;
1083 return -1;
1084 }
1085
1086 retval = access (cp_filename, mode);
1087 save_errno = errno;
1088
1089 g_free (cp_filename);
1090
1091 errno = save_errno;
1092 return retval;
1093 }
1094 }
1095 #endif
1096
1097

mercurial