mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
3d7534eae5
Compiling with clang 3.8.1-18 (debian, x86_64) I ran across this error: gio-tool.c:40:31: error: format string is not a string literal [-Werror,-Wformat-nonliteral] message = g_strdup_vprintf (format, args); ^~~~~~ gio-tool.c:55:31: error: format string is not a string literal [-Werror,-Wformat-nonliteral] message = g_strdup_vprintf (format, args); ^~~~~~ 2 errors generated. To fix the first one, related with the function print_error(), this patch adds to the function prototype a compiler's attribute. For the second one, since the usage of that function is to print one string and the format is already provided, the patch simplifies the function by no receiving variadic arguments. https://bugzilla.gnome.org/show_bug.cgi?id=781125
209 lines
5.3 KiB
C
209 lines
5.3 KiB
C
/*
|
|
* Copyright 2015 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the licence, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Matthias Clasen <mclasen@redhat.com>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gio/gio.h>
|
|
#include <gi18n.h>
|
|
|
|
#ifdef G_OS_WIN32
|
|
#include <io.h>
|
|
#endif
|
|
|
|
#ifndef STDIN_FILENO
|
|
#define STDIN_FILENO 0
|
|
#endif
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "gio-tool.h"
|
|
|
|
static char *etag = NULL;
|
|
static gboolean backup = FALSE;
|
|
static gboolean create = FALSE;
|
|
static gboolean append = FALSE;
|
|
static gboolean priv = FALSE;
|
|
static gboolean replace_dest = FALSE;
|
|
static gboolean print_etag = FALSE;
|
|
|
|
static const GOptionEntry entries[] =
|
|
{
|
|
{ "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, N_("Backup existing destination files"), NULL },
|
|
{ "create", 'c', 0, G_OPTION_ARG_NONE, &create, N_("Only create if not existing"), NULL },
|
|
{ "append", 'a', 0, G_OPTION_ARG_NONE, &append, N_("Append to end of file"), NULL },
|
|
{ "private", 'p', 0, G_OPTION_ARG_NONE, &priv, N_("When creating, restrict access to the current user"), NULL },
|
|
{ "unlink", 'u', 0, G_OPTION_ARG_NONE, &replace_dest, N_("When replacing, replace as if the destination did not exist"), NULL },
|
|
/* Translators: The "etag" is a token allowing to verify whether a file has been modified */
|
|
{ "print-etag", 'v', 0, G_OPTION_ARG_NONE, &print_etag, N_("Print new etag at end"), NULL },
|
|
/* Translators: The "etag" is a token allowing to verify whether a file has been modified */
|
|
{ "etag", 'e', 0, G_OPTION_ARG_STRING, &etag, N_("The etag of the file being overwritten"), N_("ETAG") },
|
|
{ NULL }
|
|
};
|
|
|
|
static gboolean
|
|
save (GFile *file)
|
|
{
|
|
GOutputStream *out;
|
|
GFileCreateFlags flags;
|
|
char buffer[1025];
|
|
char *p;
|
|
gssize res;
|
|
gboolean close_res;
|
|
GError *error;
|
|
gboolean save_res;
|
|
|
|
error = NULL;
|
|
|
|
flags = priv ? G_FILE_CREATE_PRIVATE : G_FILE_CREATE_NONE;
|
|
flags |= replace_dest ? G_FILE_CREATE_REPLACE_DESTINATION : 0;
|
|
|
|
if (create)
|
|
out = (GOutputStream *)g_file_create (file, flags, NULL, &error);
|
|
else if (append)
|
|
out = (GOutputStream *)g_file_append_to (file, flags, NULL, &error);
|
|
else
|
|
out = (GOutputStream *)g_file_replace (file, etag, backup, flags, NULL, &error);
|
|
if (out == NULL)
|
|
{
|
|
print_file_error (file, error->message);
|
|
g_error_free (error);
|
|
return FALSE;
|
|
}
|
|
|
|
save_res = TRUE;
|
|
|
|
while (1)
|
|
{
|
|
res = read (STDIN_FILENO, buffer, 1024);
|
|
if (res > 0)
|
|
{
|
|
gssize written;
|
|
|
|
p = buffer;
|
|
while (res > 0)
|
|
{
|
|
error = NULL;
|
|
written = g_output_stream_write (out, p, res, NULL, &error);
|
|
if (written == -1)
|
|
{
|
|
save_res = FALSE;
|
|
print_error ("%s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
res -= written;
|
|
p += written;
|
|
}
|
|
}
|
|
else if (res < 0)
|
|
{
|
|
save_res = FALSE;
|
|
print_error ("%s", _("Error reading from standard input"));
|
|
break;
|
|
}
|
|
else if (res == 0)
|
|
break;
|
|
}
|
|
|
|
out:
|
|
|
|
close_res = g_output_stream_close (out, NULL, &error);
|
|
if (!close_res)
|
|
{
|
|
save_res = FALSE;
|
|
print_error ("%s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
|
|
if (close_res && print_etag)
|
|
{
|
|
char *etag;
|
|
etag = g_file_output_stream_get_etag (G_FILE_OUTPUT_STREAM (out));
|
|
|
|
if (etag)
|
|
g_print ("Etag: %s\n", etag);
|
|
else
|
|
/* Translators: The "etag" is a token allowing to verify whether a file has been modified */
|
|
g_print (_("Etag not available\n"));
|
|
g_free (etag);
|
|
}
|
|
|
|
g_object_unref (out);
|
|
|
|
return save_res;
|
|
}
|
|
|
|
int
|
|
handle_save (int argc, char *argv[], gboolean do_help)
|
|
{
|
|
GOptionContext *context;
|
|
GError *error = NULL;
|
|
GFile *file;
|
|
gboolean res;
|
|
|
|
g_set_prgname ("gio save");
|
|
|
|
/* Translators: commandline placeholder */
|
|
context = g_option_context_new (_("DESTINATION"));
|
|
g_option_context_set_help_enabled (context, FALSE);
|
|
g_option_context_set_summary (context,
|
|
_("Read from standard input and save to DEST."));
|
|
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
|
|
|
|
if (do_help)
|
|
{
|
|
show_help (context, NULL);
|
|
g_option_context_free (context);
|
|
return 0;
|
|
}
|
|
|
|
if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
{
|
|
show_help (context, error->message);
|
|
g_error_free (error);
|
|
g_option_context_free (context);
|
|
return 1;
|
|
}
|
|
|
|
if (argc < 2)
|
|
{
|
|
show_help (context, _("No destination given"));
|
|
g_option_context_free (context);
|
|
return 1;
|
|
}
|
|
|
|
if (argc > 2)
|
|
{
|
|
show_help (context, _("Too many arguments"));
|
|
g_option_context_free (context);
|
|
return 1;
|
|
}
|
|
|
|
g_option_context_free (context);
|
|
|
|
file = g_file_new_for_commandline_arg (argv[1]);
|
|
res = save (file);
|
|
g_object_unref (file);
|
|
|
|
return res ? 0 : 2;
|
|
}
|
|
|