summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McDermott <patrick.mcdermott@libiquity.com>2023-05-22 20:40:43 (EDT)
committer Patrick McDermott <patrick.mcdermott@libiquity.com>2023-05-28 19:10:32 (EDT)
commit2a5c9127ad298fd8ad11579f33c4d931d59c53dc (patch)
treeea5a9cb9cd17771dc5aa4cbb1e9e26593910046f
parent194db3b3400e2f56a91e1e97ab14f6a475d4ea75 (diff)
opk/write: Fix path length handling, add virt path
-rw-r--r--src/opk.c3
-rw-r--r--src/opk/opk.h6
-rw-r--r--src/opk/write.c78
3 files changed, 47 insertions, 40 deletions
diff --git a/src/opk.c b/src/opk.c
index 178db6c..e1d7a43 100644
--- a/src/opk.c
+++ b/src/opk.c
@@ -18,6 +18,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include "defs.h"
#include "specials.h"
#include "opk.h"
@@ -109,6 +110,7 @@ int
opkg_opk_opk_control_dir(struct opkg_opk_opk *opk, const char *dir)
{
opk->control_dir = dir;
+ opk->control_dir_len = strlen(dir);
return OPKG_OPK_OK;
}
@@ -116,6 +118,7 @@ int
opkg_opk_opk_data_dir(struct opkg_opk_opk *opk, const char *dir)
{
opk->data_dir = dir;
+ opk->data_dir_len = strlen(dir);
return OPKG_OPK_OK;
}
diff --git a/src/opk/opk.h b/src/opk/opk.h
index d66e0a7..e57be4f 100644
--- a/src/opk/opk.h
+++ b/src/opk/opk.h
@@ -39,7 +39,9 @@ struct opkg_opk_opk {
int list_control;
int list_data;
const char *control_dir;
+ size_t control_dir_len;
const char *data_dir;
+ size_t data_dir_len;
FILE *file;
struct opkg_opk_specials *specials;
char file_buffer[8192];
@@ -52,8 +54,8 @@ struct opkg_opk_opk {
struct opkg_opk_gzip *inner_gzip;
struct opkg_opk_ustar *inner_ustar;
int previously_printed;
- size_t path_len;
- char *path;
+ char *path_real;
+ char *path_virt;
char *temp_file_name;
};
diff --git a/src/opk/write.c b/src/opk/write.c
index fa13dbf..c3a88c8 100644
--- a/src/opk/write.c
+++ b/src/opk/write.c
@@ -81,10 +81,9 @@ _opkg_opk_opk_write_compar(const struct dirent **a, const struct dirent **b)
return strcmp((*a)->d_name, (*b)->d_name);
}
-/* path_len excludes '\0' */
static int
_opkg_opk_opk_write_dir_read(struct opkg_opk_opk *opk,
- struct opkg_opk_dirent *dir)
+ struct opkg_opk_dirent *dir, size_t path_off)
{
int ret;
char *child_path;
@@ -110,25 +109,15 @@ _opkg_opk_opk_write_dir_read(struct opkg_opk_opk *opk,
ret = OPKG_OPK_OK;
- child_path = strchr(opk->path, '\0');
- if (opk->path_len < 2) {
- fprintf(stderr, "Error: File name \"%s\" too long", opk->path);
- ret = OPKG_OPK_ERROR;
- goto out0;
- }
- *child_path = '/';
- ++child_path;
- *child_path = '\0';
- --opk->path_len;
-
- children_n = scandir(opk->path, &children, _opkg_opk_opk_write_filter,
+ child_path = opk->path_virt + path_off;
+ children_n = scandir(opk->path_real, &children, _opkg_opk_opk_write_filter,
_opkg_opk_opk_write_compar);
for (children_i = 0; children_i < children_n; ++children_i) {
child.name = children[children_i]->d_name;
child.parent = dir;
for (name_i = 0; children[children_i]->d_name[name_i] != '\0';
++name_i) {
- if (name_i == opk->path_len) {
+ if (path_off + name_i + 1 == OPKG_OPK_USTAR_NAME_SIZE) {
fprintf(stderr, "Error: File name \"%s\" too "
"long",
children[children_i]->d_name);
@@ -139,9 +128,9 @@ _opkg_opk_opk_write_dir_read(struct opkg_opk_opk *opk,
children[children_i]->d_name[name_i];
}
child_path[name_i] = '\0';
- if (lstat(opk->path, &st) != 0) {
+ if (lstat(opk->path_real, &st) != 0) {
fprintf(stderr, _("Error: Failed to stat \"%s\"\n"),
- opk->path);
+ opk->path_real);
ret = OPKG_OPK_ERROR;
goto out1;
}
@@ -151,6 +140,14 @@ _opkg_opk_opk_write_dir_read(struct opkg_opk_opk *opk,
gid = st.st_gid;
gname = getgrgid(gid)->gr_name;
if (S_ISDIR(st.st_mode)) {
+ if (path_off + name_i + 2 == OPKG_OPK_USTAR_NAME_SIZE) {
+ fprintf(stderr, "Error: File name \"%s\" too "
+ "long", child_path);
+ ret = OPKG_OPK_ERROR;
+ goto out1;
+ }
+ child_path[name_i] = '/';
+ child_path[++name_i] = '\0';
if (opkg_opk_ustar_write_header(opk->inner_ustar,
&child, st.st_mode & 0777,
uid, uname, gid, gname, 0, 0, 0,
@@ -161,13 +158,14 @@ _opkg_opk_opk_write_dir_read(struct opkg_opk_opk *opk,
ret = OPKG_OPK_ERROR;
goto out1;
}
- if (_opkg_opk_opk_write_dir_read(opk, &child) !=
+ if (_opkg_opk_opk_write_dir_read(opk, &child,
+ path_off + name_i) !=
OPKG_OPK_OK) {
ret = OPKG_OPK_ERROR;
goto out1;
}
} else if (S_ISLNK(st.st_mode)) {
- link_len = readlink(opk->path, link,
+ link_len = readlink(opk->path_real, link,
OPKG_OPK_USTAR_LINKNAME_SIZE);
if (link_len < 0) {
ret = OPKG_OPK_ERROR;
@@ -236,10 +234,11 @@ _opkg_opk_opk_write_dir_read(struct opkg_opk_opk *opk,
ret = OPKG_OPK_ERROR;
goto out1;
}
- fp = fopen(opk->path, "rb");
+ fp = fopen(opk->path_real, "rb");
if (fp == NULL) {
fprintf(stderr, _("Error: Failed to open file "
- "\"%s\"\n"), opk->path);
+ "\"%s\"\n"),
+ opk->path_real);
ret = OPKG_OPK_ERROR;
goto out1;
}
@@ -273,7 +272,7 @@ _opkg_opk_opk_write_dir_read(struct opkg_opk_opk *opk,
}
} else {
fprintf(stderr, _("Error: Unknown type of file \"%s\"\n"
- ), opk->path);
+ ), opk->path_real);
ret = OPKG_OPK_ERROR;
goto out1;
}
@@ -334,12 +333,15 @@ _opkg_opk_opk_build_inner_archive(struct opkg_opk_opk *opk,
dirent.name = ".";
dirent.parent = NULL;
if (archive_type == OPKG_OPK_OPK_ARCHIVE_TYPE_CONTROL_) {
- strcpy(opk->path, opk->control_dir);
+ sprintf(opk->path_real, "%s/", opk->control_dir);
+ opk->path_virt = opk->path_real + opk->control_dir_len;
} else {
- strcpy(opk->path, opk->data_dir);
+ sprintf(opk->path_real, "%s/", opk->data_dir);
+ opk->path_virt = opk->path_real + opk->data_dir_len;
}
- if (stat(opk->path, &st) != 0) {
- fprintf(stderr, _("Error: Failed to stat \"%s\"\n"), opk->path);
+ if (stat(opk->path_real, &st) != 0) {
+ fprintf(stderr, _("Error: Failed to stat \"%s\"\n"),
+ opk->path_real);
goto err3;
}
uid = st.st_uid;
@@ -353,7 +355,8 @@ _opkg_opk_opk_build_inner_archive(struct opkg_opk_opk *opk,
stderr);
goto err3;
}
- if (_opkg_opk_opk_write_dir_read(opk, &dirent) != OPKG_OPK_OK) {
+ if (_opkg_opk_opk_write_dir_read(opk, &dirent, 1 /* Skip '/' */) !=
+ OPKG_OPK_OK) {
goto err3;
}
@@ -426,8 +429,7 @@ opkg_opk_opk_write(struct opkg_opk_opk *opk, const char *file_name)
struct opkg_opk_dirent dirent;
char *buffer;
size_t size;
- size_t control_dir_len;
- size_t data_dir_len;
+ size_t path_len;
ret = OPKG_OPK_OK;
@@ -487,14 +489,14 @@ opkg_opk_opk_write(struct opkg_opk_opk *opk, const char *file_name)
}
/* Allocate control and data file path buffer. */
- opk->path_len = control_dir_len = strlen(opk->control_dir);
- data_dir_len = strlen(opk->data_dir);
- if (data_dir_len > opk->path_len) {
- opk->path_len = data_dir_len;
- }
- opk->path_len += 257;
- opk->path = malloc(opk->path_len);
- if (opk->path == NULL) {
+ if (opk->control_dir_len >= opk->data_dir_len) {
+ path_len = opk->control_dir_len;
+ } else {
+ path_len = opk->data_dir_len;
+ }
+ path_len += 1 /* '/' */ + OPKG_OPK_USTAR_NAME_SIZE;
+ opk->path_real = malloc(path_len);
+ if (opk->path_real == NULL) {
ret = OPKG_OPK_ERROR;
goto out3;
}
@@ -530,7 +532,7 @@ opkg_opk_opk_write(struct opkg_opk_opk *opk, const char *file_name)
out5:
free(opk->temp_file_name);
out4:
- free(opk->path);
+ free(opk->path_real);
out3:
opkg_opk_ustar_free(opk->outer_ustar);
out2: