~ubuntu-branches/ubuntu/utopic/pgadmin3/utopic-proposed

« back to all changes in this revision

Viewing changes to pgadmin/libssh2/misc.c

  • Committer: Package Import Robot
  • Author(s): Christoph Berg
  • Date: 2013-09-10 16:16:38 UTC
  • mfrom: (1.3.4)
  • Revision ID: package-import@ubuntu.com-20130910161638-wwup1q553ylww7dr
Tags: 1.18.0-1
* New upstream release.
* Don't install /usr/bin/png2c anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
 
2
 * Copyright (c) 2009-2010 by Daniel Stenberg
 
3
 * Copyright (c) 2010  Simon Josefsson
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms,
 
7
 * with or without modification, are permitted provided
 
8
 * that the following conditions are met:
 
9
 *
 
10
 *   Redistributions of source code must retain the above
 
11
 *   copyright notice, this list of conditions and the
 
12
 *   following disclaimer.
 
13
 *
 
14
 *   Redistributions in binary form must reproduce the above
 
15
 *   copyright notice, this list of conditions and the following
 
16
 *   disclaimer in the documentation and/or other materials
 
17
 *   provided with the distribution.
 
18
 *
 
19
 *   Neither the name of the copyright holder nor the names
 
20
 *   of any other contributors may be used to endorse or
 
21
 *   promote products derived from this software without
 
22
 *   specific prior written permission.
 
23
 *
 
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 
25
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
26
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
27
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
28
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
29
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
30
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 
31
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
32
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
33
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
34
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 
35
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 
36
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 
37
 * OF SUCH DAMAGE.
 
38
 */
 
39
 
 
40
#include "libssh2_priv.h"
 
41
#include "misc.h"
 
42
 
 
43
#ifdef HAVE_UNISTD_H
 
44
#include <unistd.h>
 
45
#endif
 
46
 
 
47
#ifdef HAVE_SYS_TIME_H
 
48
#include <sys/time.h>
 
49
#endif
 
50
 
 
51
#include <stdio.h>
 
52
#include <errno.h>
 
53
 
 
54
int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
 
55
{
 
56
    session->err_msg = errmsg;
 
57
    session->err_code = errcode;
 
58
#ifdef LIBSSH2DEBUG
 
59
    if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode)
 
60
        /* if this is EAGAIN and we're in non-blocking mode, don't generate
 
61
           a debug output for this */
 
62
        return errcode;
 
63
    _libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
 
64
                   session->err_msg);
 
65
#endif
 
66
 
 
67
    return errcode;
 
68
}
 
69
 
 
70
#ifdef WIN32
 
71
static int wsa2errno(void)
 
72
{
 
73
    switch (WSAGetLastError()) {
 
74
    case WSAEWOULDBLOCK:
 
75
        return EAGAIN;
 
76
 
 
77
    case WSAENOTSOCK:
 
78
        return EBADF;
 
79
 
 
80
    case WSAEINTR:
 
81
        return EINTR;
 
82
 
 
83
    default:
 
84
        /* It is most important to ensure errno does not stay at EAGAIN
 
85
         * when a different error occurs so just set errno to a generic
 
86
         * error */
 
87
        return EIO;
 
88
    }
 
89
}
 
90
#endif
 
91
 
 
92
/* _libssh2_recv
 
93
 *
 
94
 * Replacement for the standard recv, return -errno on failure.
 
95
 */
 
96
ssize_t
 
97
_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags, void **abstract)
 
98
{
 
99
    ssize_t rc = recv(sock, buffer, length, flags);
 
100
#ifdef WIN32
 
101
    if (rc < 0 )
 
102
        return -wsa2errno();
 
103
#elif defined(__VMS)
 
104
    if (rc < 0 ){
 
105
        if ( errno == EWOULDBLOCK )
 
106
            return -EAGAIN;
 
107
        else
 
108
            return -errno;
 
109
    }
 
110
#else
 
111
    if (rc < 0 ){
 
112
        /* Sometimes the first recv() function call sets errno to ENOENT on
 
113
           Solaris and HP-UX */
 
114
        if ( errno == ENOENT )
 
115
            return -EAGAIN;
 
116
        else
 
117
            return -errno;
 
118
    }
 
119
#endif
 
120
    return rc;
 
121
}
 
