~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to app/config/gimpconfigwriter.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
2
 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
 
 *
4
 
 * GimpConfigWriter
5
 
 * Copyright (C) 2003  Sven Neumann <sven@gimp.org>
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; either version 2 of the License, or
10
 
 * (at your option) any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
 
 */
21
 
 
22
 
#include "config.h"
23
 
 
24
 
#include <errno.h>
25
 
#include <fcntl.h>
26
 
#include <stdio.h>
27
 
#include <string.h>
28
 
#ifdef HAVE_UNISTD_H
29
 
#include <unistd.h>
30
 
#endif
31
 
#include <sys/types.h>
32
 
#include <sys/stat.h>
33
 
 
34
 
#include <glib-object.h>
35
 
 
36
 
#ifdef G_OS_WIN32
37
 
#include <io.h>
38
 
#endif
39
 
 
40
 
#include "libgimpbase/gimpbase.h"
41
 
 
42
 
#include "config-types.h"
43
 
 
44
 
#include "gimpconfig-error.h"
45
 
#include "gimpconfig-serialize.h"
46
 
#include "gimpconfig-utils.h"
47
 
#include "gimpconfigwriter.h"
48
 
 
49
 
#include "gimp-intl.h"
50
 
 
51
 
 
52
 
struct _GimpConfigWriter
53
 
{
54
 
  gint      fd;
55
 
  gchar    *filename;
56
 
  gchar    *tmpname;
57
 
  GError   *error;
58
 
  GString  *buffer;
59
 
  gboolean  comment;
60
 
  gint      depth;
61
 
  gint      marker;
62
 
};
63
 
 
64
 
 
65
 
static inline void  gimp_config_writer_flush      (GimpConfigWriter  *writer);
66
 
static inline void  gimp_config_writer_newline    (GimpConfigWriter  *writer);
67
 
static gboolean     gimp_config_writer_close_file (GimpConfigWriter  *writer,
68
 
                                                   GError           **error);
69
 
 
70
 
static inline void
71
 
gimp_config_writer_flush (GimpConfigWriter *writer)
72
 
{
73
 
  if (write (writer->fd, writer->buffer->str, writer->buffer->len) < 0)
74
 
    g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
75
 
                 g_strerror (errno));
76
 
 
77
 
  g_string_truncate (writer->buffer, 0);
78
 
}
79
 
 
80
 
static inline void
81
 
gimp_config_writer_newline (GimpConfigWriter *writer)
82
 
{
83
 
  gint i;
84
 
 
85
 
  g_string_append_c (writer->buffer, '\n');
86
 
 
87
 
  if (writer->comment)
88
 
    g_string_append_len (writer->buffer, "# ", 2);
89
 
 
90
 
  for (i = 0; i < writer->depth; i++)
91
 
    g_string_append_len (writer->buffer, "    ", 4);
92
 
}
93
 
 
94
 
/**
95
 
 * gimp_config_writer_new_file:
96
 
 * @filename: a filename
97
 
 * @atomic: if %TRUE the file is written atomically
98
 
 * @header: text to include as comment at the top of the file
99
 
 * @error: return location for errors
100
 
 *
101
 
 * Creates a new #GimpConfigWriter and sets it up to write to
102
 
 * @filename. If @atomic is %TRUE, a temporary file is used to avoid
103
 
 * possible race conditions. The temporary file is then moved to
104
 
 * @filename when the writer is closed.
105
 
 *
106
 
 * Return value: a new #GimpConfigWriter or %NULL in case of an error
107
 
 **/
108
 
GimpConfigWriter *
109
 
gimp_config_writer_new_file (const gchar  *filename,
110
 
                             gboolean      atomic,
111
 
                             const gchar  *header,
112
 
                             GError      **error)
113
 
{
114
 
  GimpConfigWriter *writer;
115
 
  gchar            *tmpname = NULL;
116
 
  gint              fd;
117
 
 
118
 
  g_return_val_if_fail (filename != NULL, NULL);
119
 
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
120
 
 
121
 
  if (atomic)
122
 
    {
123
 
      tmpname = g_strconcat (filename, "XXXXXX", NULL);
124
 
 
125
 
      fd = g_mkstemp (tmpname);
126
 
 
127
 
      if (fd == -1)
128
 
        {
129
 
          g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
130
 
                       _("Could not create temporary file for '%s': %s"),
131
 
                       gimp_filename_to_utf8 (filename), g_strerror (errno));
132
 
          g_free (tmpname);
133
 
          return NULL;
134
 
        }
135
 
    }
136
 
  else
