Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/reference/libinfinity/libinfinity-0.7-sections.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1420,6 +1420,7 @@ inf_file_util_delete_file
inf_file_util_delete_single_directory
inf_file_util_delete_directory
inf_file_util_delete
inf_file_util_write_private_data
</SECTION>

<SECTION>
Expand Down
5 changes: 3 additions & 2 deletions libinfinity/common/inf-cert-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
**/

#include <libinfinity/common/inf-cert-util.h>
#include <libinfinity/common/inf-file-util.h>
#include <libinfinity/common/inf-error.h>
#include <libinfinity/inf-i18n.h>

Expand Down Expand Up @@ -604,7 +605,7 @@ inf_cert_util_write_private_key(gnutls_x509_privkey_t key,
return FALSE;
}

result = g_file_set_contents(
result = inf_file_util_write_private_data(
filename,
string->str,
string->len,
Expand Down Expand Up @@ -980,7 +981,7 @@ inf_cert_util_write_certificate_with_key(gnutls_x509_privkey_t key,
return FALSE;
}

g_file_set_contents(
result = inf_file_util_write_private_data(
filename,
string->str,
string->len,
Expand Down
72 changes: 72 additions & 0 deletions libinfinity/common/inf-file-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,4 +517,76 @@ inf_file_util_delete(const gchar* path,
return inf_file_util_delete_file(path, error);
}

/**
* inf_file_util_write_private_data:
* @filename: Filename of the file to be written to.
* @data: Data that should be written to file.
* @length: Length of data in bytes.
* @error: Location to store error information, if any, or %NULL.
*
* Writes @data to the file pointed to by @filename. On Unix-like systems,
* @filename is created with 0600 permission. If the function fails, %FALSE is
* returned and @error is set.
*
* Returns: %TRUE on success or %FALSE on error.
*/
gboolean
inf_file_util_write_private_data(const gchar* filename,
const void* data,
size_t length,
GError** error)
{
#ifdef G_OS_WIN32
return g_file_set_contents(
filename,
data,
length,
error
);
#else
gchar *temp_file = g_strconcat(filename, ".XXXXXX", NULL);
gint fd = g_mkstemp_full(
temp_file,
O_WRONLY|O_CREAT|O_TRUNC,
0600
);
if (fd == -1)
{
inf_file_util_set_error_from_errno(error, errno);
g_free(temp_file);
return FALSE;
}
size_t remaining = length;
while (remaining > 0)
{
ssize_t written = write(fd, data, remaining);
if (written == -1)
{
inf_file_util_set_error_from_errno(error, errno);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must be called before g_close, because otherwise the call to g_close can modify errno (for example set it to 0 if close() was successful).

Also, g_close should either be called with NULL error, or, if you want to handle errors during close, a local GError and use g_warning to print a warning (I don't think there is much value in somehow trying to return a GError from g_close to the caller if write already failed).

g_close(fd, NULL);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a g_unlink(temp_file) missing here

g_unlink(temp_file);
g_free(temp_file);
return FALSE;
}
remaining -= written;
Copy link
Copy Markdown
Contributor

@aburgm aburgm May 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data needs to be advanced by written bytes at this point, or in the next iteration of the loop it will point to an incorrect location. Sorry I didn't see this the first time.

data = ((gchar*)data) + written;
}
if (g_close(fd, error) == FALSE)
{
g_unlink(temp_file);
g_free(temp_file);
return FALSE;
}
if (g_rename(temp_file, filename) == -1)
{
inf_file_util_set_error_from_errno(error, errno);
g_unlink(temp_file);
g_free(temp_file);
return FALSE;
}
g_free(temp_file);
return TRUE;
#endif
}

/* vim:set et sw=2 ts=2: */
6 changes: 6 additions & 0 deletions libinfinity/common/inf-file-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ gboolean
inf_file_util_delete(const gchar* path,
GError** error);

gboolean
inf_file_util_write_private_data(const gchar* filename,
const void* data,
size_t length,
GError** error);

G_END_DECLS

#endif /* __INF_FILE_UTIL_H__ */
Expand Down