122
 
 
123
/* _libssh2_send
 
124
 *
 
125
 * Replacement for the standard send, return -errno on failure.
 
126
 */
 
127
ssize_t
 
128
_libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
 
129
              int flags, void **abstract)
 
130
{
 
131
    ssize_t rc = send(sock, buffer, length, flags);
 
132
#ifdef WIN32
 
133
    if (rc < 0 )
 
134
        return -wsa2errno();
 
135
#elif defined(__VMS)
 
136
    if (rc < 0 ) {
 
137
        if ( errno == EWOULDBLOCK )
 
138
            return -EAGAIN;
 
139
        else
 
140
            return -errno;
 
141
    }
 
142
#else
 
143
    if (rc < 0 )
 
144
        return -errno;
 
145
#endif
 
146
    return rc;
 
147
}
 
148
 
 
149
/* libssh2_ntohu32
 
150
 */
 
151
unsigned int
 
152
_libssh2_ntohu32(const unsigned char *buf)
 
153
{
 
154
    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
 
155
}
 
156
 
 
157
 
 
158
/* _libssh2_ntohu64
 
159
 */
 
160
libssh2_uint64_t
 
161
_libssh2_ntohu64(const unsigned char *buf)
 
162
{
 
163
    unsigned long msl, lsl;
 
164
 
 
165
    msl = ((libssh2_uint64_t)buf[0] << 24) | ((libssh2_uint64_t)buf[1] << 16)
 
166
        | ((libssh2_uint64_t)buf[2] << 8) | (libssh2_uint64_t)buf[3];
 
167
    lsl = ((libssh2_uint64_t)buf[4] << 24) | ((libssh2_uint64_t)buf[5] << 16)
 
168
        | ((libssh2_uint64_t)buf[6] << 8) | (libssh2_uint64_t)buf[7];
 
169
 
 
170
    return ((libssh2_uint64_t)msl <<32) | lsl;
 
171
}
 
172
 
 
173
/* _libssh2_htonu32
 
174
 */
 
175
void
 
176
_libssh2_htonu32(unsigned char *buf, uint32_t value)
 
177
{
 
178
    buf[0] = (value >> 24) & 0xFF;
 
179
    buf[1] = (value >> 16) & 0xFF;
 
180
    buf[2] = (value >> 8) & 0xFF;
 
181
    buf[3] = value & 0xFF;
 
182
}
 
183
 
 
184
/* _libssh2_store_u32
 
185
 */
 
186
void _libssh2_store_u32(unsigned char **buf, uint32_t value)
 
187
{
 
188
    _libssh2_htonu32(*buf, value);
 
189
    *buf += sizeof(uint32_t);
 
190
}
 
191
 
 
192
/* _libssh2_store_str
 
193
 */
 
194
void _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
 
195
{
 
196
    _libssh2_store_u32(buf, (uint32_t)len);
 
197
    if(len) {
 
198
        memcpy(*buf, str, len);
 
199
        *buf += len;
 
200
    }
 
201
}
 
202
 
 
203
/* Base64 Conversion */
 
204
 
 
205
static const char base64_table[] =
 
206
{
 
207
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
 
208
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
 
209
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
 
210
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
 
211
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
 
212
};
 
213
 
 
214
static const char base64_pad = '=';
 
215
 
 
216
static const short base64_reverse_table[256] = {
 
217
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
218
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
219
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
 
220
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
 
221
    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
 
222
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
 
223
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
 
224
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
 
225
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
226
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
227
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
228
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
229
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
230
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
231
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 
232
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 
233
};
 
234
 
 
235
/* libssh2_base64_decode
 
236
 *
 
237
 * Decode a base64 chunk and store it into a newly alloc'd buffer
 
238
 */
 
239
LIBSSH2_API int
 
240
libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
 
241
                      unsigned int *datalen, const char *src,
 
242
                      unsigned int src_len)
 
