Files
RedBear-OS/local/recipes/libs/glib/source/gio/gzlibdecompressor.c
T
vasilito cee25393d8 fix: boot process improvements — dependency cycle, INIT_NOTIFY, probing loop, and log spam fixes
- Fix P15-8-init-cycle-detection.patch: replace visiting+error with seen+silent-skip
  to eliminate 11 false-positive 'dependency cycle detected' errors on shared deps
- Fix P0-daemon-fix-init-notify-unwrap.patch: remove eprintln! for missing
  INIT_NOTIFY (expected for oneshot_async services, ~7 daemons affected)
- Fix driver-manager hotplug loop: add PERMANENTLY_SKIPPED static set shared
  between hotplug handler and DriverConfig::probe() to stop infinite re-probing
  of Fatal/NotSupported/deferred-exhausted device+driver pairs (e.g. ided)
- Fix driver-manager log_timeline: suppress repeated EPIPE/ENOENT errors with
  AtomicI32 dedup and AtomicBool one-shot guards for boot timeline JSON
- Add driver-manager SIGTERM handler, ACPI bus registration, --status mode,
  driver reap loop, graceful shutdown, and reduced deferred retries (30→3)
2026-05-17 12:34:02 +03:00

411 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2009 Red Hat, Inc.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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.1 of the License, 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: Alexander Larsson <alexl@redhat.com>
*/
#include "config.h"
#include "gzlibdecompressor.h"
#include <errno.h>
#include <zlib.h>
#include <string.h>
#include "gfileinfo.h"
#include "gioerror.h"
#include "gioenums.h"
#include "gioenumtypes.h"
#include "glibintl.h"
enum {
PROP_0,
PROP_FORMAT,
PROP_FILE_INFO
};
/**
* GZlibDecompressor:
*
* `GZlibDecompressor` is an implementation of [iface@Gio.Converter] that
* decompresses data compressed with zlib.
*/
static void g_zlib_decompressor_iface_init (GConverterIface *iface);
typedef struct {
gz_header gzheader;
char filename[257];
GFileInfo *file_info;
} HeaderData;
struct _GZlibDecompressor
{
GObject parent_instance;
GZlibCompressorFormat format;
z_stream zstream;
HeaderData *header_data;
};
static void
g_zlib_decompressor_set_gzheader (GZlibDecompressor *decompressor)
{
/* On win32, these functions were not exported before 1.2.4 */
#if !defined (G_OS_WIN32) || ZLIB_VERNUM >= 0x1240
if (decompressor->format != G_ZLIB_COMPRESSOR_FORMAT_GZIP)
return;
if (decompressor->header_data != NULL)
{
if (decompressor->header_data->file_info)
g_object_unref (decompressor->header_data->file_info);
memset (decompressor->header_data, 0, sizeof (HeaderData));
}
else
{
decompressor->header_data = g_new0 (HeaderData, 1);
}
decompressor->header_data->gzheader.name = (Bytef*) &decompressor->header_data->filename;
/* We keep one byte to guarantee the string is 0-terminated */
decompressor->header_data->gzheader.name_max = 256;
if (inflateGetHeader (&decompressor->zstream, &decompressor->header_data->gzheader) != Z_OK)
g_warning ("unexpected zlib error: %s", decompressor->zstream.msg);
#endif /* !G_OS_WIN32 || ZLIB >= 1.2.4 */
}
G_DEFINE_TYPE_WITH_CODE (GZlibDecompressor, g_zlib_decompressor, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
g_zlib_decompressor_iface_init))
static void
g_zlib_decompressor_finalize (GObject *object)
{
GZlibDecompressor *decompressor;
decompressor = G_ZLIB_DECOMPRESSOR (object);
inflateEnd (&decompressor->zstream);
if (decompressor->header_data != NULL)
{
if (decompressor->header_data->file_info)
g_object_unref (decompressor->header_data->file_info);
g_free (decompressor->header_data);
}
G_OBJECT_CLASS (g_zlib_decompressor_parent_class)->finalize (object);
}
static void
g_zlib_decompressor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GZlibDecompressor *decompressor;
decompressor = G_ZLIB_DECOMPRESSOR (object);
switch (prop_id)
{
case PROP_FORMAT:
decompressor->format = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_zlib_decompressor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GZlibDecompressor *decompressor;
decompressor = G_ZLIB_DECOMPRESSOR (object);
switch (prop_id)
{
case PROP_FORMAT:
g_value_set_enum (value, decompressor->format);
break;
case PROP_FILE_INFO:
if (decompressor->header_data)
g_value_set_object (value, decompressor->header_data->file_info);
else
g_value_set_object (value, NULL);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_zlib_decompressor_init (GZlibDecompressor *decompressor)
{
}
static void
g_zlib_decompressor_constructed (GObject *object)
{
GZlibDecompressor *decompressor;
int res;
decompressor = G_ZLIB_DECOMPRESSOR (object);
if (decompressor->format == G_ZLIB_COMPRESSOR_FORMAT_GZIP)
{
/* + 16 for gzip */
res = inflateInit2 (&decompressor->zstream, MAX_WBITS + 16);
}
else if (decompressor->format == G_ZLIB_COMPRESSOR_FORMAT_RAW)
{
/* Negative for raw */
res = inflateInit2 (&decompressor->zstream, -MAX_WBITS);
}
else /* ZLIB */
res = inflateInit (&decompressor->zstream);
if (res == Z_MEM_ERROR )
g_error ("GZlibDecompressor: Not enough memory for zlib use");
if (res != Z_OK)
g_warning ("unexpected zlib error: %s", decompressor->zstream.msg);
g_zlib_decompressor_set_gzheader (decompressor);
}
static void
g_zlib_decompressor_class_init (GZlibDecompressorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_zlib_decompressor_finalize;
gobject_class->constructed = g_zlib_decompressor_constructed;
gobject_class->get_property = g_zlib_decompressor_get_property;
gobject_class->set_property = g_zlib_decompressor_set_property;
/**
* GZlibDecompressor:format:
*
* The format of the compressed data.
*
* Since: 2.24
*/
g_object_class_install_property (gobject_class,
PROP_FORMAT,
g_param_spec_enum ("format", NULL, NULL,
G_TYPE_ZLIB_COMPRESSOR_FORMAT,
G_ZLIB_COMPRESSOR_FORMAT_ZLIB,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
* GZlibDecompressor:file-info:
*
* A [class@Gio.FileInfo] containing the information found in the gzip header
* of the data stream processed.
*
* This will be `NULL` if the header was not yet fully processed, is not
* present at all, or the compressors [property@Gio.ZlibDecompressor:format]
* property is not [enum@Gio.ZlibCompressorFormat.GZIP].
*
* Since: 2.26
*/
g_object_class_install_property (gobject_class,
PROP_FILE_INFO,
g_param_spec_object ("file-info", NULL, NULL,
G_TYPE_FILE_INFO,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
}
/**
* g_zlib_decompressor_new:
* @format: the format to use for the compressed data
*
* Creates a new decompressor.
*
* Returns: a new [class@Gio.ZlibDecompressor]
* Since: 2.24
**/
GZlibDecompressor *
g_zlib_decompressor_new (GZlibCompressorFormat format)
{
GZlibDecompressor *decompressor;
decompressor = g_object_new (G_TYPE_ZLIB_DECOMPRESSOR,
"format", format,
NULL);
return decompressor;
}
/**
* g_zlib_decompressor_get_file_info:
* @decompressor: a #GZlibDecompressor
*
* Gets the [property@Gio.ZlibDecompressor:file-info] property.
*
* Returns: (nullable) (transfer none): file info from the gzip header, if available
* Since: 2.26
*/
GFileInfo *
g_zlib_decompressor_get_file_info (GZlibDecompressor *decompressor)
{
g_return_val_if_fail (G_IS_ZLIB_DECOMPRESSOR (decompressor), NULL);
if (decompressor->header_data)
return decompressor->header_data->file_info;
return NULL;
}
static void
g_zlib_decompressor_reset (GConverter *converter)
{
GZlibDecompressor *decompressor = G_ZLIB_DECOMPRESSOR (converter);
int res;
res = inflateReset (&decompressor->zstream);
if (res != Z_OK)
g_warning ("unexpected zlib error: %s", decompressor->zstream.msg);
g_zlib_decompressor_set_gzheader (decompressor);
}
static GConverterResult
g_zlib_decompressor_convert (GConverter *converter,
const void *inbuf,
gsize inbuf_size,
void *outbuf,
gsize outbuf_size,
GConverterFlags flags,
gsize *bytes_read,
gsize *bytes_written,
GError **error)
{
GZlibDecompressor *decompressor;
int res;
decompressor = G_ZLIB_DECOMPRESSOR (converter);
decompressor->zstream.next_in = (void *)inbuf;
decompressor->zstream.avail_in = inbuf_size;
decompressor->zstream.next_out = outbuf;
decompressor->zstream.avail_out = outbuf_size;
res = inflate (&decompressor->zstream, Z_NO_FLUSH);
if (res == Z_DATA_ERROR || res == Z_NEED_DICT)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
_("Invalid compressed data"));
return G_CONVERTER_ERROR;
}
if (res == Z_MEM_ERROR)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Not enough memory"));
return G_CONVERTER_ERROR;
}
if (res == Z_STREAM_ERROR)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Internal error: %s"), decompressor->zstream.msg);
return G_CONVERTER_ERROR;
}
if (res == Z_BUF_ERROR)
{
if (flags & G_CONVERTER_FLUSH)
return G_CONVERTER_FLUSHED;
/* Z_FINISH not set, so this means no progress could be made */
/* We do have output space, so this should only happen if we
have no input but need some */
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT,
_("Need more input"));
return G_CONVERTER_ERROR;
}
g_assert (res == Z_OK || res == Z_STREAM_END);
*bytes_read = inbuf_size - decompressor->zstream.avail_in;
*bytes_written = outbuf_size - decompressor->zstream.avail_out;
#if !defined (G_OS_WIN32) || ZLIB_VERNUM >= 0x1240
if (decompressor->header_data != NULL &&
decompressor->header_data->gzheader.done == 1)
{
HeaderData *data = decompressor->header_data;
/* So we don't notify again */
data->gzheader.done = 2;
data->file_info = g_file_info_new ();
g_file_info_set_attribute_uint64 (data->file_info,
G_FILE_ATTRIBUTE_TIME_MODIFIED,
data->gzheader.time);
g_file_info_set_attribute_uint32 (data->file_info,
G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
0);
g_file_info_set_attribute_uint32 (data->file_info,
G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
0);
if (data->filename[0] != '\0')
g_file_info_set_attribute_byte_string (data->file_info,
G_FILE_ATTRIBUTE_STANDARD_NAME,
data->filename);
g_object_notify (G_OBJECT (decompressor), "file-info");
}
#endif /* !G_OS_WIN32 || ZLIB >= 1.2.4 */
if (res == Z_STREAM_END)
return G_CONVERTER_FINISHED;
return G_CONVERTER_CONVERTED;
}
static void
g_zlib_decompressor_iface_init (GConverterIface *iface)
{
iface->convert = g_zlib_decompressor_convert;
iface->reset = g_zlib_decompressor_reset;
}