137
 
    {
138
 
      fd = creat (filename, 0644);
139
 
 
140
 
      if (fd == -1)
141
 
        {
142
 
          g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
143
 
                       _("Could not open '%s' for writing: %s"),
144
 
                       gimp_filename_to_utf8 (filename), g_strerror (errno));
145
 
          return NULL;
146
 
        }
147
 
    }
148
 
 
149
 
  writer = g_new0 (GimpConfigWriter, 1);
150
 
 
151
 
  writer->fd       = fd;
152
 
  writer->filename = g_strdup (filename);
153
 
  writer->tmpname  = tmpname;
154
 
  writer->buffer   = g_string_new (NULL);
155
 
 
156
 
  if (header)
157
 
    {
158
 
      gimp_config_writer_comment (writer, header);
159
 
      gimp_config_writer_linefeed (writer);
160
 
    }
161
 
 
162
 
  return writer;
163
 
}
164
 
 
165
 
GimpConfigWriter *
166
 
gimp_config_writer_new_fd (gint fd)
167
 
{
168
 
  GimpConfigWriter *writer;
169
 
 
170
 
  g_return_val_if_fail (fd > 0, NULL);
171
 
 
172
 
  writer = g_new0 (GimpConfigWriter, 1);
173
 
 
174
 
  writer->fd     = fd;
175
 
  writer->buffer = g_string_new (NULL);
176
 
 
177
 
  return writer;
178
 
}
179
 
 
180
 
GimpConfigWriter *
181
 
gimp_config_writer_new_string (GString *string)
182
 
{
183
 
  GimpConfigWriter *writer;
184
 
 
185
 
  g_return_val_if_fail (string != NULL, NULL);
186
 
 
187
 
  writer = g_new0 (GimpConfigWriter, 1);
188
 
 
189
 
  writer->buffer = string;
190
 
 
191
 
  return writer;
192
 
}
193
 
 
194
 
/**
195
 
 * gimp_config_writer_comment_mode:
196
 
 * @writer: a #GimpConfigWriter
197
 
 * @enable: %TRUE to enable comment mode, %FALSE to disable it
198
 
 *
199
 
 * This function toggles whether the @writer should create commented
200
 
 * or uncommented output. This feature is used to generate the
201
 
 * system-wide installed gimprc that documents the default settings.
202
 
 *
203
 
 * Since comments have to start at the beginning of a line, this
204
 
 * funtion will insert a newline if necessary.
205
 
 **/
206
 
void
207
 
gimp_config_writer_comment_mode (GimpConfigWriter *writer,
208
 
                                 gboolean          enable)
209
 
{
210
 
  g_return_if_fail (writer != NULL);
211
 
 
212
 
  if (writer->error)
213
 
    return;
214
 
 
215
 
  enable = (enable ? TRUE : FALSE);
216
 
 
217
 
  if (writer->comment == enable)
218
 
    return;
219
 
 
220
 
  writer->comment = enable;
221
 
 
222
 
  if (enable)
223
 
    {
224
 
     if (writer->buffer->len == 0)
225
 
       g_string_append_len (writer->buffer, "# ", 2);
226
 
     else
227
 
       gimp_config_writer_newline (writer);
228
 
    }
229
 
}
230
 
 
231
 
 
232
 
/**
233
 
 * gimp_config_writer_open:
234
 
 * @writer: a #GimpConfigWriter
235
 
 * @name: name of the element to open
236
 
 *
237
 
 * This function writes the opening parenthese followed by @name.
238
 
 * It also increases the indentation level and sets a mark that
239
 
 * can be used by gimp_config_writer_revert().
240
 
 **/
241
 
void
242
 
gimp_config_writer_open (GimpConfigWriter *writer,
243
 
                         const gchar      *name)
244
 
{
245
 
  g_return_if_fail (writer != NULL);
246
 
  g_return_if_fail (name != NULL);
247
 
 
248
 
  if (writer->error)
249
 
    return;
250
 
 
251
 
  /* store the current buffer length so we can revert to this state */
252
 
  writer->marker = writer->buffer->len;
253
 
 
254
 
  if (writer->depth > 0)
255
 
    gimp_config_writer_newline (writer);
256
 
 
257
 
  writer->depth++;
258
 
 
259
 
  g_string_append_printf (writer->buffer, "(%s", name);
260
 
}
261
 
 
262
 
/**
263
 
 * gimp_config_writer_print:
264
 
 * @writer: a #GimpConfigWriter
265
 
 * @string: a string to write
266
 
 * @len: number of bytes from @string or -1 if @string is NUL-terminated.
267
 
 *
268
 
 * Appends a space followed by @string to the @writer. Note that string
269
 
 * must not contain any special characters that might need to be escaped.
270
 
 **/