243
{
 
244
    unsigned char *s, *d;
 
245
    short v;
 
246
    int i = 0, len = 0;
 
247
 
 
248
    *data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
 
249
    d = (unsigned char *) *data;
 
250
    if (!d) {
 
251
        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
 
252
                              "Unable to allocate memory for base64 decoding");
 
253
    }
 
254
 
 
255
    for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
 
256
        if ((v = base64_reverse_table[*s]) < 0)
 
257
            continue;
 
258
        switch (i % 4) {
 
259
        case 0:
 
260
            d[len] = v << 2;
 
261
            break;
 
262
        case 1:
 
263
            d[len++] |= v >> 4;
 
264
            d[len] = v << 4;
 
265
            break;
 
266
        case 2:
 
267
            d[len++] |= v >> 2;
 
268
            d[len] = v << 6;
 
269
            break;
 
270
        case 3:
 
271
            d[len++] |= v;
 
272
            break;
 
273
        }
 
274
        i++;
 
275
    }
 
276
    if ((i % 4) == 1) {
 
277
        /* Invalid -- We have a byte which belongs exclusively to a partial
 
278
           octet */
 
279
        LIBSSH2_FREE(session, *data);
 
280
        return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64");
 
281
    }
 
282
 
 
283
    *datalen = len;
 
284
    return 0;
 
285
}
 
286
 
 
287
/* ---- Base64 Encoding/Decoding Table --- */
 
288
static const char table64[]=
 
289
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
290
 
 
291
/*
 
292
 * _libssh2_base64_encode()
 
293
 *
 
294
 * Returns the length of the newly created base64 string. The third argument
 
295
 * is a pointer to an allocated area holding the base64 data. If something
 
296
 * went wrong, 0 is returned.
 
297
 *
 
298
 */
 
299
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
 
300
                              const char *inp, size_t insize, char **outptr)
 
301
{
 
302
  unsigned char ibuf[3];
 
303
  unsigned char obuf[4];
 
304
  int i;
 
305
  int inputparts;
 
306
  char *output;
 
307
  char *base64data;
 
308
  const char *indata = inp;
 
309
 
 
310
  *outptr = NULL; /* set to NULL in case of failure before we reach the end */
 
311
 
 
312
  if(0 == insize)
 
313
    insize = strlen(indata);
 
314
 
 
315
  base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4);
 
316
  if(NULL == output)
 
317
    return 0;
 
318
 
 
319
  while(insize > 0) {
 
320
    for (i = inputparts = 0; i < 3; i++) {
 
321
      if(insize > 0) {
 
322
        inputparts++;
 
323
        ibuf[i] = *indata;
 
324
        indata++;
 
325
        insize--;
 
326
      }
 
327
      else
 
328
        ibuf[i] = 0;
 
329
    }
 
330
 
 
331
    obuf[0] = (unsigned char)  ((ibuf[0] & 0xFC) >> 2);
 
332
    obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
 
333
                               ((ibuf[1] & 0xF0) >> 4));
 
334
    obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
 
335
                               ((ibuf[2] & 0xC0) >> 6));
 
336
    obuf[3] = (unsigned char)   (ibuf[2] & 0x3F);
 
337
 
 
338
    switch(inputparts) {
 
339
    case 1: /* only one byte read */
 
340
      snprintf(output, 5, "%c%c==",
 
341
               table64[obuf[0]],
 
342
               table64[obuf[1]]);
 
343
      break;
 
344
    case 2: /* two bytes read */
 
345
      snprintf(output, 5, "%c%c%c=",
 
346
               table64[obuf[0]],
 
347
               table64[obuf[1]],
 
348
               table64[obuf[2]]);
 
349
      break;
 
350
    default:
 
351
      snprintf(output, 5, "%c%c%c%c",
 
352
               table64[obuf[0]],
 
353
               table64[obuf[1]],
 
354
               table64[obuf[2]],
 
355
               table64[obuf[3]] );
 
356
      break;
 
357
    }
 
358
    output += 4;
 
359
  }
 
360
  *output=0;
 
361
  *outptr = base64data; /* make it return the actual data memory */
 
362
 
 
363
  return strlen(base64data); /* return the length of the new data */
 
