Extending test-client-custom-summary to try e_book_client_get_contacts_uids()
[platform/upstream/evolution-data-server.git] / camel / camel-file-utils.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2  *
3  * Authors:
4  *   Michael Zucchi <notzed@ximian.com>
5  *   Jeffrey Stedfast <fejj@ximian.com>
6  *   Dan Winship <danw@ximian.com>
7  *
8  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of version 2 of the GNU Lesser General Public
12  * License as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
22  * USA
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35
36 #include <glib/gi18n-lib.h>
37
38 #include "camel-file-utils.h"
39 #include "camel-object.h"
40 #include "camel-operation.h"
41 #include "camel-url.h"
42
43 #ifdef G_OS_WIN32
44 #include <winsock2.h>
45 #define EWOULDBLOCK EAGAIN
46 #endif
47
48 #define IO_TIMEOUT (60*4)
49
50 /**
51  * camel_file_util_encode_uint32:
52  * @out: file to output to
53  * @value: value to output
54  *
55  * Utility function to save an uint32 to a file.
56  *
57  * Returns: %0 on success, %-1 on error.
58  **/
59 gint
60 camel_file_util_encode_uint32 (FILE *out,
61                                guint32 value)
62 {
63         gint i;
64
65         for (i = 28; i > 0; i -= 7) {
66                 if (value >= (1 << i)) {
67                         guint c = (value >> i) & 0x7f;
68                         if (fputc (c, out) == -1)
69                                 return -1;
70                 }
71         }
72         return fputc (value | 0x80, out);
73 }
74
75 /**
76  * camel_file_util_decode_uint32:
77  * @in: file to read from
78  * @dest: pointer to a variable to store the value in
79  *
80  * Retrieve an encoded uint32 from a file.
81  *
82  * Returns: %0 on success, %-1 on error.  @*dest will contain the
83  * decoded value.
84  **/
85 gint
86 camel_file_util_decode_uint32 (FILE *in,
87                                guint32 *dest)
88 {
89         guint32 value = 0;
90         gint v;
91
92         /* until we get the last byte, keep decoding 7 bits at a time */
93         while ( ((v = fgetc (in)) & 0x80) == 0 && v != EOF) {
94                 value |= v;
95                 value <<= 7;
96         }
97         if (v == EOF) {
98                 *dest = value >> 7;
99                 return -1;
100         }
101         *dest = value | (v & 0x7f);
102
103         return 0;
104 }
105
106 /**
107  * camel_file_util_encode_fixed_int32:
108  * @out: file to output to
109  * @value: value to output
110  *
111  * Encode a gint32, performing no compression, but converting
112  * to network order.
113  *
114  * Returns: %0 on success, %-1 on error.
115  **/
116 gint
117 camel_file_util_encode_fixed_int32 (FILE *out,
118                                     gint32 value)
119 {
120         guint32 save;
121
122         save = g_htonl (value);
123         if (fwrite (&save, sizeof (save), 1, out) != 1)
124                 return -1;
125         return 0;
126 }
127
128 /**
129  * camel_file_util_decode_fixed_int32:
130  * @in: file to read from
131  * @dest: pointer to a variable to store the value in
132  *
133  * Retrieve a gint32.
134  *
135  * Returns: %0 on success, %-1 on error.
136  **/
137 gint
138 camel_file_util_decode_fixed_int32 (FILE *in,
139                                     gint32 *dest)
140 {
141         guint32 save;
142
143         if (fread (&save, sizeof (save), 1, in) == 1) {
144                 *dest = g_ntohl (save);
145                 return 0;
146         } else {
147                 return -1;
148         }
149 }
150
151 #define CFU_ENCODE_T(type)                                              \
152 gint                                                                    \
153 camel_file_util_encode_##type (FILE *out, type value)                   \
154 {                                                                       \
155         gint i;                                                         \
156                                                                         \
157         for (i = sizeof (type) - 1; i >= 0; i--) {                      \
158                 if (fputc ((value >> (i * 8)) & 0xff, out) == -1)       \
159                         return -1;                                      \
160         }                                                               \
161         return 0;                                                       \
162 }
163
164 #define CFU_DECODE_T(type)                              \
165 gint                                                    \
166 camel_file_util_decode_##type (FILE *in, type *dest)    \
167 {                                                       \
168         type save = 0;                                  \
169         gint i = sizeof (type) - 1;                     \
170         gint v = EOF;                                   \
171                                                         \
172         while (i >= 0 && (v = fgetc (in)) != EOF) {     \
173                 save |= ((type) v) << (i * 8);          \
174                 i--;                                    \
175         }                                               \
176         *dest = save;                                   \
177         if (v == EOF)                                   \
178                 return -1;                              \
179         return 0;                                       \
180 }
181
182 /**
183  * camel_file_util_encode_time_t:
184  * @out: file to output to
185  * @value: value to output
186  *
187  * Encode a time_t value to the file.
188  *
189  * Returns: %0 on success, %-1 on error.
190  **/
191 CFU_ENCODE_T (time_t)
192
193 /**
194  * camel_file_util_decode_time_t:
195  * @in: file to read from
196  * @dest: pointer to a variable to store the value in
197  *
198  * Decode a time_t value.
199  *
200  * Returns: %0 on success, %-1 on error.
201  **/
202 CFU_DECODE_T (time_t)
203
204 /**
205  * camel_file_util_encode_off_t:
206  * @out: file to output to
207  * @value: value to output
208  *
209  * Encode an off_t type.
210  *
211  * Returns: %0 on success, %-1 on error.
212  **/
213 CFU_ENCODE_T (off_t)
214
215 /**
216  * camel_file_util_decode_off_t:
217  * @in: file to read from
218  * @dest: pointer to a variable to put the value in
219  *
220  * Decode an off_t type.
221  *
222  * Returns: %0 on success, %-1 on failure.
223  **/
224 CFU_DECODE_T (off_t)
225
226 /**
227  * camel_file_util_encode_gsize:
228  * @out: file to output to
229  * @value: value to output
230  *
231  * Encode an gsize type.
232  *
233  * Returns: %0 on success, %-1 on error.
234  **/
235 CFU_ENCODE_T (gsize)
236
237 /**
238  * camel_file_util_decode_gsize:
239  * @in: file to read from
240  * @dest: pointer to a variable to put the value in
241  *
242  * Decode an gsize type.
243  *
244  * Returns: %0 on success, %-1 on failure.
245  **/
246 CFU_DECODE_T (gsize)
247
248 /**
249  * camel_file_util_encode_string:
250  * @out: file to output to
251  * @str: value to output
252  *
253  * Encode a normal string and save it in the output file.
254  *
255  * Returns: %0 on success, %-1 on error.
256  **/
257 gint
258 camel_file_util_encode_string (FILE *out,
259                                const gchar *str)
260 {
261         register gint len;
262
263         if (str == NULL)
264                 return camel_file_util_encode_uint32 (out, 1);
265
266         if ((len = strlen (str)) > 65536)
267                 len = 65536;
268
269         if (camel_file_util_encode_uint32 (out, len + 1) == -1)
270                 return -1;
271         if (len == 0 || fwrite (str, len, 1, out) == 1)
272                 return 0;
273         return -1;
274 }
275
276 /**
277  * camel_file_util_decode_string:
278  * @in: file to read from
279  * @str: pointer to a variable to store the value in
280  *
281  * Decode a normal string from the input file.
282  *
283  * Returns: %0 on success, %-1 on error.
284  **/
285 gint
286 camel_file_util_decode_string (FILE *in,
287                                gchar **str)
288 {
289         guint32 len;
290         register gchar *ret;
291
292         if (camel_file_util_decode_uint32 (in, &len) == -1) {
293                 *str = NULL;
294                 return -1;
295         }
296
297         len--;
298         if (len > 65536) {
299                 *str = NULL;
300                 return -1;
301         }
302
303         ret = g_malloc (len + 1);
304         if (len > 0 && fread (ret, len, 1, in) != 1) {
305                 g_free (ret);
306                 *str = NULL;
307                 return -1;
308         }
309
310         ret[len] = 0;
311         *str = ret;
312         return 0;
313 }
314
315 /**
316  * camel_file_util_encode_fixed_string:
317  * @out: file to output to
318  * @str: value to output
319  * @len: total-len of str to store
320  *
321  * Encode a normal string and save it in the output file.
322  * Unlike @camel_file_util_encode_string, it pads the
323  * @str with "NULL" bytes, if @len is > strlen(str)
324  *
325  * Returns: %0 on success, %-1 on error.
326  **/
327 gint
328 camel_file_util_encode_fixed_string (FILE *out,
329                                      const gchar *str,
330                                      gsize len)
331 {
332         gint retval = -1;
333
334         /* Max size is 64K */
335         if (len > 65536)
336                 len = 65536;
337
338         /* Don't allow empty strings to be written. */
339         if (len > 0) {
340                 gchar *buf;
341
342                 buf = g_malloc0 (len);
343                 g_strlcpy (buf, str, len);
344
345                 if (fwrite (buf, len, 1, out) == len)
346                         retval = 0;
347
348                 g_free (buf);
349         }
350
351         return retval;
352 }
353
354 /**
355  * camel_file_util_decode_fixed_string:
356  * @in: file to read from
357  * @str: pointer to a variable to store the value in
358  * @len: total-len to decode.
359  *
360  * Decode a normal string from the input file.
361  *
362  * Returns: %0 on success, %-1 on error.
363  **/
364 gint
365 camel_file_util_decode_fixed_string (FILE *in,
366                                      gchar **str,
367                                      gsize len)
368 {
369         register gchar *ret;
370
371         if (len > 65536) {
372                 *str = NULL;
373                 return -1;
374         }
375
376         ret = g_malloc (len + 1);
377         if (len > 0 && fread (ret, len, 1, in) != 1) {
378                 g_free (ret);
379                 *str = NULL;
380                 return -1;
381         }
382
383         ret[len] = 0;
384         *str = ret;
385         return 0;
386 }
387
388 /**
389  * camel_file_util_safe_filename:
390  * @name: string to 'flattened' into a safe filename
391  *
392  * 'Flattens' @name into a safe filename string by hex encoding any
393  * chars that may cause problems on the filesystem.
394  *
395  * Returns: a safe filename string.
396  **/
397 gchar *
398 camel_file_util_safe_filename (const gchar *name)
399 {
400 #ifdef G_OS_WIN32
401         const gchar *unsafe_chars = "/?()'*<>:\"\\|";
402 #else
403         const gchar *unsafe_chars = "/?()'*";
404 #endif
405
406         if (name == NULL)
407                 return NULL;
408
409         return camel_url_encode (name, unsafe_chars);
410 }
411
412 /* FIXME: poll() might be more efficient and more portable? */
413
414 /**
415  * camel_read:
416  * @fd: file descriptor
417  * @buf: buffer to fill
418  * @n: number of bytes to read into @buf
419  * @cancellable: optional #GCancellable object, or %NULL
420  * @error: return location for a #GError, or %NULL
421  *
422  * Cancellable libc read() replacement.
423  *
424  * Code that intends to be portable to Win32 should call this function
425  * only on file descriptors returned from open(), not on sockets.
426  *
427  * Returns: number of bytes read or -1 on fail. On failure, errno will
428  * be set appropriately.
429  **/
430 gssize
431 camel_read (gint fd,
432             gchar *buf,
433             gsize n,
434             GCancellable *cancellable,
435             GError **error)
436 {
437         gssize nread;
438         gint cancel_fd;
439
440         if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
441                 errno = EINTR;
442                 return -1;
443         }
444
445         cancel_fd = g_cancellable_get_fd (cancellable);
446
447         if (cancel_fd == -1) {
448                 do {
449                         nread = read (fd, buf, n);
450                 } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
451         } else {
452 #ifndef G_OS_WIN32
453                 gint errnosav, flags, fdmax;
454                 fd_set rdset;
455
456                 flags = fcntl (fd, F_GETFL);
457                 fcntl (fd, F_SETFL, flags | O_NONBLOCK);
458
459                 do {
460                         struct timeval tv;
461                         gint res;
462
463                         FD_ZERO (&rdset);
464                         FD_SET (fd, &rdset);
465                         FD_SET (cancel_fd, &rdset);
466                         fdmax = MAX (fd, cancel_fd) + 1;
467                         tv.tv_sec = IO_TIMEOUT;
468                         tv.tv_usec = 0;
469                         nread = -1;
470
471                         res = select (fdmax, &rdset, 0, 0, &tv);
472                         if (res == -1)
473                                 ;
474                         else if (res == 0)
475                                 errno = ETIMEDOUT;
476                         else if (FD_ISSET (cancel_fd, &rdset)) {
477                                 errno = EINTR;
478                                 goto failed;
479                         } else {
480                                 do {
481                                         nread = read (fd, buf, n);
482                                 } while (nread == -1 && errno == EINTR);
483                         }
484                 } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
485         failed:
486                 errnosav = errno;
487                 fcntl (fd, F_SETFL, flags);
488                 errno = errnosav;
489 #endif
490         }
491
492         g_cancellable_release_fd (cancellable);
493
494         if (g_cancellable_set_error_if_cancelled (cancellable, error))
495                 return -1;
496
497         if (nread == -1)
498                 g_set_error (
499                         error, G_IO_ERROR,
500                         g_io_error_from_errno (errno),
501                         "%s", g_strerror (errno));
502
503         return nread;
504 }
505
506 /**
507  * camel_write:
508  * @fd: file descriptor
509  * @buf: buffer to write
510  * @n: number of bytes of @buf to write
511  * @cancellable: optional #GCancellable object, or %NULL
512  * @error: return location for a #GError, or %NULL
513  *
514  * Cancellable libc write() replacement.
515  *
516  * Code that intends to be portable to Win32 should call this function
517  * only on file descriptors returned from open(), not on sockets.
518  *
519  * Returns: number of bytes written or -1 on fail. On failure, errno will
520  * be set appropriately.
521  **/
522 gssize
523 camel_write (gint fd,
524              const gchar *buf,
525              gsize n,
526              GCancellable *cancellable,
527              GError **error)
528 {
529         gssize w, written = 0;
530         gint cancel_fd;
531
532         if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
533                 errno = EINTR;
534                 return -1;
535         }
536
537         cancel_fd = g_cancellable_get_fd (cancellable);
538
539         if (cancel_fd == -1) {
540                 do {
541                         do {
542                                 w = write (fd, buf + written, n - written);
543                         } while (w == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
544                         if (w > 0)
545                                 written += w;
546                 } while (w != -1 && written < n);
547         } else {
548 #ifndef G_OS_WIN32
549                 gint errnosav, flags, fdmax;
550                 fd_set rdset, wrset;
551
552                 flags = fcntl (fd, F_GETFL);
553                 fcntl (fd, F_SETFL, flags | O_NONBLOCK);
554
555                 fdmax = MAX (fd, cancel_fd) + 1;
556                 do {
557                         struct timeval tv;
558                         gint res;
559
560                         FD_ZERO (&rdset);
561                         FD_ZERO (&wrset);
562                         FD_SET (fd, &wrset);
563                         FD_SET (cancel_fd, &rdset);
564                         tv.tv_sec = IO_TIMEOUT;
565                         tv.tv_usec = 0;
566                         w = -1;
567
568                         res = select (fdmax, &rdset, &wrset, 0, &tv);
569                         if (res == -1) {
570                                 if (errno == EINTR)
571                                         w = 0;
572                         } else if (res == 0)
573                                 errno = ETIMEDOUT;
574                         else if (FD_ISSET (cancel_fd, &rdset))
575                                 errno = EINTR;
576                         else {
577                                 do {
578                                         w = write (fd, buf + written, n - written);
579                                 } while (w == -1 && errno == EINTR);
580
581                                 if (w == -1) {
582                                         if (errno == EAGAIN || errno == EWOULDBLOCK)
583                                                 w = 0;
584                                 } else
585                                         written += w;
586                         }
587                 } while (w != -1 && written < n);
588
589                 errnosav = errno;
590                 fcntl (fd, F_SETFL, flags);
591                 errno = errnosav;
592 #endif
593         }
594
595         g_cancellable_release_fd (cancellable);
596
597         if (g_cancellable_set_error_if_cancelled (cancellable, error))
598                 return -1;
599
600         if (w == -1) {
601                 g_set_error (
602                         error, G_IO_ERROR,
603                         g_io_error_from_errno (errno),
604                         "%s", g_strerror (errno));
605                 return -1;
606         }
607
608         return written;
609 }
610
611 /**
612  * camel_read_socket:
613  * @fd: a socket
614  * @buf: buffer to fill
615  * @n: number of bytes to read into @buf
616  * @cancellable: optional #GCancellable object, or %NULL
617  * @error: return location for a #GError, or %NULL
618  *
619  * Cancellable read() replacement for sockets. Code that intends to be
620  * portable to Win32 should call this function only on sockets
621  * returned from socket(), or accept().
622  *
623  * Returns: number of bytes read or -1 on fail. On failure, errno will
624  * be set appropriately. If the socket is nonblocking
625  * camel_read_socket() will retry the read until it gets something.
626  **/
627 gssize
628 camel_read_socket (gint fd,
629                    gchar *buf,
630                    gsize n,
631                    GCancellable *cancellable,
632                    GError **error)
633 {
634 #ifndef G_OS_WIN32
635         return camel_read (fd, buf, n, cancellable, error);
636 #else
637         gssize nread;
638         gint cancel_fd;
639
640         if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
641                 errno = EINTR;
642                 return -1;
643         }
644
645         cancel_fd = g_cancellable_get_fd (cancellable);
646
647         if (cancel_fd == -1) {
648                 do {
649                         nread = recv (fd, buf, n, 0);
650                 } while (nread == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK);
651         } else {
652                 gint fdmax;
653                 fd_set rdset;
654                 u_long yes = 1;
655
656                 ioctlsocket (fd, FIONBIO, &yes);
657                 fdmax = MAX (fd, cancel_fd) + 1;
658                 do {
659                         struct timeval tv;
660                         gint res;
661
662                         FD_ZERO (&rdset);
663                         FD_SET (fd, &rdset);
664                         FD_SET (cancel_fd, &rdset);
665                         tv.tv_sec = IO_TIMEOUT;
666                         tv.tv_usec = 0;
667                         nread = -1;
668
669                         res = select (fdmax, &rdset, 0, 0, &tv);
670                         if (res == -1)
671                                 ;
672                         else if (res == 0)
673                                 errno = EAGAIN;
674                         else if (FD_ISSET (cancel_fd, &rdset)) {
675                                 errno = EINTR;
676                                 goto failed;
677                         } else {
678                                 nread = recv (fd, buf, n, 0);
679                         }
680                 } while (nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK);
681         failed:
682                 ;
683         }
684
685         g_cancellable_release_fd (cancellable);
686
687         if (g_cancellable_set_error_if_cancelled (cancellable, error))
688                 return -1;
689
690         if (nread == -1)
691                 g_set_error (
692                         error, G_IO_ERROR,
693                         g_io_error_from_errno (errno),
694                         "%s", g_strerror (errno));
695
696         return nread;
697 #endif
698 }
699
700 /**
701  * camel_write_socket:
702  * @fd: file descriptor
703  * @buf: buffer to write
704  * @n: number of bytes of @buf to write
705  * @error: return location for a #GError, or %NULL
706  *
707  * Cancellable write() replacement for sockets. Code that intends to
708  * be portable to Win32 should call this function only on sockets
709  * returned from socket() or accept().
710  *
711  * Returns: number of bytes written or -1 on fail. On failure, errno will
712  * be set appropriately.
713  **/
714 gssize
715 camel_write_socket (gint fd,
716                     const gchar *buf,
717                     gsize n,
718                     GCancellable *cancellable,
719                     GError **error)
720 {
721 #ifndef G_OS_WIN32
722         return camel_write (fd, buf, n, cancellable, error);
723 #else
724         gssize w, written = 0;
725         gint cancel_fd;
726
727         if (g_cancellable_is_cancelled (cancellable)) {
728                 errno = EINTR;
729                 g_set_error (
730                         error, G_IO_ERROR,
731                         G_IO_ERROR_CANCELLED,
732                         _("Canceled"));
733                 return -1;
734         }
735
736         cancel_fd = g_cancellable_get_fd (cancellable);
737
738         if (cancel_fd == -1) {
739                 do {
740                         do {
741                                 w = send (fd, buf + written, n - written, 0);
742                         } while (w == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK);
743                         if (w > 0)
744                                 written += w;
745                 } while (w != -1 && written < n);
746         } else {
747                 gint fdmax;
748                 fd_set rdset, wrset;
749                 u_long arg = 1;
750
751                 ioctlsocket (fd, FIONBIO, &arg);
752                 fdmax = MAX (fd, cancel_fd) + 1;
753                 do {
754                         struct timeval tv;
755                         gint res;
756
757                         FD_ZERO (&rdset);
758                         FD_ZERO (&wrset);
759                         FD_SET (fd, &wrset);
760                         FD_SET (cancel_fd, &rdset);
761                         tv.tv_sec = IO_TIMEOUT;
762                         tv.tv_usec = 0;
763                         w = -1;
764
765                         res = select (fdmax, &rdset, &wrset, 0, &tv);
766                         if (res == SOCKET_ERROR) {
767                                 /* w still being -1 will catch this */
768                         } else if (res == 0)
769                                 errno = EAGAIN;
770                         else if (FD_ISSET (cancel_fd, &rdset))
771                                 errno = EINTR;
772                         else {
773                                 w = send (fd, buf + written, n - written, 0);
774                                 if (w == SOCKET_ERROR) {
775                                         if (WSAGetLastError () == WSAEWOULDBLOCK)
776                                                 w = 0;
777                                 } else
778                                         written += w;
779                         }
780                 } while (w != -1 && written < n);
781                 arg = 0;
782                 ioctlsocket (fd, FIONBIO, &arg);
783         }
784
785         g_cancellable_release_fd (cancellable);
786
787         if (g_cancellable_set_error_if_cancelled (cancellable, error))
788                 return -1;
789
790         if (w == -1) {
791                 g_set_error (
792                         error, G_IO_ERROR,
793                         g_io_error_from_errno (errno),
794                         "%s", g_strerror (errno));
795                 return -1;
796         }
797
798         return written;
799 #endif
800 }
801
802 /**
803  * camel_file_util_savename:
804  * @filename: a pathname
805  *
806  * Builds a pathname where the basename is of the form ".#" + the
807  * basename of @filename, for instance used in a two-stage commit file
808  * write.
809  *
810  * Returns: The new pathname.  It must be free'd with g_free().
811  **/
812 gchar *
813 camel_file_util_savename (const gchar *filename)
814 {
815         gchar *dirname, *retval;
816
817         dirname = g_path_get_dirname (filename);
818
819         if (strcmp (dirname, ".") == 0) {
820                 retval = g_strconcat (".#", filename, NULL);
821         } else {
822                 gchar *basename = g_path_get_basename (filename);
823                 gchar *newbasename = g_strconcat (".#", basename, NULL);
824
825                 retval = g_build_filename (dirname, newbasename, NULL);
826
827                 g_free (newbasename);
828                 g_free (basename);
829         }
830         g_free (dirname);
831
832         return retval;
833 }