271
 
void
272
 
gimp_config_writer_print (GimpConfigWriter  *writer,
273
 
                          const gchar       *string,
274
 
                          gint               len)
275
 
{
276
 
  g_return_if_fail (writer != NULL);
277
 
  g_return_if_fail (len == 0 || string != NULL);
278
 
 
279
 
  if (writer->error)
280
 
    return;
281
 
 
282
 
  if (len < 0)
283
 
    len = strlen (string);
284
 
 
285
 
  if (len)
286
 
    {
287
 
      g_string_append_c (writer->buffer, ' ');
288
 
      g_string_append_len (writer->buffer, string, len);
289
 
    }
290
 
}
291
 
 
292
 
/**
293
 
 * gimp_config_writer_printf:
294
 
 * @writer: a #GimpConfigWriter
295
 
 * @format: a format string as described for g_strdup_printf().
296
 
 * @Varargs: list of arguments according to @format
297
 
 *
298
 
 * A printf-like function for #GimpConfigWriter.
299
 
 **/
300
 
void
301
 
gimp_config_writer_printf (GimpConfigWriter *writer,
302
 
                           const gchar      *format,
303
 
                           ...)
304
 
{
305
 
  gchar   *buffer;
306
 
  va_list  args;
307
 
 
308
 
  g_return_if_fail (writer != NULL);
309
 
  g_return_if_fail (format != NULL);
310
 
 
311
 
  if (writer->error)
312
 
    return;
313
 
 
314
 
  va_start (args, format);
315
 
  buffer = g_strdup_vprintf (format, args);
316
 
  va_end (args);
317
 
 
318
 
  g_string_append_c (writer->buffer, ' ');
319
 
  g_string_append (writer->buffer, buffer);
320
 
 
321
 
  g_free (buffer);
322
 
}
323
 
 
324
 
/**
325
 
 * gimp_config_writer_string:
326
 
 * @writer: a #GimpConfigWriter
327
 
 * @string: a NUL-terminated string
328
 
 *
329
 
 * Writes a string value to @writer. The @string is quoted and special
330
 
 * characters are escaped.
331
 
 **/
332
 
void
333
 
gimp_config_writer_string (GimpConfigWriter *writer,
334
 
                           const gchar      *string)
335
 
{
336
 
  g_return_if_fail (writer != NULL);
337
 
 
338
 
  if (writer->error)
339
 
    return;
340
 
 
341
 
  g_string_append_c (writer->buffer, ' ');
342
 
  gimp_config_string_append_escaped (writer->buffer, string);
343
 
}
344
 
 
345
 
/**
346
 
 * gimp_config_writer_identifier:
347
 
 * @writer:     a #GimpConfigWriter
348
 
 * @identifier: a NUL-terminated string
349
 
 *
350
 
 * Writes an identifier to @writer. The @string is *not* quoted and special
351
 
 * characters are *not* escaped.
352
 
 **/
353
 
void
354
 
gimp_config_writer_identifier (GimpConfigWriter *writer,
355
 
                               const gchar      *identifier)
356
 
{
357
 
  g_return_if_fail (writer != NULL);
358
 
  g_return_if_fail (identifier != NULL);
359
 
 
360
 
  if (writer->error)
361
 
    return;
362
 
 
363
 
  g_string_append_printf (writer->buffer, " %s", identifier);
364
 
}
365
 
 
366
 
void
367
 
gimp_config_writer_data (GimpConfigWriter *writer,
368
 
                         gint              length,
369
 
                         const guint8     *data)
370
 
{
371
 
  gint i;
372
 
 
373
 
  g_return_if_fail (writer != NULL);
374
 
  g_return_if_fail (length > 0);
375
 
  g_return_if_fail (data != NULL);
376
 
 
377
 
  if (writer->error)
378
 
    return;
379
 
 
380
 
  g_string_append (writer->buffer, " \"");
381
 
 
382
 
  for (i = 0; i < length; i++)
383
 
    {
384
 
      if (g_ascii_isalpha (data[i]))
385
 
        g_string_append_c (writer->buffer, data[i]);
386
 
      else
387
 
        g_string_append_printf (writer->buffer, "\\%o", data[i]);
388
 
    }
389
 
 
390
 
  g_string_append (writer->buffer, "\"");
391
 
}
392
 
 
393
 
