Skip to content

Commit

Permalink
Merge pull request #1243 from jluebbe/utils
Browse files Browse the repository at this point in the history
make open_ helpers reusable and add r_syncfs
  • Loading branch information
ejoerns committed Sep 5, 2023
2 parents a5d984e + 038187a commit 9a8daaa
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 66 deletions.
29 changes: 28 additions & 1 deletion include/update_utils.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
#pragma once

#include <gio/gio.h>
#include <gio/gunixinputstream.h>
#include <gio/gunixoutputstream.h>
#include <glib.h>

/* These functions can be used by slot and artifact update handlers. */

/**
* Opens a device for writing and returns a GUnixOutputStream for it.
* Optionally, the FD is returned as well.
*
* @param filename the file to be opened
* @param fd the associated file descriptor, for use with ioctls
* @param error return location for a GError, or NULL
*
* @return the new GUnixOutputStream if successful, NULL otherwise
*/
GUnixOutputStream* r_open_unix_output_stream(const gchar *filename, int *fd, GError **error)
G_GNUC_WARN_UNUSED_RESULT;

/**
* Opens a file for reading and returns a GUnixInputStream for it.
* Optionally, the FD is returned as well.
*
* @param filename the file to be opened
* @param fd the associated file descriptor, for use with ioctls
* @param error return location for a GError, or NULL
*
* @return the new GUnixInputStream if successful, NULL otherwise
*/
GUnixInputStream* r_open_unix_input_stream(const gchar *filename, int *fd, GError **error)
G_GNUC_WARN_UNUSED_RESULT;

/**
* Copies data from an input stream to an output stream, while generating
* progress updates.
Expand All @@ -16,7 +44,6 @@
*
* @return TRUE if copying was successful, FALSE otherwise
*/

gboolean r_copy_stream_with_progress(GInputStream *in_stream, GOutputStream *out_stream,
goffset size, GError **error)
G_GNUC_WARN_UNUSED_RESULT;
11 changes: 11 additions & 0 deletions include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,14 @@ G_GNUC_WARN_UNUSED_RESULT;
*/
gboolean r_update_symlink(const gchar *target, const gchar *name, GError **error)
G_GNUC_WARN_UNUSED_RESULT;

/**
* Calls syncfs on a given filesystem.
*
* @param path path on the filesystem to sync
* @param error return location for a GError, or NULL
*
* @return TRUE if the filesystem was synced, FALSE otherwise
*/
gboolean r_syncfs(const gchar *path, GError **error)
G_GNUC_WARN_UNUSED_RESULT;
71 changes: 6 additions & 65 deletions src/update_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,65 +61,6 @@ static gboolean check_image_size(int fd, const RaucImage *image, GError **error)
return TRUE;
}

/* the fd will only live as long as the returned output stream */
static GUnixOutputStream* open_slot_device(RaucSlot *slot, int *fd, GError **error)
{
GUnixOutputStream *outstream = NULL;
int fd_out;

g_return_val_if_fail(slot, NULL);
g_return_val_if_fail(error == NULL || *error == NULL, NULL);

fd_out = g_open(slot->device, O_WRONLY | O_EXCL);

if (fd_out == -1) {
g_set_error(error, R_UPDATE_ERROR, R_UPDATE_ERROR_FAILED,
"Opening output device %s failed: %s", slot->device, strerror(errno));
return NULL;
}

outstream = G_UNIX_OUTPUT_STREAM(g_unix_output_stream_new(fd_out, TRUE));
if (outstream == NULL) {
g_set_error(error, R_UPDATE_ERROR, R_UPDATE_ERROR_FAILED,
"Failed to create stream for output device %s", slot->device);
return NULL;
}

if (fd != NULL)
*fd = fd_out;

return outstream;
}

static GUnixInputStream* open_file_as_unix_input_stream(const gchar *filename, int *fd, GError **error)
{
GUnixInputStream *instream = NULL;
int fd_out;

g_return_val_if_fail(filename, NULL);
g_return_val_if_fail(error == NULL || *error == NULL, NULL);

fd_out = g_open(filename, O_RDONLY);
if (fd_out < 0) {
int err = errno;
g_set_error(error, G_IO_ERROR, g_io_error_from_errno(err),
"Failed to open file %s: %s", filename, g_strerror(err));
return NULL;
}

instream = G_UNIX_INPUT_STREAM(g_unix_input_stream_new(fd_out, TRUE));
if (instream == NULL) {
g_set_error(error, R_UPDATE_ERROR, R_UPDATE_ERROR_FAILED,
"Failed to create stream for file %s", filename);
return NULL;
}

if (fd != NULL)
*fd = fd_out;

return instream;
}