364
}
 
365
/* ---- End of Base64 Encoding ---- */
 
366
 
 
367
LIBSSH2_API void
 
368
libssh2_free(LIBSSH2_SESSION *session, void *ptr)
 
369
{
 
370
    LIBSSH2_FREE(session, ptr);
 
371
}
 
372
 
 
373
#ifdef LIBSSH2DEBUG
 
374
LIBSSH2_API int
 
375
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
 
376
{
 
377
    session->showmask = bitmask;
 
378
    return 0;
 
379
}
 
380
 
 
381
LIBSSH2_API int
 
382
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
 
383
                         libssh2_trace_handler_func callback)
 
384
{
 
385
    session->tracehandler = callback;
 
386
    session->tracehandler_context = handler_context;
 
387
    return 0;
 
388
}
 
389
 
 
390
void
 
391
_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
 
392
{
 
393
    char buffer[1536];
 
394
    int len, msglen, buflen = sizeof(buffer);
 
395
    va_list vargs;
 
396
    struct timeval now;
 
397
    static int firstsec;
 
398
    static const char *const contexts[] = {
 
399
        "Unknown",
 
400
        "Transport",
 
401
        "Key Ex",
 
402
        "Userauth",
 
403
        "Conn",
 
404
        "SCP",
 
405
        "SFTP",
 
406
        "Failure Event",
 
407
        "Publickey",
 
408
        "Socket",
 
409
    };
 
410
    const char* contexttext = contexts[0];
 
411
    unsigned int contextindex;
 
412
 
 
413
    if (!(session->showmask & context)) {
 
414
        /* no such output asked for */
 
415
        return;
 
416
    }
 
417
 
 
418
    /* Find the first matching context string for this message */
 
419
    for (contextindex = 0; contextindex < ARRAY_SIZE(contexts);
 
420
         contextindex++) {
 
421
        if ((context & (1 << contextindex)) != 0) {
 
422
            contexttext = contexts[contextindex];
 
423
            break;
 
424
        }
 
425
    }
 
426
 
 
427
    _libssh2_gettimeofday(&now, NULL);
 
428
    if(!firstsec) {
 
429
        firstsec = now.tv_sec;
 
430
    }
 
431
    now.tv_sec -= firstsec;
 
432
 
 
433
    len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ",
 
434
                   (int)now.tv_sec, (int)now.tv_usec, contexttext);
 
435
 
 
436
    if (len >= buflen)
 
437
        msglen = buflen - 1;
 
438
    else {
 
439
        buflen -= len;
 
440
        msglen = len;
 
441
        va_start(vargs, format);
 
442
        len = vsnprintf(buffer + msglen, buflen, format, vargs);
 
443
        va_end(vargs);
 
444
        msglen += len < buflen ? len : buflen - 1;
 
445
    }
 
446
 
 
447
    if (session->tracehandler)
 
448
        (session->tracehandler)(session, session->tracehandler_context, buffer,
 
449
                                msglen);
 
450
    else
 
451
        fprintf(stderr, "%s\n", buffer);
 
452
}
 
453
 
 
454
#else
 
455
LIBSSH2_API int
 
456
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
 
457
{
 
458
    (void) session;
 
459
    (void) bitmask;
 
460
    return 0;
 
461
}
 
462
 
 
463
LIBSSH2_API int
 
464
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
 
465
                         libssh2_trace_handler_func callback)
 
466
{
 
467
    (void) session;
 
468
    (void) handler_context;
 
469
    (void) callback;
 
470
    return 0;
 
471
}
 
472
#endif
 
473
 
 
474
/* init the list head */
 
475
void _libssh2_list_init(struct list_head *head)
 
476
{
 
477
    head->first = head->last = NULL;
 
478
}
 
479
 
 
480
/* add a node to the list */
 
481
void _libssh2_list_add(struct list_head *head,
 
482
                       struct list_node *entry)
 