/**
394
 
 * gimp_config_writer_revert:
395
 
 * @writer: a #GimpConfigWriter
396
 
 *
397
 
 * Reverts all changes to @writer that were done since the last call
398
 
 * to gimp_config_writer_open(). This can only work if you didn't call
399
 
 * gimp_config_writer_close() yet.
400
 
 **/
401
 
void
402
 
gimp_config_writer_revert (GimpConfigWriter *writer)
403
 
{
404
 
  g_return_if_fail (writer != NULL);
405
 
 
406
 
  if (writer->error)
407
 
    return;
408
 
 
409
 
  g_return_if_fail (writer->depth > 0);
410
 
  g_return_if_fail (writer->marker != -1);
411
 
 
412
 
  g_string_truncate (writer->buffer, writer->marker);
413
 
 
414
 
  writer->depth--;
415
 
  writer->marker = -1;
416
 
}
417
 
 
418
 
/**
419
 
 * gimp_config_writer_close:
420
 
 * @writer: a #GimpConfigWriter
421
 
 *
422
 
 * Closes an element opened with gimp_config_writer_open().
423
 
 **/
424
 
void
425
 
gimp_config_writer_close (GimpConfigWriter *writer)
426
 
{
427
 
  g_return_if_fail (writer != NULL);
428
 
 
429
 
  if (writer->error)
430
 
    return;
431
 
 
432
 
  g_return_if_fail (writer->depth > 0);
433
 
 
434
 
  g_string_append_c (writer->buffer, ')');
435
 
 
436
 
  if (--writer->depth == 0)
437
 
    {
438
 
      g_string_append_c (writer->buffer, '\n');
439
 
 
440
 
      if (writer->fd)
441
 
        gimp_config_writer_flush (writer);
442
 
    }
443
 
}
444
 
 
445
 
/**
446
 
 * gimp_config_writer_finish:
447
 
 * @writer: a #GimpConfigWriter
448
 
 * @footer: text to include as comment at the bottom of the file
449
 
 * @error: return location for possible errors
450
 
 *
451
 
 * This function finishes the work of @writer and frees it afterwards.
452
 
 * It closes all open elements, appends an optional comment and
453
 
 * releases all resources allocated by @writer. You must not access
454
 
 * the @writer afterwards.
455
 
 *
456
 
 * Return value: %TRUE if everything could be successfully written,
457
 
 *               %FALSE otherwise
458
 
 **/
459
 
gboolean
460
 
gimp_config_writer_finish (GimpConfigWriter  *writer,
461
 
                           const gchar       *footer,
462
 
                           GError           **error)
463
 
{
464
 
  gboolean success = TRUE;
465
 
 
466
 
  g_return_val_if_fail (writer != NULL, FALSE);
467
 
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
468
 
 
469
 
  if (writer->depth < 0)
470
 
    {
471
 
      g_warning ("gimp_config_writer_finish: depth < 0 !!");
472
 
    }
473
 
  else
474
 
    {
475
 
      while (writer->depth)
476
 
        gimp_config_writer_close (writer);
477
 
    }
478
 
 
479
 
  if (footer)
480
 
    {
481
 
      gimp_config_writer_linefeed (writer);
482
 
      gimp_config_writer_comment (writer, footer);
483
 
    }
484
 
 
485
 
  if (writer->fd)
486
 
    {
487
 
      success = gimp_config_writer_close_file (writer, error);
488
 
 
489
 
      g_free (writer->filename);
490
 
      g_free (writer->tmpname);
491
 
 
492
 
      g_string_free (writer->buffer, TRUE);
493
 
    }
494
 
  else
495
 
    {
496
 
      success = TRUE;
497
 
    }
498
 
 
499
 
  g_free (writer);
500
 
 
501
 
  return success;
502
 
}
503
 
 
504
 
void
505
 
gimp_config_writer_linefeed (GimpConfigWriter *writer)
506
 
{
507
 
  g_return_if_fail (writer != NULL);
508
 
 
509
 
  if (writer->error)
510
 
    return;
511
 
 
512
 
  if (writer->buffer->len == 0 && !writer->comment)
513
 
    {
514
 
      if (write (writer->fd, "\n", 1) < 0)
515
 
        g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
516
 
                     g_strerror (errno));
517
 
    }
518
 
  else
519
 
    {
520
 
      gimp_config_writer_newline (writer);
521
 
    }
522
 
}
523
 
 
524
 
/**
525
 
 * gimp_config_writer_comment:
526
 
 * @writer: a #GimpConfigWriter
527
 
 * @comment: the comment to write (ASCII only)
528
 
 *
529
 
 * Appends the @comment to @str and inserts linebreaks and hash-marks to
530
 
 * format it as a comment. Note that this function does not handle non-ASCII
531
 
 * characters.
532
 
 **/