#if ENABLE_EMMC_BOOT_SUPPORT == 1
static gboolean clear_slot(RaucSlot *slot, GError **error)
{
Expand All @@ -128,7 +69,7 @@ static gboolean clear_slot(RaucSlot *slot, GError **error)
g_autoptr(GOutputStream) outstream = NULL;
gint write_count = 0;

outstream = G_OUTPUT_STREAM(open_slot_device(slot, NULL, &ierror));
outstream = G_OUTPUT_STREAM(r_open_unix_output_stream(slot->device, NULL, &ierror));
if (outstream == NULL) {
g_propagate_error(error, ierror);
return FALSE;
Expand Down Expand Up @@ -292,7 +233,7 @@ static gboolean splice_file_to_outstream(const gchar *filename,
g_return_val_if_fail(out_stream, FALSE);
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);

image_stream = open_file_as_unix_input_stream(filename, NULL, &ierror);
image_stream = r_open_unix_input_stream(filename, NULL, &ierror);
if (image_stream == NULL) {
g_propagate_prefixed_error(
error,
Expand Down Expand Up @@ -697,7 +638,7 @@ static gboolean copy_raw_image_to_dev(RaucImage *image, RaucSlot *slot, GError *

/* open */
g_message("opening slot device %s", slot->device);
outstream = open_slot_device(slot, NULL, &ierror);
outstream = r_open_unix_output_stream(slot->device, NULL, &ierror);
if (outstream == NULL) {
res = FALSE;
g_propagate_error(error, ierror);
Expand Down Expand Up @@ -1585,7 +1526,7 @@ static gboolean img_to_ubivol_handler(RaucImage *image, RaucSlot *dest_slot, con

/* open */
g_message("opening slot device %s", dest_slot->device);
outstream = open_slot_device(dest_slot, &out_fd, &ierror);
outstream = r_open_unix_output_stream(dest_slot->device, &out_fd, &ierror);
if (outstream == NULL) {
res = FALSE;
g_propagate_error(error, ierror);
Expand Down Expand Up @@ -1654,7 +1595,7 @@ static gboolean img_to_ubifs_handler(RaucImage *image, RaucSlot *dest_slot, cons

/* open */
g_message("opening slot device %s", dest_slot->device);
outstream = open_slot_device(dest_slot, &out_fd, &ierror);
outstream = r_open_unix_output_stream(dest_slot->device, &out_fd, &ierror);
if (outstream == NULL) {
res = FALSE;
g_propagate_error(error, ierror);
Expand Down Expand Up @@ -2377,7 +2318,7 @@ static gboolean img_to_boot_emmc_handler(RaucImage *image, RaucSlot *dest_slot,

/* open */
g_message("Opening slot device partition %s", part_slot->device);
outstream = open_slot_device(part_slot, &out_fd, &ierror);
outstream = r_open_unix_output_stream(part_slot->device, &out_fd, &ierror);
if (outstream == NULL) {
g_propagate_error(error, ierror);
res = FALSE;
Expand Down
62 changes: 62 additions & 0 deletions src/update_utils.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,76 @@
#include <errno.h>
#include <fcntl.h>
#include <gio/gio.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "update_handler.h"
#include "update_utils.h"
#include "context.h"

/* the fd will only live as long as the returned output stream */
GUnixOutputStream* r_open_unix_output_stream(const gchar *filename, int *fd, GError **error)
{
GUnixOutputStream *outstream = NULL;
int fd_out;

g_return_val_if_fail(filename, NULL);
g_return_val_if_fail(error == NULL || *error == NULL, NULL);

fd_out = g_open(filename, O_WRONLY | O_EXCL);

if (fd_out == -1) {
g_set_error(error, R_UPDATE_ERROR, R_UPDATE_ERROR_FAILED,
"Failed to open output file/device %s failed: %s", filename, strerror(errno));
return NULL;
}

outstream = G_UNIX_OUTPUT_STREAM(g_unix_output_stream_new(fd_out, TRUE));
if (outstream == NULL) {
g_set_error(error, R_UPDATE_ERROR, R_UPDATE_ERROR_FAILED,
"Failed to create stream for output device %s", filename);
return NULL;
}

if (fd != NULL)
*fd = fd_out;

return outstream;
}

/* the fd will only live as long as the returned input stream */
GUnixInputStream* r_open_unix_input_stream(const gchar *filename, int *fd, GError **error)
{
GUnixInputStream *instream = NULL;
int fd_out;

g_return_val_if_fail(filename, NULL);
g_return_val_if_fail(error == NULL || *error == NULL, NULL);

fd_out = g_open(filename, O_RDONLY);
if (fd_out < 0) {
int err = errno;
g_set_error(error, G_IO_ERROR, g_io_error_from_errno(err),
"Failed to open file %s: %s", filename, g_strerror(err));
return NULL;
}

instream = G_UNIX_INPUT_STREAM(g_unix_input_stream_new(fd_out, TRUE));
if (instream == NULL) {
g_set_error(error, R_UPDATE_ERROR, R_UPDATE_ERROR_FAILED,
"Failed to create stream for file %s", filename);
return NULL;
}

if (fd != NULL)
*fd = fd_out;

return instream;
}

gboolean r_copy_stream_with_progress(GInputStream *in_stream, GOutputStream *out_stream,
goffset size, GError **error)
{
Expand Down
30 changes: 30 additions & 0 deletions src/utils.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <errno.h>
#include <fcntl.h>
#include <ftw.h>
#include <gio/gio.h>
#include <glib.h>
Expand Down Expand Up @@ -621,3 +622,32 @@ gboolean r_update_symlink(const gchar *target, const gchar *name, GError **error

return TRUE;
}

gboolean r_syncfs(const gchar *path, GError **error)
{
g_auto(filedesc) fd = -1;

g_return_val_if_fail(path != NULL, FALSE);
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);

fd = g_open(path, O_RDONLY);
if (fd == -1) {
int err = errno;
g_set_error(error,
G_FILE_ERROR,
g_file_error_from_errno(err),
"Failed to open %s for syncfs: %s", path, g_strerror(err));
return FALSE;
}

if (syncfs(fd) == -1) {
int err = errno;
g_set_error(error,
G_FILE_ERROR,
g_file_error_from_errno(err),
"Failed to sync filesystem for %s: %s", path, g_strerror(err));
return FALSE;
}

return TRUE;
}

0 comments on commit 9a8daaa

Please sign in to comment.