483
{
 
484
    /* store a pointer to the head */
 
485
    entry->head = head;
 
486
 
 
487
    /* we add this entry at the "top" so it has no next */
 
488
    entry->next = NULL;
 
489
 
 
490
    /* make our prev point to what the head thinks is last */
 
491
    entry->prev = head->last;
 
492
 
 
493
    /* and make head's last be us now */
 
494
    head->last = entry;
 
495
 
 
496
    /* make sure our 'prev' node points to us next */
 
497
    if(entry->prev)
 
498
        entry->prev->next = entry;
 
499
    else
 
500
        head->first = entry;
 
501
}
 
502
 
 
503
/* return the "first" node in the list this head points to */
 
504
void *_libssh2_list_first(struct list_head *head)
 
505
{
 
506
    return head->first;
 
507
}
 
508
 
 
509
/* return the next node in the list */
 
510
void *_libssh2_list_next(struct list_node *node)
 
511
{
 
512
    return node->next;
 
513
}
 
514
 
 
515
/* return the prev node in the list */
 
516
void *_libssh2_list_prev(struct list_node *node)
 
517
{
 
518
    return node->prev;
 
519
}
 
520
 
 
521
/* remove this node from the list */
 
522
void _libssh2_list_remove(struct list_node *entry)
 
523
{
 
524
    if(entry->prev)
 
525
        entry->prev->next = entry->next;
 
526
    else
 
527
        entry->head->first = entry->next;
 
528
 
 
529
    if(entry->next)
 
530
        entry->next->prev = entry->prev;
 
531
    else
 
532
        entry->head->last = entry->prev;
 
533
}
 
534
 
 
535
#if 0
 
536
/* insert a node before the given 'after' entry */
 
537
void _libssh2_list_insert(struct list_node *after, /* insert before this */
 
538
                          struct list_node *entry)
 
539
{
 
540
    /* 'after' is next to 'entry' */
 
541
    bentry->next = after;
 
542
 
 
543
    /* entry's prev is then made to be the prev after current has */
 
544
    entry->prev = after->prev;
 
545
 
 
546
    /* the node that is now before 'entry' was previously before 'after'
 
547
       and must be made to point to 'entry' correctly */
 
548
    if(entry->prev)
 
549
        entry->prev->next = entry;
 
550
    else
 
551
      /* there was no node before this, so we make sure we point the head
 
552
         pointer to this node */
 
553
      after->head->first = entry;
 
554
 
 
555
    /* after's prev entry points back to entry */
 
556
    after->prev = entry;
 
557
 
 
558
    /* after's next entry is still the same as before */
 
559
 
 
560
    /* entry's head is the same as after's */
 
561
    entry->head = after->head;
 
562
}
 
563
 
 
564
#endif
 
565
 
 
566
/* this define is defined in misc.h for the correct platforms */
 
567
#ifdef LIBSSH2_GETTIMEOFDAY_WIN32
 
568
/*
 
569
 * gettimeofday
 
570
 * Implementation according to:
 
571
 * The Open Group Base Specifications Issue 6
 
572
 * IEEE Std 1003.1, 2004 Edition
 
573
 */
 
574
 
 
575
/*
 
576
 *  THIS SOFTWARE IS NOT COPYRIGHTED
 
577
 *
 
578
 *  This source code is offered for use in the public domain. You may
 
579
 *  use, modify or distribute it freely.
 
580
 *
 
581
 *  This code is distributed in the hope that it will be useful but
 
582
 *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
 
583
 *  DISCLAIMED. This includes but is not limited to warranties of
 
584
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
585
 *
 
586
 *  Contributed by:
 
587
 *  Danny Smith <dannysmith@users.sourceforge.net>
 
588
 */
 
589
 
 
590
/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
 
591
#define _W32_FT_OFFSET (116444736000000000)
 
592
 
 
593
int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp)
 
594
 {
 
595
  union {
 
596
    unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
 
597
    FILETIME ft;
 
598
  }  _now;
 
599
 
 
600
  if(tp)
 
601
    {
 
602
      GetSystemTimeAsFileTime (&_now.ft);
 
603
      tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 );
 
604
      tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
 
605
    }
 
606
  /* Always return 0 as per Open Group Base Specifications Issue 6.
 
607
     Do not set errno on error.  */
 
608
  return 0;
 
609
}
 
610
 
 
611
 
 
612
#endif