533
 
void
534
 
gimp_config_writer_comment (GimpConfigWriter *writer,
535
 
                            const gchar      *comment)
536
 
{
537
 
  const gchar *s;
538
 
  gboolean     comment_mode;
539
 
  gint         i, len, space;
540
 
 
541
 
#define LINE_LENGTH 75
542
 
 
543
 
  g_return_if_fail (writer != NULL);
544
 
 
545
 
  if (writer->error)
546
 
    return;
547
 
 
548
 
  g_return_if_fail (writer->depth == 0);
549
 
 
550
 
  if (!comment)
551
 
    return;
552
 
 
553
 
  comment_mode = writer->comment;
554
 
  gimp_config_writer_comment_mode (writer, TRUE);
555
 
 
556
 
  len = strlen (comment);
557
 
 
558
 
  while (len > 0)
559
 
    {
560
 
      for (s = comment, i = 0, space = 0;
561
 
           *s != '\n' && (i <= LINE_LENGTH || space == 0) && i < len;
562
 
           s++, i++)
563
 
        {
564
 
          if (g_ascii_isspace (*s))
565
 
            space = i;
566
 
        }
567
 
 
568
 
      if (i > LINE_LENGTH && space && *s != '\n')
569
 
        i = space;
570
 
 
571
 
      g_string_append_len (writer->buffer, comment, i);
572
 
 
573
 
      i++;
574
 
 
575
 
      comment += i;
576
 
      len     -= i;
577
 
 
578
 
      if (len > 0)
579
 
        gimp_config_writer_newline (writer);
580
 
    }
581
 
 
582
 
  gimp_config_writer_comment_mode (writer, comment_mode);
583
 
  gimp_config_writer_newline (writer);
584
 
 
585
 
  if (writer->depth == 0)
586
 
    gimp_config_writer_flush (writer);
587
 
 
588
 
#undef LINE_LENGTH
589
 
}
590
 
 
591
 
static gboolean
592
 
gimp_config_writer_close_file (GimpConfigWriter  *writer,
593
 
                               GError           **error)
594
 
{
595
 
  g_return_val_if_fail (writer->fd != 0, FALSE);
596
 
 
597
 
  if (! writer->filename)
598
 
    return TRUE;
599
 
 
600
 
  if (writer->error)
601
 
    {
602
 
      close (writer->fd);
603
 
 
604
 
      if (writer->tmpname)
605
 
        unlink (writer->tmpname);
606
 
 
607
 
      return TRUE;
608
 
    }
609
 
 
610
 
  if (close (writer->fd) != 0)
611
 
    {
612
 
      if (writer->tmpname)
613
 
        {
614
 
          if (g_file_test (writer->filename, G_FILE_TEST_EXISTS))
615
 
            {
616
 
              g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
617
 
                           _("Error writing to temporary file for '%s': %s\n"
618
 
                             "The original file has not been touched."),
619
 
                           gimp_filename_to_utf8 (writer->filename),
620
 
                           g_strerror (errno));
621
 
            }
622
 
          else
623
 
            {
624
 
              g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
625
 
                           _("Error writing to temporary file for '%s': %s\n"
626
 
                             "No file has been created."),
627
 
                           gimp_filename_to_utf8 (writer->filename),
628
 
                           g_strerror (errno));
629
 
            }
630
 
 
631
 
          unlink (writer->tmpname);
632
 
        }
633
 
      else
634
 
        {
635
 
          g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
636
 
                       _("Error writing to '%s': %s"),
637
 
                       gimp_filename_to_utf8 (writer->filename),
638
 
                       g_strerror (errno));
639
 
        }
640
 
 
641
 
      return FALSE;
642
 
    }
643
 
 
644
 
  if (writer->tmpname)
645
 
    {
646
 
#ifdef G_OS_WIN32
647
 
      /* win32 rename can't overwrite */
648
 
      unlink (writer->filename);
649
 
#endif
650
 
 
651
 
      if (rename (writer->tmpname, writer->filename) == -1)
652
 
        {
653
 
          g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
654
 
                       _("Could not create '%s': %s"),
655
 
                       gimp_filename_to_utf8 (writer->filename),
656
 
                       g_strerror (errno));
657
 
 
658
 
          unlink (writer->tmpname);
659
 
          return FALSE;
660
 
        }
661
 
    }
662
 
 
663
 
  return TRUE;
664
 
}