Add some more cases to the app-id unit tests
[glib.git] / gio / gio-tool-save.c
bloba955a24c0d6c4af05955a2223f3055601ce1d5ab
1 /*
2 * Copyright 2015 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the licence, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 * Author: Matthias Clasen <mclasen@redhat.com>
20 #include "config.h"
22 #include <gio/gio.h>
23 #include <gi18n.h>
25 #ifdef G_OS_WIN32
26 #include <io.h>
27 #endif
29 #ifndef STDIN_FILENO
30 #define STDIN_FILENO 0
31 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
37 #include "gio-tool.h"
39 static char *etag = NULL;
40 static gboolean backup = FALSE;
41 static gboolean create = FALSE;
42 static gboolean append = FALSE;
43 static gboolean priv = FALSE;
44 static gboolean replace_dest = FALSE;
45 static gboolean print_etag = FALSE;
47 static const GOptionEntry entries[] =
49 { "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, N_("Backup existing destination files"), NULL },
50 { "create", 'c', 0, G_OPTION_ARG_NONE, &create, N_("Only create if not existing"), NULL },
51 { "append", 'a', 0, G_OPTION_ARG_NONE, &append, N_("Append to end of file"), NULL },
52 { "private", 'p', 0, G_OPTION_ARG_NONE, &priv, N_("When creating, restrict access to the current user"), NULL },
53 { "unlink", 'u', 0, G_OPTION_ARG_NONE, &replace_dest, N_("When replacing, replace as if the destination did not exist"), NULL },
54 /* Translators: The "etag" is a token allowing to verify whether a file has been modified */
55 { "print-etag", 'v', 0, G_OPTION_ARG_NONE, &print_etag, N_("Print new etag at end"), NULL },
56 /* Translators: The "etag" is a token allowing to verify whether a file has been modified */
57 { "etag", 'e', 0, G_OPTION_ARG_STRING, &etag, N_("The etag of the file being overwritten"), N_("ETAG") },
58 { NULL }
61 static gboolean
62 save (GFile *file)
64 GOutputStream *out;
65 GFileCreateFlags flags;
66 char buffer[1025];
67 char *p;
68 gssize res;
69 gboolean close_res;
70 GError *error;
71 gboolean save_res;
73 error = NULL;
75 flags = priv ? G_FILE_CREATE_PRIVATE : G_FILE_CREATE_NONE;
76 flags |= replace_dest ? G_FILE_CREATE_REPLACE_DESTINATION : 0;
78 if (create)
79 out = (GOutputStream *)g_file_create (file, flags, NULL, &error);
80 else if (append)
81 out = (GOutputStream *)g_file_append_to (file, flags, NULL, &error);
82 else
83 out = (GOutputStream *)g_file_replace (file, etag, backup, flags, NULL, &error);
84 if (out == NULL)
86 print_file_error (file, error->message);
87 g_error_free (error);
88 return FALSE;
91 save_res = TRUE;
93 while (1)
95 res = read (STDIN_FILENO, buffer, 1024);
96 if (res > 0)
98 gssize written;
100 p = buffer;
101 while (res > 0)
103 error = NULL;
104 written = g_output_stream_write (out, p, res, NULL, &error);
105 if (written == -1)
107 save_res = FALSE;
108 g_printerr ("gio: Error writing to stream: %s\n", error->message);
109 g_error_free (error);
110 goto out;
112 res -= written;
113 p += written;
116 else if (res < 0)
118 save_res = FALSE;
119 g_printerr ("gio: Error reading from standard input\n");
120 break;
122 else if (res == 0)
123 break;
126 out:
128 close_res = g_output_stream_close (out, NULL, &error);
129 if (!close_res)
131 save_res = FALSE;
132 g_printerr ("gio: Error closing: %s\n", error->message);
133 g_error_free (error);
136 if (close_res && print_etag)
138 char *etag;
139 etag = g_file_output_stream_get_etag (G_FILE_OUTPUT_STREAM (out));
141 if (etag)
142 g_print ("Etag: %s\n", etag);
143 else
144 /* Translators: The "etag" is a token allowing to verify whether a file has been modified */
145 g_print (_("Etag not available\n"));
146 g_free (etag);
149 g_object_unref (out);
151 return save_res;
155 handle_save (int argc, char *argv[], gboolean do_help)
157 GOptionContext *context;
158 GError *error = NULL;
159 GFile *file;
160 gboolean res;
162 g_set_prgname ("gio save");
164 /* Translators: commandline placeholder */
165 context = g_option_context_new (_("DESTINATION"));
166 g_option_context_set_help_enabled (context, FALSE);
167 g_option_context_set_summary (context,
168 _("Read from standard input and save to DEST."));
169 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
171 if (do_help)
173 show_help (context, NULL);
174 return 0;
177 if (!g_option_context_parse (context, &argc, &argv, &error))
179 show_help (context, error->message);
180 g_error_free (error);
181 return 1;
184 if (argc < 2)
186 show_help (context, _("No destination given"));
187 return 1;
190 if (argc > 2)
192 show_help (context, _("Too many arguments"));
193 return 1;
196 g_option_context_free (context);
198 file = g_file_new_for_commandline_arg (argv[1]);
199 res = save (file);
200 g_object_unref (file);
202 return res ? 0 : 2;