* [PATCH 00/19] reftable: stop using "git-compat-util.h"
@ 2025-01-27 13:04 Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 01/19] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
` (24 more replies)
0 siblings, 25 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Hi,
this patch series is the final step to fully decouple the reftable
library from the rest of the Git codebase. The goal of this is to make
the library reusable by other projects like libgit2 by simply copying
over the source files, making Git the canonical upstream for reftable
functionality.
This patch series stops using all kinds of helpers exposed by our
"git-compat-util.h" header and open-codes them instead. In order to keep
us from using these helpers by accident the final step is to pull out
POSIX-related bits and pieces into a new "compat/posix.h" header, which
the reftable library then uses instead of "git-compat-util.h".
The series is built on top of master at 5f8f7081f7 (The third batch,
2025-01-23) with ps/reftable-sign-compare at 33319b0976 (reftable:
address trivial -Wsign-compare warnings, 2025-01-20) merged into it.
There is a trivial merge conflict with ps/zlib-ng that can be solved
like this:
diff --cc reftable/system.h
index e4a8944a70,d02eacea8f..0000000000
--- a/reftable/system.h
+++ b/reftable/system.h
@@@ -11,15 -11,9 +11,15 @@@ https://developers.google.com/open-sour
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "compat/posix.h"
- #include <zlib.h>
+ #include "compat/zlib-compat.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
Thanks!
Patrick
---
Patrick Steinhardt (19):
reftable/stack: stop using `read_in_full()`
reftable/stack: stop using `write_in_full()`
reftable/blocksource: stop using `xmmap()`
reftable/record: stop using `COPY_ARRAY()`
reftable/record: stop using `BUG()` in `reftable_record_init()`
reftable/record: don't `BUG()` in `reftable_record_cmp()`
reftable: stop using `BUG()` in trivial cases
reftable/basics: stop using `st_mult()` in array allocators
reftable/basics: provide wrappers for big endian conversion
reftable/reader: stop using `ARRAY_SIZE()` macro
reftable/system: introduce `reftable_rand()`
reftable/stack: stop using `sleep_millisec()`
reftable/basics: stop using `SWAP()` macro
reftable/basics: stop using `UNUSED` annotation
compat/mingw: split out POSIX-related bits
compat/msvc: split out POSIX-related bits
git-compat-util.h: split out POSIX-emulating bits
reftable: decouple from Git codebase by pulling in "compat/posix.h"
Makefile: skip reftable library for Coccinelle
Makefile | 2 +-
compat/{mingw.c => mingw/compat-util.c} | 0
compat/mingw/compat-util.h | 220 +++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------
compat/{msvc.c => msvc/compat-util.c} | 2 +-
compat/msvc/compat-util.h | 7 +
compat/{msvc.h => msvc/posix.h} | 8 +-
compat/posix.h | 541 ++++++++++++++++++++++++++++++++
config.mak.uname | 6 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 535 +------------------------------
meson.build | 8 +-
reftable/basics.c | 19 --
reftable/basics.h | 123 +++++++-
reftable/block.c | 16 +-
reftable/blocksource.c | 21 +-
reftable/iter.c | 20 +-
reftable/merged.c | 27 +-
reftable/pq.c | 40 ++-
reftable/pq.h | 2 +-
reftable/reader.c | 33 +-
reftable/record.c | 96 +++---
reftable/record.h | 6 +-
reftable/stack.c | 52 ++-
reftable/system.c | 7 +
reftable/system.h | 9 +-
reftable/writer.c | 29 +-
t/unit-tests/t-reftable-basics.c | 28 +-
t/unit-tests/t-reftable-pq.c | 22 +-
t/unit-tests/t-reftable-record.c | 42 ++-
30 files changed, 1214 insertions(+), 925 deletions(-)
---
base-commit: 5f8f7081f7761acdf83d0a4c6819fe3d724f01d7
change-id: 20241119-pks-reftable-drop-git-compat-util-470f2bfde562
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH 01/19] reftable/stack: stop using `read_in_full()`
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 16:57 ` Justin Tobler
2025-01-27 13:04 ` [PATCH 02/19] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
` (23 subsequent siblings)
24 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
There is a single callsite of `read_in_full()` in the reftable library.
Open-code the function to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index f7c1845e15..9490366795 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -115,13 +115,16 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
static int fd_read_lines(int fd, char ***namesp)
{
- off_t size = lseek(fd, 0, SEEK_END);
char *buf = NULL;
int err = 0;
+ off_t size;
+
+ size = lseek(fd, 0, SEEK_END);
if (size < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
+
err = lseek(fd, 0, SEEK_SET);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp)
goto done;
}
- if (read_in_full(fd, buf, size) != size) {
- err = REFTABLE_IO_ERROR;
- goto done;
+ for (size_t total_read = 0; total_read < (size_t) size; ) {
+ ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
+ if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_read < 0 || !bytes_read) {
+ err = REFTABLE_IO_ERROR;
+ goto done;
+ }
+
+ total_read += bytes_read;
}
buf[size] = 0;
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 02/19] reftable/stack: stop using `write_in_full()`
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 01/19] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 03/19] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
` (22 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Similar to the preceding commit, drop our use of `write_in_full()` and
implement a new wrapper `reftable_write_full()` that handles this logic
for us. This is done to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 9490366795..5f155b344b 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -48,6 +48,25 @@ static int stack_fsync(const struct reftable_write_options *opts, int fd)
return fsync(fd);
}
+static ssize_t reftable_write_data(int fd, const void *data, size_t size)
+{
+ size_t total_written = 0;
+ const char *p = data;
+
+ while (total_written < size) {
+ ssize_t bytes_written = write(fd, p, size - total_written);
+ if (bytes_written < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_written < 0)
+ return REFTABLE_IO_ERROR;
+
+ total_written += bytes_written;
+ p += bytes_written;
+ }
+
+ return total_written;
+}
+
struct fd_writer {
const struct reftable_write_options *opts;
int fd;
@@ -56,7 +75,7 @@ struct fd_writer {
static ssize_t fd_writer_write(void *arg, const void *data, size_t sz)
{
struct fd_writer *writer = arg;
- return write_in_full(writer->fd, data, sz);
+ return reftable_write_data(writer->fd, data, sz);
}
static int fd_writer_flush(void *arg)
@@ -784,7 +803,8 @@ int reftable_addition_commit(struct reftable_addition *add)
goto done;
}
- err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len);
+ err = reftable_write_data(add->tables_list_lock.fd,
+ table_list.buf, table_list.len);
reftable_buf_release(&table_list);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -1468,8 +1488,8 @@ static int stack_compact_range(struct reftable_stack *st,
goto done;
}
- err = write_in_full(tables_list_lock.fd,
- tables_list_buf.buf, tables_list_buf.len);
+ err = reftable_write_data(tables_list_lock.fd,
+ tables_list_buf.buf, tables_list_buf.len);
if (err < 0) {
err = REFTABLE_IO_ERROR;
unlink(new_table_path.buf);
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 03/19] reftable/blocksource: stop using `xmmap()`
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 01/19] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 02/19] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 04/19] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
` (21 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
We use `xmmap()` to map reftables into memory. This function has two
problems:
- It causes us to die in case the mmap fails.
- It ties us to the Git codebase.
Refactor the code to use mmap(3p) instead with manual error checking.
Note that this function may not be the system-provided mmap(3p), but may
point to our `git_mmap()` wrapper that emulates the syscall on systems
that do not have mmap(3p) available.
Fix `reftable_block_source_from_file()` to properly bubble up the error
code in case the map(3p) call fails.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/blocksource.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index bba4a45b98..02972c46f4 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -98,7 +98,7 @@ static struct reftable_block_source_vtable file_vtable = {
int reftable_block_source_from_file(struct reftable_block_source *bs,
const char *name)
{
- struct file_block_source *p;
+ struct file_block_source *p = NULL;
struct stat st;
int fd, err;
@@ -122,7 +122,12 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
}
p->size = st.st_size;
- p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ p->data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p->data == MAP_FAILED) {
+ err = REFTABLE_IO_ERROR;
+ p->data = NULL;
+ goto out;
+ }
assert(!bs->ops);
bs->ops = &file_vtable;
@@ -135,5 +140,5 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
close(fd);
if (err < 0)
reftable_free(p);
- return 0;
+ return err;
}
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 04/19] reftable/record: stop using `COPY_ARRAY()`
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (2 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 03/19] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 05/19] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
` (20 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Drop our use of `COPY_ARRAY()`, replacing it with an open-coded variant
thereof. This is done to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/record.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/reftable/record.c b/reftable/record.c
index 8919df8a4d..d1664c47ca 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -508,7 +508,8 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
if (!obj->offsets)
return REFTABLE_OUT_OF_MEMORY_ERROR;
obj->offset_len = src->offset_len;
- COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
+ if (src->offset_len)
+ memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len);
return 0;
}
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 05/19] reftable/record: stop using `BUG()` in `reftable_record_init()`
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (3 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 04/19] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 17:36 ` Justin Tobler
2025-01-27 13:04 ` [PATCH 06/19] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
` (19 subsequent siblings)
24 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
We're aborting the program via `BUG()` in case `reftable_record_init()`
was invoked with an unknown record type. This is bad because we may now
die in library code, and because it makes us depend on the Git codebase.
Refactor the code such that `reftable_record_init()` can return an error
code to the caller. Adapt any callers accordingly.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/block.c | 4 +++-
reftable/merged.c | 5 ++++-
reftable/reader.c | 5 ++++-
reftable/record.c | 8 ++++----
reftable/record.h | 4 ++--
t/unit-tests/t-reftable-pq.c | 6 +++---
t/unit-tests/t-reftable-record.c | 2 +-
7 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/reftable/block.c b/reftable/block.c
index 8ac865ce78..255d566854 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -509,7 +509,9 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,
it->block_len = br->block_len;
it->hash_size = br->hash_size;
- reftable_record_init(&rec, block_reader_type(br));
+ err = reftable_record_init(&rec, block_reader_type(br));
+ if (err < 0)
+ goto done;
/*
* We're looking for the last entry less than the wanted key so that
diff --git a/reftable/merged.c b/reftable/merged.c
index e72b39e178..4156eec07f 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -253,7 +253,10 @@ int merged_table_init_iter(struct reftable_merged_table *mt,
}
for (size_t i = 0; i < mt->readers_len; i++) {
- reftable_record_init(&subiters[i].rec, typ);
+ ret = reftable_record_init(&subiters[i].rec, typ);
+ if (ret < 0)
+ goto out;
+
ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
if (ret < 0)
goto out;
diff --git a/reftable/reader.c b/reftable/reader.c
index 3f2e4b2800..de6e6dd932 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -360,7 +360,10 @@ static int table_iter_seek_linear(struct table_iter *ti,
struct reftable_record rec;
int err;
- reftable_record_init(&rec, reftable_record_type(want));
+ err = reftable_record_init(&rec, reftable_record_type(want));
+ if (err < 0)
+ goto done;
+
err = reftable_record_key(want, &want_key);
if (err < 0)
goto done;
diff --git a/reftable/record.c b/reftable/record.c
index d1664c47ca..31985bb977 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1301,7 +1301,7 @@ reftable_record_vtable(struct reftable_record *rec)
abort();
}
-void reftable_record_init(struct reftable_record *rec, uint8_t typ)
+int reftable_record_init(struct reftable_record *rec, uint8_t typ)
{
memset(rec, 0, sizeof(*rec));
rec->type = typ;
@@ -1310,11 +1310,11 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)
case BLOCK_TYPE_REF:
case BLOCK_TYPE_LOG:
case BLOCK_TYPE_OBJ:
- return;
+ return 0;
case BLOCK_TYPE_INDEX:
reftable_buf_init(&rec->u.idx.last_key);
- return;
+ return 0;
default:
- BUG("unhandled record type");
+ return REFTABLE_API_ERROR;
}
}
diff --git a/reftable/record.h b/reftable/record.h
index c7755a4d75..e1846c294b 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -130,8 +130,8 @@ struct reftable_record {
} u;
};
-/* Initialize the reftable record for the given type */
-void reftable_record_init(struct reftable_record *rec, uint8_t typ);
+/* Initialize the reftable record for the given type. */
+int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index f3f8a0cdf3..d8a4c283a1 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -32,7 +32,7 @@ static void t_pq_record(void)
char *last = NULL;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
}
@@ -72,7 +72,7 @@ static void t_pq_index(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
@@ -111,7 +111,7 @@ static void t_merged_iter_pqueue_top(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index d49d2a2729..6540bd20e3 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -17,7 +17,7 @@ static void t_copy(struct reftable_record *rec)
uint8_t typ;
typ = reftable_record_type(rec);
- reftable_record_init(©, typ);
+ check(!reftable_record_init(©, typ));
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
/* do it twice to catch memory leaks */
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 06/19] reftable/record: don't `BUG()` in `reftable_record_cmp()`
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (4 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 05/19] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 19:21 ` Justin Tobler
2025-01-27 13:04 ` [PATCH 07/19] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
` (18 subsequent siblings)
24 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
The refatble library aborts with a bug in case `reftable_record_cmp()`
is invoked with two records of differing types. This would cause the
program to die without the caller being able to handle the error, which
is not something we want in the context of library code. And it ties us
to the Git codebase.
Refactor the code such that `reftable_record_cmp()` returns an error
code separate from the actual comparison result. This requires us to
also adapt some callers up the callchain in a similar fashion.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/merged.c | 20 +++++++++++++++-----
reftable/pq.c | 36 +++++++++++++++++++++++++++++-------
reftable/pq.h | 2 +-
reftable/record.c | 10 ++++++----
reftable/record.h | 2 +-
t/unit-tests/t-reftable-pq.c | 16 ++++++++++++----
t/unit-tests/t-reftable-record.c | 40 ++++++++++++++++++++++++++++------------
7 files changed, 92 insertions(+), 34 deletions(-)
diff --git a/reftable/merged.c b/reftable/merged.c
index 4156eec07f..563864068c 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -66,8 +66,11 @@ static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want
int err;
mi->advance_index = -1;
- while (!merged_iter_pqueue_is_empty(mi->pq))
- merged_iter_pqueue_remove(&mi->pq);
+ while (!merged_iter_pqueue_is_empty(mi->pq)) {
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+ }
for (size_t i = 0; i < mi->subiters_len; i++) {
err = iterator_seek(&mi->subiters[i].iter, want);
@@ -120,7 +123,9 @@ static int merged_iter_next_entry(struct merged_iter *mi,
if (empty)
return 1;
- entry = merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, &entry);
+ if (err < 0)
+ return err;
/*
One can also use reftable as datacenter-local storage, where the ref
@@ -134,11 +139,16 @@ static int merged_iter_next_entry(struct merged_iter *mi,
struct pq_entry top = merged_iter_pqueue_top(mi->pq);
int cmp;
- cmp = reftable_record_cmp(top.rec, entry.rec);
+ err = reftable_record_cmp(top.rec, entry.rec, &cmp);
+ if (err < 0)
+ return err;
if (cmp > 0)
break;
- merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+
err = merged_iter_advance_subiter(mi, top.index);
if (err < 0)
return err;
diff --git a/reftable/pq.c b/reftable/pq.c
index 5591e875e1..ef8035cfd9 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -15,13 +15,18 @@ license that can be found in the LICENSE file or at
int pq_less(struct pq_entry *a, struct pq_entry *b)
{
- int cmp = reftable_record_cmp(a->rec, b->rec);
+ int cmp, err;
+
+ err = reftable_record_cmp(a->rec, b->rec, &cmp);
+ if (err < 0)
+ return err;
+
if (cmp == 0)
return a->index > b->index;
return cmp < 0;
}
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out)
{
size_t i = 0;
struct pq_entry e = pq->heap[0];
@@ -32,17 +37,34 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
size_t min = i;
size_t j = 2 * i + 1;
size_t k = 2 * i + 2;
- if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i]))
- min = j;
- if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min]))
- min = k;
+ int cmp;
+
+ if (j < pq->len) {
+ cmp = pq_less(&pq->heap[j], &pq->heap[i]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = j;
+ }
+
+ if (k < pq->len) {
+ cmp = pq_less(&pq->heap[k], &pq->heap[min]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = k;
+ }
+
if (min == i)
break;
SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
- return e;
+ if (out)
+ *out = e;
+
+ return 0;
}
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
diff --git a/reftable/pq.h b/reftable/pq.h
index 83c062eeca..ff39016445 100644
--- a/reftable/pq.h
+++ b/reftable/pq.h
@@ -22,7 +22,7 @@ struct merged_iter_pqueue {
size_t cap;
};
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out);
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
diff --git a/reftable/record.c b/reftable/record.c
index 31985bb977..da550494a2 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1190,12 +1190,14 @@ int reftable_record_is_deletion(struct reftable_record *rec)
reftable_record_data(rec));
}
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b)
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b,
+ int *cmp)
{
if (a->type != b->type)
- BUG("cannot compare reftable records of different type");
- return reftable_record_vtable(a)->cmp(
- reftable_record_data(a), reftable_record_data(b));
+ return -1;
+ *cmp = reftable_record_vtable(a)->cmp(reftable_record_data(a),
+ reftable_record_data(b));
+ return 0;
}
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size)
diff --git a/reftable/record.h b/reftable/record.h
index e1846c294b..867810a932 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -134,7 +134,7 @@ struct reftable_record {
int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b, int *cmp);
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size);
int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);
int reftable_record_copy_from(struct reftable_record *rec,
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index d8a4c283a1..c128fe8616 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -21,7 +21,9 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq)
static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b)
{
- return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index);
+ int cmp;
+ check(!reftable_record_cmp(a->rec, b->rec, &cmp));
+ return !cmp && (a->index == b->index);
}
static void t_pq_record(void)
@@ -49,7 +51,9 @@ static void t_pq_record(void)
while (!merged_iter_pqueue_is_empty(pq)) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -90,7 +94,9 @@ static void t_pq_index(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -129,7 +135,9 @@ static void t_merged_iter_pqueue_top(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index 6540bd20e3..5954966373 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -100,16 +100,20 @@ static void t_reftable_ref_record_comparison(void)
.u.ref.value.symref = (char *) "refs/heads/master",
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.ref.value_type = in[0].u.ref.value_type;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_ref_record_compare_name(void)
@@ -209,17 +213,20 @@ static void t_reftable_log_record_comparison(void)
.u.log.update_index = 22,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
/* comparison should be reversed for equal keys, because
* comparison is now performed on the basis of update indices */
- check_int(reftable_record_cmp(&in[0], &in[1]), <, 0);
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check_int(cmp, <, 0);
in[1].u.log.update_index = in[0].u.log.update_index;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
}
static void t_reftable_log_record_compare_key(void)
@@ -396,16 +403,20 @@ static void t_reftable_obj_record_comparison(void)
.u.obj.hash_prefix_len = 5,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.obj.offset_len = in[0].u.obj.offset_len;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_obj_record_roundtrip(void)
@@ -486,19 +497,24 @@ static void t_reftable_index_record_comparison(void)
.u.idx.last_key = REFTABLE_BUF_INIT,
},
};
+ int cmp;
+
check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch"));
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.idx.offset = in[0].u.idx.offset;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
for (size_t i = 0; i < ARRAY_SIZE(in); i++)
reftable_record_release(&in[i]);
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 07/19] reftable: stop using `BUG()` in trivial cases
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (5 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 06/19] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 08/19] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
` (17 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Stop using `BUG()` in the remaining trivial cases that we still have in
the reftable library. Instead of aborting the program, we'll now bubble
up a `REFTABLE_API_ERROR` to indicate misuse of the calling conventions.
Note that in both `reftable_reader_{inc,dec}ref()` we simply stop
calling `BUG()` altogether. The only situation where the counter should
be zero is when the structure has already been free'd anyway, so we
would run into undefined behaviour regardless of whether we try to abort
the program or not.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/iter.c | 3 +--
reftable/reader.c | 4 ----
reftable/writer.c | 5 ++---
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/reftable/iter.c b/reftable/iter.c
index 86e801ca9f..b2ffb09c16 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -146,8 +146,7 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
static int indexed_table_ref_iter_seek(void *p UNUSED,
struct reftable_record *want UNUSED)
{
- BUG("seeking indexed table is not supported");
- return -1;
+ return REFTABLE_API_ERROR;
}
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
diff --git a/reftable/reader.c b/reftable/reader.c
index de6e6dd932..36a5633ede 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -677,8 +677,6 @@ int reftable_reader_new(struct reftable_reader **out,
void reftable_reader_incref(struct reftable_reader *r)
{
- if (!r->refcount)
- BUG("cannot increment ref counter of dead reader");
r->refcount++;
}
@@ -686,8 +684,6 @@ void reftable_reader_decref(struct reftable_reader *r)
{
if (!r)
return;
- if (!r->refcount)
- BUG("cannot decrement ref counter of dead reader");
if (--r->refcount)
return;
block_source_close(&r->source);
diff --git a/reftable/writer.c b/reftable/writer.c
index 91d6629486..155863ee5f 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -158,7 +158,7 @@ int reftable_writer_new(struct reftable_writer **out,
opts = *_opts;
options_set_defaults(&opts);
if (opts.block_size >= (1 << 24))
- BUG("configured block size exceeds 16MB");
+ return REFTABLE_API_ERROR;
reftable_buf_init(&wp->block_writer_data.last_key);
reftable_buf_init(&wp->last_key);
@@ -289,8 +289,7 @@ static int writer_add_record(struct reftable_writer *w,
}
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
- BUG("record of type %d added to writer of type %d",
- reftable_record_type(rec), block_writer_type(w->block_writer));
+ return REFTABLE_API_ERROR;
/*
* Try to add the record to the writer. If this succeeds then we're
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 08/19] reftable/basics: stop using `st_mult()` in array allocators
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (6 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 07/19] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 09/19] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
` (16 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
We're using `st_mult()` as part of our macro helpers that allocate
arrays. This is bad due two two reasons:
- `st_mult()` causes us to die in case the multiplication overflows.
- `st_mult()` ties us to the Git codebase.
Refactor the code to instead detect overflows manually and return an
error in such cases.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index a2a010a0e1..646f8d67f2 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -117,18 +117,46 @@ void reftable_free(void *p);
void *reftable_calloc(size_t nelem, size_t elsize);
char *reftable_strdup(const char *str);
-#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
+static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out)
+{
+ if (nelem && elsize > SIZE_MAX / nelem)
+ return -1;
+ *out = nelem * elsize;
+ return 0;
+}
+
+#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_malloc(alloc_size); \
+ } \
+ } while (0)
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
-#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc)))
+#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_realloc((x), alloc_size); \
+ } \
+ } while (0)
static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
size_t *allocp)
{
void *new_p;
- size_t alloc = *allocp * 2 + 1;
+ size_t alloc = *allocp * 2 + 1, alloc_bytes;
if (alloc < nelem)
alloc = nelem;
- new_p = reftable_realloc(p, st_mult(elsize, alloc));
+ if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) {
+ errno = ENOMEM;
+ return p;
+ }
+ new_p = reftable_realloc(p, alloc_bytes);
if (!new_p)
return p;
*allocp = alloc;
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 09/19] reftable/basics: provide wrappers for big endian conversion
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (7 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 08/19] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 10/19] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
` (15 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
We're using a mixture of big endian conversion functions provided by
both the reftable library, but also by the Git codebase. Refactor the
code so that we exclusively use reftable-provided wrappers in order to
untangle us from the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.c | 19 ----------
reftable/basics.h | 76 ++++++++++++++++++++++++++++++++++++++--
reftable/block.c | 12 +++----
reftable/reader.c | 22 ++++++------
reftable/record.c | 8 ++---
reftable/writer.c | 20 +++++------
t/unit-tests/t-reftable-basics.c | 28 ++++++++++++---
7 files changed, 127 insertions(+), 58 deletions(-)
diff --git a/reftable/basics.c b/reftable/basics.c
index 3b5ea27bbd..8c4a4433e4 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -147,25 +147,6 @@ char *reftable_buf_detach(struct reftable_buf *buf)
return result;
}
-void put_be24(uint8_t *out, uint32_t i)
-{
- out[0] = (uint8_t)((i >> 16) & 0xff);
- out[1] = (uint8_t)((i >> 8) & 0xff);
- out[2] = (uint8_t)(i & 0xff);
-}
-
-uint32_t get_be24(uint8_t *in)
-{
- return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 |
- (uint32_t)(in[2]);
-}
-
-void put_be16(uint8_t *out, uint16_t i)
-{
- out[0] = (uint8_t)((i >> 8) & 0xff);
- out[1] = (uint8_t)(i & 0xff);
-}
-
size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
{
size_t lo = 0;
diff --git a/reftable/basics.h b/reftable/basics.h
index 646f8d67f2..c1ddbaec3f 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -76,9 +76,79 @@ char *reftable_buf_detach(struct reftable_buf *buf);
/* Bigendian en/decoding of integers */
-void put_be24(uint8_t *out, uint32_t i);
-uint32_t get_be24(uint8_t *in);
-void put_be16(uint8_t *out, uint16_t i);
+static inline void reftable_put_be16(void *out, uint16_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 8) & 0xff);
+ p[1] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be24(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 16) & 0xff);
+ p[1] = (uint8_t)((i >> 8) & 0xff);
+ p[2] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be32(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 24) & 0xff);
+ p[1] = (uint8_t)((i >> 16) & 0xff);
+ p[2] = (uint8_t)((i >> 8) & 0xff);
+ p[3] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be64(void *out, uint64_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 56) & 0xff);
+ p[1] = (uint8_t)((i >> 48) & 0xff);
+ p[2] = (uint8_t)((i >> 40) & 0xff);
+ p[3] = (uint8_t)((i >> 32) & 0xff);
+ p[4] = (uint8_t)((i >> 24) & 0xff);
+ p[5] = (uint8_t)((i >> 16) & 0xff);
+ p[6] = (uint8_t)((i >> 8) & 0xff);
+ p[7] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline uint16_t reftable_get_be16(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint16_t)(p[0]) << 8 |
+ (uint16_t)(p[1]) << 0;
+}
+
+static inline uint32_t reftable_get_be24(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 16 |
+ (uint32_t)(p[1]) << 8 |
+ (uint32_t)(p[2]) << 0;
+}
+
+static inline uint32_t reftable_get_be32(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 24 |
+ (uint32_t)(p[1]) << 16 |
+ (uint32_t)(p[2]) << 8|
+ (uint32_t)(p[3]) << 0;
+}
+
+static inline uint64_t reftable_get_be64(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint64_t)(p[0]) << 56 |
+ (uint64_t)(p[1]) << 48 |
+ (uint64_t)(p[2]) << 40 |
+ (uint64_t)(p[3]) << 32 |
+ (uint64_t)(p[4]) << 24 |
+ (uint64_t)(p[5]) << 16 |
+ (uint64_t)(p[6]) << 8 |
+ (uint64_t)(p[7]) << 0;
+}
/*
* find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is
diff --git a/reftable/block.c b/reftable/block.c
index 255d566854..373908807e 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -148,13 +148,13 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
int block_writer_finish(struct block_writer *w)
{
for (uint32_t i = 0; i < w->restart_len; i++) {
- put_be24(w->block + w->next, w->restarts[i]);
+ reftable_put_be24(w->block + w->next, w->restarts[i]);
w->next += 3;
}
- put_be16(w->block + w->next, w->restart_len);
+ reftable_put_be16(w->block + w->next, w->restart_len);
w->next += 2;
- put_be24(w->block + 1 + w->header_off, w->next);
+ reftable_put_be24(w->block + 1 + w->header_off, w->next);
/*
* Log records are stored zlib-compressed. Note that the compression
@@ -216,7 +216,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
{
uint32_t full_block_size = table_block_size;
uint8_t typ = block->data[header_off];
- uint32_t sz = get_be24(block->data + header_off + 1);
+ uint32_t sz = reftable_get_be24(block->data + header_off + 1);
int err = 0;
uint16_t restart_count = 0;
uint32_t restart_start = 0;
@@ -300,7 +300,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
full_block_size = sz;
}
- restart_count = get_be16(block->data + sz - 2);
+ restart_count = reftable_get_be16(block->data + sz - 2);
restart_start = sz - 2 - 3 * restart_count;
restart_bytes = block->data + restart_start;
@@ -355,7 +355,7 @@ int block_reader_first_key(const struct block_reader *br, struct reftable_buf *k
static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx)
{
- return get_be24(br->restart_bytes + 3 * idx);
+ return reftable_get_be24(br->restart_bytes + 3 * idx);
}
void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)
diff --git a/reftable/reader.c b/reftable/reader.c
index 36a5633ede..bf07a0a586 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -101,18 +101,18 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
}
f++;
- r->block_size = get_be24(f);
+ r->block_size = reftable_get_be24(f);
f += 3;
- r->min_update_index = get_be64(f);
+ r->min_update_index = reftable_get_be64(f);
f += 8;
- r->max_update_index = get_be64(f);
+ r->max_update_index = reftable_get_be64(f);
f += 8;
if (r->version == 1) {
r->hash_id = REFTABLE_HASH_SHA1;
} else {
- switch (get_be32(f)) {
+ switch (reftable_get_be32(f)) {
case REFTABLE_FORMAT_ID_SHA1:
r->hash_id = REFTABLE_HASH_SHA1;
break;
@@ -127,24 +127,24 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
f += 4;
}
- r->ref_offsets.index_offset = get_be64(f);
+ r->ref_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->obj_offsets.offset = get_be64(f);
+ r->obj_offsets.offset = reftable_get_be64(f);
f += 8;
r->object_id_len = r->obj_offsets.offset & ((1 << 5) - 1);
r->obj_offsets.offset >>= 5;
- r->obj_offsets.index_offset = get_be64(f);
+ r->obj_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.offset = get_be64(f);
+ r->log_offsets.offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.index_offset = get_be64(f);
+ r->log_offsets.index_offset = reftable_get_be64(f);
f += 8;
computed_crc = crc32(0, footer, f - footer);
- file_crc = get_be32(f);
+ file_crc = reftable_get_be32(f);
f += 4;
if (computed_crc != file_crc) {
err = REFTABLE_FORMAT_ERROR;
@@ -214,7 +214,7 @@ static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
*typ = data[0];
if (reftable_is_block_type(*typ)) {
- result = get_be24(data + 1);
+ result = reftable_get_be24(data + 1);
}
return result;
}
diff --git a/reftable/record.c b/reftable/record.c
index da550494a2..286659c098 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -684,7 +684,7 @@ static int reftable_log_record_key(const void *r, struct reftable_buf *dest)
return err;
ts = (~ts) - rec->update_index;
- put_be64(&i64[0], ts);
+ reftable_put_be64(&i64[0], ts);
err = reftable_buf_add(dest, i64, sizeof(i64));
if (err < 0)
@@ -809,7 +809,7 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,
if (s.len < 2)
return -1;
- put_be16(s.buf, r->value.update.tz_offset);
+ reftable_put_be16(s.buf, r->value.update.tz_offset);
string_view_consume(&s, 2);
n = encode_string(
@@ -841,7 +841,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
}
memcpy(r->refname, key.buf, key.len - 8);
- ts = get_be64(key.buf + key.len - 8);
+ ts = reftable_get_be64((unsigned char *)key.buf + key.len - 8);
r->update_index = (~max) - ts;
@@ -932,7 +932,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
goto done;
}
- r->value.update.tz_offset = get_be16(in.buf);
+ r->value.update.tz_offset = reftable_get_be16(in.buf);
string_view_consume(&in, 2);
n = decode_string(scratch, in);
diff --git a/reftable/writer.c b/reftable/writer.c
index 155863ee5f..5961698311 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -99,9 +99,9 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
dest[4] = writer_version(w);
- put_be24(dest + 5, w->opts.block_size);
- put_be64(dest + 8, w->min_update_index);
- put_be64(dest + 16, w->max_update_index);
+ reftable_put_be24(dest + 5, w->opts.block_size);
+ reftable_put_be64(dest + 8, w->min_update_index);
+ reftable_put_be64(dest + 16, w->max_update_index);
if (writer_version(w) == 2) {
uint32_t hash_id;
@@ -116,7 +116,7 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
return -1;
}
- put_be32(dest + 24, hash_id);
+ reftable_put_be32(dest + 24, hash_id);
}
return header_size(writer_version(w));
@@ -717,19 +717,19 @@ int reftable_writer_close(struct reftable_writer *w)
}
p += writer_write_header(w, footer);
- put_be64(p, w->stats.ref_stats.index_offset);
+ reftable_put_be64(p, w->stats.ref_stats.index_offset);
p += 8;
- put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
+ reftable_put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
p += 8;
- put_be64(p, w->stats.obj_stats.index_offset);
+ reftable_put_be64(p, w->stats.obj_stats.index_offset);
p += 8;
- put_be64(p, w->stats.log_stats.offset);
+ reftable_put_be64(p, w->stats.log_stats.offset);
p += 8;
- put_be64(p, w->stats.log_stats.index_offset);
+ reftable_put_be64(p, w->stats.log_stats.index_offset);
p += 8;
- put_be32(p, crc32(0, footer, p - footer));
+ reftable_put_be32(p, crc32(0, footer, p - footer));
p += 4;
err = w->flush(w->write_arg);
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
index 9ba7eb05ad..c9e751e49e 100644
--- a/t/unit-tests/t-reftable-basics.c
+++ b/t/unit-tests/t-reftable-basics.c
@@ -128,12 +128,30 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
reftable_buf_release(&b);
}
- if_test ("put_be24 and get_be24 work") {
+ if_test ("reftable_put_be64 and reftable_get_be64 work") {
+ uint64_t in = 0x1122334455667788;
+ uint8_t dest[8];
+ uint64_t out;
+ reftable_put_be64(dest, in);
+ out = reftable_get_be64(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be32 and reftable_get_be32 work") {
+ uint32_t in = 0x11223344;
+ uint8_t dest[4];
+ uint32_t out;
+ reftable_put_be32(dest, in);
+ out = reftable_get_be32(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be24 and reftable_get_be24 work") {
uint32_t in = 0x112233;
uint8_t dest[3];
uint32_t out;
- put_be24(dest, in);
- out = get_be24(dest);
+ reftable_put_be24(dest, in);
+ out = reftable_get_be24(dest);
check_int(in, ==, out);
}
@@ -141,8 +159,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
uint32_t in = 0xfef1;
uint8_t dest[3];
uint32_t out;
- put_be16(dest, in);
- out = get_be16(dest);
+ reftable_put_be16(dest, in);
+ out = reftable_get_be16(dest);
check_int(in, ==, out);
}
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 10/19] reftable/reader: stop using `ARRAY_SIZE()` macro
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (8 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 09/19] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 11/19] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
` (14 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
We have a single user of the `ARRAY_SIZE()` macro in the reftable
reader. Drop its use to reduce our dependence on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/reader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/reader.c b/reftable/reader.c
index bf07a0a586..c3a3674665 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -849,7 +849,7 @@ int reftable_reader_print_blocks(const char *tablename)
printf("header:\n");
printf(" block_size: %d\n", r->block_size);
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
+ for (i = 0; i < sizeof(sections) / sizeof(*sections); i++) {
err = table_iter_seek_start(&ti, sections[i].type, 0);
if (err < 0)
goto done;
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 11/19] reftable/system: introduce `reftable_rand()`
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (9 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 10/19] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 12/19] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
` (13 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Introduce a new system-level `reftable_rand()` function that generates a
single unsigned integer for us. The implementation of this function is
to be provided by the calling codebase, which allows us to more easily
hook into pre-seeded random number generators.
Adapt the two callsites where we generated random data.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 4 ++--
reftable/system.c | 5 +++++
reftable/system.h | 6 ++++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 5f155b344b..82bdf5169f 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -523,7 +523,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
close(fd);
fd = -1;
- delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1;
+ delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
sleep_millisec(delay);
}
@@ -688,7 +688,7 @@ int reftable_stack_add(struct reftable_stack *st,
static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
{
char buf[100];
- uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE);
+ uint32_t rnd = reftable_rand();
snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
min, max, rnd);
reftable_buf_reset(dest);
diff --git a/reftable/system.c b/reftable/system.c
index adf8e4d30b..e25ccc0da3 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -4,6 +4,11 @@
#include "../lockfile.h"
#include "../tempfile.h"
+uint32_t reftable_rand(void)
+{
+ return git_rand(CSPRNG_BYTES_INSECURE);
+}
+
int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern)
{
struct tempfile *tempfile;
diff --git a/reftable/system.h b/reftable/system.h
index 7d5f803eeb..3bd4a4e322 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -13,6 +13,12 @@ license that can be found in the LICENSE file or at
#include "git-compat-util.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 12/19] reftable/stack: stop using `sleep_millisec()`
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (10 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 11/19] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 13/19] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
` (12 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Refactor our use of `sleep_millisec()` by open-coding it with poll(3p),
which is the current implementation of this function. Ideally, we'd use
a more direct way to sleep, but there is no equivalent to sleep(3p) that
would accept milliseconds as input.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 82bdf5169f..8e9836aef3 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -524,7 +524,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
fd = -1;
delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
- sleep_millisec(delay);
+ poll(NULL, 0, delay);
}
out:
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 13/19] reftable/basics: stop using `SWAP()` macro
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (11 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 12/19] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 14/19] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
` (11 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Stop using `SWAP()` macro in favor of an open-coded variant of it. Note
that this also requires us to open-code the build assert that `SWAP()`
itself uses to verify that the size of both variables matches.
This is done to reduce our dependency on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 9 +++++++++
reftable/merged.c | 2 +-
reftable/pq.c | 4 ++--
reftable/record.c | 16 ++++++++--------
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index c1ddbaec3f..59000798f0 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -266,6 +266,15 @@ static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
# define strdup(str) REFTABLE_BANNED(strdup)
#endif
+#define REFTABLE_SWAP(a, b) do { \
+ void *_swap_a_ptr = &(a); \
+ void *_swap_b_ptr = &(b); \
+ unsigned char _swap_buffer[sizeof(a) - 2 * sizeof(a) * (sizeof(a) != sizeof(b))]; \
+ memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \
+ memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a)); \
+ memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
+} while (0)
+
/* Find the longest shared prefix size of `a` and `b` */
size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);
diff --git a/reftable/merged.c b/reftable/merged.c
index 563864068c..4ff1553772 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -155,7 +155,7 @@ static int merged_iter_next_entry(struct merged_iter *mi,
}
mi->advance_index = entry.index;
- SWAP(*rec, *entry.rec);
+ REFTABLE_SWAP(*rec, *entry.rec);
return 0;
}
diff --git a/reftable/pq.c b/reftable/pq.c
index ef8035cfd9..82394a972d 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -57,7 +57,7 @@ int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *ou
if (min == i)
break;
- SWAP(pq->heap[i], pq->heap[min]);
+ REFTABLE_SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
@@ -81,7 +81,7 @@ int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry
size_t j = (i - 1) / 2;
if (pq_less(&pq->heap[j], &pq->heap[i]))
break;
- SWAP(pq->heap[j], pq->heap[i]);
+ REFTABLE_SWAP(pq->heap[j], pq->heap[i]);
i = j;
}
diff --git a/reftable/record.c b/reftable/record.c
index 286659c098..d86cd65bb4 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -237,11 +237,11 @@ static int reftable_ref_record_copy_from(void *rec, const void *src_rec,
size_t refname_cap = 0;
int err;
- SWAP(refname, ref->refname);
- SWAP(refname_cap, ref->refname_cap);
+ REFTABLE_SWAP(refname, ref->refname);
+ REFTABLE_SWAP(refname_cap, ref->refname_cap);
reftable_ref_record_release(ref);
- SWAP(ref->refname, refname);
- SWAP(ref->refname_cap, refname_cap);
+ REFTABLE_SWAP(ref->refname, refname);
+ REFTABLE_SWAP(ref->refname_cap, refname_cap);
if (src->refname) {
size_t refname_len = strlen(src->refname);
@@ -376,11 +376,11 @@ static int reftable_ref_record_decode(void *rec, struct reftable_buf key,
return n;
string_view_consume(&in, n);
- SWAP(refname, r->refname);
- SWAP(refname_cap, r->refname_cap);
+ REFTABLE_SWAP(refname, r->refname);
+ REFTABLE_SWAP(refname_cap, r->refname_cap);
reftable_ref_record_release(r);
- SWAP(r->refname, refname);
- SWAP(r->refname_cap, refname_cap);
+ REFTABLE_SWAP(r->refname, refname);
+ REFTABLE_SWAP(r->refname_cap, refname_cap);
REFTABLE_ALLOC_GROW_OR_NULL(r->refname, key.len + 1, r->refname_cap);
if (!r->refname) {
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 14/19] reftable/basics: stop using `UNUSED` annotation
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (12 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 13/19] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 15/19] compat/mingw: split out POSIX-related bits Patrick Steinhardt
` (10 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Stop using the `UNUSED` annotation and replace it with a new
`REFTABLE_UNUSED` macro. The latter is a weaker guarantee compared to
`UNUSED` as it only suppresses unused parameters without generating a
warning in case a parameter marked as unused is in fact used. But it's
good enough, and by relaxing the behaviour a bit we avoid having to wire
up compiler-specific logic.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 2 ++
reftable/blocksource.c | 10 +++++++---
reftable/iter.c | 17 ++++++++++++-----
reftable/record.c | 51 ++++++++++++++++++++++++++++++++++++--------------
reftable/writer.c | 4 +++-
5 files changed, 61 insertions(+), 23 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index 59000798f0..4d0645a4e9 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -16,6 +16,8 @@ license that can be found in the LICENSE file or at
#include "system.h"
#include "reftable-basics.h"
+#define REFTABLE_UNUSED(x) (void)(x)
+
struct reftable_buf {
size_t alloc;
size_t len;
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index 02972c46f4..bfd64b0e48 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -13,15 +13,17 @@ license that can be found in the LICENSE file or at
#include "reftable-blocksource.h"
#include "reftable-error.h"
-static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)
+static void reftable_buf_return_block(void *b, struct reftable_block *dest)
{
+ REFTABLE_UNUSED(b);
if (dest->len)
memset(dest->data, 0xff, dest->len);
reftable_free(dest->data);
}
-static void reftable_buf_close(void *b UNUSED)
+static void reftable_buf_close(void *b)
{
+ REFTABLE_UNUSED(b);
}
static ssize_t reftable_buf_read_block(void *v, struct reftable_block *dest,
@@ -67,8 +69,10 @@ static uint64_t file_size(void *b)
return ((struct file_block_source *)b)->size;
}
-static void file_return_block(void *b UNUSED, struct reftable_block *dest UNUSED)
+static void file_return_block(void *b, struct reftable_block *dest)
{
+ REFTABLE_UNUSED(b);
+ REFTABLE_UNUSED(dest);
}
static void file_close(void *v)
diff --git a/reftable/iter.c b/reftable/iter.c
index b2ffb09c16..452add2705 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -25,18 +25,23 @@ int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
return it->ops->next(it->iter_arg, rec);
}
-static int empty_iterator_seek(void *arg UNUSED, struct reftable_record *want UNUSED)
+static int empty_iterator_seek(void *arg, struct reftable_record *want)
{
+ REFTABLE_UNUSED(arg);
+ REFTABLE_UNUSED(want);
return 0;
}
-static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED)
+static int empty_iterator_next(void *arg, struct reftable_record *rec)
{
+ REFTABLE_UNUSED(arg);
+ REFTABLE_UNUSED(rec);
return 1;
}
-static void empty_iterator_close(void *arg UNUSED)
+static void empty_iterator_close(void *arg)
{
+ REFTABLE_UNUSED(arg);
}
static struct reftable_iterator_vtable empty_vtable = {
@@ -143,9 +148,11 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
return 0;
}
-static int indexed_table_ref_iter_seek(void *p UNUSED,
- struct reftable_record *want UNUSED)
+static int indexed_table_ref_iter_seek(void *p,
+ struct reftable_record *want)
{
+ REFTABLE_UNUSED(p);
+ REFTABLE_UNUSED(want);
return REFTABLE_API_ERROR;
}
diff --git a/reftable/record.c b/reftable/record.c
index d86cd65bb4..46093ef987 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -490,11 +490,13 @@ static void reftable_obj_record_release(void *rec)
}
static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_obj_record *obj = rec;
const struct reftable_obj_record *src = src_rec;
+ REFTABLE_UNUSED(hash_size);
+
reftable_obj_record_release(obj);
REFTABLE_ALLOC_ARRAY(obj->hash_prefix, src->hash_prefix_len);
@@ -523,13 +525,16 @@ static uint8_t reftable_obj_record_val_type(const void *rec)
}
static int reftable_obj_record_encode(const void *rec, struct string_view s,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
const struct reftable_obj_record *r = rec;
struct string_view start = s;
int i = 0;
int n = 0;
uint64_t last = 0;
+
+ REFTABLE_UNUSED(hash_size);
+
if (r->offset_len == 0 || r->offset_len >= 8) {
n = put_var_int(&s, r->offset_len);
if (n < 0) {
@@ -558,8 +563,8 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,
static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
uint8_t val_type, struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size,
+ struct reftable_buf *scratch)
{
struct string_view start = in;
struct reftable_obj_record *r = rec;
@@ -567,6 +572,9 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
int n = 0;
uint64_t last;
+ REFTABLE_UNUSED(hash_size);
+ REFTABLE_UNUSED(scratch);
+
reftable_obj_record_release(r);
REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len);
@@ -613,17 +621,20 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
return start.len - in.len;
}
-static int not_a_deletion(const void *p UNUSED)
+static int not_a_deletion(const void *p)
{
+ REFTABLE_UNUSED(p);
return 0;
}
static int reftable_obj_record_equal_void(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_obj_record *ra = (struct reftable_obj_record *) a;
struct reftable_obj_record *rb = (struct reftable_obj_record *) b;
+ REFTABLE_UNUSED(hash_size);
+
if (ra->hash_prefix_len != rb->hash_prefix_len
|| ra->offset_len != rb->offset_len)
return 0;
@@ -1049,12 +1060,14 @@ static int reftable_index_record_key(const void *r, struct reftable_buf *dest)
}
static int reftable_index_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_index_record *dst = rec;
const struct reftable_index_record *src = src_rec;
int err;
+ REFTABLE_UNUSED(hash_size);
+
reftable_buf_reset(&dst->last_key);
err = reftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);
if (err < 0)
@@ -1070,19 +1083,23 @@ static void reftable_index_record_release(void *rec)
reftable_buf_release(&idx->last_key);
}
-static uint8_t reftable_index_record_val_type(const void *rec UNUSED)
+static uint8_t reftable_index_record_val_type(const void *rec)
{
+ REFTABLE_UNUSED(rec);
return 0;
}
static int reftable_index_record_encode(const void *rec, struct string_view out,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
const struct reftable_index_record *r =
(const struct reftable_index_record *)rec;
struct string_view start = out;
+ int n;
- int n = put_var_int(&out, r->offset);
+ REFTABLE_UNUSED(hash_size);
+
+ n = put_var_int(&out, r->offset);
if (n < 0)
return n;
@@ -1092,15 +1109,19 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,
}
static int reftable_index_record_decode(void *rec, struct reftable_buf key,
- uint8_t val_type UNUSED,
+ uint8_t val_type,
struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size,
+ struct reftable_buf *scratch)
{
struct string_view start = in;
struct reftable_index_record *r = rec;
int err, n = 0;
+ REFTABLE_UNUSED(val_type);
+ REFTABLE_UNUSED(hash_size);
+ REFTABLE_UNUSED(scratch);
+
reftable_buf_reset(&r->last_key);
err = reftable_buf_add(&r->last_key, key.buf, key.len);
if (err < 0)
@@ -1115,11 +1136,13 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,
}
static int reftable_index_record_equal(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_index_record *ia = (struct reftable_index_record *) a;
struct reftable_index_record *ib = (struct reftable_index_record *) b;
+ REFTABLE_UNUSED(hash_size);
+
return ia->offset == ib->offset && !reftable_buf_cmp(&ia->last_key, &ib->last_key);
}
diff --git a/reftable/writer.c b/reftable/writer.c
index 5961698311..0040a1b1c4 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -636,10 +636,12 @@ static void write_object_record(void *void_arg, void *key)
done:;
}
-static void object_record_free(void *void_arg UNUSED, void *key)
+static void object_record_free(void *void_arg, void *key)
{
struct obj_index_tree_node *entry = key;
+ REFTABLE_UNUSED(void_arg);
+
REFTABLE_FREE_AND_NULL(entry->offsets);
reftable_buf_release(&entry->hash);
reftable_free(entry);
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 15/19] compat/mingw: split out POSIX-related bits
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (13 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 14/19] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 16/19] compat/msvc: " Patrick Steinhardt
` (9 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Split out the POSIX-related bits from "compat/mingw.h". This is in
preparation for splitting up "git-compat-utils.h" into a header that
provides POSIX-compatibility and a header that provides common wrappers
used by the Git project.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/{mingw.c => mingw/compat-util.c} | 0
compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
compat/msvc.c | 2 +-
compat/msvc.h | 2 +-
config.mak.uname | 4 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 4 +-
meson.build | 6 +-
9 files changed, 234 insertions(+), 222 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw/compat-util.c
similarity index 100%
rename from compat/mingw.c
rename to compat/mingw/compat-util.c
diff --git a/compat/mingw/compat-util.h b/compat/mingw/compat-util.h
new file mode 100644
index 0000000000..b433762526
--- /dev/null
+++ b/compat/mingw/compat-util.h
@@ -0,0 +1,220 @@
+#ifndef COMPAT_MINGW_COMPAT_UTIL_H
+#define COMPAT_MINGW_COMPAT_UTIL_H
+
+#include "compat/mingw/posix.h"
+
+struct config_context;
+int mingw_core_config(const char *var, const char *value,
+ const struct config_context *ctx, void *cb);
+#define platform_core_config mingw_core_config
+
+#ifndef NO_OPENSSL
+#include <openssl/ssl.h>
+static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
+{
+ return SSL_set_fd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_fd mingw_SSL_set_fd
+
+static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
+{
+ return SSL_set_rfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_rfd mingw_SSL_set_rfd
+
+static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
+{
+ return SSL_set_wfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_wfd mingw_SSL_set_wfd
+#endif
+
+/*
+ * git specific compatibility
+ */
+
+static inline void convert_slashes(char *path)
+{
+ for (; *path; path++)
+ if (*path == '\\')
+ *path = '/';
+}
+#define PATH_SEP ';'
+char *mingw_query_user_email(void);
+#define query_user_email mingw_query_user_email
+
+/**
+ * Verifies that the specified path is owned by the user running the
+ * current process.
+ */
+int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
+#define is_path_owned_by_current_user is_path_owned_by_current_sid
+
+/**
+ * Verifies that the given path is a valid one on Windows.
+ *
+ * In particular, path segments are disallowed which
+ *
+ * - end in a period or a space (except the special directories `.` and `..`).
+ *
+ * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
+ *
+ * - correspond to reserved names (such as `AUX`, `PRN`, etc)
+ *
+ * The `allow_literal_nul` parameter controls whether the path `NUL` should
+ * be considered valid (this makes sense e.g. before opening files, as it is
+ * perfectly legitimate to open `NUL` on Windows, just as it is to open
+ * `/dev/null` on Unix/Linux).
+ *
+ * Returns 1 upon success, otherwise 0.
+ */
+int is_valid_win32_path(const char *path, int allow_literal_nul);
+#define is_valid_path(path) is_valid_win32_path(path, 0)
+
+/**
+ * Converts UTF-8 encoded string to UTF-16LE.
+ *
+ * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
+ * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
+ * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
+ * Unicode) are converted to hex-code.
+ *
+ * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
+ * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
+ *
+ * Maximum space requirement for the target buffer is two wide chars per UTF-8
+ * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
+ *
+ * | | UTF-8 | UTF-16 |
+ * Code point | UTF-8 sequence | bytes | words | ratio
+ * --------------+-------------------+-------+--------+-------
+ * 000000-00007f | 0-7f | 1 | 1 | 1
+ * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
+ * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
+ * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
+ * invalid | 80-9f | 1 | 2 (b) | 2
+ * invalid | a0-ff | 1 | 1 | 1
+ *
+ * (a) encoded as UTF-16 surrogate pair
+ * (b) encoded as two hex digits
+ *
+ * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
+ * or even indefinite-byte sequences, the largest valid code point \u10ffff
+ * encodes as only 4 UTF-8 bytes.
+ *
+ * Parameters:
+ * wcs: wide char target buffer
+ * utf: string to convert
+ * wcslen: size of target buffer (in wchar_t's)
+ * utflen: size of string to convert, or -1 if 0-terminated
+ *
+ * Returns:
+ * length of converted string (_wcslen(wcs)), or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
+
+/**
+ * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
+ */
+static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
+{
+ return xutftowcsn(wcs, utf, wcslen, -1);
+}
+
+/**
+ * Simplified file system specific variant of xutftowcsn, assumes output
+ * buffer size is MAX_PATH wide chars and input string is \0-terminated,
+ * fails with ENAMETOOLONG if input string is too long.
+ */
+static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
+{
+ int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
+ if (result < 0 && errno == ERANGE)
+ errno = ENAMETOOLONG;
+ return result;
+}
+
+/**
+ * Converts UTF-16LE encoded string to UTF-8.
+ *
+ * Maximum space requirement for the target buffer is three UTF-8 chars per
+ * wide char ((_wcslen(wcs) * 3) + 1).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
+ * modulo surrogate pairs), as per the following table:
+ *
+ * | | UTF-16 | UTF-8 |
+ * Code point | UTF-16 sequence | words | bytes | ratio
+ * --------------+-----------------------+--------+-------+-------
+ * 000000-00007f | 0000-007f | 1 | 1 | 1
+ * 000080-0007ff | 0080-07ff | 1 | 2 | 2
+ * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
+ * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
+ *
+ * Note that invalid code points > 10ffff cannot be represented in UTF-16.
+ *
+ * Parameters:
+ * utf: target buffer
+ * wcs: wide string to convert
+ * utflen: size of target buffer
+ *
+ * Returns:
+ * length of converted string, or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
+
+/*
+ * A critical section used in the implementation of the spawn
+ * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
+ * the replacement main() macro below.
+ */
+extern CRITICAL_SECTION pinfo_cs;
+
+/*
+ * Git, like most portable C applications, implements a main() function. On
+ * Windows, this main() function would receive parameters encoded in the
+ * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
+ *
+ * To make that happen, we still declare main() here, and then declare and
+ * implement wmain() (which is the Unicode variant of main()) and compile with
+ * -municode. This wmain() function reencodes the parameters from UTF-16 to
+ * UTF-8 format, sets up a couple of other things as required on Windows, and
+ * then hands off to the main() function.
+ */
+int wmain(int argc, const wchar_t **w_argv);
+int main(int argc, const char **argv);
+
+/*
+ * For debugging: if a problem occurs, say, in a Git process that is spawned
+ * from another Git process which in turn is spawned from yet another Git
+ * process, it can be quite daunting to figure out what is going on.
+ *
+ * Call this function to open a new MinTTY (this assumes you are in Git for
+ * Windows' SDK) with a GDB that attaches to the current process right away.
+ */
+void open_in_gdb(void);
+
+/*
+ * Used by Pthread API implementation for Windows
+ */
+int err_win_to_posix(DWORD winerr);
+
+#ifndef NO_UNIX_SOCKETS
+int mingw_have_unix_sockets(void);
+#undef have_unix_sockets
+#define have_unix_sockets mingw_have_unix_sockets
+#endif
+
+#endif /* COMPAT_MINGW_COMPAT_UTIL_H */
diff --git a/compat/mingw.h b/compat/mingw/posix.h
similarity index 59%
rename from compat/mingw.h
rename to compat/mingw/posix.h
index ebfb8ba423..8dddfa818d 100644
--- a/compat/mingw.h
+++ b/compat/mingw/posix.h
@@ -1,3 +1,6 @@
+#ifndef COMPAT_MINGW_POSIX_H
+#define COMPAT_MINGW_POSIX_H
+
#ifdef __MINGW64_VERSION_MAJOR
#include <stdint.h>
#include <wchar.h>
@@ -11,11 +14,6 @@ typedef _sigset_t sigset_t;
#undef _POSIX_THREAD_SAFE_FUNCTIONS
#endif
-struct config_context;
-int mingw_core_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb);
-#define platform_core_config mingw_core_config
-
/*
* things that are not available in header files
*/
@@ -180,27 +178,6 @@ int mingw_kill(pid_t pid, int sig);
#define locate_in_PATH mingw_locate_in_PATH
char *mingw_locate_in_PATH(const char *cmd);
-#ifndef NO_OPENSSL
-#include <openssl/ssl.h>
-static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
-{
- return SSL_set_fd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_fd mingw_SSL_set_fd
-
-static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
-{
- return SSL_set_rfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_rfd mingw_SSL_set_rfd
-
-static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
-{
- return SSL_set_wfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_wfd mingw_SSL_set_wfd
-#endif
-
/*
* implementations of missing functions
*/
@@ -444,19 +421,6 @@ int winansi_dup2(int oldfd, int newfd);
void winansi_init(void);
HANDLE winansi_get_osfhandle(int fd);
-/*
- * git specific compatibility
- */
-
-static inline void convert_slashes(char *path)
-{
- for (; *path; path++)
- if (*path == '\\')
- *path = '/';
-}
-#define PATH_SEP ';'
-char *mingw_query_user_email(void);
-#define query_user_email mingw_query_user_email
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
#define PRIuMAX "I64u"
#define PRId64 "I64d"
@@ -464,176 +428,4 @@ char *mingw_query_user_email(void);
#include <inttypes.h>
#endif
-/**
- * Verifies that the specified path is owned by the user running the
- * current process.
- */
-int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
-#define is_path_owned_by_current_user is_path_owned_by_current_sid
-
-/**
- * Verifies that the given path is a valid one on Windows.
- *
- * In particular, path segments are disallowed which
- *
- * - end in a period or a space (except the special directories `.` and `..`).
- *
- * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
- *
- * - correspond to reserved names (such as `AUX`, `PRN`, etc)
- *
- * The `allow_literal_nul` parameter controls whether the path `NUL` should
- * be considered valid (this makes sense e.g. before opening files, as it is
- * perfectly legitimate to open `NUL` on Windows, just as it is to open
- * `/dev/null` on Unix/Linux).
- *
- * Returns 1 upon success, otherwise 0.
- */
-int is_valid_win32_path(const char *path, int allow_literal_nul);
-#define is_valid_path(path) is_valid_win32_path(path, 0)
-
-/**
- * Converts UTF-8 encoded string to UTF-16LE.
- *
- * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
- * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
- * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
- * Unicode) are converted to hex-code.
- *
- * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
- * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
- *
- * Maximum space requirement for the target buffer is two wide chars per UTF-8
- * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
- *
- * The maximum space is needed only if the entire input string consists of
- * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
- *
- * | | UTF-8 | UTF-16 |
- * Code point | UTF-8 sequence | bytes | words | ratio
- * --------------+-------------------+-------+--------+-------
- * 000000-00007f | 0-7f | 1 | 1 | 1
- * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
- * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
- * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
- * invalid | 80-9f | 1 | 2 (b) | 2
- * invalid | a0-ff | 1 | 1 | 1
- *
- * (a) encoded as UTF-16 surrogate pair
- * (b) encoded as two hex digits
- *
- * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
- * or even indefinite-byte sequences, the largest valid code point \u10ffff
- * encodes as only 4 UTF-8 bytes.
- *
- * Parameters:
- * wcs: wide char target buffer
- * utf: string to convert
- * wcslen: size of target buffer (in wchar_t's)
- * utflen: size of string to convert, or -1 if 0-terminated
- *
- * Returns:
- * length of converted string (_wcslen(wcs)), or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
-
-/**
- * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
- */
-static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
-{
- return xutftowcsn(wcs, utf, wcslen, -1);
-}
-
-/**
- * Simplified file system specific variant of xutftowcsn, assumes output
- * buffer size is MAX_PATH wide chars and input string is \0-terminated,
- * fails with ENAMETOOLONG if input string is too long.
- */
-static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
-{
- int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
- if (result < 0 && errno == ERANGE)
- errno = ENAMETOOLONG;
- return result;
-}
-
-/**
- * Converts UTF-16LE encoded string to UTF-8.
- *
- * Maximum space requirement for the target buffer is three UTF-8 chars per
- * wide char ((_wcslen(wcs) * 3) + 1).
- *
- * The maximum space is needed only if the entire input string consists of
- * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
- * modulo surrogate pairs), as per the following table:
- *
- * | | UTF-16 | UTF-8 |
- * Code point | UTF-16 sequence | words | bytes | ratio
- * --------------+-----------------------+--------+-------+-------
- * 000000-00007f | 0000-007f | 1 | 1 | 1
- * 000080-0007ff | 0080-07ff | 1 | 2 | 2
- * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
- * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
- *
- * Note that invalid code points > 10ffff cannot be represented in UTF-16.
- *
- * Parameters:
- * utf: target buffer
- * wcs: wide string to convert
- * utflen: size of target buffer
- *
- * Returns:
- * length of converted string, or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
-
-/*
- * A critical section used in the implementation of the spawn
- * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
- * the replacement main() macro below.
- */
-extern CRITICAL_SECTION pinfo_cs;
-
-/*
- * Git, like most portable C applications, implements a main() function. On
- * Windows, this main() function would receive parameters encoded in the
- * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
- *
- * To make that happen, we still declare main() here, and then declare and
- * implement wmain() (which is the Unicode variant of main()) and compile with
- * -municode. This wmain() function reencodes the parameters from UTF-16 to
- * UTF-8 format, sets up a couple of other things as required on Windows, and
- * then hands off to the main() function.
- */
-int wmain(int argc, const wchar_t **w_argv);
-int main(int argc, const char **argv);
-
-/*
- * For debugging: if a problem occurs, say, in a Git process that is spawned
- * from another Git process which in turn is spawned from yet another Git
- * process, it can be quite daunting to figure out what is going on.
- *
- * Call this function to open a new MinTTY (this assumes you are in Git for
- * Windows' SDK) with a GDB that attaches to the current process right away.
- */
-void open_in_gdb(void);
-
-/*
- * Used by Pthread API implementation for Windows
- */
-int err_win_to_posix(DWORD winerr);
-
-#ifndef NO_UNIX_SOCKETS
-int mingw_have_unix_sockets(void);
-#undef have_unix_sockets
-#define have_unix_sockets mingw_have_unix_sockets
-#endif
+#endif /* COMPAT_MINGW_POSIX_H */
diff --git a/compat/msvc.c b/compat/msvc.c
index 71843d7eef..7f228a6399 100644
--- a/compat/msvc.c
+++ b/compat/msvc.c
@@ -3,4 +3,4 @@
#include <conio.h>
#include "../strbuf.h"
-#include "mingw.c"
+#include "mingw/compat-util.c"
diff --git a/compat/msvc.h b/compat/msvc.h
index 1d7a8c6145..df39978f4f 100644
--- a/compat/msvc.h
+++ b/compat/msvc.h
@@ -28,6 +28,6 @@ typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-#include "compat/mingw.h"
+#include "compat/mingw/compat-util.h"
#endif
diff --git a/config.mak.uname b/config.mak.uname
index b12d4e168a..cc4152e87e 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -541,7 +541,7 @@ endif
EXTRA_PROGRAMS += headless-git$X
-compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
+compat/msvc.o: compat/msvc.c compat/mingw/compat-util.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease
@@ -694,7 +694,7 @@ ifeq ($(uname_S),MINGW)
BASIC_LDFLAGS += -municode
COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/winansi.o \
+ COMPAT_OBJS += compat/mingw/compat-util.o compat/winansi.o \
compat/win32/trace2_win32_process_info.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 10dc54fdcb..65ce8705f0 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -258,7 +258,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET HAVE_RTLGENRANDOM)
list(APPEND compat_SOURCES
- compat/mingw.c
+ compat/mingw/compat-util.c
compat/winansi.c
compat/win32/flush.c
compat/win32/path-utils.c
diff --git a/git-compat-util.h b/git-compat-util.h
index e283c46c6f..b96fb98e1e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -304,10 +304,10 @@ static inline int is_xplatform_dir_sep(int c)
#if defined(__MINGW32__)
/* pull in Windows compatibility stuff */
#include "compat/win32/path-utils.h"
-#include "compat/mingw.h"
+#include "compat/mingw/compat-util.h"
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
-#include "compat/msvc.h"
+#include "compat/msvc/compat-util.h"
#else
#include <sys/utsname.h>
#include <sys/wait.h>
diff --git a/meson.build b/meson.build
index 2297f5e9dd..32eb0a86d5 100644
--- a/meson.build
+++ b/meson.build
@@ -1054,7 +1054,7 @@ if host_machine.system() == 'cygwin'
]
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw.c',
+ 'compat/mingw/compat-util.c',
'compat/winansi.c',
'compat/win32/flush.c',
'compat/win32/path-utils.c',
@@ -1157,7 +1157,7 @@ else
error('Native regex support requested but not found')
endif
-# setitimer and friends are provided by compat/mingw.c.
+# setitimer and friends are provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows'
if not compiler.compiles('''
#include <sys/time.h>
@@ -1237,7 +1237,7 @@ if not compiler.has_function('qsort')
endif
libgit_sources += 'compat/qsort_s.c'
-# unsetenv is provided by compat/mingw.c.
+# unsetenv is provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows' and not compiler.has_function('unsetenv')
libgit_c_args += '-DNO_UNSETENV'
libgit_sources += 'compat/unsetenv.c'
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 16/19] compat/msvc: split out POSIX-related bits
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (14 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 15/19] compat/mingw: split out POSIX-related bits Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 17/19] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
` (8 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
Split out the POSIX-related bits from "compat/msvc.h". This is in
preparation for splitting up "git-compat-utils.h" into a header that
provides POSIX-compatibility and a header that provides common wrappers
used by the Git project.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/{msvc.c => msvc/compat-util.c} | 0
compat/msvc/compat-util.h | 7 +++++++
compat/{msvc.h => msvc/posix.h} | 8 ++++----
config.mak.uname | 4 ++--
meson.build | 4 +++-
5 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/compat/msvc.c b/compat/msvc/compat-util.c
similarity index 100%
rename from compat/msvc.c
rename to compat/msvc/compat-util.c
diff --git a/compat/msvc/compat-util.h b/compat/msvc/compat-util.h
new file mode 100644
index 0000000000..e409e9910c
--- /dev/null
+++ b/compat/msvc/compat-util.h
@@ -0,0 +1,7 @@
+#ifndef COMPAT_MSVC_COMPAT_UTIL_H
+#define COMPAT_MSVC_COMPAT_UTIL_H
+
+#include "compat/msvc/posix.h"
+#include "compat/mingw/compat-util.h"
+
+#endif /* COMPAT_MSVC_COMPAT_UTIL_H */
diff --git a/compat/msvc.h b/compat/msvc/posix.h
similarity index 86%
rename from compat/msvc.h
rename to compat/msvc/posix.h
index df39978f4f..47062293cb 100644
--- a/compat/msvc.h
+++ b/compat/msvc/posix.h
@@ -1,5 +1,5 @@
-#ifndef __MSVC__HEAD
-#define __MSVC__HEAD
+#ifndef COMPAT_MSVC_POSIX_H
+#define COMPAT_MSVC_POSIX_H
#include <direct.h>
#include <process.h>
@@ -28,6 +28,6 @@ typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-#include "compat/mingw/compat-util.h"
+#include "compat/mingw/posix.h"
-#endif
+#endif /* COMPAT_MSVC_POSIX_H */
diff --git a/config.mak.uname b/config.mak.uname
index cc4152e87e..dbd05adb5d 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -495,7 +495,7 @@ endif
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
- COMPAT_OBJS = compat/msvc.o compat/winansi.o \
+ COMPAT_OBJS = compat/msvc/compat-util.o compat/winansi.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
compat/win32/pthread.o compat/win32/syslog.o \
@@ -541,7 +541,7 @@ endif
EXTRA_PROGRAMS += headless-git$X
-compat/msvc.o: compat/msvc.c compat/mingw/compat-util.c GIT-CFLAGS
+compat/msvc/compat-util.o: compat/msvc/compat-util.c compat/mingw/compat-util.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease
diff --git a/meson.build b/meson.build
index 32eb0a86d5..e8abf798f5 100644
--- a/meson.build
+++ b/meson.build
@@ -1054,7 +1054,6 @@ if host_machine.system() == 'cygwin'
]
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw/compat-util.c',
'compat/winansi.c',
'compat/win32/flush.c',
'compat/win32/path-utils.c',
@@ -1081,6 +1080,9 @@ elif host_machine.system() == 'windows'
libgit_include_directories += 'compat/win32'
if compiler.get_id() == 'msvc'
libgit_include_directories += 'compat/vcbuild/include'
+ libgit_sources += 'compat/msvc/compat-util.c'
+ else
+ libgit_sources += 'compat/mingw/compat-util.c'
endif
endif
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 17/19] git-compat-util.h: split out POSIX-emulating bits
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (15 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 16/19] compat/msvc: " Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 19:25 ` Justin Tobler
2025-01-27 13:04 ` [PATCH 18/19] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
` (7 subsequent siblings)
24 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
The "git-compat-util.h" header is a treasure trove of various bits and
pieces used throughout the project. It basically mixes two different
things into one:
- Providing a POSIX-like interface even on platforms that aren't
POSIX-compliant.
- Providing low-level functionality that is specific to Git.
This intermixing is a bit of a problem for the reftable library as we
don't want to recreate the POSIX-like interface there. But neither do we
want to pull in the Git-specific functionality, as it is otherwise quite
easy to start depedning on the Git codebase again.
Split out a new header "compat/posix.h" that only contains the bits and
pieces relevant for the emulation of POSIX, which we will start using in
the next commit.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/posix.h | 541 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
git-compat-util.h | 531 +----------------------------------------------------
2 files changed, 543 insertions(+), 529 deletions(-)
diff --git a/compat/posix.h b/compat/posix.h
new file mode 100644
index 0000000000..2b2da97965
--- /dev/null
+++ b/compat/posix.h
@@ -0,0 +1,541 @@
+#ifndef COMPAT_POSIX_H
+#define COMPAT_POSIX_H
+
+#define _FILE_OFFSET_BITS 64
+
+/*
+ * Derived from Linux "Features Test Macro" header
+ * Convenience macros to test the versions of gcc (or
+ * a compatible compiler).
+ * Use them like this:
+ * #if GIT_GNUC_PREREQ (2,8)
+ * ... code requiring gcc 2.8 or later ...
+ * #endif
+ *
+ * This macro of course is not part of POSIX, but we need it for the UNUSED
+ * macro which is used by some of our POSIX compatibility wrappers.
+*/
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define GIT_GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+ #define GIT_GNUC_PREREQ(maj, min) 0
+#endif
+
+/*
+ * UNUSED marks a function parameter that is always unused. It also
+ * can be used to annotate a function, a variable, or a type that is
+ * always unused.
+ *
+ * A callback interface may dictate that a function accepts a
+ * parameter at that position, but the implementation of the function
+ * may not need to use the parameter. In such a case, mark the parameter
+ * with UNUSED.
+ *
+ * When a parameter may be used or unused, depending on conditional
+ * compilation, consider using MAYBE_UNUSED instead.
+ */
+#if GIT_GNUC_PREREQ(4, 5)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated ("parameter declared as UNUSED")))
+#elif defined(__GNUC__)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated))
+#else
+#define UNUSED
+#endif
+
+#ifdef __MINGW64__
+#define _POSIX_C_SOURCE 1
+#elif defined(__sun__)
+ /*
+ * On Solaris, when _XOPEN_EXTENDED is set, its header file
+ * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
+ * setting to say we are XPG5 or XPG6. Also on Solaris,
+ * XPG6 programs must be compiled with a c99 compiler, while
+ * non XPG6 programs must be compiled with a pre-c99 compiler.
+ */
+# if __STDC_VERSION__ - 0 >= 199901L
+# define _XOPEN_SOURCE 600
+# else
+# define _XOPEN_SOURCE 500
+# endif
+#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
+ !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
+ !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
+ !defined(__CYGWIN__)
+#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
+#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
+#endif
+#define _ALL_SOURCE 1
+#define _GNU_SOURCE 1
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+#define _NETBSD_SOURCE 1
+#define _SGI_SOURCE 1
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
+# if !defined(_WIN32_WINNT)
+# define _WIN32_WINNT 0x0600
+# endif
+#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
+#include <winsock2.h>
+#ifndef NO_UNIX_SOCKETS
+#include <afunix.h>
+#endif
+#include <windows.h>
+#define GIT_WINDOWS_NATIVE
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h> /* for strcasecmp() */
+#endif
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#ifdef NEEDS_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#include <syslog.h>
+#if !defined(NO_POLL_H)
+#include <poll.h>
+#elif !defined(NO_SYS_POLL_H)
+#include <sys/poll.h>
+#else
+/* Pull the compat stuff */
+#include <poll.h>
+#endif
+#ifdef HAVE_BSD_SYSCTL
+#include <sys/sysctl.h>
+#endif
+
+#if defined(__MINGW32__)
+#include "compat/mingw/posix.h"
+#elif defined(_MSC_VER)
+#include "compat/msvc/posix.h"
+#else
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/statvfs.h>
+#include <termios.h>
+#ifndef NO_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/un.h>
+#ifndef NO_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+#ifdef HAVE_ARC4RANDOM_LIBBSD
+#include <bsd/stdlib.h>
+#endif
+#ifdef HAVE_GETRANDOM
+#include <sys/random.h>
+#endif
+#ifdef NO_INTPTR_T
+/*
+ * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
+ * on LLP86, IL33LLP64 and P64 it needs to be "long long",
+ * while on IP16 and IP16L32 it is "int" (resp. "short")
+ * Size needs to match (or exceed) 'sizeof(void *)'.
+ * We can't take "long long" here as not everybody has it.
+ */
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+#endif
+#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
+#include <grp.h>
+#define _ALL_SOURCE 1
+#endif
+
+#ifdef MKDIR_WO_TRAILING_SLASH
+#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
+int compat_mkdir_wo_trailing_slash(const char*, mode_t);
+#endif
+
+#ifdef time
+#undef time
+#endif
+static inline time_t git_time(time_t *tloc)
+{
+ struct timeval tv;
+
+ /*
+ * Avoid time(NULL), which can disagree with gettimeofday(2)
+ * and filesystem timestamps.
+ */
+ gettimeofday(&tv, NULL);
+
+ if (tloc)
+ *tloc = tv.tv_sec;
+ return tv.tv_sec;
+}
+#define time git_time
+
+#ifdef NO_STRUCT_ITIMERVAL
+struct itimerval {
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+#endif
+
+#ifdef NO_SETITIMER
+static inline int git_setitimer(int which UNUSED,
+ const struct itimerval *value UNUSED,
+ struct itimerval *newvalue UNUSED) {
+ return 0; /* pretend success */
+}
+#undef setitimer
+#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
+#endif
+
+#ifndef NO_LIBGEN_H
+#include <libgen.h>
+#else
+#define basename gitbasename
+char *gitbasename(char *);
+#define dirname gitdirname
+char *gitdirname(char *);
+#endif
+
+#ifndef NO_ICONV
+#include <iconv.h>
+#endif
+
+/* On most systems <netdb.h> would have given us this, but
+ * not on some systems (e.g. z/OS).
+ */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+/* On most systems <limits.h> would have given us this, but
+ * not on some systems (e.g. GNU/Hurd).
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+typedef uintmax_t timestamp_t;
+#define PRItime PRIuMAX
+#define parse_timestamp strtoumax
+#define TIME_MAX UINTMAX_MAX
+#define TIME_MIN 0
+
+int lstat_cache_aware_rmdir(const char *path);
+#if !defined(__MINGW32__) && !defined(_MSC_VER)
+#define rmdir lstat_cache_aware_rmdir
+#endif
+
+#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
+
+#ifndef PROT_READ
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define MAP_PRIVATE 1
+#endif
+
+#define mmap git_mmap
+#define munmap git_munmap
+void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int git_munmap(void *start, size_t length);
+
+#else /* NO_MMAP || USE_WIN32_MMAP */
+
+#include <sys/mman.h>
+
+#endif /* NO_MMAP || USE_WIN32_MMAP */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#ifdef NEEDS_MODE_TRANSLATION
+#undef S_IFMT
+#undef S_IFREG
+#undef S_IFDIR
+#undef S_IFLNK
+#undef S_IFBLK
+#undef S_IFCHR
+#undef S_IFIFO
+#undef S_IFSOCK
+#define S_IFMT 0170000
+#define S_IFREG 0100000
+#define S_IFDIR 0040000
+#define S_IFLNK 0120000
+#define S_IFBLK 0060000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_IFSOCK 0140000
+#ifdef stat
+#undef stat
+#endif
+#define stat(path, buf) git_stat(path, buf)
+int git_stat(const char *, struct stat *);
+#ifdef fstat
+#undef fstat
+#endif
+#define fstat(fd, buf) git_fstat(fd, buf)
+int git_fstat(int, struct stat *);
+#ifdef lstat
+#undef lstat
+#endif
+#define lstat(path, buf) git_lstat(path, buf)
+int git_lstat(const char *, struct stat *);
+#endif
+
+#ifdef NO_PREAD
+#define pread git_pread
+ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+
+#ifdef NO_SETENV
+#define setenv gitsetenv
+int gitsetenv(const char *, const char *, int);
+#endif
+
+#ifdef NO_MKDTEMP
+#define mkdtemp gitmkdtemp
+char *gitmkdtemp(char *);
+#endif
+
+#ifdef NO_UNSETENV
+#define unsetenv gitunsetenv
+int gitunsetenv(const char *);
+#endif
+
+#ifdef NO_STRCASESTR
+#define strcasestr gitstrcasestr
+char *gitstrcasestr(const char *haystack, const char *needle);
+#endif
+
+#ifdef NO_STRLCPY
+#define strlcpy gitstrlcpy
+size_t gitstrlcpy(char *, const char *, size_t);
+#endif
+
+#ifdef NO_STRTOUMAX
+#define strtoumax gitstrtoumax
+uintmax_t gitstrtoumax(const char *, char **, int);
+#define strtoimax gitstrtoimax
+intmax_t gitstrtoimax(const char *, char **, int);
+#endif
+
+#ifdef NO_HSTRERROR
+#define hstrerror githstrerror
+const char *githstrerror(int herror);
+#endif
+
+#ifdef NO_MEMMEM
+#define memmem gitmemmem
+void *gitmemmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+#endif
+
+#ifdef OVERRIDE_STRDUP
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup gitstrdup
+char *gitstrdup(const char *s);
+#endif
+
+#ifdef NO_GETPAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifdef FREAD_READS_DIRECTORIES
+# if !defined(SUPPRESS_FOPEN_REDEFINITION)
+# ifdef fopen
+# undef fopen
+# endif
+# define fopen(a,b) git_fopen(a,b)
+# endif
+FILE *git_fopen(const char*, const char*);
+#endif
+
+#ifdef SNPRINTF_RETURNS_BOGUS
+#ifdef snprintf
+#undef snprintf
+#endif
+#define snprintf git_snprintf
+int git_snprintf(char *str, size_t maxsize,
+ const char *format, ...);
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#define vsnprintf git_vsnprintf
+int git_vsnprintf(char *str, size_t maxsize,
+ const char *format, va_list ap);
+#endif
+
+#ifdef OPEN_RETURNS_EINTR
+#undef open
+#define open git_open_with_retry
+int git_open_with_retry(const char *path, int flag, ...);
+#endif
+
+#ifdef __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2, 1)
+#define HAVE_STRCHRNUL
+#endif
+#endif
+
+#ifndef HAVE_STRCHRNUL
+#define strchrnul gitstrchrnul
+static inline char *gitstrchrnul(const char *s, int c)
+{
+ while (*s && *s != c)
+ s++;
+ return (char *)s;
+}
+#endif
+
+#ifdef NO_INET_PTON
+int inet_pton(int af, const char *src, void *dst);
+#endif
+
+#ifdef NO_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
+#ifdef NO_PTHREADS
+#define atexit git_atexit
+int git_atexit(void (*handler)(void));
+#endif
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
+#include "sane-ctype.h"
+
+void git_stable_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
+#ifdef INTERNAL_QSORT
+#define qsort git_stable_qsort
+#endif
+
+#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
+static inline void sane_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *))
+{
+ if (nmemb > 1)
+ qsort(base, nmemb, size, compar);
+}
+
+#define STABLE_QSORT(base, n, compar) \
+ git_stable_qsort((base), (n), sizeof(*(base)), compar)
+
+#ifndef HAVE_ISO_QSORT_S
+int git_qsort_s(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *), void *ctx);
+#define qsort_s git_qsort_s
+#endif
+
+#define QSORT_S(base, n, compar, ctx) do { \
+ if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
+ BUG("qsort_s() failed"); \
+} while (0)
+
+#ifdef NO_NSEC
+#undef USE_NSEC
+#define ST_CTIME_NSEC(st) 0
+#define ST_MTIME_NSEC(st) 0
+#else
+#ifdef USE_ST_TIMESPEC
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
+#else
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
+#endif
+#endif
+
+#ifndef va_copy
+/*
+ * Since an obvious implementation of va_list would be to make it a
+ * pointer into the stack frame, a simple assignment will work on
+ * many systems. But let's try to be more portable.
+ */
+#ifdef __va_copy
+#define va_copy(dst, src) __va_copy(dst, src)
+#else
+#define va_copy(dst, src) ((dst) = (src))
+#endif
+#endif
+
+#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+static inline void git_flockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+static inline void git_funlockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+#undef flockfile
+#undef funlockfile
+#undef getc_unlocked
+#define flockfile(fh) git_flockfile(fh)
+#define funlockfile(fh) git_funlockfile(fh)
+#define getc_unlocked(fh) getc(fh)
+#endif
+
+#ifdef FILENO_IS_A_MACRO
+int git_fileno(FILE *stream);
+# ifndef COMPAT_CODE_FILENO
+# undef fileno
+# define fileno(p) git_fileno(p)
+# endif
+#endif
+
+#ifdef NEED_ACCESS_ROOT_HANDLER
+int git_access(const char *path, int mode);
+# ifndef COMPAT_CODE_ACCESS
+# ifdef access
+# undef access
+# endif
+# define access(path, mode) git_access(path, mode)
+# endif
+#endif
+
+#endif /* COMPAT_POSIX_H */
diff --git a/git-compat-util.h b/git-compat-util.h
index b96fb98e1e..30ad0725fb 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -23,26 +23,9 @@
#include <crtdbg.h>
#endif
-struct strbuf;
-
-
-#define _FILE_OFFSET_BITS 64
+#include "compat/posix.h"
-
-/* Derived from Linux "Features Test Macro" header
- * Convenience macros to test the versions of gcc (or
- * a compatible compiler).
- * Use them like this:
- * #if GIT_GNUC_PREREQ (2,8)
- * ... code requiring gcc 2.8 or later ...
- * #endif
-*/
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define GIT_GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-#else
- #define GIT_GNUC_PREREQ(maj, min) 0
-#endif
+struct strbuf;
#if defined(__GNUC__) || defined(__clang__)
# define PRAGMA(pragma) _Pragma(#pragma)
@@ -176,71 +159,6 @@ DISABLE_WARNING(-Wsign-compare)
/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-#ifdef __MINGW64__
-#define _POSIX_C_SOURCE 1
-#elif defined(__sun__)
- /*
- * On Solaris, when _XOPEN_EXTENDED is set, its header file
- * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
- * setting to say we are XPG5 or XPG6. Also on Solaris,
- * XPG6 programs must be compiled with a c99 compiler, while
- * non XPG6 programs must be compiled with a pre-c99 compiler.
- */
-# if __STDC_VERSION__ - 0 >= 199901L
-# define _XOPEN_SOURCE 600
-# else
-# define _XOPEN_SOURCE 500
-# endif
-#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
- !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
- !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
- !defined(__CYGWIN__)
-#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
-#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
-#endif
-#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
-#define _BSD_SOURCE 1
-#define _DEFAULT_SOURCE 1
-#define _NETBSD_SOURCE 1
-#define _SGI_SOURCE 1
-
-/*
- * UNUSED marks a function parameter that is always unused. It also
- * can be used to annotate a function, a variable, or a type that is
- * always unused.
- *
- * A callback interface may dictate that a function accepts a
- * parameter at that position, but the implementation of the function
- * may not need to use the parameter. In such a case, mark the parameter
- * with UNUSED.
- *
- * When a parameter may be used or unused, depending on conditional
- * compilation, consider using MAYBE_UNUSED instead.
- */
-#if GIT_GNUC_PREREQ(4, 5)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated ("parameter declared as UNUSED")))
-#elif defined(__GNUC__)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated))
-#else
-#define UNUSED
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
-# if !defined(_WIN32_WINNT)
-# define _WIN32_WINNT 0x0600
-# endif
-#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
-#include <winsock2.h>
-#ifndef NO_UNIX_SOCKETS
-#include <afunix.h>
-#endif
-#include <windows.h>
-#define GIT_WINDOWS_NATIVE
-#endif
-
#if defined(NO_UNIX_SOCKETS) || !defined(GIT_WINDOWS_NATIVE)
static inline int _have_unix_sockets(void)
{
@@ -253,45 +171,6 @@ static inline int _have_unix_sockets(void)
#define have_unix_sockets _have_unix_sockets
#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h> /* for strcasecmp() */
-#endif
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#ifdef NEEDS_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <time.h>
-#include <signal.h>
-#include <assert.h>
-#include <regex.h>
-#include <utime.h>
-#include <syslog.h>
-#if !defined(NO_POLL_H)
-#include <poll.h>
-#elif !defined(NO_SYS_POLL_H)
-#include <sys/poll.h>
-#else
-/* Pull the compat stuff */
-#include <poll.h>
-#endif
-#ifdef HAVE_BSD_SYSCTL
-#include <sys/sysctl.h>
-#endif
-
/* Used by compat/win32/path-utils.h, and more */
static inline int is_xplatform_dir_sep(int c)
{
@@ -308,48 +187,6 @@ static inline int is_xplatform_dir_sep(int c)
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
#include "compat/msvc/compat-util.h"
-#else
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/statvfs.h>
-#include <termios.h>
-#ifndef NO_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <sys/un.h>
-#ifndef NO_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <stdint.h>
-#endif
-#ifdef HAVE_ARC4RANDOM_LIBBSD
-#include <bsd/stdlib.h>
-#endif
-#ifdef HAVE_GETRANDOM
-#include <sys/random.h>
-#endif
-#ifdef NO_INTPTR_T
-/*
- * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
- * on LLP86, IL33LLP64 and P64 it needs to be "long long",
- * while on IP16 and IP16L32 it is "int" (resp. "short")
- * Size needs to match (or exceed) 'sizeof(void *)'.
- * We can't take "long long" here as not everybody has it.
- */
-typedef long intptr_t;
-typedef unsigned long uintptr_t;
-#endif
-#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
-#include <grp.h>
-#define _ALL_SOURCE 1
#endif
/* used on Mac OS X */
@@ -370,60 +207,6 @@ static inline const char *precompose_string_if_needed(const char *in)
#define probe_utf8_pathname_composition()
#endif
-#ifdef MKDIR_WO_TRAILING_SLASH
-#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
-int compat_mkdir_wo_trailing_slash(const char*, mode_t);
-#endif
-
-#ifdef time
-#undef time
-#endif
-static inline time_t git_time(time_t *tloc)
-{
- struct timeval tv;
-
- /*
- * Avoid time(NULL), which can disagree with gettimeofday(2)
- * and filesystem timestamps.
- */
- gettimeofday(&tv, NULL);
-
- if (tloc)
- *tloc = tv.tv_sec;
- return tv.tv_sec;
-}
-#define time git_time
-
-#ifdef NO_STRUCT_ITIMERVAL
-struct itimerval {
- struct timeval it_interval;
- struct timeval it_value;
-};
-#endif
-
-#ifdef NO_SETITIMER
-static inline int git_setitimer(int which UNUSED,
- const struct itimerval *value UNUSED,
- struct itimerval *newvalue UNUSED) {
- return 0; /* pretend success */
-}
-#undef setitimer
-#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
-#endif
-
-#ifndef NO_LIBGEN_H
-#include <libgen.h>
-#else
-#define basename gitbasename
-char *gitbasename(char *);
-#define dirname gitdirname
-char *gitdirname(char *);
-#endif
-
-#ifndef NO_ICONV
-#include <iconv.h>
-#endif
-
#ifndef NO_OPENSSL
#ifdef __APPLE__
#undef __AVAILABILITY_MACROS_USES_AVAILABILITY
@@ -441,34 +224,6 @@ char *gitdirname(char *);
# include <sys/sysinfo.h>
#endif
-/* On most systems <netdb.h> would have given us this, but
- * not on some systems (e.g. z/OS).
- */
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
-
-/* On most systems <limits.h> would have given us this, but
- * not on some systems (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-typedef uintmax_t timestamp_t;
-#define PRItime PRIuMAX
-#define parse_timestamp strtoumax
-#define TIME_MAX UINTMAX_MAX
-#define TIME_MIN 0
-
#ifndef PATH_SEP
#define PATH_SEP ':'
#endif
@@ -492,11 +247,6 @@ static inline int noop_core_config(const char *var UNUSED,
#define platform_core_config noop_core_config
#endif
-int lstat_cache_aware_rmdir(const char *path);
-#if !defined(__MINGW32__) && !defined(_MSC_VER)
-#define rmdir lstat_cache_aware_rmdir
-#endif
-
#ifndef has_dos_drive_prefix
static inline int git_has_dos_drive_prefix(const char *path UNUSED)
{
@@ -822,25 +572,6 @@ static inline bool strip_suffix(const char *str, const char *suffix,
memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
} while (0)
-#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-
-#ifndef PROT_READ
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define MAP_PRIVATE 1
-#endif
-
-#define mmap git_mmap
-#define munmap git_munmap
-void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-int git_munmap(void *start, size_t length);
-
-#else /* NO_MMAP || USE_WIN32_MMAP */
-
-#include <sys/mman.h>
-
-#endif /* NO_MMAP || USE_WIN32_MMAP */
-
#ifdef NO_MMAP
/* This value must be multiple of (pagesize * 2) */
@@ -856,177 +587,15 @@ int git_munmap(void *start, size_t length);
#endif /* NO_MMAP */
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
#define on_disk_bytes(st) ((st).st_size)
#else
#define on_disk_bytes(st) ((st).st_blocks * 512)
#endif
-#ifdef NEEDS_MODE_TRANSLATION
-#undef S_IFMT
-#undef S_IFREG
-#undef S_IFDIR
-#undef S_IFLNK
-#undef S_IFBLK
-#undef S_IFCHR
-#undef S_IFIFO
-#undef S_IFSOCK
-#define S_IFMT 0170000
-#define S_IFREG 0100000
-#define S_IFDIR 0040000
-#define S_IFLNK 0120000
-#define S_IFBLK 0060000
-#define S_IFCHR 0020000
-#define S_IFIFO 0010000
-#define S_IFSOCK 0140000
-#ifdef stat
-#undef stat
-#endif
-#define stat(path, buf) git_stat(path, buf)
-int git_stat(const char *, struct stat *);
-#ifdef fstat
-#undef fstat
-#endif
-#define fstat(fd, buf) git_fstat(fd, buf)
-int git_fstat(int, struct stat *);
-#ifdef lstat
-#undef lstat
-#endif
-#define lstat(path, buf) git_lstat(path, buf)
-int git_lstat(const char *, struct stat *);
-#endif
-
#define DEFAULT_PACKED_GIT_LIMIT \
((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))
-#ifdef NO_PREAD
-#define pread git_pread
-ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
-#endif
-
-#ifdef NO_SETENV
-#define setenv gitsetenv
-int gitsetenv(const char *, const char *, int);
-#endif
-
-#ifdef NO_MKDTEMP
-#define mkdtemp gitmkdtemp
-char *gitmkdtemp(char *);
-#endif
-
-#ifdef NO_UNSETENV
-#define unsetenv gitunsetenv
-int gitunsetenv(const char *);
-#endif
-
-#ifdef NO_STRCASESTR
-#define strcasestr gitstrcasestr
-char *gitstrcasestr(const char *haystack, const char *needle);
-#endif
-
-#ifdef NO_STRLCPY
-#define strlcpy gitstrlcpy
-size_t gitstrlcpy(char *, const char *, size_t);
-#endif
-
-#ifdef NO_STRTOUMAX
-#define strtoumax gitstrtoumax
-uintmax_t gitstrtoumax(const char *, char **, int);
-#define strtoimax gitstrtoimax
-intmax_t gitstrtoimax(const char *, char **, int);
-#endif
-
-#ifdef NO_HSTRERROR
-#define hstrerror githstrerror
-const char *githstrerror(int herror);
-#endif
-
-#ifdef NO_MEMMEM
-#define memmem gitmemmem
-void *gitmemmem(const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen);
-#endif
-
-#ifdef OVERRIDE_STRDUP
-#ifdef strdup
-#undef strdup
-#endif
-#define strdup gitstrdup
-char *gitstrdup(const char *s);
-#endif
-
-#ifdef NO_GETPAGESIZE
-#define getpagesize() sysconf(_SC_PAGESIZE)
-#endif
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
-#endif
-
-#ifdef FREAD_READS_DIRECTORIES
-# if !defined(SUPPRESS_FOPEN_REDEFINITION)
-# ifdef fopen
-# undef fopen
-# endif
-# define fopen(a,b) git_fopen(a,b)
-# endif
-FILE *git_fopen(const char*, const char*);
-#endif
-
-#ifdef SNPRINTF_RETURNS_BOGUS
-#ifdef snprintf
-#undef snprintf
-#endif
-#define snprintf git_snprintf
-int git_snprintf(char *str, size_t maxsize,
- const char *format, ...);
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#define vsnprintf git_vsnprintf
-int git_vsnprintf(char *str, size_t maxsize,
- const char *format, va_list ap);
-#endif
-
-#ifdef OPEN_RETURNS_EINTR
-#undef open
-#define open git_open_with_retry
-int git_open_with_retry(const char *path, int flag, ...);
-#endif
-
-#ifdef __GLIBC_PREREQ
-#if __GLIBC_PREREQ(2, 1)
-#define HAVE_STRCHRNUL
-#endif
-#endif
-
-#ifndef HAVE_STRCHRNUL
-#define strchrnul gitstrchrnul
-static inline char *gitstrchrnul(const char *s, int c)
-{
- while (*s && *s != c)
- s++;
- return (char *)s;
-}
-#endif
-
-#ifdef NO_INET_PTON
-int inet_pton(int af, const char *src, void *dst);
-#endif
-
-#ifdef NO_INET_NTOP
-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-#endif
-
-#ifdef NO_PTHREADS
-#define atexit git_atexit
-int git_atexit(void (*handler)(void));
-#endif
-
static inline size_t st_add(size_t a, size_t b)
{
if (unsigned_add_overflows(a, b))
@@ -1293,12 +862,6 @@ static inline size_t xsize_t(off_t len)
return (size_t) len;
}
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
-#endif
-
-#include "sane-ctype.h"
-
/*
* Like skip_prefix, but compare case-insensitively. Note that the comparison
* is done via tolower(), so it is strictly ASCII (no multi-byte characters or
@@ -1364,34 +927,6 @@ static inline int strtol_i(char const *s, int base, int *result)
return 0;
}
-void git_stable_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *));
-#ifdef INTERNAL_QSORT
-#define qsort git_stable_qsort
-#endif
-
-#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
-static inline void sane_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *))
-{
- if (nmemb > 1)
- qsort(base, nmemb, size, compar);
-}
-
-#define STABLE_QSORT(base, n, compar) \
- git_stable_qsort((base), (n), sizeof(*(base)), compar)
-
-#ifndef HAVE_ISO_QSORT_S
-int git_qsort_s(void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *, void *), void *ctx);
-#define qsort_s git_qsort_s
-#endif
-
-#define QSORT_S(base, n, compar, ctx) do { \
- if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
- BUG("qsort_s() failed"); \
-} while (0)
-
#ifndef REG_STARTEND
#error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd"
#endif
@@ -1416,39 +951,12 @@ int git_regcomp(regex_t *preg, const char *pattern, int cflags);
# define FORCE_DIR_SET_GID 0
#endif
-#ifdef NO_NSEC
-#undef USE_NSEC
-#define ST_CTIME_NSEC(st) 0
-#define ST_MTIME_NSEC(st) 0
-#else
-#ifdef USE_ST_TIMESPEC
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
-#else
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
-#endif
-#endif
-
#ifdef UNRELIABLE_FSTAT
#define fstat_is_reliable() 0
#else
#define fstat_is_reliable() 1
#endif
-#ifndef va_copy
-/*
- * Since an obvious implementation of va_list would be to make it a
- * pointer into the stack frame, a simple assignment will work on
- * many systems. But let's try to be more portable.
- */
-#ifdef __va_copy
-#define va_copy(dst, src) __va_copy(dst, src)
-#else
-#define va_copy(dst, src) ((dst) = (src))
-#endif
-#endif
-
/* usage.c: only to be used for testing BUG() implementation (see test-tool) */
extern int BUG_exit_code;
@@ -1478,41 +986,6 @@ void bug_fl(const char *file, int line, const char *fmt, ...);
# define SHELL_PATH "/bin/sh"
#endif
-#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
-static inline void git_flockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-static inline void git_funlockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-#undef flockfile
-#undef funlockfile
-#undef getc_unlocked
-#define flockfile(fh) git_flockfile(fh)
-#define funlockfile(fh) git_funlockfile(fh)
-#define getc_unlocked(fh) getc(fh)
-#endif
-
-#ifdef FILENO_IS_A_MACRO
-int git_fileno(FILE *stream);
-# ifndef COMPAT_CODE_FILENO
-# undef fileno
-# define fileno(p) git_fileno(p)
-# endif
-#endif
-
-#ifdef NEED_ACCESS_ROOT_HANDLER
-int git_access(const char *path, int mode);
-# ifndef COMPAT_CODE_ACCESS
-# ifdef access
-# undef access
-# endif
-# define access(path, mode) git_access(path, mode)
-# endif
-#endif
-
/*
* Our code often opens a path to an optional file, to work on its
* contents when we can successfully open it. We can ignore a failure
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 18/19] reftable: decouple from Git codebase by pulling in "compat/posix.h"
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (16 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 17/19] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 19/19] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
` (6 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
The reftable library includes "git-compat-util.h" in order to get a
POSIX-like programming environment that papers over various differences
between platforms. The header also brings with it a couple of helpers
specific to the Git codebase though, and over time we have started to
use these helpers in the reftable library, as well.
This makes it very hard to use the reftable library as a standalone
library without the rest of the Git codebase, so other libraries like
e.g. libgit2 cannot easily use it. But now that we have removed all
calls to Git-specific functionality and have split out "compat/posix.h"
as a separate header we can address this.
Stop including "git-compat-util.h" and instead include "compat/posix.h"
to finalize the decoupling of the reftable library from the rest of the
Git codebase. The only bits which remain specific to Git are "system.h"
and "system.c", which projects will have to provide.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/system.c | 2 ++
reftable/system.h | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/reftable/system.c b/reftable/system.c
index e25ccc0da3..1ee268b125 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -1,3 +1,5 @@
+#include "../git-compat-util.h"
+
#include "system.h"
#include "basics.h"
#include "reftable-error.h"
diff --git a/reftable/system.h b/reftable/system.h
index 3bd4a4e322..e4a8944a70 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -11,7 +11,8 @@ license that can be found in the LICENSE file or at
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "compat/posix.h"
+#include <zlib.h>
/*
* Return a random 32 bit integer. This function is expected to return
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH 19/19] Makefile: skip reftable library for Coccinelle
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (17 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 18/19] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
@ 2025-01-27 13:04 ` Patrick Steinhardt
2025-01-27 17:44 ` [PATCH 00/19] reftable: stop using "git-compat-util.h" Junio C Hamano
` (5 subsequent siblings)
24 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-27 13:04 UTC (permalink / raw)
To: git; +Cc: Edward Thomson
The reftable library does not use any of the common helpers that the Git
project has. Consequently, most of the rules that we have in Coccinelle
do not apply to the library at all and may even generate false positives
when a pattern can be converted to use a Git helper function.
Exclude reftable library sources from being checked by Coccinelle to
avoid such false positives.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index d3011e30f7..dc2ac32e4a 100644
--- a/Makefile
+++ b/Makefile
@@ -946,7 +946,7 @@ FOUND_SOURCE_FILES := $(filter-out $(GENERATED_H),$(shell $(SOURCES_CMD)))
FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES))
FOUND_H_SOURCES = $(filter %.h,$(FOUND_SOURCE_FILES))
-COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
+COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES) reftable/%,$(FOUND_C_SOURCES))
LIB_H = $(FOUND_H_SOURCES)
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* Re: [PATCH 01/19] reftable/stack: stop using `read_in_full()`
2025-01-27 13:04 ` [PATCH 01/19] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
@ 2025-01-27 16:57 ` Justin Tobler
2025-01-28 8:06 ` Patrick Steinhardt
0 siblings, 1 reply; 146+ messages in thread
From: Justin Tobler @ 2025-01-27 16:57 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson
On 25/01/27 02:04PM, Patrick Steinhardt wrote:
> There is a single callsite of `read_in_full()` in the reftable library.
> Open-code the function to reduce our dependency on the Git library.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> reftable/stack.c | 18 ++++++++++++++----
> 1 file changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/reftable/stack.c b/reftable/stack.c
> index f7c1845e15..9490366795 100644
> --- a/reftable/stack.c
> +++ b/reftable/stack.c
> @@ -115,13 +115,16 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
>
> static int fd_read_lines(int fd, char ***namesp)
> {
> - off_t size = lseek(fd, 0, SEEK_END);
> char *buf = NULL;
> int err = 0;
> + off_t size;
> +
> + size = lseek(fd, 0, SEEK_END);
> if (size < 0) {
> err = REFTABLE_IO_ERROR;
> goto done;
> }
> +
> err = lseek(fd, 0, SEEK_SET);
> if (err < 0) {
> err = REFTABLE_IO_ERROR;
> @@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp)
> goto done;
> }
>
> - if (read_in_full(fd, buf, size) != size) {
> - err = REFTABLE_IO_ERROR;
> - goto done;
> + for (size_t total_read = 0; total_read < (size_t) size; ) {
The cast from off_t -> size_t matches the currect behavior, but is it
always safe to do this? In `git-compat-util.h` it looks like we have
`xsize_t()` to safely handle these conversions. Since this series is
moving away from `git-compat-util.h` should ideally something similar be
implemented?
> + ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
> + if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
The error handling here for EAGAIN doesn't go as far as what `xread()`
does via `handle_nonblock()`. In this scenario is that ok?
> + continue;
> + if (bytes_read < 0 || !bytes_read) {
> + err = REFTABLE_IO_ERROR;
> + goto done;
> + }
> +
> + total_read += bytes_read;
> }
> buf[size] = 0;
>
>
> --
> 2.48.1.362.g079036d154.dirty
>
>
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH 05/19] reftable/record: stop using `BUG()` in `reftable_record_init()`
2025-01-27 13:04 ` [PATCH 05/19] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
@ 2025-01-27 17:36 ` Justin Tobler
0 siblings, 0 replies; 146+ messages in thread
From: Justin Tobler @ 2025-01-27 17:36 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson
On 25/01/27 02:04PM, Patrick Steinhardt wrote:
> We're aborting the program via `BUG()` in case `reftable_record_init()`
> was invoked with an unknown record type. This is bad because we may now
> die in library code, and because it makes us depend on the Git codebase.
>
> Refactor the code such that `reftable_record_init()` can return an error
> code to the caller. Adapt any callers accordingly.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
[snip]
> diff --git a/reftable/record.c b/reftable/record.c
> index d1664c47ca..31985bb977 100644
> --- a/reftable/record.c
> +++ b/reftable/record.c
> @@ -1301,7 +1301,7 @@ reftable_record_vtable(struct reftable_record *rec)
> abort();
> }
>
> -void reftable_record_init(struct reftable_record *rec, uint8_t typ)
> +int reftable_record_init(struct reftable_record *rec, uint8_t typ)
> {
> memset(rec, 0, sizeof(*rec));
> rec->type = typ;
> @@ -1310,11 +1310,11 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)
> case BLOCK_TYPE_REF:
> case BLOCK_TYPE_LOG:
> case BLOCK_TYPE_OBJ:
> - return;
> + return 0;
> case BLOCK_TYPE_INDEX:
> reftable_buf_init(&rec->u.idx.last_key);
> - return;
> + return 0;
> default:
> - BUG("unhandled record type");
> + return REFTABLE_API_ERROR;
I was initially unsure if `REFTABLE_API_ERROR` would be the most
appropriate error to return here in this situation, but looking at its
documented use case, I would say this fits as a "misuse of the API". The
other option would be to add a more granular error type to indicate the
unsupported record type, but that seems unnecessary here.
> }
> }
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH 00/19] reftable: stop using "git-compat-util.h"
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (18 preceding siblings ...)
2025-01-27 13:04 ` [PATCH 19/19] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
@ 2025-01-27 17:44 ` Junio C Hamano
2025-01-28 8:22 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (4 subsequent siblings)
24 siblings, 1 reply; 146+ messages in thread
From: Junio C Hamano @ 2025-01-27 17:44 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson
Patrick Steinhardt <ps@pks.im> writes:
> This patch series stops using all kinds of helpers exposed by our
> "git-compat-util.h" header and open-codes them instead. In order to keep
> us from using these helpers by accident the final step is to pull out
> POSIX-related bits and pieces into a new "compat/posix.h" header, which
> the reftable library then uses instead of "git-compat-util.h".
Very nice.
Is there something we can also do in order to keep reftable from using
stale version of these helpers that it copied with this series when
we make improvements on our side to the original?
I think the answer might be "then use a common library
implementation that is used by both Git and reftable", but then we
might be in the same place as before? I dunno.
What do "libification" folks think? Anybody?
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH 06/19] reftable/record: don't `BUG()` in `reftable_record_cmp()`
2025-01-27 13:04 ` [PATCH 06/19] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
@ 2025-01-27 19:21 ` Justin Tobler
0 siblings, 0 replies; 146+ messages in thread
From: Justin Tobler @ 2025-01-27 19:21 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson
On 25/01/27 02:04PM, Patrick Steinhardt wrote:
> The refatble library aborts with a bug in case `reftable_record_cmp()`
s/refatble/reftable/
> is invoked with two records of differing types. This would cause the
> program to die without the caller being able to handle the error, which
> is not something we want in the context of library code. And it ties us
> to the Git codebase.
>
> Refactor the code such that `reftable_record_cmp()` returns an error
> code separate from the actual comparison result. This requires us to
> also adapt some callers up the callchain in a similar fashion.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH 17/19] git-compat-util.h: split out POSIX-emulating bits
2025-01-27 13:04 ` [PATCH 17/19] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
@ 2025-01-27 19:25 ` Justin Tobler
0 siblings, 0 replies; 146+ messages in thread
From: Justin Tobler @ 2025-01-27 19:25 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson
On 25/01/27 02:04PM, Patrick Steinhardt wrote:
> The "git-compat-util.h" header is a treasure trove of various bits and
> pieces used throughout the project. It basically mixes two different
> things into one:
>
> - Providing a POSIX-like interface even on platforms that aren't
> POSIX-compliant.
>
> - Providing low-level functionality that is specific to Git.
>
> This intermixing is a bit of a problem for the reftable library as we
> don't want to recreate the POSIX-like interface there. But neither do we
> want to pull in the Git-specific functionality, as it is otherwise quite
> easy to start depedning on the Git codebase again.
s/depedning/depending/
> Split out a new header "compat/posix.h" that only contains the bits and
> pieces relevant for the emulation of POSIX, which we will start using in
> the next commit.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH 01/19] reftable/stack: stop using `read_in_full()`
2025-01-27 16:57 ` Justin Tobler
@ 2025-01-28 8:06 ` Patrick Steinhardt
2025-01-28 17:05 ` Junio C Hamano
0 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:06 UTC (permalink / raw)
To: Justin Tobler; +Cc: git, Edward Thomson
On Mon, Jan 27, 2025 at 10:57:20AM -0600, Justin Tobler wrote:
> On 25/01/27 02:04PM, Patrick Steinhardt wrote:
> > diff --git a/reftable/stack.c b/reftable/stack.c
> > index f7c1845e15..9490366795 100644
> > --- a/reftable/stack.c
> > +++ b/reftable/stack.c
> > @@ -115,13 +115,16 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
> >
> > static int fd_read_lines(int fd, char ***namesp)
> > {
> > - off_t size = lseek(fd, 0, SEEK_END);
> > char *buf = NULL;
> > int err = 0;
> > + off_t size;
> > +
> > + size = lseek(fd, 0, SEEK_END);
> > if (size < 0) {
> > err = REFTABLE_IO_ERROR;
> > goto done;
> > }
> > +
> > err = lseek(fd, 0, SEEK_SET);
> > if (err < 0) {
> > err = REFTABLE_IO_ERROR;
> > @@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp)
> > goto done;
> > }
> >
> > - if (read_in_full(fd, buf, size) != size) {
> > - err = REFTABLE_IO_ERROR;
> > - goto done;
> > + for (size_t total_read = 0; total_read < (size_t) size; ) {
>
> The cast from off_t -> size_t matches the currect behavior, but is it
> always safe to do this? In `git-compat-util.h` it looks like we have
> `xsize_t()` to safely handle these conversions. Since this series is
> moving away from `git-compat-util.h` should ideally something similar be
> implemented?
It is safe, because a couple lines further up we check for `size < 0`
and error out if that is the case. So we know it's a positive integer,
and thus it can be represented via `size_t`.
> > + ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
> > + if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
>
> The error handling here for EAGAIN doesn't go as far as what `xread()`
> does via `handle_nonblock()`. In this scenario is that ok?
Yes, because we don't set `O_NONBLOCK` in the reftable library.
I'll note that in the commit message.
Patrick
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH 00/19] reftable: stop using "git-compat-util.h"
2025-01-27 17:44 ` [PATCH 00/19] reftable: stop using "git-compat-util.h" Junio C Hamano
@ 2025-01-28 8:22 ` Patrick Steinhardt
2025-01-28 17:32 ` Junio C Hamano
0 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:22 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Edward Thomson
On Mon, Jan 27, 2025 at 09:44:24AM -0800, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> writes:
>
> > This patch series stops using all kinds of helpers exposed by our
> > "git-compat-util.h" header and open-codes them instead. In order to keep
> > us from using these helpers by accident the final step is to pull out
> > POSIX-related bits and pieces into a new "compat/posix.h" header, which
> > the reftable library then uses instead of "git-compat-util.h".
>
> Very nice.
>
> Is there something we can also do in order to keep reftable from using
> stale version of these helpers that it copied with this series when
> we make improvements on our side to the original?
Overall the amount of duplication is quite limited. It looks like a lot
in this patch series, but many of the changes are really only a couple
of lines of code that are quite unlikely to grow stale. The subsystems
that really are complex (think tempfiles, lockfiles) use the same
underlying implementation as Git does via shims in "reftable/system.c".
My hope is that by starting to use the reftable library in libgit2 we'll
get additional test coverage thereof that helps weed out any issues we
have, including issues in the compatibility layer. But I also assume
that almost all bugs that we'll find will not be in the low-level code,
but rather in the business logic of reftables themselves.
> I think the answer might be "then use a common library
> implementation that is used by both Git and reftable", but then we
> might be in the same place as before? I dunno.
I don't really have a good idea for how to do this. Using a common
library would likely push us into the same place as before indeed,
unless we started to split out standalone files that aren't allowed to
link against anything but the "compat/" directory. But even if we had
that it would be quite painful to take the reftable library and reuse it
somewhere else, because now it's more than just "cp -r reftable/" and
reimplementing system-specific bits in "reftable/system.c".
I guess time will tell how much of a problem this really is. As said, my
prediction is that we won't face many bugs in the low-level code, and
then the question becomes moot anyway. But if time proves me wrong I'll
think a bit more about potential solutions.
Patrick
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v2 00/20] reftable: stop using "git-compat-util.h"
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (19 preceding siblings ...)
2025-01-27 17:44 ` [PATCH 00/19] reftable: stop using "git-compat-util.h" Junio C Hamano
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 01/20] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
` (20 more replies)
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (3 subsequent siblings)
24 siblings, 21 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Hi,
this patch series is the final step to fully decouple the reftable
library from the rest of the Git codebase. The goal of this is to make
the library reusable by other projects like libgit2 by simply copying
over the source files, making Git the canonical upstream for reftable
functionality.
This patch series stops using all kinds of helpers exposed by our
"git-compat-util.h" header and open-codes them instead. In order to keep
us from using these helpers by accident the final step is to pull out
POSIX-related bits and pieces into a new "compat/posix.h" header, which
the reftable library then uses instead of "git-compat-util.h".
The series is built on top of master at 5f8f7081f7 (The third batch,
2025-01-23) with ps/reftable-sign-compare at 33319b0976 (reftable:
address trivial -Wsign-compare warnings, 2025-01-20) merged into it.
There is a trivial merge conflict with ps/zlib-ng that can be solved
like this:
diff --cc reftable/system.h
index e4a8944a70,d02eacea8f..0000000000
--- a/reftable/system.h
+++ b/reftable/system.h
@@@ -11,15 -11,9 +11,15 @@@ https://developers.google.com/open-sour
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "compat/posix.h"
- #include <zlib.h>
+ #include "compat/zlib-compat.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
Changes in v2:
- The splitup of Windows headers has broken compilation because some
of the headers couldn't be found anymore. I've fixed this more
generally by converting includes in "compat/" to always be relative
to the project source directory, dropping the platform-specific
`-Icompat/` include.
- Explain why we don't port over `EWOULDBLOCK` handling.
- Fix commit message typos.
- Link to v1: https://lore.kernel.org/r/20250127-pks-reftable-drop-git-compat-util-v1-0-6e280a564877@pks.im
Thanks!
Patrick
---
Patrick Steinhardt (20):
reftable/stack: stop using `read_in_full()`
reftable/stack: stop using `write_in_full()`
reftable/blocksource: stop using `xmmap()`
reftable/record: stop using `COPY_ARRAY()`
reftable/record: stop using `BUG()` in `reftable_record_init()`
reftable/record: don't `BUG()` in `reftable_record_cmp()`
reftable: stop using `BUG()` in trivial cases
reftable/basics: stop using `st_mult()` in array allocators
reftable/basics: provide wrappers for big endian conversion
reftable/reader: stop using `ARRAY_SIZE()` macro
reftable/system: introduce `reftable_rand()`
reftable/stack: stop using `sleep_millisec()`
reftable/basics: stop using `SWAP()` macro
reftable/basics: stop using `UNUSED` annotation
compat: consistently resolve headers via project root
compat/mingw: split out POSIX-related bits
compat/msvc: split out POSIX-related bits
git-compat-util.h: split out POSIX-emulating bits
reftable: decouple from Git codebase by pulling in "compat/posix.h"
Makefile: skip reftable library for Coccinelle
Makefile | 2 +-
compat/access.c | 3 +-
compat/basename.c | 4 +-
compat/fileno.c | 2 +-
compat/fopen.c | 2 +-
compat/fsmonitor/fsm-health-darwin.c | 2 +-
compat/fsmonitor/fsm-health-win32.c | 2 +-
compat/fsmonitor/fsm-listen-darwin.c | 4 +-
compat/fsmonitor/fsm-listen-win32.c | 2 +-
compat/inet_ntop.c | 2 +-
compat/inet_pton.c | 2 +-
compat/memmem.c | 2 +-
compat/{mingw.c => mingw/compat-util.c} | 24 +-
compat/mingw/compat-util.h | 220 +++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +-----------
compat/mkdir.c | 2 +-
compat/mkdtemp.c | 2 +-
compat/mmap.c | 2 +-
compat/msvc.c | 6 -
compat/msvc/compat-util.c | 6 +
compat/msvc/compat-util.h | 7 +
compat/{msvc.h => msvc/posix.h} | 8 +-
compat/nonblock.c | 4 +-
compat/obstack.c | 2 +-
compat/posix.h | 541 +++++++++++++++++++++++++++++++
compat/pread.c | 4 +-
compat/precompose_utf8.c | 2 +-
compat/qsort_s.c | 2 +-
compat/regcomp_enhanced.c | 2 +-
compat/setenv.c | 2 +-
compat/snprintf.c | 2 +-
compat/strcasestr.c | 2 +-
compat/strdup.c | 2 +-
compat/strlcpy.c | 2 +-
compat/strtoimax.c | 2 +-
compat/strtoumax.c | 2 +-
compat/unsetenv.c | 2 +-
compat/win32/dirent.c | 2 +-
compat/win32/flush.c | 2 +-
compat/win32/path-utils.c | 4 +-
compat/win32/pthread.c | 4 +-
compat/win32/syslog.c | 2 +-
compat/win32/trace2_win32_process_info.c | 10 +-
compat/win32mmap.c | 2 +-
compat/winansi.c | 6 +-
config.mak.uname | 10 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 535 +-----------------------------
meson.build | 8 +-
reftable/basics.c | 19 --
reftable/basics.h | 123 ++++++-
reftable/block.c | 16 +-
reftable/blocksource.c | 21 +-
reftable/iter.c | 20 +-
reftable/merged.c | 27 +-
reftable/pq.c | 40 ++-
reftable/pq.h | 2 +-
reftable/reader.c | 33 +-
reftable/record.c | 96 ++++--
reftable/record.h | 6 +-
reftable/stack.c | 52 ++-
reftable/system.c | 7 +
reftable/system.h | 9 +-
reftable/writer.c | 29 +-
t/unit-tests/t-reftable-basics.c | 28 +-
t/unit-tests/t-reftable-pq.c | 22 +-
t/unit-tests/t-reftable-record.c | 42 ++-
67 files changed, 1282 insertions(+), 992 deletions(-)
Range-diff versus v1:
1: 1dc7341c0d ! 1: a0985a8b32 reftable/stack: stop using `read_in_full()`
@@ Commit message
There is a single callsite of `read_in_full()` in the reftable library.
Open-code the function to reduce our dependency on the Git library.
+ Note that we only partially port over the logic from `read_in_full()`
+ and its underlying `xread()` helper. Most importantly, the latter also
+ knows to handle `EWOULDBLOCK` via `handle_nonblock()`. This logic is
+ irrelevant for us though because the reftable library never sets the
+ `O_NONBLOCK` option in the first place.
+
Signed-off-by: Patrick Steinhardt <ps@pks.im>
## reftable/stack.c ##
2: a3a8bc7e8f = 2: 09e27dcfaf reftable/stack: stop using `write_in_full()`
3: 43b83eb8e8 = 3: 0ecdb7a440 reftable/blocksource: stop using `xmmap()`
4: d89df1bac5 = 4: b5e5803ec9 reftable/record: stop using `COPY_ARRAY()`
5: 94fd212a82 = 5: 5f479bf84d reftable/record: stop using `BUG()` in `reftable_record_init()`
6: c110e452fe ! 6: 9b10ec8f35 reftable/record: don't `BUG()` in `reftable_record_cmp()`
@@ Metadata
## Commit message ##
reftable/record: don't `BUG()` in `reftable_record_cmp()`
- The refatble library aborts with a bug in case `reftable_record_cmp()`
+ The reftable library aborts with a bug in case `reftable_record_cmp()`
is invoked with two records of differing types. This would cause the
program to die without the caller being able to handle the error, which
is not something we want in the context of library code. And it ties us
7: 61165df24e = 7: 0fe9c21db3 reftable: stop using `BUG()` in trivial cases
8: a3e2d8f194 = 8: b1f8ed2e92 reftable/basics: stop using `st_mult()` in array allocators
9: 75c719d097 = 9: 40a5989b25 reftable/basics: provide wrappers for big endian conversion
10: 754391b32e = 10: 6c258880f1 reftable/reader: stop using `ARRAY_SIZE()` macro
11: 4e14362169 = 11: 65a78993fc reftable/system: introduce `reftable_rand()`
12: 142610e800 = 12: e8a5090382 reftable/stack: stop using `sleep_millisec()`
13: 2b748b36ee = 13: af72104f1c reftable/basics: stop using `SWAP()` macro
14: fda87c2ec7 = 14: 4634e83e47 reftable/basics: stop using `UNUSED` annotation
-: ---------- > 15: 3a4949d74d compat: consistently resolve headers via project root
15: 34f81f0477 ! 16: 3520bf9252 compat/mingw: split out POSIX-related bits
@@ compat/mingw/posix.h: char *mingw_query_user_email(void);
## compat/msvc.c ##
@@
#include <conio.h>
- #include "../strbuf.h"
+ #include "strbuf.h"
--#include "mingw.c"
-+#include "mingw/compat-util.c"
+-#include "compat/mingw.c"
++#include "compat/mingw/compat-util.c"
## compat/msvc.h ##
@@ compat/msvc.h: typedef int sigset_t;
@@ config.mak.uname: endif
NO_INITGROUPS = YesPlease
@@ config.mak.uname: ifeq ($(uname_S),MINGW)
BASIC_LDFLAGS += -municode
- COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
+ COMPAT_CFLAGS += -DNOGDI -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/winansi.o \
+ COMPAT_OBJS += compat/mingw/compat-util.o compat/winansi.o \
16: ed9da5dbf4 = 17: fbb53e8526 compat/msvc: split out POSIX-related bits
17: f19f95e6d8 ! 18: 6d57bc4b26 git-compat-util.h: split out POSIX-emulating bits
@@ Commit message
This intermixing is a bit of a problem for the reftable library as we
don't want to recreate the POSIX-like interface there. But neither do we
want to pull in the Git-specific functionality, as it is otherwise quite
- easy to start depedning on the Git codebase again.
+ easy to start depending on the Git codebase again.
Split out a new header "compat/posix.h" that only contains the bits and
pieces relevant for the emulation of POSIX, which we will start using in
18: 463c285baa = 19: 746698c8ef reftable: decouple from Git codebase by pulling in "compat/posix.h"
19: 0973de24c0 = 20: 0f34ac6145 Makefile: skip reftable library for Coccinelle
---
base-commit: 5f8f7081f7761acdf83d0a4c6819fe3d724f01d7
change-id: 20241119-pks-reftable-drop-git-compat-util-470f2bfde562
prerequisite-message-id: <20250120-b4-pks-reftable-sign-compare-v2-0-b4566d02e4a5@pks.im>
prerequisite-patch-id: fda53cfaa42008baf9e5e66f9805f1091d5e28f0
prerequisite-patch-id: 5b9f06f4b50f51c0afb42fbf4a1a678069b38056
prerequisite-patch-id: 864d6d587b43aae2dedbb6a327a1632eafae51c7
prerequisite-patch-id: aec82a709396ae48b44c86016533517f2a9983cb
prerequisite-patch-id: 89087dd9f69dabfaac9b14874a6e8d8c1a42eada
prerequisite-patch-id: 87ec0aec4990da55346179776f9326725256642f
prerequisite-patch-id: b19cbfbe4fdd75d9ae319ca0e222ea01902f513e
prerequisite-patch-id: 1395a747e0005f729ef88a47f0d0dd4cd7c4dca2
prerequisite-patch-id: d0e48535aa481bb1770753858cd6a093a1ad625b
prerequisite-patch-id: d11a8b914e70cd56a5280e75fb7158f5de87eb22
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v2 01/20] reftable/stack: stop using `read_in_full()`
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 02/20] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
` (19 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
There is a single callsite of `read_in_full()` in the reftable library.
Open-code the function to reduce our dependency on the Git library.
Note that we only partially port over the logic from `read_in_full()`
and its underlying `xread()` helper. Most importantly, the latter also
knows to handle `EWOULDBLOCK` via `handle_nonblock()`. This logic is
irrelevant for us though because the reftable library never sets the
`O_NONBLOCK` option in the first place.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index f7c1845e15..9490366795 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -115,13 +115,16 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
static int fd_read_lines(int fd, char ***namesp)
{
- off_t size = lseek(fd, 0, SEEK_END);
char *buf = NULL;
int err = 0;
+ off_t size;
+
+ size = lseek(fd, 0, SEEK_END);
if (size < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
+
err = lseek(fd, 0, SEEK_SET);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp)
goto done;
}
- if (read_in_full(fd, buf, size) != size) {
- err = REFTABLE_IO_ERROR;
- goto done;
+ for (size_t total_read = 0; total_read < (size_t) size; ) {
+ ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
+ if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_read < 0 || !bytes_read) {
+ err = REFTABLE_IO_ERROR;
+ goto done;
+ }
+
+ total_read += bytes_read;
}
buf[size] = 0;
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 02/20] reftable/stack: stop using `write_in_full()`
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 01/20] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 03/20] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
` (18 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Similar to the preceding commit, drop our use of `write_in_full()` and
implement a new wrapper `reftable_write_full()` that handles this logic
for us. This is done to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 9490366795..5f155b344b 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -48,6 +48,25 @@ static int stack_fsync(const struct reftable_write_options *opts, int fd)
return fsync(fd);
}
+static ssize_t reftable_write_data(int fd, const void *data, size_t size)
+{
+ size_t total_written = 0;
+ const char *p = data;
+
+ while (total_written < size) {
+ ssize_t bytes_written = write(fd, p, size - total_written);
+ if (bytes_written < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_written < 0)
+ return REFTABLE_IO_ERROR;
+
+ total_written += bytes_written;
+ p += bytes_written;
+ }
+
+ return total_written;
+}
+
struct fd_writer {
const struct reftable_write_options *opts;
int fd;
@@ -56,7 +75,7 @@ struct fd_writer {
static ssize_t fd_writer_write(void *arg, const void *data, size_t sz)
{
struct fd_writer *writer = arg;
- return write_in_full(writer->fd, data, sz);
+ return reftable_write_data(writer->fd, data, sz);
}
static int fd_writer_flush(void *arg)
@@ -784,7 +803,8 @@ int reftable_addition_commit(struct reftable_addition *add)
goto done;
}
- err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len);
+ err = reftable_write_data(add->tables_list_lock.fd,
+ table_list.buf, table_list.len);
reftable_buf_release(&table_list);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -1468,8 +1488,8 @@ static int stack_compact_range(struct reftable_stack *st,
goto done;
}
- err = write_in_full(tables_list_lock.fd,
- tables_list_buf.buf, tables_list_buf.len);
+ err = reftable_write_data(tables_list_lock.fd,
+ tables_list_buf.buf, tables_list_buf.len);
if (err < 0) {
err = REFTABLE_IO_ERROR;
unlink(new_table_path.buf);
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 03/20] reftable/blocksource: stop using `xmmap()`
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 01/20] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 02/20] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 04/20] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
` (17 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We use `xmmap()` to map reftables into memory. This function has two
problems:
- It causes us to die in case the mmap fails.
- It ties us to the Git codebase.
Refactor the code to use mmap(3p) instead with manual error checking.
Note that this function may not be the system-provided mmap(3p), but may
point to our `git_mmap()` wrapper that emulates the syscall on systems
that do not have mmap(3p) available.
Fix `reftable_block_source_from_file()` to properly bubble up the error
code in case the map(3p) call fails.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/blocksource.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index bba4a45b98..02972c46f4 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -98,7 +98,7 @@ static struct reftable_block_source_vtable file_vtable = {
int reftable_block_source_from_file(struct reftable_block_source *bs,
const char *name)
{
- struct file_block_source *p;
+ struct file_block_source *p = NULL;
struct stat st;
int fd, err;
@@ -122,7 +122,12 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
}
p->size = st.st_size;
- p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ p->data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p->data == MAP_FAILED) {
+ err = REFTABLE_IO_ERROR;
+ p->data = NULL;
+ goto out;
+ }
assert(!bs->ops);
bs->ops = &file_vtable;
@@ -135,5 +140,5 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
close(fd);
if (err < 0)
reftable_free(p);
- return 0;
+ return err;
}
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 04/20] reftable/record: stop using `COPY_ARRAY()`
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (2 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 03/20] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-29 15:46 ` Justin Tobler
2025-01-28 8:28 ` [PATCH v2 05/20] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
` (16 subsequent siblings)
20 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Drop our use of `COPY_ARRAY()`, replacing it with an open-coded variant
thereof. This is done to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/record.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/reftable/record.c b/reftable/record.c
index 8919df8a4d..d1664c47ca 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -508,7 +508,8 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
if (!obj->offsets)
return REFTABLE_OUT_OF_MEMORY_ERROR;
obj->offset_len = src->offset_len;
- COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
+ if (src->offset_len)
+ memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len);
return 0;
}
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 05/20] reftable/record: stop using `BUG()` in `reftable_record_init()`
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (3 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 04/20] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 06/20] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
` (15 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We're aborting the program via `BUG()` in case `reftable_record_init()`
was invoked with an unknown record type. This is bad because we may now
die in library code, and because it makes us depend on the Git codebase.
Refactor the code such that `reftable_record_init()` can return an error
code to the caller. Adapt any callers accordingly.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/block.c | 4 +++-
reftable/merged.c | 5 ++++-
reftable/reader.c | 5 ++++-
reftable/record.c | 8 ++++----
reftable/record.h | 4 ++--
t/unit-tests/t-reftable-pq.c | 6 +++---
t/unit-tests/t-reftable-record.c | 2 +-
7 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/reftable/block.c b/reftable/block.c
index 8ac865ce78..255d566854 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -509,7 +509,9 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,
it->block_len = br->block_len;
it->hash_size = br->hash_size;
- reftable_record_init(&rec, block_reader_type(br));
+ err = reftable_record_init(&rec, block_reader_type(br));
+ if (err < 0)
+ goto done;
/*
* We're looking for the last entry less than the wanted key so that
diff --git a/reftable/merged.c b/reftable/merged.c
index e72b39e178..4156eec07f 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -253,7 +253,10 @@ int merged_table_init_iter(struct reftable_merged_table *mt,
}
for (size_t i = 0; i < mt->readers_len; i++) {
- reftable_record_init(&subiters[i].rec, typ);
+ ret = reftable_record_init(&subiters[i].rec, typ);
+ if (ret < 0)
+ goto out;
+
ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
if (ret < 0)
goto out;
diff --git a/reftable/reader.c b/reftable/reader.c
index 3f2e4b2800..de6e6dd932 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -360,7 +360,10 @@ static int table_iter_seek_linear(struct table_iter *ti,
struct reftable_record rec;
int err;
- reftable_record_init(&rec, reftable_record_type(want));
+ err = reftable_record_init(&rec, reftable_record_type(want));
+ if (err < 0)
+ goto done;
+
err = reftable_record_key(want, &want_key);
if (err < 0)
goto done;
diff --git a/reftable/record.c b/reftable/record.c
index d1664c47ca..31985bb977 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1301,7 +1301,7 @@ reftable_record_vtable(struct reftable_record *rec)
abort();
}
-void reftable_record_init(struct reftable_record *rec, uint8_t typ)
+int reftable_record_init(struct reftable_record *rec, uint8_t typ)
{
memset(rec, 0, sizeof(*rec));
rec->type = typ;
@@ -1310,11 +1310,11 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)
case BLOCK_TYPE_REF:
case BLOCK_TYPE_LOG:
case BLOCK_TYPE_OBJ:
- return;
+ return 0;
case BLOCK_TYPE_INDEX:
reftable_buf_init(&rec->u.idx.last_key);
- return;
+ return 0;
default:
- BUG("unhandled record type");
+ return REFTABLE_API_ERROR;
}
}
diff --git a/reftable/record.h b/reftable/record.h
index c7755a4d75..e1846c294b 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -130,8 +130,8 @@ struct reftable_record {
} u;
};
-/* Initialize the reftable record for the given type */
-void reftable_record_init(struct reftable_record *rec, uint8_t typ);
+/* Initialize the reftable record for the given type. */
+int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index f3f8a0cdf3..d8a4c283a1 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -32,7 +32,7 @@ static void t_pq_record(void)
char *last = NULL;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
}
@@ -72,7 +72,7 @@ static void t_pq_index(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
@@ -111,7 +111,7 @@ static void t_merged_iter_pqueue_top(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index d49d2a2729..6540bd20e3 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -17,7 +17,7 @@ static void t_copy(struct reftable_record *rec)
uint8_t typ;
typ = reftable_record_type(rec);
- reftable_record_init(©, typ);
+ check(!reftable_record_init(©, typ));
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
/* do it twice to catch memory leaks */
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 06/20] reftable/record: don't `BUG()` in `reftable_record_cmp()`
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (4 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 05/20] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 07/20] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
` (14 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The reftable library aborts with a bug in case `reftable_record_cmp()`
is invoked with two records of differing types. This would cause the
program to die without the caller being able to handle the error, which
is not something we want in the context of library code. And it ties us
to the Git codebase.
Refactor the code such that `reftable_record_cmp()` returns an error
code separate from the actual comparison result. This requires us to
also adapt some callers up the callchain in a similar fashion.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/merged.c | 20 +++++++++++++++-----
reftable/pq.c | 36 +++++++++++++++++++++++++++++-------
reftable/pq.h | 2 +-
reftable/record.c | 10 ++++++----
reftable/record.h | 2 +-
t/unit-tests/t-reftable-pq.c | 16 ++++++++++++----
t/unit-tests/t-reftable-record.c | 40 ++++++++++++++++++++++++++++------------
7 files changed, 92 insertions(+), 34 deletions(-)
diff --git a/reftable/merged.c b/reftable/merged.c
index 4156eec07f..563864068c 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -66,8 +66,11 @@ static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want
int err;
mi->advance_index = -1;
- while (!merged_iter_pqueue_is_empty(mi->pq))
- merged_iter_pqueue_remove(&mi->pq);
+ while (!merged_iter_pqueue_is_empty(mi->pq)) {
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+ }
for (size_t i = 0; i < mi->subiters_len; i++) {
err = iterator_seek(&mi->subiters[i].iter, want);
@@ -120,7 +123,9 @@ static int merged_iter_next_entry(struct merged_iter *mi,
if (empty)
return 1;
- entry = merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, &entry);
+ if (err < 0)
+ return err;
/*
One can also use reftable as datacenter-local storage, where the ref
@@ -134,11 +139,16 @@ static int merged_iter_next_entry(struct merged_iter *mi,
struct pq_entry top = merged_iter_pqueue_top(mi->pq);
int cmp;
- cmp = reftable_record_cmp(top.rec, entry.rec);
+ err = reftable_record_cmp(top.rec, entry.rec, &cmp);
+ if (err < 0)
+ return err;
if (cmp > 0)
break;
- merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+
err = merged_iter_advance_subiter(mi, top.index);
if (err < 0)
return err;
diff --git a/reftable/pq.c b/reftable/pq.c
index 5591e875e1..ef8035cfd9 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -15,13 +15,18 @@ license that can be found in the LICENSE file or at
int pq_less(struct pq_entry *a, struct pq_entry *b)
{
- int cmp = reftable_record_cmp(a->rec, b->rec);
+ int cmp, err;
+
+ err = reftable_record_cmp(a->rec, b->rec, &cmp);
+ if (err < 0)
+ return err;
+
if (cmp == 0)
return a->index > b->index;
return cmp < 0;
}
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out)
{
size_t i = 0;
struct pq_entry e = pq->heap[0];
@@ -32,17 +37,34 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
size_t min = i;
size_t j = 2 * i + 1;
size_t k = 2 * i + 2;
- if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i]))
- min = j;
- if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min]))
- min = k;
+ int cmp;
+
+ if (j < pq->len) {
+ cmp = pq_less(&pq->heap[j], &pq->heap[i]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = j;
+ }
+
+ if (k < pq->len) {
+ cmp = pq_less(&pq->heap[k], &pq->heap[min]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = k;
+ }
+
if (min == i)
break;
SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
- return e;
+ if (out)
+ *out = e;
+
+ return 0;
}
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
diff --git a/reftable/pq.h b/reftable/pq.h
index 83c062eeca..ff39016445 100644
--- a/reftable/pq.h
+++ b/reftable/pq.h
@@ -22,7 +22,7 @@ struct merged_iter_pqueue {
size_t cap;
};
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out);
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
diff --git a/reftable/record.c b/reftable/record.c
index 31985bb977..da550494a2 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1190,12 +1190,14 @@ int reftable_record_is_deletion(struct reftable_record *rec)
reftable_record_data(rec));
}
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b)
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b,
+ int *cmp)
{
if (a->type != b->type)
- BUG("cannot compare reftable records of different type");
- return reftable_record_vtable(a)->cmp(
- reftable_record_data(a), reftable_record_data(b));
+ return -1;
+ *cmp = reftable_record_vtable(a)->cmp(reftable_record_data(a),
+ reftable_record_data(b));
+ return 0;
}
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size)
diff --git a/reftable/record.h b/reftable/record.h
index e1846c294b..867810a932 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -134,7 +134,7 @@ struct reftable_record {
int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b, int *cmp);
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size);
int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);
int reftable_record_copy_from(struct reftable_record *rec,
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index d8a4c283a1..c128fe8616 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -21,7 +21,9 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq)
static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b)
{
- return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index);
+ int cmp;
+ check(!reftable_record_cmp(a->rec, b->rec, &cmp));
+ return !cmp && (a->index == b->index);
}
static void t_pq_record(void)
@@ -49,7 +51,9 @@ static void t_pq_record(void)
while (!merged_iter_pqueue_is_empty(pq)) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -90,7 +94,9 @@ static void t_pq_index(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -129,7 +135,9 @@ static void t_merged_iter_pqueue_top(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index 6540bd20e3..5954966373 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -100,16 +100,20 @@ static void t_reftable_ref_record_comparison(void)
.u.ref.value.symref = (char *) "refs/heads/master",
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.ref.value_type = in[0].u.ref.value_type;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_ref_record_compare_name(void)
@@ -209,17 +213,20 @@ static void t_reftable_log_record_comparison(void)
.u.log.update_index = 22,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
/* comparison should be reversed for equal keys, because
* comparison is now performed on the basis of update indices */
- check_int(reftable_record_cmp(&in[0], &in[1]), <, 0);
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check_int(cmp, <, 0);
in[1].u.log.update_index = in[0].u.log.update_index;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
}
static void t_reftable_log_record_compare_key(void)
@@ -396,16 +403,20 @@ static void t_reftable_obj_record_comparison(void)
.u.obj.hash_prefix_len = 5,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.obj.offset_len = in[0].u.obj.offset_len;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_obj_record_roundtrip(void)
@@ -486,19 +497,24 @@ static void t_reftable_index_record_comparison(void)
.u.idx.last_key = REFTABLE_BUF_INIT,
},
};
+ int cmp;
+
check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch"));
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.idx.offset = in[0].u.idx.offset;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
for (size_t i = 0; i < ARRAY_SIZE(in); i++)
reftable_record_release(&in[i]);
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 07/20] reftable: stop using `BUG()` in trivial cases
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (5 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 06/20] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 08/20] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
` (13 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Stop using `BUG()` in the remaining trivial cases that we still have in
the reftable library. Instead of aborting the program, we'll now bubble
up a `REFTABLE_API_ERROR` to indicate misuse of the calling conventions.
Note that in both `reftable_reader_{inc,dec}ref()` we simply stop
calling `BUG()` altogether. The only situation where the counter should
be zero is when the structure has already been free'd anyway, so we
would run into undefined behaviour regardless of whether we try to abort
the program or not.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/iter.c | 3 +--
reftable/reader.c | 4 ----
reftable/writer.c | 5 ++---
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/reftable/iter.c b/reftable/iter.c
index 86e801ca9f..b2ffb09c16 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -146,8 +146,7 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
static int indexed_table_ref_iter_seek(void *p UNUSED,
struct reftable_record *want UNUSED)
{
- BUG("seeking indexed table is not supported");
- return -1;
+ return REFTABLE_API_ERROR;
}
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
diff --git a/reftable/reader.c b/reftable/reader.c
index de6e6dd932..36a5633ede 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -677,8 +677,6 @@ int reftable_reader_new(struct reftable_reader **out,
void reftable_reader_incref(struct reftable_reader *r)
{
- if (!r->refcount)
- BUG("cannot increment ref counter of dead reader");
r->refcount++;
}
@@ -686,8 +684,6 @@ void reftable_reader_decref(struct reftable_reader *r)
{
if (!r)
return;
- if (!r->refcount)
- BUG("cannot decrement ref counter of dead reader");
if (--r->refcount)
return;
block_source_close(&r->source);
diff --git a/reftable/writer.c b/reftable/writer.c
index 91d6629486..155863ee5f 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -158,7 +158,7 @@ int reftable_writer_new(struct reftable_writer **out,
opts = *_opts;
options_set_defaults(&opts);
if (opts.block_size >= (1 << 24))
- BUG("configured block size exceeds 16MB");
+ return REFTABLE_API_ERROR;
reftable_buf_init(&wp->block_writer_data.last_key);
reftable_buf_init(&wp->last_key);
@@ -289,8 +289,7 @@ static int writer_add_record(struct reftable_writer *w,
}
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
- BUG("record of type %d added to writer of type %d",
- reftable_record_type(rec), block_writer_type(w->block_writer));
+ return REFTABLE_API_ERROR;
/*
* Try to add the record to the writer. If this succeeds then we're
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 08/20] reftable/basics: stop using `st_mult()` in array allocators
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (6 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 07/20] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 09/20] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
` (12 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We're using `st_mult()` as part of our macro helpers that allocate
arrays. This is bad due two two reasons:
- `st_mult()` causes us to die in case the multiplication overflows.
- `st_mult()` ties us to the Git codebase.
Refactor the code to instead detect overflows manually and return an
error in such cases.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index a2a010a0e1..646f8d67f2 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -117,18 +117,46 @@ void reftable_free(void *p);
void *reftable_calloc(size_t nelem, size_t elsize);
char *reftable_strdup(const char *str);
-#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
+static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out)
+{
+ if (nelem && elsize > SIZE_MAX / nelem)
+ return -1;
+ *out = nelem * elsize;
+ return 0;
+}
+
+#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_malloc(alloc_size); \
+ } \
+ } while (0)
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
-#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc)))
+#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_realloc((x), alloc_size); \
+ } \
+ } while (0)
static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
size_t *allocp)
{
void *new_p;
- size_t alloc = *allocp * 2 + 1;
+ size_t alloc = *allocp * 2 + 1, alloc_bytes;
if (alloc < nelem)
alloc = nelem;
- new_p = reftable_realloc(p, st_mult(elsize, alloc));
+ if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) {
+ errno = ENOMEM;
+ return p;
+ }
+ new_p = reftable_realloc(p, alloc_bytes);
if (!new_p)
return p;
*allocp = alloc;
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 09/20] reftable/basics: provide wrappers for big endian conversion
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (7 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 08/20] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 10/20] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
` (11 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We're using a mixture of big endian conversion functions provided by
both the reftable library, but also by the Git codebase. Refactor the
code so that we exclusively use reftable-provided wrappers in order to
untangle us from the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.c | 19 ----------
reftable/basics.h | 76 ++++++++++++++++++++++++++++++++++++++--
reftable/block.c | 12 +++----
reftable/reader.c | 22 ++++++------
reftable/record.c | 8 ++---
reftable/writer.c | 20 +++++------
t/unit-tests/t-reftable-basics.c | 28 ++++++++++++---
7 files changed, 127 insertions(+), 58 deletions(-)
diff --git a/reftable/basics.c b/reftable/basics.c
index 3b5ea27bbd..8c4a4433e4 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -147,25 +147,6 @@ char *reftable_buf_detach(struct reftable_buf *buf)
return result;
}
-void put_be24(uint8_t *out, uint32_t i)
-{
- out[0] = (uint8_t)((i >> 16) & 0xff);
- out[1] = (uint8_t)((i >> 8) & 0xff);
- out[2] = (uint8_t)(i & 0xff);
-}
-
-uint32_t get_be24(uint8_t *in)
-{
- return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 |
- (uint32_t)(in[2]);
-}
-
-void put_be16(uint8_t *out, uint16_t i)
-{
- out[0] = (uint8_t)((i >> 8) & 0xff);
- out[1] = (uint8_t)(i & 0xff);
-}
-
size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
{
size_t lo = 0;
diff --git a/reftable/basics.h b/reftable/basics.h
index 646f8d67f2..c1ddbaec3f 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -76,9 +76,79 @@ char *reftable_buf_detach(struct reftable_buf *buf);
/* Bigendian en/decoding of integers */
-void put_be24(uint8_t *out, uint32_t i);
-uint32_t get_be24(uint8_t *in);
-void put_be16(uint8_t *out, uint16_t i);
+static inline void reftable_put_be16(void *out, uint16_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 8) & 0xff);
+ p[1] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be24(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 16) & 0xff);
+ p[1] = (uint8_t)((i >> 8) & 0xff);
+ p[2] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be32(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 24) & 0xff);
+ p[1] = (uint8_t)((i >> 16) & 0xff);
+ p[2] = (uint8_t)((i >> 8) & 0xff);
+ p[3] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be64(void *out, uint64_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 56) & 0xff);
+ p[1] = (uint8_t)((i >> 48) & 0xff);
+ p[2] = (uint8_t)((i >> 40) & 0xff);
+ p[3] = (uint8_t)((i >> 32) & 0xff);
+ p[4] = (uint8_t)((i >> 24) & 0xff);
+ p[5] = (uint8_t)((i >> 16) & 0xff);
+ p[6] = (uint8_t)((i >> 8) & 0xff);
+ p[7] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline uint16_t reftable_get_be16(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint16_t)(p[0]) << 8 |
+ (uint16_t)(p[1]) << 0;
+}
+
+static inline uint32_t reftable_get_be24(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 16 |
+ (uint32_t)(p[1]) << 8 |
+ (uint32_t)(p[2]) << 0;
+}
+
+static inline uint32_t reftable_get_be32(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 24 |
+ (uint32_t)(p[1]) << 16 |
+ (uint32_t)(p[2]) << 8|
+ (uint32_t)(p[3]) << 0;
+}
+
+static inline uint64_t reftable_get_be64(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint64_t)(p[0]) << 56 |
+ (uint64_t)(p[1]) << 48 |
+ (uint64_t)(p[2]) << 40 |
+ (uint64_t)(p[3]) << 32 |
+ (uint64_t)(p[4]) << 24 |
+ (uint64_t)(p[5]) << 16 |
+ (uint64_t)(p[6]) << 8 |
+ (uint64_t)(p[7]) << 0;
+}
/*
* find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is
diff --git a/reftable/block.c b/reftable/block.c
index 255d566854..373908807e 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -148,13 +148,13 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
int block_writer_finish(struct block_writer *w)
{
for (uint32_t i = 0; i < w->restart_len; i++) {
- put_be24(w->block + w->next, w->restarts[i]);
+ reftable_put_be24(w->block + w->next, w->restarts[i]);
w->next += 3;
}
- put_be16(w->block + w->next, w->restart_len);
+ reftable_put_be16(w->block + w->next, w->restart_len);
w->next += 2;
- put_be24(w->block + 1 + w->header_off, w->next);
+ reftable_put_be24(w->block + 1 + w->header_off, w->next);
/*
* Log records are stored zlib-compressed. Note that the compression
@@ -216,7 +216,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
{
uint32_t full_block_size = table_block_size;
uint8_t typ = block->data[header_off];
- uint32_t sz = get_be24(block->data + header_off + 1);
+ uint32_t sz = reftable_get_be24(block->data + header_off + 1);
int err = 0;
uint16_t restart_count = 0;
uint32_t restart_start = 0;
@@ -300,7 +300,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
full_block_size = sz;
}
- restart_count = get_be16(block->data + sz - 2);
+ restart_count = reftable_get_be16(block->data + sz - 2);
restart_start = sz - 2 - 3 * restart_count;
restart_bytes = block->data + restart_start;
@@ -355,7 +355,7 @@ int block_reader_first_key(const struct block_reader *br, struct reftable_buf *k
static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx)
{
- return get_be24(br->restart_bytes + 3 * idx);
+ return reftable_get_be24(br->restart_bytes + 3 * idx);
}
void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)
diff --git a/reftable/reader.c b/reftable/reader.c
index 36a5633ede..bf07a0a586 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -101,18 +101,18 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
}
f++;
- r->block_size = get_be24(f);
+ r->block_size = reftable_get_be24(f);
f += 3;
- r->min_update_index = get_be64(f);
+ r->min_update_index = reftable_get_be64(f);
f += 8;
- r->max_update_index = get_be64(f);
+ r->max_update_index = reftable_get_be64(f);
f += 8;
if (r->version == 1) {
r->hash_id = REFTABLE_HASH_SHA1;
} else {
- switch (get_be32(f)) {
+ switch (reftable_get_be32(f)) {
case REFTABLE_FORMAT_ID_SHA1:
r->hash_id = REFTABLE_HASH_SHA1;
break;
@@ -127,24 +127,24 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
f += 4;
}
- r->ref_offsets.index_offset = get_be64(f);
+ r->ref_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->obj_offsets.offset = get_be64(f);
+ r->obj_offsets.offset = reftable_get_be64(f);
f += 8;
r->object_id_len = r->obj_offsets.offset & ((1 << 5) - 1);
r->obj_offsets.offset >>= 5;
- r->obj_offsets.index_offset = get_be64(f);
+ r->obj_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.offset = get_be64(f);
+ r->log_offsets.offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.index_offset = get_be64(f);
+ r->log_offsets.index_offset = reftable_get_be64(f);
f += 8;
computed_crc = crc32(0, footer, f - footer);
- file_crc = get_be32(f);
+ file_crc = reftable_get_be32(f);
f += 4;
if (computed_crc != file_crc) {
err = REFTABLE_FORMAT_ERROR;
@@ -214,7 +214,7 @@ static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
*typ = data[0];
if (reftable_is_block_type(*typ)) {
- result = get_be24(data + 1);
+ result = reftable_get_be24(data + 1);
}
return result;
}
diff --git a/reftable/record.c b/reftable/record.c
index da550494a2..286659c098 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -684,7 +684,7 @@ static int reftable_log_record_key(const void *r, struct reftable_buf *dest)
return err;
ts = (~ts) - rec->update_index;
- put_be64(&i64[0], ts);
+ reftable_put_be64(&i64[0], ts);
err = reftable_buf_add(dest, i64, sizeof(i64));
if (err < 0)
@@ -809,7 +809,7 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,
if (s.len < 2)
return -1;
- put_be16(s.buf, r->value.update.tz_offset);
+ reftable_put_be16(s.buf, r->value.update.tz_offset);
string_view_consume(&s, 2);
n = encode_string(
@@ -841,7 +841,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
}
memcpy(r->refname, key.buf, key.len - 8);
- ts = get_be64(key.buf + key.len - 8);
+ ts = reftable_get_be64((unsigned char *)key.buf + key.len - 8);
r->update_index = (~max) - ts;
@@ -932,7 +932,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
goto done;
}
- r->value.update.tz_offset = get_be16(in.buf);
+ r->value.update.tz_offset = reftable_get_be16(in.buf);
string_view_consume(&in, 2);
n = decode_string(scratch, in);
diff --git a/reftable/writer.c b/reftable/writer.c
index 155863ee5f..5961698311 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -99,9 +99,9 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
dest[4] = writer_version(w);
- put_be24(dest + 5, w->opts.block_size);
- put_be64(dest + 8, w->min_update_index);
- put_be64(dest + 16, w->max_update_index);
+ reftable_put_be24(dest + 5, w->opts.block_size);
+ reftable_put_be64(dest + 8, w->min_update_index);
+ reftable_put_be64(dest + 16, w->max_update_index);
if (writer_version(w) == 2) {
uint32_t hash_id;
@@ -116,7 +116,7 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
return -1;
}
- put_be32(dest + 24, hash_id);
+ reftable_put_be32(dest + 24, hash_id);
}
return header_size(writer_version(w));
@@ -717,19 +717,19 @@ int reftable_writer_close(struct reftable_writer *w)
}
p += writer_write_header(w, footer);
- put_be64(p, w->stats.ref_stats.index_offset);
+ reftable_put_be64(p, w->stats.ref_stats.index_offset);
p += 8;
- put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
+ reftable_put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
p += 8;
- put_be64(p, w->stats.obj_stats.index_offset);
+ reftable_put_be64(p, w->stats.obj_stats.index_offset);
p += 8;
- put_be64(p, w->stats.log_stats.offset);
+ reftable_put_be64(p, w->stats.log_stats.offset);
p += 8;
- put_be64(p, w->stats.log_stats.index_offset);
+ reftable_put_be64(p, w->stats.log_stats.index_offset);
p += 8;
- put_be32(p, crc32(0, footer, p - footer));
+ reftable_put_be32(p, crc32(0, footer, p - footer));
p += 4;
err = w->flush(w->write_arg);
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
index 9ba7eb05ad..c9e751e49e 100644
--- a/t/unit-tests/t-reftable-basics.c
+++ b/t/unit-tests/t-reftable-basics.c
@@ -128,12 +128,30 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
reftable_buf_release(&b);
}
- if_test ("put_be24 and get_be24 work") {
+ if_test ("reftable_put_be64 and reftable_get_be64 work") {
+ uint64_t in = 0x1122334455667788;
+ uint8_t dest[8];
+ uint64_t out;
+ reftable_put_be64(dest, in);
+ out = reftable_get_be64(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be32 and reftable_get_be32 work") {
+ uint32_t in = 0x11223344;
+ uint8_t dest[4];
+ uint32_t out;
+ reftable_put_be32(dest, in);
+ out = reftable_get_be32(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be24 and reftable_get_be24 work") {
uint32_t in = 0x112233;
uint8_t dest[3];
uint32_t out;
- put_be24(dest, in);
- out = get_be24(dest);
+ reftable_put_be24(dest, in);
+ out = reftable_get_be24(dest);
check_int(in, ==, out);
}
@@ -141,8 +159,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
uint32_t in = 0xfef1;
uint8_t dest[3];
uint32_t out;
- put_be16(dest, in);
- out = get_be16(dest);
+ reftable_put_be16(dest, in);
+ out = reftable_get_be16(dest);
check_int(in, ==, out);
}
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 10/20] reftable/reader: stop using `ARRAY_SIZE()` macro
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (8 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 09/20] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 11/20] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
` (10 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We have a single user of the `ARRAY_SIZE()` macro in the reftable
reader. Drop its use to reduce our dependence on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/reader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/reader.c b/reftable/reader.c
index bf07a0a586..c3a3674665 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -849,7 +849,7 @@ int reftable_reader_print_blocks(const char *tablename)
printf("header:\n");
printf(" block_size: %d\n", r->block_size);
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
+ for (i = 0; i < sizeof(sections) / sizeof(*sections); i++) {
err = table_iter_seek_start(&ti, sections[i].type, 0);
if (err < 0)
goto done;
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 11/20] reftable/system: introduce `reftable_rand()`
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (9 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 10/20] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 12/20] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
` (9 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Introduce a new system-level `reftable_rand()` function that generates a
single unsigned integer for us. The implementation of this function is
to be provided by the calling codebase, which allows us to more easily
hook into pre-seeded random number generators.
Adapt the two callsites where we generated random data.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 4 ++--
reftable/system.c | 5 +++++
reftable/system.h | 6 ++++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 5f155b344b..82bdf5169f 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -523,7 +523,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
close(fd);
fd = -1;
- delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1;
+ delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
sleep_millisec(delay);
}
@@ -688,7 +688,7 @@ int reftable_stack_add(struct reftable_stack *st,
static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
{
char buf[100];
- uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE);
+ uint32_t rnd = reftable_rand();
snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
min, max, rnd);
reftable_buf_reset(dest);
diff --git a/reftable/system.c b/reftable/system.c
index adf8e4d30b..e25ccc0da3 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -4,6 +4,11 @@
#include "../lockfile.h"
#include "../tempfile.h"
+uint32_t reftable_rand(void)
+{
+ return git_rand(CSPRNG_BYTES_INSECURE);
+}
+
int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern)
{
struct tempfile *tempfile;
diff --git a/reftable/system.h b/reftable/system.h
index 7d5f803eeb..3bd4a4e322 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -13,6 +13,12 @@ license that can be found in the LICENSE file or at
#include "git-compat-util.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 12/20] reftable/stack: stop using `sleep_millisec()`
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (10 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 11/20] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 13/20] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
` (8 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Refactor our use of `sleep_millisec()` by open-coding it with poll(3p),
which is the current implementation of this function. Ideally, we'd use
a more direct way to sleep, but there is no equivalent to sleep(3p) that
would accept milliseconds as input.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 82bdf5169f..8e9836aef3 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -524,7 +524,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
fd = -1;
delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
- sleep_millisec(delay);
+ poll(NULL, 0, delay);
}
out:
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 13/20] reftable/basics: stop using `SWAP()` macro
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (11 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 12/20] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 14/20] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
` (7 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Stop using `SWAP()` macro in favor of an open-coded variant of it. Note
that this also requires us to open-code the build assert that `SWAP()`
itself uses to verify that the size of both variables matches.
This is done to reduce our dependency on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 9 +++++++++
reftable/merged.c | 2 +-
reftable/pq.c | 4 ++--
reftable/record.c | 16 ++++++++--------
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index c1ddbaec3f..59000798f0 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -266,6 +266,15 @@ static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
# define strdup(str) REFTABLE_BANNED(strdup)
#endif
+#define REFTABLE_SWAP(a, b) do { \
+ void *_swap_a_ptr = &(a); \
+ void *_swap_b_ptr = &(b); \
+ unsigned char _swap_buffer[sizeof(a) - 2 * sizeof(a) * (sizeof(a) != sizeof(b))]; \
+ memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \
+ memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a)); \
+ memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
+} while (0)
+
/* Find the longest shared prefix size of `a` and `b` */
size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);
diff --git a/reftable/merged.c b/reftable/merged.c
index 563864068c..4ff1553772 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -155,7 +155,7 @@ static int merged_iter_next_entry(struct merged_iter *mi,
}
mi->advance_index = entry.index;
- SWAP(*rec, *entry.rec);
+ REFTABLE_SWAP(*rec, *entry.rec);
return 0;
}
diff --git a/reftable/pq.c b/reftable/pq.c
index ef8035cfd9..82394a972d 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -57,7 +57,7 @@ int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *ou
if (min == i)
break;
- SWAP(pq->heap[i], pq->heap[min]);
+ REFTABLE_SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
@@ -81,7 +81,7 @@ int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry
size_t j = (i - 1) / 2;
if (pq_less(&pq->heap[j], &pq->heap[i]))
break;
- SWAP(pq->heap[j], pq->heap[i]);
+ REFTABLE_SWAP(pq->heap[j], pq->heap[i]);
i = j;
}
diff --git a/reftable/record.c b/reftable/record.c
index 286659c098..d86cd65bb4 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -237,11 +237,11 @@ static int reftable_ref_record_copy_from(void *rec, const void *src_rec,
size_t refname_cap = 0;
int err;
- SWAP(refname, ref->refname);
- SWAP(refname_cap, ref->refname_cap);
+ REFTABLE_SWAP(refname, ref->refname);
+ REFTABLE_SWAP(refname_cap, ref->refname_cap);
reftable_ref_record_release(ref);
- SWAP(ref->refname, refname);
- SWAP(ref->refname_cap, refname_cap);
+ REFTABLE_SWAP(ref->refname, refname);
+ REFTABLE_SWAP(ref->refname_cap, refname_cap);
if (src->refname) {
size_t refname_len = strlen(src->refname);
@@ -376,11 +376,11 @@ static int reftable_ref_record_decode(void *rec, struct reftable_buf key,
return n;
string_view_consume(&in, n);
- SWAP(refname, r->refname);
- SWAP(refname_cap, r->refname_cap);
+ REFTABLE_SWAP(refname, r->refname);
+ REFTABLE_SWAP(refname_cap, r->refname_cap);
reftable_ref_record_release(r);
- SWAP(r->refname, refname);
- SWAP(r->refname_cap, refname_cap);
+ REFTABLE_SWAP(r->refname, refname);
+ REFTABLE_SWAP(r->refname_cap, refname_cap);
REFTABLE_ALLOC_GROW_OR_NULL(r->refname, key.len + 1, r->refname_cap);
if (!r->refname) {
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 14/20] reftable/basics: stop using `UNUSED` annotation
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (12 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 13/20] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 15/20] compat: consistently resolve headers via project root Patrick Steinhardt
` (6 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Stop using the `UNUSED` annotation and replace it with a new
`REFTABLE_UNUSED` macro. The latter is a weaker guarantee compared to
`UNUSED` as it only suppresses unused parameters without generating a
warning in case a parameter marked as unused is in fact used. But it's
good enough, and by relaxing the behaviour a bit we avoid having to wire
up compiler-specific logic.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 2 ++
reftable/blocksource.c | 10 +++++++---
reftable/iter.c | 17 ++++++++++++-----
reftable/record.c | 51 ++++++++++++++++++++++++++++++++++++--------------
reftable/writer.c | 4 +++-
5 files changed, 61 insertions(+), 23 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index 59000798f0..4d0645a4e9 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -16,6 +16,8 @@ license that can be found in the LICENSE file or at
#include "system.h"
#include "reftable-basics.h"
+#define REFTABLE_UNUSED(x) (void)(x)
+
struct reftable_buf {
size_t alloc;
size_t len;
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index 02972c46f4..bfd64b0e48 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -13,15 +13,17 @@ license that can be found in the LICENSE file or at
#include "reftable-blocksource.h"
#include "reftable-error.h"
-static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)
+static void reftable_buf_return_block(void *b, struct reftable_block *dest)
{
+ REFTABLE_UNUSED(b);
if (dest->len)
memset(dest->data, 0xff, dest->len);
reftable_free(dest->data);
}
-static void reftable_buf_close(void *b UNUSED)
+static void reftable_buf_close(void *b)
{
+ REFTABLE_UNUSED(b);
}
static ssize_t reftable_buf_read_block(void *v, struct reftable_block *dest,
@@ -67,8 +69,10 @@ static uint64_t file_size(void *b)
return ((struct file_block_source *)b)->size;
}
-static void file_return_block(void *b UNUSED, struct reftable_block *dest UNUSED)
+static void file_return_block(void *b, struct reftable_block *dest)
{
+ REFTABLE_UNUSED(b);
+ REFTABLE_UNUSED(dest);
}
static void file_close(void *v)
diff --git a/reftable/iter.c b/reftable/iter.c
index b2ffb09c16..452add2705 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -25,18 +25,23 @@ int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
return it->ops->next(it->iter_arg, rec);
}
-static int empty_iterator_seek(void *arg UNUSED, struct reftable_record *want UNUSED)
+static int empty_iterator_seek(void *arg, struct reftable_record *want)
{
+ REFTABLE_UNUSED(arg);
+ REFTABLE_UNUSED(want);
return 0;
}
-static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED)
+static int empty_iterator_next(void *arg, struct reftable_record *rec)
{
+ REFTABLE_UNUSED(arg);
+ REFTABLE_UNUSED(rec);
return 1;
}
-static void empty_iterator_close(void *arg UNUSED)
+static void empty_iterator_close(void *arg)
{
+ REFTABLE_UNUSED(arg);
}
static struct reftable_iterator_vtable empty_vtable = {
@@ -143,9 +148,11 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
return 0;
}
-static int indexed_table_ref_iter_seek(void *p UNUSED,
- struct reftable_record *want UNUSED)
+static int indexed_table_ref_iter_seek(void *p,
+ struct reftable_record *want)
{
+ REFTABLE_UNUSED(p);
+ REFTABLE_UNUSED(want);
return REFTABLE_API_ERROR;
}
diff --git a/reftable/record.c b/reftable/record.c
index d86cd65bb4..46093ef987 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -490,11 +490,13 @@ static void reftable_obj_record_release(void *rec)
}
static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_obj_record *obj = rec;
const struct reftable_obj_record *src = src_rec;
+ REFTABLE_UNUSED(hash_size);
+
reftable_obj_record_release(obj);
REFTABLE_ALLOC_ARRAY(obj->hash_prefix, src->hash_prefix_len);
@@ -523,13 +525,16 @@ static uint8_t reftable_obj_record_val_type(const void *rec)
}
static int reftable_obj_record_encode(const void *rec, struct string_view s,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
const struct reftable_obj_record *r = rec;
struct string_view start = s;
int i = 0;
int n = 0;
uint64_t last = 0;
+
+ REFTABLE_UNUSED(hash_size);
+
if (r->offset_len == 0 || r->offset_len >= 8) {
n = put_var_int(&s, r->offset_len);
if (n < 0) {
@@ -558,8 +563,8 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,
static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
uint8_t val_type, struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size,
+ struct reftable_buf *scratch)
{
struct string_view start = in;
struct reftable_obj_record *r = rec;
@@ -567,6 +572,9 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
int n = 0;
uint64_t last;
+ REFTABLE_UNUSED(hash_size);
+ REFTABLE_UNUSED(scratch);
+
reftable_obj_record_release(r);
REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len);
@@ -613,17 +621,20 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
return start.len - in.len;
}
-static int not_a_deletion(const void *p UNUSED)
+static int not_a_deletion(const void *p)
{
+ REFTABLE_UNUSED(p);
return 0;
}
static int reftable_obj_record_equal_void(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_obj_record *ra = (struct reftable_obj_record *) a;
struct reftable_obj_record *rb = (struct reftable_obj_record *) b;
+ REFTABLE_UNUSED(hash_size);
+
if (ra->hash_prefix_len != rb->hash_prefix_len
|| ra->offset_len != rb->offset_len)
return 0;
@@ -1049,12 +1060,14 @@ static int reftable_index_record_key(const void *r, struct reftable_buf *dest)
}
static int reftable_index_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_index_record *dst = rec;
const struct reftable_index_record *src = src_rec;
int err;
+ REFTABLE_UNUSED(hash_size);
+
reftable_buf_reset(&dst->last_key);
err = reftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);
if (err < 0)
@@ -1070,19 +1083,23 @@ static void reftable_index_record_release(void *rec)
reftable_buf_release(&idx->last_key);
}
-static uint8_t reftable_index_record_val_type(const void *rec UNUSED)
+static uint8_t reftable_index_record_val_type(const void *rec)
{
+ REFTABLE_UNUSED(rec);
return 0;
}
static int reftable_index_record_encode(const void *rec, struct string_view out,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
const struct reftable_index_record *r =
(const struct reftable_index_record *)rec;
struct string_view start = out;
+ int n;
- int n = put_var_int(&out, r->offset);
+ REFTABLE_UNUSED(hash_size);
+
+ n = put_var_int(&out, r->offset);
if (n < 0)
return n;
@@ -1092,15 +1109,19 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,
}
static int reftable_index_record_decode(void *rec, struct reftable_buf key,
- uint8_t val_type UNUSED,
+ uint8_t val_type,
struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size,
+ struct reftable_buf *scratch)
{
struct string_view start = in;
struct reftable_index_record *r = rec;
int err, n = 0;
+ REFTABLE_UNUSED(val_type);
+ REFTABLE_UNUSED(hash_size);
+ REFTABLE_UNUSED(scratch);
+
reftable_buf_reset(&r->last_key);
err = reftable_buf_add(&r->last_key, key.buf, key.len);
if (err < 0)
@@ -1115,11 +1136,13 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,
}
static int reftable_index_record_equal(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_index_record *ia = (struct reftable_index_record *) a;
struct reftable_index_record *ib = (struct reftable_index_record *) b;
+ REFTABLE_UNUSED(hash_size);
+
return ia->offset == ib->offset && !reftable_buf_cmp(&ia->last_key, &ib->last_key);
}
diff --git a/reftable/writer.c b/reftable/writer.c
index 5961698311..0040a1b1c4 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -636,10 +636,12 @@ static void write_object_record(void *void_arg, void *key)
done:;
}
-static void object_record_free(void *void_arg UNUSED, void *key)
+static void object_record_free(void *void_arg, void *key)
{
struct obj_index_tree_node *entry = key;
+ REFTABLE_UNUSED(void_arg);
+
REFTABLE_FREE_AND_NULL(entry->offsets);
reftable_buf_release(&entry->hash);
reftable_free(entry);
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 15/20] compat: consistently resolve headers via project root
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (13 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 14/20] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-29 7:50 ` Johannes Sixt
2025-01-28 8:28 ` [PATCH v2 16/20] compat/mingw: split out POSIX-related bits Patrick Steinhardt
` (5 subsequent siblings)
20 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The way we include headers in the "compat/" directory is inconsistent:
- Sometimes we use includes relative to the current file.
- Sometimes we use includes relative to the project root directory,
which is being added via a `-I` compiler switch.
- On Windows we also use includes relative to "compat/", which is
being added via another platform-specific `-I` compiler switch in
"compat.mak.uname".
This makes it very confusing to figure out which specific file is being
included right now and from what layer that file comes.
Stop adding "compat/" to the Windows-specific include directories and
adapt all includes in "compat/" to be relative to the projet's root
directory. Despite being more consistent, it also makes it way easier to
spot where an include comes from.
This change also prepares for subsequent commits where we split up both
"compat/mingw.h" and "compat/msvc.h".
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/access.c | 3 ++-
compat/basename.c | 4 ++--
compat/fileno.c | 2 +-
compat/fopen.c | 2 +-
compat/fsmonitor/fsm-health-darwin.c | 2 +-
compat/fsmonitor/fsm-health-win32.c | 2 +-
compat/fsmonitor/fsm-listen-darwin.c | 4 ++--
compat/fsmonitor/fsm-listen-win32.c | 2 +-
compat/inet_ntop.c | 2 +-
compat/inet_pton.c | 2 +-
compat/memmem.c | 2 +-
compat/mingw.c | 24 ++++++++++++------------
compat/mkdir.c | 2 +-
compat/mkdtemp.c | 2 +-
compat/mmap.c | 2 +-
compat/msvc.c | 8 ++++----
compat/nonblock.c | 4 ++--
compat/obstack.c | 2 +-
compat/pread.c | 4 ++--
compat/precompose_utf8.c | 2 +-
compat/qsort_s.c | 2 +-
compat/regcomp_enhanced.c | 2 +-
compat/setenv.c | 2 +-
compat/snprintf.c | 2 +-
compat/strcasestr.c | 2 +-
compat/strdup.c | 2 +-
compat/strlcpy.c | 2 +-
compat/strtoimax.c | 2 +-
compat/strtoumax.c | 2 +-
compat/unsetenv.c | 2 +-
compat/win32/dirent.c | 2 +-
compat/win32/flush.c | 2 +-
compat/win32/path-utils.c | 4 ++--
compat/win32/pthread.c | 4 ++--
compat/win32/syslog.c | 2 +-
compat/win32/trace2_win32_process_info.c | 10 +++++-----
compat/win32mmap.c | 2 +-
compat/winansi.c | 6 +++---
config.mak.uname | 4 ++--
39 files changed, 67 insertions(+), 66 deletions(-)
diff --git a/compat/access.c b/compat/access.c
index 19fda3e877..918f51a08b 100644
--- a/compat/access.c
+++ b/compat/access.c
@@ -1,5 +1,6 @@
#define COMPAT_CODE_ACCESS
-#include "../git-compat-util.h"
+
+#include "git-compat-util.h"
/* Do the same thing access(2) does, but use the effective uid,
* and don't make the mistake of telling root that any file is
diff --git a/compat/basename.c b/compat/basename.c
index c33579ef61..2f59c5475b 100644
--- a/compat/basename.c
+++ b/compat/basename.c
@@ -1,5 +1,5 @@
-#include "../git-compat-util.h"
-#include "../strbuf.h"
+#include "git-compat-util.h"
+#include "strbuf.h"
/* Adapted from libiberty's basename.c. */
char *gitbasename (char *path)
diff --git a/compat/fileno.c b/compat/fileno.c
index 8e80ef335d..977d63bf62 100644
--- a/compat/fileno.c
+++ b/compat/fileno.c
@@ -1,5 +1,5 @@
#define COMPAT_CODE_FILENO
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
int git_fileno(FILE *stream)
{
diff --git a/compat/fopen.c b/compat/fopen.c
index 107b3e8182..4af1f14996 100644
--- a/compat/fopen.c
+++ b/compat/fopen.c
@@ -9,7 +9,7 @@
* fopen after including git-compat-util.h is inadequate in this case.
*/
#define SUPPRESS_FOPEN_REDEFINITION
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
FILE *git_fopen(const char *path, const char *mode)
{
diff --git a/compat/fsmonitor/fsm-health-darwin.c b/compat/fsmonitor/fsm-health-darwin.c
index c2afcbe6c8..68c9fd7363 100644
--- a/compat/fsmonitor/fsm-health-darwin.c
+++ b/compat/fsmonitor/fsm-health-darwin.c
@@ -1,7 +1,7 @@
#include "git-compat-util.h"
+#include "compat/fsmonitor/fsm-health.h"
#include "config.h"
#include "fsmonitor-ll.h"
-#include "fsm-health.h"
#include "fsmonitor--daemon.h"
int fsm_health__ctor(struct fsmonitor_daemon_state *state UNUSED)
diff --git a/compat/fsmonitor/fsm-health-win32.c b/compat/fsmonitor/fsm-health-win32.c
index 2aa8c219ac..16e073383b 100644
--- a/compat/fsmonitor/fsm-health-win32.c
+++ b/compat/fsmonitor/fsm-health-win32.c
@@ -1,7 +1,7 @@
#include "git-compat-util.h"
+#include "compat/fsmonitor/fsm-health.h"
#include "config.h"
#include "fsmonitor-ll.h"
-#include "fsm-health.h"
#include "fsmonitor--daemon.h"
#include "gettext.h"
#include "simple-ipc.h"
diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c
index 43c3a915a0..b9414da0d1 100644
--- a/compat/fsmonitor/fsm-listen-darwin.c
+++ b/compat/fsmonitor/fsm-listen-darwin.c
@@ -1,6 +1,6 @@
#ifndef __clang__
#include <dispatch/dispatch.h>
-#include "fsm-darwin-gcc.h"
+#include "compat/fsmonitor/fsm-darwin-gcc.h"
#else
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
@@ -24,8 +24,8 @@
#endif
#include "git-compat-util.h"
+#include "compat/fsmonitor/fsm-listen.h"
#include "fsmonitor-ll.h"
-#include "fsm-listen.h"
#include "fsmonitor--daemon.h"
#include "fsmonitor-path-utils.h"
#include "gettext.h"
diff --git a/compat/fsmonitor/fsm-listen-win32.c b/compat/fsmonitor/fsm-listen-win32.c
index 9a6efc9bea..3fb5710e21 100644
--- a/compat/fsmonitor/fsm-listen-win32.c
+++ b/compat/fsmonitor/fsm-listen-win32.c
@@ -1,7 +1,7 @@
#include "git-compat-util.h"
+#include "compat/fsmonitor/fsm-listen.h"
#include "config.h"
#include "fsmonitor-ll.h"
-#include "fsm-listen.h"
#include "fsmonitor--daemon.h"
#include "gettext.h"
#include "simple-ipc.h"
diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c
index 68307262be..3bac8377cc 100644
--- a/compat/inet_ntop.c
+++ b/compat/inet_ntop.c
@@ -15,7 +15,7 @@
* SOFTWARE.
*/
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
#ifndef NS_INADDRSZ
#define NS_INADDRSZ 4
diff --git a/compat/inet_pton.c b/compat/inet_pton.c
index 2b9a0a4e22..60935a1c83 100644
--- a/compat/inet_pton.c
+++ b/compat/inet_pton.c
@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
#ifndef NS_INT16SZ
#define NS_INT16SZ 2
diff --git a/compat/memmem.c b/compat/memmem.c
index 56bcb4277f..2df3e7b7b9 100644
--- a/compat/memmem.c
+++ b/compat/memmem.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
void *gitmemmem(const void *haystack, size_t haystack_len,
const void *needle, size_t needle_len)
diff --git a/compat/mingw.c b/compat/mingw.c
index 1d5b211b54..5b0593c59d 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1,22 +1,22 @@
#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS
-#include "../git-compat-util.h"
-#include "win32.h"
+#include "git-compat-util.h"
+#include "compat/win32.h"
#include <aclapi.h>
#include <sddl.h>
#include <conio.h>
#include <wchar.h>
-#include "../strbuf.h"
-#include "../run-command.h"
-#include "../abspath.h"
-#include "../alloc.h"
-#include "win32/lazyload.h"
-#include "../config.h"
-#include "../environment.h"
-#include "../trace2.h"
-#include "../symlinks.h"
-#include "../wrapper.h"
+#include "strbuf.h"
+#include "run-command.h"
+#include "abspath.h"
+#include "alloc.h"
+#include "compat/win32/lazyload.h"
+#include "config.h"
+#include "environment.h"
+#include "trace2.h"
+#include "symlinks.h"
+#include "wrapper.h"
#include "dir.h"
#include "gettext.h"
#define SECURITY_WIN32
diff --git a/compat/mkdir.c b/compat/mkdir.c
index 02aea3b32e..8bd7c9a927 100644
--- a/compat/mkdir.c
+++ b/compat/mkdir.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
#undef mkdir
/* for platforms that can't deal with a trailing '/' */
diff --git a/compat/mkdtemp.c b/compat/mkdtemp.c
index 1136119592..4349e15eee 100644
--- a/compat/mkdtemp.c
+++ b/compat/mkdtemp.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
char *gitmkdtemp(char *template)
{
diff --git a/compat/mmap.c b/compat/mmap.c
index 2fe1c7732e..0a50adc9b9 100644
--- a/compat/mmap.c
+++ b/compat/mmap.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
diff --git a/compat/msvc.c b/compat/msvc.c
index 71843d7eef..5aacf3af19 100644
--- a/compat/msvc.c
+++ b/compat/msvc.c
@@ -1,6 +1,6 @@
-#include "../git-compat-util.h"
-#include "win32.h"
+#include "git-compat-util.h"
+#include "compat/win32.h"
#include <conio.h>
-#include "../strbuf.h"
+#include "strbuf.h"
-#include "mingw.c"
+#include "compat/mingw.c"
diff --git a/compat/nonblock.c b/compat/nonblock.c
index 5b51195c32..99ea76a7a4 100644
--- a/compat/nonblock.c
+++ b/compat/nonblock.c
@@ -1,5 +1,5 @@
#include "git-compat-util.h"
-#include "nonblock.h"
+#include "compat/nonblock.h"
#ifdef O_NONBLOCK
@@ -14,7 +14,7 @@ int enable_pipe_nonblock(int fd)
#elif defined(GIT_WINDOWS_NATIVE)
-#include "win32.h"
+#include "compat/win32.h"
int enable_pipe_nonblock(int fd)
{
diff --git a/compat/obstack.c b/compat/obstack.c
index 27cd5c1ea1..baab07aca4 100644
--- a/compat/obstack.c
+++ b/compat/obstack.c
@@ -19,7 +19,7 @@
#include "git-compat-util.h"
#include <gettext.h>
-#include "obstack.h"
+#include "compat/obstack.h"
/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
incremented whenever callers compiled using an old obstack.h can no
diff --git a/compat/pread.c b/compat/pread.c
index 484e6d4c71..82161b5a2a 100644
--- a/compat/pread.c
+++ b/compat/pread.c
@@ -1,5 +1,5 @@
-#include "../git-compat-util.h"
-#include "../wrapper.h"
+#include "git-compat-util.h"
+#include "wrapper.h"
ssize_t git_pread(int fd, void *buf, size_t count, off_t offset)
{
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index f7cc7b3be5..994a2f1303 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -7,13 +7,13 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
+#include "compat/precompose_utf8.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
#include "path.h"
#include "strbuf.h"
#include "utf8.h"
-#include "precompose_utf8.h"
typedef char *iconv_ibp;
static const char *repo_encoding = "UTF-8";
diff --git a/compat/qsort_s.c b/compat/qsort_s.c
index 0f7ff30f5f..66cd6e096d 100644
--- a/compat/qsort_s.c
+++ b/compat/qsort_s.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
/*
* A merge sort implementation, simplified from the qsort implementation
diff --git a/compat/regcomp_enhanced.c b/compat/regcomp_enhanced.c
index 84193ce53b..693b63c2c4 100644
--- a/compat/regcomp_enhanced.c
+++ b/compat/regcomp_enhanced.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
#undef regcomp
int git_regcomp(regex_t *preg, const char *pattern, int cflags)
diff --git a/compat/setenv.c b/compat/setenv.c
index 7849f258d2..c49df82534 100644
--- a/compat/setenv.c
+++ b/compat/setenv.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
int gitsetenv(const char *name, const char *value, int replace)
{
diff --git a/compat/snprintf.c b/compat/snprintf.c
index 0b11688537..91a63cf3f7 100644
--- a/compat/snprintf.c
+++ b/compat/snprintf.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
/*
* The size parameter specifies the available space, i.e. includes
diff --git a/compat/strcasestr.c b/compat/strcasestr.c
index 26896deca6..d66609361b 100644
--- a/compat/strcasestr.c
+++ b/compat/strcasestr.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
char *gitstrcasestr(const char *haystack, const char *needle)
{
diff --git a/compat/strdup.c b/compat/strdup.c
index f3fb978eb3..9ef99f88f2 100644
--- a/compat/strdup.c
+++ b/compat/strdup.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
char *gitstrdup(const char *s1)
{
diff --git a/compat/strlcpy.c b/compat/strlcpy.c
index 4024c36030..780b39ff82 100644
--- a/compat/strlcpy.c
+++ b/compat/strlcpy.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
size_t gitstrlcpy(char *dest, const char *src, size_t size)
{
diff --git a/compat/strtoimax.c b/compat/strtoimax.c
index ac09ed89e7..c9ed79f0d1 100644
--- a/compat/strtoimax.c
+++ b/compat/strtoimax.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
intmax_t gitstrtoimax (const char *nptr, char **endptr, int base)
{
diff --git a/compat/strtoumax.c b/compat/strtoumax.c
index 5541353a77..50fe26d746 100644
--- a/compat/strtoumax.c
+++ b/compat/strtoumax.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
uintmax_t gitstrtoumax (const char *nptr, char **endptr, int base)
{
diff --git a/compat/unsetenv.c b/compat/unsetenv.c
index b9d34af613..d96e0d7bcc 100644
--- a/compat/unsetenv.c
+++ b/compat/unsetenv.c
@@ -1,4 +1,4 @@
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
int gitunsetenv(const char *name)
{
diff --git a/compat/win32/dirent.c b/compat/win32/dirent.c
index 52420ec7d4..362622746d 100644
--- a/compat/win32/dirent.c
+++ b/compat/win32/dirent.c
@@ -1,4 +1,4 @@
-#include "../../git-compat-util.h"
+#include "git-compat-util.h"
struct DIR {
struct dirent dd_dir; /* includes d_type */
diff --git a/compat/win32/flush.c b/compat/win32/flush.c
index 291f90ea94..bcad557eb4 100644
--- a/compat/win32/flush.c
+++ b/compat/win32/flush.c
@@ -1,6 +1,6 @@
#include "git-compat-util.h"
#include <winternl.h>
-#include "lazyload.h"
+#include "compat/win32/lazyload.h"
int win32_fsync_no_flush(int fd)
{
diff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c
index 966ef779b9..20e9a69f56 100644
--- a/compat/win32/path-utils.c
+++ b/compat/win32/path-utils.c
@@ -1,7 +1,7 @@
#define USE_THE_REPOSITORY_VARIABLE
-#include "../../git-compat-util.h"
-#include "../../environment.h"
+#include "git-compat-util.h"
+#include "environment.h"
int win32_has_dos_drive_prefix(const char *path)
{
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c
index 58980a529c..86199d67ba 100644
--- a/compat/win32/pthread.c
+++ b/compat/win32/pthread.c
@@ -7,8 +7,8 @@
* no need for double-checking.
*/
-#include "../../git-compat-util.h"
-#include "pthread.h"
+#include "git-compat-util.h"
+#include "compat/win32/pthread.h"
#include <errno.h>
#include <limits.h>
diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c
index 4e4794743a..587fb99ba9 100644
--- a/compat/win32/syslog.c
+++ b/compat/win32/syslog.c
@@ -1,4 +1,4 @@
-#include "../../git-compat-util.h"
+#include "git-compat-util.h"
static HANDLE ms_eventlog;
diff --git a/compat/win32/trace2_win32_process_info.c b/compat/win32/trace2_win32_process_info.c
index f147da706a..55e482f100 100644
--- a/compat/win32/trace2_win32_process_info.c
+++ b/compat/win32/trace2_win32_process_info.c
@@ -1,10 +1,10 @@
#define USE_THE_REPOSITORY_VARIABLE
-#include "../../git-compat-util.h"
-#include "../../json-writer.h"
-#include "../../repository.h"
-#include "../../trace2.h"
-#include "lazyload.h"
+#include "git-compat-util.h"
+#include "compat/win32/lazyload.h"
+#include "json-writer.h"
+#include "repository.h"
+#include "trace2.h"
#include <psapi.h>
#include <tlhelp32.h>
diff --git a/compat/win32mmap.c b/compat/win32mmap.c
index e951934316..aff1768acb 100644
--- a/compat/win32mmap.c
+++ b/compat/win32mmap.c
@@ -1,6 +1,6 @@
#define DISABLE_SIGN_COMPARE_WARNINGS
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
diff --git a/compat/winansi.c b/compat/winansi.c
index ac2ffb7869..143685e5ab 100644
--- a/compat/winansi.c
+++ b/compat/winansi.c
@@ -6,11 +6,11 @@
#define DISABLE_SIGN_COMPARE_WARNINGS
-#include "../git-compat-util.h"
+#include "git-compat-util.h"
#include <wingdi.h>
#include <winreg.h>
-#include "win32.h"
-#include "win32/lazyload.h"
+#include "compat/win32.h"
+#include "compat/win32/lazyload.h"
static int fd_is_interactive[3] = { 0, 0, 0 };
#define FD_CONSOLE 0x1
diff --git a/config.mak.uname b/config.mak.uname
index b12d4e168a..cd9535a65c 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -501,7 +501,7 @@ endif
compat/win32/pthread.o compat/win32/syslog.o \
compat/win32/trace2_win32_process_info.o \
compat/win32/dirent.o
- COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
+ COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DNOGDI -DHAVE_STRING_H -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -ENTRY:wmainCRTStartup -SUBSYSTEM:CONSOLE
# invalidcontinue.obj allows Git's source code to close the same file
# handle twice, or to access the osfhandle of an already-closed stdout
@@ -692,7 +692,7 @@ ifeq ($(uname_S),MINGW)
HAVE_PLATFORM_PROCINFO = YesPlease
CSPRNG_METHOD = rtlgenrandom
BASIC_LDFLAGS += -municode
- COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
+ COMPAT_CFLAGS += -DNOGDI -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
COMPAT_OBJS += compat/mingw.o compat/winansi.o \
compat/win32/trace2_win32_process_info.o \
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 16/20] compat/mingw: split out POSIX-related bits
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (14 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 15/20] compat: consistently resolve headers via project root Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 17/20] compat/msvc: " Patrick Steinhardt
` (4 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Split out the POSIX-related bits from "compat/mingw.h". This is in
preparation for splitting up "git-compat-utils.h" into a header that
provides POSIX-compatibility and a header that provides common wrappers
used by the Git project.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/{mingw.c => mingw/compat-util.c} | 0
compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
compat/msvc.c | 2 +-
compat/msvc.h | 2 +-
config.mak.uname | 4 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 4 +-
meson.build | 6 +-
9 files changed, 234 insertions(+), 222 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw/compat-util.c
similarity index 100%
rename from compat/mingw.c
rename to compat/mingw/compat-util.c
diff --git a/compat/mingw/compat-util.h b/compat/mingw/compat-util.h
new file mode 100644
index 0000000000..b433762526
--- /dev/null
+++ b/compat/mingw/compat-util.h
@@ -0,0 +1,220 @@
+#ifndef COMPAT_MINGW_COMPAT_UTIL_H
+#define COMPAT_MINGW_COMPAT_UTIL_H
+
+#include "compat/mingw/posix.h"
+
+struct config_context;
+int mingw_core_config(const char *var, const char *value,
+ const struct config_context *ctx, void *cb);
+#define platform_core_config mingw_core_config
+
+#ifndef NO_OPENSSL
+#include <openssl/ssl.h>
+static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
+{
+ return SSL_set_fd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_fd mingw_SSL_set_fd
+
+static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
+{
+ return SSL_set_rfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_rfd mingw_SSL_set_rfd
+
+static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
+{
+ return SSL_set_wfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_wfd mingw_SSL_set_wfd
+#endif
+
+/*
+ * git specific compatibility
+ */
+
+static inline void convert_slashes(char *path)
+{
+ for (; *path; path++)
+ if (*path == '\\')
+ *path = '/';
+}
+#define PATH_SEP ';'
+char *mingw_query_user_email(void);
+#define query_user_email mingw_query_user_email
+
+/**
+ * Verifies that the specified path is owned by the user running the
+ * current process.
+ */
+int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
+#define is_path_owned_by_current_user is_path_owned_by_current_sid
+
+/**
+ * Verifies that the given path is a valid one on Windows.
+ *
+ * In particular, path segments are disallowed which
+ *
+ * - end in a period or a space (except the special directories `.` and `..`).
+ *
+ * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
+ *
+ * - correspond to reserved names (such as `AUX`, `PRN`, etc)
+ *
+ * The `allow_literal_nul` parameter controls whether the path `NUL` should
+ * be considered valid (this makes sense e.g. before opening files, as it is
+ * perfectly legitimate to open `NUL` on Windows, just as it is to open
+ * `/dev/null` on Unix/Linux).
+ *
+ * Returns 1 upon success, otherwise 0.
+ */
+int is_valid_win32_path(const char *path, int allow_literal_nul);
+#define is_valid_path(path) is_valid_win32_path(path, 0)
+
+/**
+ * Converts UTF-8 encoded string to UTF-16LE.
+ *
+ * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
+ * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
+ * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
+ * Unicode) are converted to hex-code.
+ *
+ * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
+ * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
+ *
+ * Maximum space requirement for the target buffer is two wide chars per UTF-8
+ * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
+ *
+ * | | UTF-8 | UTF-16 |
+ * Code point | UTF-8 sequence | bytes | words | ratio
+ * --------------+-------------------+-------+--------+-------
+ * 000000-00007f | 0-7f | 1 | 1 | 1
+ * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
+ * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
+ * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
+ * invalid | 80-9f | 1 | 2 (b) | 2
+ * invalid | a0-ff | 1 | 1 | 1
+ *
+ * (a) encoded as UTF-16 surrogate pair
+ * (b) encoded as two hex digits
+ *
+ * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
+ * or even indefinite-byte sequences, the largest valid code point \u10ffff
+ * encodes as only 4 UTF-8 bytes.
+ *
+ * Parameters:
+ * wcs: wide char target buffer
+ * utf: string to convert
+ * wcslen: size of target buffer (in wchar_t's)
+ * utflen: size of string to convert, or -1 if 0-terminated
+ *
+ * Returns:
+ * length of converted string (_wcslen(wcs)), or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
+
+/**
+ * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
+ */
+static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
+{
+ return xutftowcsn(wcs, utf, wcslen, -1);
+}
+
+/**
+ * Simplified file system specific variant of xutftowcsn, assumes output
+ * buffer size is MAX_PATH wide chars and input string is \0-terminated,
+ * fails with ENAMETOOLONG if input string is too long.
+ */
+static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
+{
+ int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
+ if (result < 0 && errno == ERANGE)
+ errno = ENAMETOOLONG;
+ return result;
+}
+
+/**
+ * Converts UTF-16LE encoded string to UTF-8.
+ *
+ * Maximum space requirement for the target buffer is three UTF-8 chars per
+ * wide char ((_wcslen(wcs) * 3) + 1).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
+ * modulo surrogate pairs), as per the following table:
+ *
+ * | | UTF-16 | UTF-8 |
+ * Code point | UTF-16 sequence | words | bytes | ratio
+ * --------------+-----------------------+--------+-------+-------
+ * 000000-00007f | 0000-007f | 1 | 1 | 1
+ * 000080-0007ff | 0080-07ff | 1 | 2 | 2
+ * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
+ * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
+ *
+ * Note that invalid code points > 10ffff cannot be represented in UTF-16.
+ *
+ * Parameters:
+ * utf: target buffer
+ * wcs: wide string to convert
+ * utflen: size of target buffer
+ *
+ * Returns:
+ * length of converted string, or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
+
+/*
+ * A critical section used in the implementation of the spawn
+ * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
+ * the replacement main() macro below.
+ */
+extern CRITICAL_SECTION pinfo_cs;
+
+/*
+ * Git, like most portable C applications, implements a main() function. On
+ * Windows, this main() function would receive parameters encoded in the
+ * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
+ *
+ * To make that happen, we still declare main() here, and then declare and
+ * implement wmain() (which is the Unicode variant of main()) and compile with
+ * -municode. This wmain() function reencodes the parameters from UTF-16 to
+ * UTF-8 format, sets up a couple of other things as required on Windows, and
+ * then hands off to the main() function.
+ */
+int wmain(int argc, const wchar_t **w_argv);
+int main(int argc, const char **argv);
+
+/*
+ * For debugging: if a problem occurs, say, in a Git process that is spawned
+ * from another Git process which in turn is spawned from yet another Git
+ * process, it can be quite daunting to figure out what is going on.
+ *
+ * Call this function to open a new MinTTY (this assumes you are in Git for
+ * Windows' SDK) with a GDB that attaches to the current process right away.
+ */
+void open_in_gdb(void);
+
+/*
+ * Used by Pthread API implementation for Windows
+ */
+int err_win_to_posix(DWORD winerr);
+
+#ifndef NO_UNIX_SOCKETS
+int mingw_have_unix_sockets(void);
+#undef have_unix_sockets
+#define have_unix_sockets mingw_have_unix_sockets
+#endif
+
+#endif /* COMPAT_MINGW_COMPAT_UTIL_H */
diff --git a/compat/mingw.h b/compat/mingw/posix.h
similarity index 59%
rename from compat/mingw.h
rename to compat/mingw/posix.h
index ebfb8ba423..8dddfa818d 100644
--- a/compat/mingw.h
+++ b/compat/mingw/posix.h
@@ -1,3 +1,6 @@
+#ifndef COMPAT_MINGW_POSIX_H
+#define COMPAT_MINGW_POSIX_H
+
#ifdef __MINGW64_VERSION_MAJOR
#include <stdint.h>
#include <wchar.h>
@@ -11,11 +14,6 @@ typedef _sigset_t sigset_t;
#undef _POSIX_THREAD_SAFE_FUNCTIONS
#endif
-struct config_context;
-int mingw_core_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb);
-#define platform_core_config mingw_core_config
-
/*
* things that are not available in header files
*/
@@ -180,27 +178,6 @@ int mingw_kill(pid_t pid, int sig);
#define locate_in_PATH mingw_locate_in_PATH
char *mingw_locate_in_PATH(const char *cmd);
-#ifndef NO_OPENSSL
-#include <openssl/ssl.h>
-static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
-{
- return SSL_set_fd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_fd mingw_SSL_set_fd
-
-static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
-{
- return SSL_set_rfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_rfd mingw_SSL_set_rfd
-
-static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
-{
- return SSL_set_wfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_wfd mingw_SSL_set_wfd
-#endif
-
/*
* implementations of missing functions
*/
@@ -444,19 +421,6 @@ int winansi_dup2(int oldfd, int newfd);
void winansi_init(void);
HANDLE winansi_get_osfhandle(int fd);
-/*
- * git specific compatibility
- */
-
-static inline void convert_slashes(char *path)
-{
- for (; *path; path++)
- if (*path == '\\')
- *path = '/';
-}
-#define PATH_SEP ';'
-char *mingw_query_user_email(void);
-#define query_user_email mingw_query_user_email
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
#define PRIuMAX "I64u"
#define PRId64 "I64d"
@@ -464,176 +428,4 @@ char *mingw_query_user_email(void);
#include <inttypes.h>
#endif
-/**
- * Verifies that the specified path is owned by the user running the
- * current process.
- */
-int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
-#define is_path_owned_by_current_user is_path_owned_by_current_sid
-
-/**
- * Verifies that the given path is a valid one on Windows.
- *
- * In particular, path segments are disallowed which
- *
- * - end in a period or a space (except the special directories `.` and `..`).
- *
- * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
- *
- * - correspond to reserved names (such as `AUX`, `PRN`, etc)
- *
- * The `allow_literal_nul` parameter controls whether the path `NUL` should
- * be considered valid (this makes sense e.g. before opening files, as it is
- * perfectly legitimate to open `NUL` on Windows, just as it is to open
- * `/dev/null` on Unix/Linux).
- *
- * Returns 1 upon success, otherwise 0.
- */
-int is_valid_win32_path(const char *path, int allow_literal_nul);
-#define is_valid_path(path) is_valid_win32_path(path, 0)
-
-/**
- * Converts UTF-8 encoded string to UTF-16LE.
- *
- * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
- * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
- * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
- * Unicode) are converted to hex-code.
- *
- * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
- * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
- *
- * Maximum space requirement for the target buffer is two wide chars per UTF-8
- * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
- *
- * The maximum space is needed only if the entire input string consists of
- * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
- *
- * | | UTF-8 | UTF-16 |
- * Code point | UTF-8 sequence | bytes | words | ratio
- * --------------+-------------------+-------+--------+-------
- * 000000-00007f | 0-7f | 1 | 1 | 1
- * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
- * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
- * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
- * invalid | 80-9f | 1 | 2 (b) | 2
- * invalid | a0-ff | 1 | 1 | 1
- *
- * (a) encoded as UTF-16 surrogate pair
- * (b) encoded as two hex digits
- *
- * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
- * or even indefinite-byte sequences, the largest valid code point \u10ffff
- * encodes as only 4 UTF-8 bytes.
- *
- * Parameters:
- * wcs: wide char target buffer
- * utf: string to convert
- * wcslen: size of target buffer (in wchar_t's)
- * utflen: size of string to convert, or -1 if 0-terminated
- *
- * Returns:
- * length of converted string (_wcslen(wcs)), or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
-
-/**
- * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
- */
-static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
-{
- return xutftowcsn(wcs, utf, wcslen, -1);
-}
-
-/**
- * Simplified file system specific variant of xutftowcsn, assumes output
- * buffer size is MAX_PATH wide chars and input string is \0-terminated,
- * fails with ENAMETOOLONG if input string is too long.
- */
-static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
-{
- int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
- if (result < 0 && errno == ERANGE)
- errno = ENAMETOOLONG;
- return result;
-}
-
-/**
- * Converts UTF-16LE encoded string to UTF-8.
- *
- * Maximum space requirement for the target buffer is three UTF-8 chars per
- * wide char ((_wcslen(wcs) * 3) + 1).
- *
- * The maximum space is needed only if the entire input string consists of
- * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
- * modulo surrogate pairs), as per the following table:
- *
- * | | UTF-16 | UTF-8 |
- * Code point | UTF-16 sequence | words | bytes | ratio
- * --------------+-----------------------+--------+-------+-------
- * 000000-00007f | 0000-007f | 1 | 1 | 1
- * 000080-0007ff | 0080-07ff | 1 | 2 | 2
- * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
- * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
- *
- * Note that invalid code points > 10ffff cannot be represented in UTF-16.
- *
- * Parameters:
- * utf: target buffer
- * wcs: wide string to convert
- * utflen: size of target buffer
- *
- * Returns:
- * length of converted string, or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
-
-/*
- * A critical section used in the implementation of the spawn
- * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
- * the replacement main() macro below.
- */
-extern CRITICAL_SECTION pinfo_cs;
-
-/*
- * Git, like most portable C applications, implements a main() function. On
- * Windows, this main() function would receive parameters encoded in the
- * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
- *
- * To make that happen, we still declare main() here, and then declare and
- * implement wmain() (which is the Unicode variant of main()) and compile with
- * -municode. This wmain() function reencodes the parameters from UTF-16 to
- * UTF-8 format, sets up a couple of other things as required on Windows, and
- * then hands off to the main() function.
- */
-int wmain(int argc, const wchar_t **w_argv);
-int main(int argc, const char **argv);
-
-/*
- * For debugging: if a problem occurs, say, in a Git process that is spawned
- * from another Git process which in turn is spawned from yet another Git
- * process, it can be quite daunting to figure out what is going on.
- *
- * Call this function to open a new MinTTY (this assumes you are in Git for
- * Windows' SDK) with a GDB that attaches to the current process right away.
- */
-void open_in_gdb(void);
-
-/*
- * Used by Pthread API implementation for Windows
- */
-int err_win_to_posix(DWORD winerr);
-
-#ifndef NO_UNIX_SOCKETS
-int mingw_have_unix_sockets(void);
-#undef have_unix_sockets
-#define have_unix_sockets mingw_have_unix_sockets
-#endif
+#endif /* COMPAT_MINGW_POSIX_H */
diff --git a/compat/msvc.c b/compat/msvc.c
index 5aacf3af19..7b6b8ddc71 100644
--- a/compat/msvc.c
+++ b/compat/msvc.c
@@ -3,4 +3,4 @@
#include <conio.h>
#include "strbuf.h"
-#include "compat/mingw.c"
+#include "compat/mingw/compat-util.c"
diff --git a/compat/msvc.h b/compat/msvc.h
index 1d7a8c6145..df39978f4f 100644
--- a/compat/msvc.h
+++ b/compat/msvc.h
@@ -28,6 +28,6 @@ typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-#include "compat/mingw.h"
+#include "compat/mingw/compat-util.h"
#endif
diff --git a/config.mak.uname b/config.mak.uname
index cd9535a65c..38a774de39 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -541,7 +541,7 @@ endif
EXTRA_PROGRAMS += headless-git$X
-compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
+compat/msvc.o: compat/msvc.c compat/mingw/compat-util.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease
@@ -694,7 +694,7 @@ ifeq ($(uname_S),MINGW)
BASIC_LDFLAGS += -municode
COMPAT_CFLAGS += -DNOGDI -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/winansi.o \
+ COMPAT_OBJS += compat/mingw/compat-util.o compat/winansi.o \
compat/win32/trace2_win32_process_info.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 10dc54fdcb..65ce8705f0 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -258,7 +258,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET HAVE_RTLGENRANDOM)
list(APPEND compat_SOURCES
- compat/mingw.c
+ compat/mingw/compat-util.c
compat/winansi.c
compat/win32/flush.c
compat/win32/path-utils.c
diff --git a/git-compat-util.h b/git-compat-util.h
index e283c46c6f..b96fb98e1e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -304,10 +304,10 @@ static inline int is_xplatform_dir_sep(int c)
#if defined(__MINGW32__)
/* pull in Windows compatibility stuff */
#include "compat/win32/path-utils.h"
-#include "compat/mingw.h"
+#include "compat/mingw/compat-util.h"
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
-#include "compat/msvc.h"
+#include "compat/msvc/compat-util.h"
#else
#include <sys/utsname.h>
#include <sys/wait.h>
diff --git a/meson.build b/meson.build
index 2297f5e9dd..32eb0a86d5 100644
--- a/meson.build
+++ b/meson.build
@@ -1054,7 +1054,7 @@ if host_machine.system() == 'cygwin'
]
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw.c',
+ 'compat/mingw/compat-util.c',
'compat/winansi.c',
'compat/win32/flush.c',
'compat/win32/path-utils.c',
@@ -1157,7 +1157,7 @@ else
error('Native regex support requested but not found')
endif
-# setitimer and friends are provided by compat/mingw.c.
+# setitimer and friends are provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows'
if not compiler.compiles('''
#include <sys/time.h>
@@ -1237,7 +1237,7 @@ if not compiler.has_function('qsort')
endif
libgit_sources += 'compat/qsort_s.c'
-# unsetenv is provided by compat/mingw.c.
+# unsetenv is provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows' and not compiler.has_function('unsetenv')
libgit_c_args += '-DNO_UNSETENV'
libgit_sources += 'compat/unsetenv.c'
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 17/20] compat/msvc: split out POSIX-related bits
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (15 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 16/20] compat/mingw: split out POSIX-related bits Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 18/20] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
` (3 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Split out the POSIX-related bits from "compat/msvc.h". This is in
preparation for splitting up "git-compat-utils.h" into a header that
provides POSIX-compatibility and a header that provides common wrappers
used by the Git project.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/{msvc.c => msvc/compat-util.c} | 0
compat/msvc/compat-util.h | 7 +++++++
compat/{msvc.h => msvc/posix.h} | 8 ++++----
config.mak.uname | 4 ++--
meson.build | 4 +++-
5 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/compat/msvc.c b/compat/msvc/compat-util.c
similarity index 100%
rename from compat/msvc.c
rename to compat/msvc/compat-util.c
diff --git a/compat/msvc/compat-util.h b/compat/msvc/compat-util.h
new file mode 100644
index 0000000000..e409e9910c
--- /dev/null
+++ b/compat/msvc/compat-util.h
@@ -0,0 +1,7 @@
+#ifndef COMPAT_MSVC_COMPAT_UTIL_H
+#define COMPAT_MSVC_COMPAT_UTIL_H
+
+#include "compat/msvc/posix.h"
+#include "compat/mingw/compat-util.h"
+
+#endif /* COMPAT_MSVC_COMPAT_UTIL_H */
diff --git a/compat/msvc.h b/compat/msvc/posix.h
similarity index 86%
rename from compat/msvc.h
rename to compat/msvc/posix.h
index df39978f4f..47062293cb 100644
--- a/compat/msvc.h
+++ b/compat/msvc/posix.h
@@ -1,5 +1,5 @@
-#ifndef __MSVC__HEAD
-#define __MSVC__HEAD
+#ifndef COMPAT_MSVC_POSIX_H
+#define COMPAT_MSVC_POSIX_H
#include <direct.h>
#include <process.h>
@@ -28,6 +28,6 @@ typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-#include "compat/mingw/compat-util.h"
+#include "compat/mingw/posix.h"
-#endif
+#endif /* COMPAT_MSVC_POSIX_H */
diff --git a/config.mak.uname b/config.mak.uname
index 38a774de39..8407efd262 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -495,7 +495,7 @@ endif
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
- COMPAT_OBJS = compat/msvc.o compat/winansi.o \
+ COMPAT_OBJS = compat/msvc/compat-util.o compat/winansi.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
compat/win32/pthread.o compat/win32/syslog.o \
@@ -541,7 +541,7 @@ endif
EXTRA_PROGRAMS += headless-git$X
-compat/msvc.o: compat/msvc.c compat/mingw/compat-util.c GIT-CFLAGS
+compat/msvc/compat-util.o: compat/msvc/compat-util.c compat/mingw/compat-util.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease
diff --git a/meson.build b/meson.build
index 32eb0a86d5..e8abf798f5 100644
--- a/meson.build
+++ b/meson.build
@@ -1054,7 +1054,6 @@ if host_machine.system() == 'cygwin'
]
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw/compat-util.c',
'compat/winansi.c',
'compat/win32/flush.c',
'compat/win32/path-utils.c',
@@ -1081,6 +1080,9 @@ elif host_machine.system() == 'windows'
libgit_include_directories += 'compat/win32'
if compiler.get_id() == 'msvc'
libgit_include_directories += 'compat/vcbuild/include'
+ libgit_sources += 'compat/msvc/compat-util.c'
+ else
+ libgit_sources += 'compat/mingw/compat-util.c'
endif
endif
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 18/20] git-compat-util.h: split out POSIX-emulating bits
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (16 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 17/20] compat/msvc: " Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 19/20] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
` (2 subsequent siblings)
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The "git-compat-util.h" header is a treasure trove of various bits and
pieces used throughout the project. It basically mixes two different
things into one:
- Providing a POSIX-like interface even on platforms that aren't
POSIX-compliant.
- Providing low-level functionality that is specific to Git.
This intermixing is a bit of a problem for the reftable library as we
don't want to recreate the POSIX-like interface there. But neither do we
want to pull in the Git-specific functionality, as it is otherwise quite
easy to start depending on the Git codebase again.
Split out a new header "compat/posix.h" that only contains the bits and
pieces relevant for the emulation of POSIX, which we will start using in
the next commit.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/posix.h | 541 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
git-compat-util.h | 531 +----------------------------------------------------
2 files changed, 543 insertions(+), 529 deletions(-)
diff --git a/compat/posix.h b/compat/posix.h
new file mode 100644
index 0000000000..2b2da97965
--- /dev/null
+++ b/compat/posix.h
@@ -0,0 +1,541 @@
+#ifndef COMPAT_POSIX_H
+#define COMPAT_POSIX_H
+
+#define _FILE_OFFSET_BITS 64
+
+/*
+ * Derived from Linux "Features Test Macro" header
+ * Convenience macros to test the versions of gcc (or
+ * a compatible compiler).
+ * Use them like this:
+ * #if GIT_GNUC_PREREQ (2,8)
+ * ... code requiring gcc 2.8 or later ...
+ * #endif
+ *
+ * This macro of course is not part of POSIX, but we need it for the UNUSED
+ * macro which is used by some of our POSIX compatibility wrappers.
+*/
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define GIT_GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+ #define GIT_GNUC_PREREQ(maj, min) 0
+#endif
+
+/*
+ * UNUSED marks a function parameter that is always unused. It also
+ * can be used to annotate a function, a variable, or a type that is
+ * always unused.
+ *
+ * A callback interface may dictate that a function accepts a
+ * parameter at that position, but the implementation of the function
+ * may not need to use the parameter. In such a case, mark the parameter
+ * with UNUSED.
+ *
+ * When a parameter may be used or unused, depending on conditional
+ * compilation, consider using MAYBE_UNUSED instead.
+ */
+#if GIT_GNUC_PREREQ(4, 5)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated ("parameter declared as UNUSED")))
+#elif defined(__GNUC__)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated))
+#else
+#define UNUSED
+#endif
+
+#ifdef __MINGW64__
+#define _POSIX_C_SOURCE 1
+#elif defined(__sun__)
+ /*
+ * On Solaris, when _XOPEN_EXTENDED is set, its header file
+ * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
+ * setting to say we are XPG5 or XPG6. Also on Solaris,
+ * XPG6 programs must be compiled with a c99 compiler, while
+ * non XPG6 programs must be compiled with a pre-c99 compiler.
+ */
+# if __STDC_VERSION__ - 0 >= 199901L
+# define _XOPEN_SOURCE 600
+# else
+# define _XOPEN_SOURCE 500
+# endif
+#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
+ !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
+ !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
+ !defined(__CYGWIN__)
+#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
+#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
+#endif
+#define _ALL_SOURCE 1
+#define _GNU_SOURCE 1
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+#define _NETBSD_SOURCE 1
+#define _SGI_SOURCE 1
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
+# if !defined(_WIN32_WINNT)
+# define _WIN32_WINNT 0x0600
+# endif
+#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
+#include <winsock2.h>
+#ifndef NO_UNIX_SOCKETS
+#include <afunix.h>
+#endif
+#include <windows.h>
+#define GIT_WINDOWS_NATIVE
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h> /* for strcasecmp() */
+#endif
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#ifdef NEEDS_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#include <syslog.h>
+#if !defined(NO_POLL_H)
+#include <poll.h>
+#elif !defined(NO_SYS_POLL_H)
+#include <sys/poll.h>
+#else
+/* Pull the compat stuff */
+#include <poll.h>
+#endif
+#ifdef HAVE_BSD_SYSCTL
+#include <sys/sysctl.h>
+#endif
+
+#if defined(__MINGW32__)
+#include "compat/mingw/posix.h"
+#elif defined(_MSC_VER)
+#include "compat/msvc/posix.h"
+#else
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/statvfs.h>
+#include <termios.h>
+#ifndef NO_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/un.h>
+#ifndef NO_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+#ifdef HAVE_ARC4RANDOM_LIBBSD
+#include <bsd/stdlib.h>
+#endif
+#ifdef HAVE_GETRANDOM
+#include <sys/random.h>
+#endif
+#ifdef NO_INTPTR_T
+/*
+ * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
+ * on LLP86, IL33LLP64 and P64 it needs to be "long long",
+ * while on IP16 and IP16L32 it is "int" (resp. "short")
+ * Size needs to match (or exceed) 'sizeof(void *)'.
+ * We can't take "long long" here as not everybody has it.
+ */
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+#endif
+#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
+#include <grp.h>
+#define _ALL_SOURCE 1
+#endif
+
+#ifdef MKDIR_WO_TRAILING_SLASH
+#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
+int compat_mkdir_wo_trailing_slash(const char*, mode_t);
+#endif
+
+#ifdef time
+#undef time
+#endif
+static inline time_t git_time(time_t *tloc)
+{
+ struct timeval tv;
+
+ /*
+ * Avoid time(NULL), which can disagree with gettimeofday(2)
+ * and filesystem timestamps.
+ */
+ gettimeofday(&tv, NULL);
+
+ if (tloc)
+ *tloc = tv.tv_sec;
+ return tv.tv_sec;
+}
+#define time git_time
+
+#ifdef NO_STRUCT_ITIMERVAL
+struct itimerval {
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+#endif
+
+#ifdef NO_SETITIMER
+static inline int git_setitimer(int which UNUSED,
+ const struct itimerval *value UNUSED,
+ struct itimerval *newvalue UNUSED) {
+ return 0; /* pretend success */
+}
+#undef setitimer
+#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
+#endif
+
+#ifndef NO_LIBGEN_H
+#include <libgen.h>
+#else
+#define basename gitbasename
+char *gitbasename(char *);
+#define dirname gitdirname
+char *gitdirname(char *);
+#endif
+
+#ifndef NO_ICONV
+#include <iconv.h>
+#endif
+
+/* On most systems <netdb.h> would have given us this, but
+ * not on some systems (e.g. z/OS).
+ */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+/* On most systems <limits.h> would have given us this, but
+ * not on some systems (e.g. GNU/Hurd).
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+typedef uintmax_t timestamp_t;
+#define PRItime PRIuMAX
+#define parse_timestamp strtoumax
+#define TIME_MAX UINTMAX_MAX
+#define TIME_MIN 0
+
+int lstat_cache_aware_rmdir(const char *path);
+#if !defined(__MINGW32__) && !defined(_MSC_VER)
+#define rmdir lstat_cache_aware_rmdir
+#endif
+
+#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
+
+#ifndef PROT_READ
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define MAP_PRIVATE 1
+#endif
+
+#define mmap git_mmap
+#define munmap git_munmap
+void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int git_munmap(void *start, size_t length);
+
+#else /* NO_MMAP || USE_WIN32_MMAP */
+
+#include <sys/mman.h>
+
+#endif /* NO_MMAP || USE_WIN32_MMAP */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#ifdef NEEDS_MODE_TRANSLATION
+#undef S_IFMT
+#undef S_IFREG
+#undef S_IFDIR
+#undef S_IFLNK
+#undef S_IFBLK
+#undef S_IFCHR
+#undef S_IFIFO
+#undef S_IFSOCK
+#define S_IFMT 0170000
+#define S_IFREG 0100000
+#define S_IFDIR 0040000
+#define S_IFLNK 0120000
+#define S_IFBLK 0060000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_IFSOCK 0140000
+#ifdef stat
+#undef stat
+#endif
+#define stat(path, buf) git_stat(path, buf)
+int git_stat(const char *, struct stat *);
+#ifdef fstat
+#undef fstat
+#endif
+#define fstat(fd, buf) git_fstat(fd, buf)
+int git_fstat(int, struct stat *);
+#ifdef lstat
+#undef lstat
+#endif
+#define lstat(path, buf) git_lstat(path, buf)
+int git_lstat(const char *, struct stat *);
+#endif
+
+#ifdef NO_PREAD
+#define pread git_pread
+ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+
+#ifdef NO_SETENV
+#define setenv gitsetenv
+int gitsetenv(const char *, const char *, int);
+#endif
+
+#ifdef NO_MKDTEMP
+#define mkdtemp gitmkdtemp
+char *gitmkdtemp(char *);
+#endif
+
+#ifdef NO_UNSETENV
+#define unsetenv gitunsetenv
+int gitunsetenv(const char *);
+#endif
+
+#ifdef NO_STRCASESTR
+#define strcasestr gitstrcasestr
+char *gitstrcasestr(const char *haystack, const char *needle);
+#endif
+
+#ifdef NO_STRLCPY
+#define strlcpy gitstrlcpy
+size_t gitstrlcpy(char *, const char *, size_t);
+#endif
+
+#ifdef NO_STRTOUMAX
+#define strtoumax gitstrtoumax
+uintmax_t gitstrtoumax(const char *, char **, int);
+#define strtoimax gitstrtoimax
+intmax_t gitstrtoimax(const char *, char **, int);
+#endif
+
+#ifdef NO_HSTRERROR
+#define hstrerror githstrerror
+const char *githstrerror(int herror);
+#endif
+
+#ifdef NO_MEMMEM
+#define memmem gitmemmem
+void *gitmemmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+#endif
+
+#ifdef OVERRIDE_STRDUP
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup gitstrdup
+char *gitstrdup(const char *s);
+#endif
+
+#ifdef NO_GETPAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifdef FREAD_READS_DIRECTORIES
+# if !defined(SUPPRESS_FOPEN_REDEFINITION)
+# ifdef fopen
+# undef fopen
+# endif
+# define fopen(a,b) git_fopen(a,b)
+# endif
+FILE *git_fopen(const char*, const char*);
+#endif
+
+#ifdef SNPRINTF_RETURNS_BOGUS
+#ifdef snprintf
+#undef snprintf
+#endif
+#define snprintf git_snprintf
+int git_snprintf(char *str, size_t maxsize,
+ const char *format, ...);
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#define vsnprintf git_vsnprintf
+int git_vsnprintf(char *str, size_t maxsize,
+ const char *format, va_list ap);
+#endif
+
+#ifdef OPEN_RETURNS_EINTR
+#undef open
+#define open git_open_with_retry
+int git_open_with_retry(const char *path, int flag, ...);
+#endif
+
+#ifdef __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2, 1)
+#define HAVE_STRCHRNUL
+#endif
+#endif
+
+#ifndef HAVE_STRCHRNUL
+#define strchrnul gitstrchrnul
+static inline char *gitstrchrnul(const char *s, int c)
+{
+ while (*s && *s != c)
+ s++;
+ return (char *)s;
+}
+#endif
+
+#ifdef NO_INET_PTON
+int inet_pton(int af, const char *src, void *dst);
+#endif
+
+#ifdef NO_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
+#ifdef NO_PTHREADS
+#define atexit git_atexit
+int git_atexit(void (*handler)(void));
+#endif
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
+#include "sane-ctype.h"
+
+void git_stable_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
+#ifdef INTERNAL_QSORT
+#define qsort git_stable_qsort
+#endif
+
+#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
+static inline void sane_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *))
+{
+ if (nmemb > 1)
+ qsort(base, nmemb, size, compar);
+}
+
+#define STABLE_QSORT(base, n, compar) \
+ git_stable_qsort((base), (n), sizeof(*(base)), compar)
+
+#ifndef HAVE_ISO_QSORT_S
+int git_qsort_s(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *), void *ctx);
+#define qsort_s git_qsort_s
+#endif
+
+#define QSORT_S(base, n, compar, ctx) do { \
+ if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
+ BUG("qsort_s() failed"); \
+} while (0)
+
+#ifdef NO_NSEC
+#undef USE_NSEC
+#define ST_CTIME_NSEC(st) 0
+#define ST_MTIME_NSEC(st) 0
+#else
+#ifdef USE_ST_TIMESPEC
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
+#else
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
+#endif
+#endif
+
+#ifndef va_copy
+/*
+ * Since an obvious implementation of va_list would be to make it a
+ * pointer into the stack frame, a simple assignment will work on
+ * many systems. But let's try to be more portable.
+ */
+#ifdef __va_copy
+#define va_copy(dst, src) __va_copy(dst, src)
+#else
+#define va_copy(dst, src) ((dst) = (src))
+#endif
+#endif
+
+#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+static inline void git_flockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+static inline void git_funlockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+#undef flockfile
+#undef funlockfile
+#undef getc_unlocked
+#define flockfile(fh) git_flockfile(fh)
+#define funlockfile(fh) git_funlockfile(fh)
+#define getc_unlocked(fh) getc(fh)
+#endif
+
+#ifdef FILENO_IS_A_MACRO
+int git_fileno(FILE *stream);
+# ifndef COMPAT_CODE_FILENO
+# undef fileno
+# define fileno(p) git_fileno(p)
+# endif
+#endif
+
+#ifdef NEED_ACCESS_ROOT_HANDLER
+int git_access(const char *path, int mode);
+# ifndef COMPAT_CODE_ACCESS
+# ifdef access
+# undef access
+# endif
+# define access(path, mode) git_access(path, mode)
+# endif
+#endif
+
+#endif /* COMPAT_POSIX_H */
diff --git a/git-compat-util.h b/git-compat-util.h
index b96fb98e1e..30ad0725fb 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -23,26 +23,9 @@
#include <crtdbg.h>
#endif
-struct strbuf;
-
-
-#define _FILE_OFFSET_BITS 64
+#include "compat/posix.h"
-
-/* Derived from Linux "Features Test Macro" header
- * Convenience macros to test the versions of gcc (or
- * a compatible compiler).
- * Use them like this:
- * #if GIT_GNUC_PREREQ (2,8)
- * ... code requiring gcc 2.8 or later ...
- * #endif
-*/
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define GIT_GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-#else
- #define GIT_GNUC_PREREQ(maj, min) 0
-#endif
+struct strbuf;
#if defined(__GNUC__) || defined(__clang__)
# define PRAGMA(pragma) _Pragma(#pragma)
@@ -176,71 +159,6 @@ DISABLE_WARNING(-Wsign-compare)
/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-#ifdef __MINGW64__
-#define _POSIX_C_SOURCE 1
-#elif defined(__sun__)
- /*
- * On Solaris, when _XOPEN_EXTENDED is set, its header file
- * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
- * setting to say we are XPG5 or XPG6. Also on Solaris,
- * XPG6 programs must be compiled with a c99 compiler, while
- * non XPG6 programs must be compiled with a pre-c99 compiler.
- */
-# if __STDC_VERSION__ - 0 >= 199901L
-# define _XOPEN_SOURCE 600
-# else
-# define _XOPEN_SOURCE 500
-# endif
-#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
- !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
- !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
- !defined(__CYGWIN__)
-#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
-#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
-#endif
-#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
-#define _BSD_SOURCE 1
-#define _DEFAULT_SOURCE 1
-#define _NETBSD_SOURCE 1
-#define _SGI_SOURCE 1
-
-/*
- * UNUSED marks a function parameter that is always unused. It also
- * can be used to annotate a function, a variable, or a type that is
- * always unused.
- *
- * A callback interface may dictate that a function accepts a
- * parameter at that position, but the implementation of the function
- * may not need to use the parameter. In such a case, mark the parameter
- * with UNUSED.
- *
- * When a parameter may be used or unused, depending on conditional
- * compilation, consider using MAYBE_UNUSED instead.
- */
-#if GIT_GNUC_PREREQ(4, 5)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated ("parameter declared as UNUSED")))
-#elif defined(__GNUC__)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated))
-#else
-#define UNUSED
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
-# if !defined(_WIN32_WINNT)
-# define _WIN32_WINNT 0x0600
-# endif
-#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
-#include <winsock2.h>
-#ifndef NO_UNIX_SOCKETS
-#include <afunix.h>
-#endif
-#include <windows.h>
-#define GIT_WINDOWS_NATIVE
-#endif
-
#if defined(NO_UNIX_SOCKETS) || !defined(GIT_WINDOWS_NATIVE)
static inline int _have_unix_sockets(void)
{
@@ -253,45 +171,6 @@ static inline int _have_unix_sockets(void)
#define have_unix_sockets _have_unix_sockets
#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h> /* for strcasecmp() */
-#endif
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#ifdef NEEDS_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <time.h>
-#include <signal.h>
-#include <assert.h>
-#include <regex.h>
-#include <utime.h>
-#include <syslog.h>
-#if !defined(NO_POLL_H)
-#include <poll.h>
-#elif !defined(NO_SYS_POLL_H)
-#include <sys/poll.h>
-#else
-/* Pull the compat stuff */
-#include <poll.h>
-#endif
-#ifdef HAVE_BSD_SYSCTL
-#include <sys/sysctl.h>
-#endif
-
/* Used by compat/win32/path-utils.h, and more */
static inline int is_xplatform_dir_sep(int c)
{
@@ -308,48 +187,6 @@ static inline int is_xplatform_dir_sep(int c)
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
#include "compat/msvc/compat-util.h"
-#else
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/statvfs.h>
-#include <termios.h>
-#ifndef NO_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <sys/un.h>
-#ifndef NO_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <stdint.h>
-#endif
-#ifdef HAVE_ARC4RANDOM_LIBBSD
-#include <bsd/stdlib.h>
-#endif
-#ifdef HAVE_GETRANDOM
-#include <sys/random.h>
-#endif
-#ifdef NO_INTPTR_T
-/*
- * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
- * on LLP86, IL33LLP64 and P64 it needs to be "long long",
- * while on IP16 and IP16L32 it is "int" (resp. "short")
- * Size needs to match (or exceed) 'sizeof(void *)'.
- * We can't take "long long" here as not everybody has it.
- */
-typedef long intptr_t;
-typedef unsigned long uintptr_t;
-#endif
-#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
-#include <grp.h>
-#define _ALL_SOURCE 1
#endif
/* used on Mac OS X */
@@ -370,60 +207,6 @@ static inline const char *precompose_string_if_needed(const char *in)
#define probe_utf8_pathname_composition()
#endif
-#ifdef MKDIR_WO_TRAILING_SLASH
-#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
-int compat_mkdir_wo_trailing_slash(const char*, mode_t);
-#endif
-
-#ifdef time
-#undef time
-#endif
-static inline time_t git_time(time_t *tloc)
-{
- struct timeval tv;
-
- /*
- * Avoid time(NULL), which can disagree with gettimeofday(2)
- * and filesystem timestamps.
- */
- gettimeofday(&tv, NULL);
-
- if (tloc)
- *tloc = tv.tv_sec;
- return tv.tv_sec;
-}
-#define time git_time
-
-#ifdef NO_STRUCT_ITIMERVAL
-struct itimerval {
- struct timeval it_interval;
- struct timeval it_value;
-};
-#endif
-
-#ifdef NO_SETITIMER
-static inline int git_setitimer(int which UNUSED,
- const struct itimerval *value UNUSED,
- struct itimerval *newvalue UNUSED) {
- return 0; /* pretend success */
-}
-#undef setitimer
-#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
-#endif
-
-#ifndef NO_LIBGEN_H
-#include <libgen.h>
-#else
-#define basename gitbasename
-char *gitbasename(char *);
-#define dirname gitdirname
-char *gitdirname(char *);
-#endif
-
-#ifndef NO_ICONV
-#include <iconv.h>
-#endif
-
#ifndef NO_OPENSSL
#ifdef __APPLE__
#undef __AVAILABILITY_MACROS_USES_AVAILABILITY
@@ -441,34 +224,6 @@ char *gitdirname(char *);
# include <sys/sysinfo.h>
#endif
-/* On most systems <netdb.h> would have given us this, but
- * not on some systems (e.g. z/OS).
- */
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
-
-/* On most systems <limits.h> would have given us this, but
- * not on some systems (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-typedef uintmax_t timestamp_t;
-#define PRItime PRIuMAX
-#define parse_timestamp strtoumax
-#define TIME_MAX UINTMAX_MAX
-#define TIME_MIN 0
-
#ifndef PATH_SEP
#define PATH_SEP ':'
#endif
@@ -492,11 +247,6 @@ static inline int noop_core_config(const char *var UNUSED,
#define platform_core_config noop_core_config
#endif
-int lstat_cache_aware_rmdir(const char *path);
-#if !defined(__MINGW32__) && !defined(_MSC_VER)
-#define rmdir lstat_cache_aware_rmdir
-#endif
-
#ifndef has_dos_drive_prefix
static inline int git_has_dos_drive_prefix(const char *path UNUSED)
{
@@ -822,25 +572,6 @@ static inline bool strip_suffix(const char *str, const char *suffix,
memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
} while (0)
-#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-
-#ifndef PROT_READ
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define MAP_PRIVATE 1
-#endif
-
-#define mmap git_mmap
-#define munmap git_munmap
-void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-int git_munmap(void *start, size_t length);
-
-#else /* NO_MMAP || USE_WIN32_MMAP */
-
-#include <sys/mman.h>
-
-#endif /* NO_MMAP || USE_WIN32_MMAP */
-
#ifdef NO_MMAP
/* This value must be multiple of (pagesize * 2) */
@@ -856,177 +587,15 @@ int git_munmap(void *start, size_t length);
#endif /* NO_MMAP */
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
#define on_disk_bytes(st) ((st).st_size)
#else
#define on_disk_bytes(st) ((st).st_blocks * 512)
#endif
-#ifdef NEEDS_MODE_TRANSLATION
-#undef S_IFMT
-#undef S_IFREG
-#undef S_IFDIR
-#undef S_IFLNK
-#undef S_IFBLK
-#undef S_IFCHR
-#undef S_IFIFO
-#undef S_IFSOCK
-#define S_IFMT 0170000
-#define S_IFREG 0100000
-#define S_IFDIR 0040000
-#define S_IFLNK 0120000
-#define S_IFBLK 0060000
-#define S_IFCHR 0020000
-#define S_IFIFO 0010000
-#define S_IFSOCK 0140000
-#ifdef stat
-#undef stat
-#endif
-#define stat(path, buf) git_stat(path, buf)
-int git_stat(const char *, struct stat *);
-#ifdef fstat
-#undef fstat
-#endif
-#define fstat(fd, buf) git_fstat(fd, buf)
-int git_fstat(int, struct stat *);
-#ifdef lstat
-#undef lstat
-#endif
-#define lstat(path, buf) git_lstat(path, buf)
-int git_lstat(const char *, struct stat *);
-#endif
-
#define DEFAULT_PACKED_GIT_LIMIT \
((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))
-#ifdef NO_PREAD
-#define pread git_pread
-ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
-#endif
-
-#ifdef NO_SETENV
-#define setenv gitsetenv
-int gitsetenv(const char *, const char *, int);
-#endif
-
-#ifdef NO_MKDTEMP
-#define mkdtemp gitmkdtemp
-char *gitmkdtemp(char *);
-#endif
-
-#ifdef NO_UNSETENV
-#define unsetenv gitunsetenv
-int gitunsetenv(const char *);
-#endif
-
-#ifdef NO_STRCASESTR
-#define strcasestr gitstrcasestr
-char *gitstrcasestr(const char *haystack, const char *needle);
-#endif
-
-#ifdef NO_STRLCPY
-#define strlcpy gitstrlcpy
-size_t gitstrlcpy(char *, const char *, size_t);
-#endif
-
-#ifdef NO_STRTOUMAX
-#define strtoumax gitstrtoumax
-uintmax_t gitstrtoumax(const char *, char **, int);
-#define strtoimax gitstrtoimax
-intmax_t gitstrtoimax(const char *, char **, int);
-#endif
-
-#ifdef NO_HSTRERROR
-#define hstrerror githstrerror
-const char *githstrerror(int herror);
-#endif
-
-#ifdef NO_MEMMEM
-#define memmem gitmemmem
-void *gitmemmem(const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen);
-#endif
-
-#ifdef OVERRIDE_STRDUP
-#ifdef strdup
-#undef strdup
-#endif
-#define strdup gitstrdup
-char *gitstrdup(const char *s);
-#endif
-
-#ifdef NO_GETPAGESIZE
-#define getpagesize() sysconf(_SC_PAGESIZE)
-#endif
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
-#endif
-
-#ifdef FREAD_READS_DIRECTORIES
-# if !defined(SUPPRESS_FOPEN_REDEFINITION)
-# ifdef fopen
-# undef fopen
-# endif
-# define fopen(a,b) git_fopen(a,b)
-# endif
-FILE *git_fopen(const char*, const char*);
-#endif
-
-#ifdef SNPRINTF_RETURNS_BOGUS
-#ifdef snprintf
-#undef snprintf
-#endif
-#define snprintf git_snprintf
-int git_snprintf(char *str, size_t maxsize,
- const char *format, ...);
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#define vsnprintf git_vsnprintf
-int git_vsnprintf(char *str, size_t maxsize,
- const char *format, va_list ap);
-#endif
-
-#ifdef OPEN_RETURNS_EINTR
-#undef open
-#define open git_open_with_retry
-int git_open_with_retry(const char *path, int flag, ...);
-#endif
-
-#ifdef __GLIBC_PREREQ
-#if __GLIBC_PREREQ(2, 1)
-#define HAVE_STRCHRNUL
-#endif
-#endif
-
-#ifndef HAVE_STRCHRNUL
-#define strchrnul gitstrchrnul
-static inline char *gitstrchrnul(const char *s, int c)
-{
- while (*s && *s != c)
- s++;
- return (char *)s;
-}
-#endif
-
-#ifdef NO_INET_PTON
-int inet_pton(int af, const char *src, void *dst);
-#endif
-
-#ifdef NO_INET_NTOP
-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-#endif
-
-#ifdef NO_PTHREADS
-#define atexit git_atexit
-int git_atexit(void (*handler)(void));
-#endif
-
static inline size_t st_add(size_t a, size_t b)
{
if (unsigned_add_overflows(a, b))
@@ -1293,12 +862,6 @@ static inline size_t xsize_t(off_t len)
return (size_t) len;
}
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
-#endif
-
-#include "sane-ctype.h"
-
/*
* Like skip_prefix, but compare case-insensitively. Note that the comparison
* is done via tolower(), so it is strictly ASCII (no multi-byte characters or
@@ -1364,34 +927,6 @@ static inline int strtol_i(char const *s, int base, int *result)
return 0;
}
-void git_stable_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *));
-#ifdef INTERNAL_QSORT
-#define qsort git_stable_qsort
-#endif
-
-#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
-static inline void sane_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *))
-{
- if (nmemb > 1)
- qsort(base, nmemb, size, compar);
-}
-
-#define STABLE_QSORT(base, n, compar) \
- git_stable_qsort((base), (n), sizeof(*(base)), compar)
-
-#ifndef HAVE_ISO_QSORT_S
-int git_qsort_s(void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *, void *), void *ctx);
-#define qsort_s git_qsort_s
-#endif
-
-#define QSORT_S(base, n, compar, ctx) do { \
- if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
- BUG("qsort_s() failed"); \
-} while (0)
-
#ifndef REG_STARTEND
#error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd"
#endif
@@ -1416,39 +951,12 @@ int git_regcomp(regex_t *preg, const char *pattern, int cflags);
# define FORCE_DIR_SET_GID 0
#endif
-#ifdef NO_NSEC
-#undef USE_NSEC
-#define ST_CTIME_NSEC(st) 0
-#define ST_MTIME_NSEC(st) 0
-#else
-#ifdef USE_ST_TIMESPEC
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
-#else
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
-#endif
-#endif
-
#ifdef UNRELIABLE_FSTAT
#define fstat_is_reliable() 0
#else
#define fstat_is_reliable() 1
#endif
-#ifndef va_copy
-/*
- * Since an obvious implementation of va_list would be to make it a
- * pointer into the stack frame, a simple assignment will work on
- * many systems. But let's try to be more portable.
- */
-#ifdef __va_copy
-#define va_copy(dst, src) __va_copy(dst, src)
-#else
-#define va_copy(dst, src) ((dst) = (src))
-#endif
-#endif
-
/* usage.c: only to be used for testing BUG() implementation (see test-tool) */
extern int BUG_exit_code;
@@ -1478,41 +986,6 @@ void bug_fl(const char *file, int line, const char *fmt, ...);
# define SHELL_PATH "/bin/sh"
#endif
-#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
-static inline void git_flockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-static inline void git_funlockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-#undef flockfile
-#undef funlockfile
-#undef getc_unlocked
-#define flockfile(fh) git_flockfile(fh)
-#define funlockfile(fh) git_funlockfile(fh)
-#define getc_unlocked(fh) getc(fh)
-#endif
-
-#ifdef FILENO_IS_A_MACRO
-int git_fileno(FILE *stream);
-# ifndef COMPAT_CODE_FILENO
-# undef fileno
-# define fileno(p) git_fileno(p)
-# endif
-#endif
-
-#ifdef NEED_ACCESS_ROOT_HANDLER
-int git_access(const char *path, int mode);
-# ifndef COMPAT_CODE_ACCESS
-# ifdef access
-# undef access
-# endif
-# define access(path, mode) git_access(path, mode)
-# endif
-#endif
-
/*
* Our code often opens a path to an optional file, to work on its
* contents when we can successfully open it. We can ignore a failure
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 19/20] reftable: decouple from Git codebase by pulling in "compat/posix.h"
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (17 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 18/20] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 20/20] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-01-28 22:48 ` [PATCH v2 00/20] reftable: stop using "git-compat-util.h" Junio C Hamano
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The reftable library includes "git-compat-util.h" in order to get a
POSIX-like programming environment that papers over various differences
between platforms. The header also brings with it a couple of helpers
specific to the Git codebase though, and over time we have started to
use these helpers in the reftable library, as well.
This makes it very hard to use the reftable library as a standalone
library without the rest of the Git codebase, so other libraries like
e.g. libgit2 cannot easily use it. But now that we have removed all
calls to Git-specific functionality and have split out "compat/posix.h"
as a separate header we can address this.
Stop including "git-compat-util.h" and instead include "compat/posix.h"
to finalize the decoupling of the reftable library from the rest of the
Git codebase. The only bits which remain specific to Git are "system.h"
and "system.c", which projects will have to provide.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/system.c | 2 ++
reftable/system.h | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/reftable/system.c b/reftable/system.c
index e25ccc0da3..1ee268b125 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -1,3 +1,5 @@
+#include "../git-compat-util.h"
+
#include "system.h"
#include "basics.h"
#include "reftable-error.h"
diff --git a/reftable/system.h b/reftable/system.h
index 3bd4a4e322..e4a8944a70 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -11,7 +11,8 @@ license that can be found in the LICENSE file or at
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "compat/posix.h"
+#include <zlib.h>
/*
* Return a random 32 bit integer. This function is expected to return
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v2 20/20] Makefile: skip reftable library for Coccinelle
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (18 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 19/20] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
@ 2025-01-28 8:28 ` Patrick Steinhardt
2025-01-28 22:48 ` [PATCH v2 00/20] reftable: stop using "git-compat-util.h" Junio C Hamano
20 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-28 8:28 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The reftable library does not use any of the common helpers that the Git
project has. Consequently, most of the rules that we have in Coccinelle
do not apply to the library at all and may even generate false positives
when a pattern can be converted to use a Git helper function.
Exclude reftable library sources from being checked by Coccinelle to
avoid such false positives.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index d3011e30f7..dc2ac32e4a 100644
--- a/Makefile
+++ b/Makefile
@@ -946,7 +946,7 @@ FOUND_SOURCE_FILES := $(filter-out $(GENERATED_H),$(shell $(SOURCES_CMD)))
FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES))
FOUND_H_SOURCES = $(filter %.h,$(FOUND_SOURCE_FILES))
-COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
+COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES) reftable/%,$(FOUND_C_SOURCES))
LIB_H = $(FOUND_H_SOURCES)
--
2.48.1.362.g079036d154.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* Re: [PATCH 01/19] reftable/stack: stop using `read_in_full()`
2025-01-28 8:06 ` Patrick Steinhardt
@ 2025-01-28 17:05 ` Junio C Hamano
2025-01-29 7:29 ` Patrick Steinhardt
0 siblings, 1 reply; 146+ messages in thread
From: Junio C Hamano @ 2025-01-28 17:05 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Justin Tobler, git, Edward Thomson
Patrick Steinhardt <ps@pks.im> writes:
>> The cast from off_t -> size_t matches the currect behavior, but is it
>> always safe to do this? In `git-compat-util.h` it looks like we have
>> `xsize_t()` to safely handle these conversions. Since this series is
>> moving away from `git-compat-util.h` should ideally something similar be
>> implemented?
>
> It is safe, because a couple lines further up we check for `size < 0`
> and error out if that is the case. So we know it's a positive integer,
> and thus it can be represented via `size_t`.
Even where off_t (which measures on-disk file in bytes) may be wider
than size_t (which measures in-core piece of memory in bytes)?
>> > + ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
>> > + if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
>>
>> The error handling here for EAGAIN doesn't go as far as what `xread()`
>> does via `handle_nonblock()`. In this scenario is that ok?
>
> Yes, because we don't set `O_NONBLOCK` in the reftable library.
>
> I'll note that in the commit message.
Good. Thanks.
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH 00/19] reftable: stop using "git-compat-util.h"
2025-01-28 8:22 ` Patrick Steinhardt
@ 2025-01-28 17:32 ` Junio C Hamano
0 siblings, 0 replies; 146+ messages in thread
From: Junio C Hamano @ 2025-01-28 17:32 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson
Patrick Steinhardt <ps@pks.im> writes:
> I guess time will tell how much of a problem this really is. As said, my
> prediction is that we won't face many bugs in the low-level code, and
> then the question becomes moot anyway. But if time proves me wrong I'll
> think a bit more about potential solutions.
Sure. I am OK with the approach of playing by the ear.
Thanks.
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v2 00/20] reftable: stop using "git-compat-util.h"
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
` (19 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 20/20] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
@ 2025-01-28 22:48 ` Junio C Hamano
2025-01-29 7:25 ` Patrick Steinhardt
20 siblings, 1 reply; 146+ messages in thread
From: Junio C Hamano @ 2025-01-28 22:48 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson, Justin Tobler
Patrick Steinhardt <ps@pks.im> writes:
> Changes in v2:
> - The splitup of Windows headers has broken compilation because some
> of the headers couldn't be found anymore. I've fixed this more
> generally by converting includes in "compat/" to always be relative
> to the project source directory, dropping the platform-specific
> `-Icompat/` include.
Nice.
Use of -Icompat/plat/ would make more sense if our sources include
a header file using the standard name of a file that usually appear
in /usr/include/ on a platform that either lacks /usr/include/foo.h
or whose /usr/include/foo.h is inadequate by giving a replacement
definition in compat/plat/foo.h we ship. But that is not how we use
them, so I very much like this change.
> -: ---------- > 15: 3a4949d74d compat: consistently resolve headers via project root
Will take a look and replace.
Thanks.
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v2 00/20] reftable: stop using "git-compat-util.h"
2025-01-28 22:48 ` [PATCH v2 00/20] reftable: stop using "git-compat-util.h" Junio C Hamano
@ 2025-01-29 7:25 ` Patrick Steinhardt
2025-01-29 13:50 ` Junio C Hamano
0 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-29 7:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Edward Thomson, Justin Tobler
On Tue, Jan 28, 2025 at 02:48:42PM -0800, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> writes:
>
> > Changes in v2:
> > - The splitup of Windows headers has broken compilation because some
> > of the headers couldn't be found anymore. I've fixed this more
> > generally by converting includes in "compat/" to always be relative
> > to the project source directory, dropping the platform-specific
> > `-Icompat/` include.
>
> Nice.
>
> Use of -Icompat/plat/ would make more sense if our sources include
> a header file using the standard name of a file that usually appear
> in /usr/include/ on a platform that either lacks /usr/include/foo.h
> or whose /usr/include/foo.h is inadequate by giving a replacement
> definition in compat/plat/foo.h we ship. But that is not how we use
> them, so I very much like this change.
We still do that for drop-in replacements like "compat/regex" or
"compat/poll", but for everything else we stop doing it.
Patrick
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH 01/19] reftable/stack: stop using `read_in_full()`
2025-01-28 17:05 ` Junio C Hamano
@ 2025-01-29 7:29 ` Patrick Steinhardt
0 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-01-29 7:29 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Justin Tobler, git, Edward Thomson
On Tue, Jan 28, 2025 at 09:05:44AM -0800, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> writes:
>
> >> The cast from off_t -> size_t matches the currect behavior, but is it
> >> always safe to do this? In `git-compat-util.h` it looks like we have
> >> `xsize_t()` to safely handle these conversions. Since this series is
> >> moving away from `git-compat-util.h` should ideally something similar be
> >> implemented?
> >
> > It is safe, because a couple lines further up we check for `size < 0`
> > and error out if that is the case. So we know it's a positive integer,
> > and thus it can be represented via `size_t`.
>
> Even where off_t (which measures on-disk file in bytes) may be wider
> than size_t (which measures in-core piece of memory in bytes)?
Wait, can that actually happen? Hm. I assume it can, for example on 32
bit systems with large-file support enabled. There I assume that `off_t`
would be a 64 bit signed integer, whereas `size_t` may be a 32 bit
unsigned integer.
Will address in v3.
Patrick
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v2 15/20] compat: consistently resolve headers via project root
2025-01-28 8:28 ` [PATCH v2 15/20] compat: consistently resolve headers via project root Patrick Steinhardt
@ 2025-01-29 7:50 ` Johannes Sixt
2025-01-29 14:23 ` Junio C Hamano
0 siblings, 1 reply; 146+ messages in thread
From: Johannes Sixt @ 2025-01-29 7:50 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, git
Am 28.01.25 um 09:28 schrieb Patrick Steinhardt:
> diff --git a/compat/fsmonitor/fsm-health-darwin.c b/compat/fsmonitor/fsm-health-darwin.c
> index c2afcbe6c8..68c9fd7363 100644
> --- a/compat/fsmonitor/fsm-health-darwin.c
> +++ b/compat/fsmonitor/fsm-health-darwin.c
> @@ -1,7 +1,7 @@
> #include "git-compat-util.h"
> +#include "compat/fsmonitor/fsm-health.h"
> #include "config.h"
> #include "fsmonitor-ll.h"
> -#include "fsm-health.h"
> #include "fsmonitor--daemon.h"
>
> int fsm_health__ctor(struct fsmonitor_daemon_state *state UNUSED)
The use of double-quotes
#include "fsm-health.h"
very clearly indicates "this file is expected to be in the same
directory as the file that is including it". On the other hand,
#include <fsm-health.h>
would state "this file is to be found somewhere on the include paths,
but not in the directory of the including file".
Therefore, changes like this one, where the new path only points back to
the same directory where the including file is, are very much
undesirable. The unpatched form is preferable.
Depending on the desired goal, is it perhaps better to use <> brackets
more liberally?
-- Hannes
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v2 00/20] reftable: stop using "git-compat-util.h"
2025-01-29 7:25 ` Patrick Steinhardt
@ 2025-01-29 13:50 ` Junio C Hamano
0 siblings, 0 replies; 146+ messages in thread
From: Junio C Hamano @ 2025-01-29 13:50 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson, Justin Tobler
Patrick Steinhardt <ps@pks.im> writes:
> On Tue, Jan 28, 2025 at 02:48:42PM -0800, Junio C Hamano wrote:
>> Patrick Steinhardt <ps@pks.im> writes:
>>
>> > Changes in v2:
>> > - The splitup of Windows headers has broken compilation because some
>> > of the headers couldn't be found anymore. I've fixed this more
>> > generally by converting includes in "compat/" to always be relative
>> > to the project source directory, dropping the platform-specific
>> > `-Icompat/` include.
>>
>> Nice.
>>
>> Use of -Icompat/plat/ would make more sense if our sources include
>> a header file using the standard name of a file that usually appear
>> in /usr/include/ on a platform that either lacks /usr/include/foo.h
>> or whose /usr/include/foo.h is inadequate by giving a replacement
>> definition in compat/plat/foo.h we ship. But that is not how we use
>> them, so I very much like this change.
>
> We still do that for drop-in replacements like "compat/regex" or
> "compat/poll", but for everything else we stop doing it.
Yup.
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v2 15/20] compat: consistently resolve headers via project root
2025-01-29 7:50 ` Johannes Sixt
@ 2025-01-29 14:23 ` Junio C Hamano
2025-02-03 8:40 ` Patrick Steinhardt
0 siblings, 1 reply; 146+ messages in thread
From: Junio C Hamano @ 2025-01-29 14:23 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Patrick Steinhardt, Edward Thomson, Justin Tobler, git
Johannes Sixt <j6t@kdbg.org> writes:
> Depending on the desired goal, is it perhaps better to use <> brackets
> more liberally?
I'd be in general in favor of that direction, as the semantics of <>
is more clear than "" from the point of view of the standard ;-)
Thanks.
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v2 04/20] reftable/record: stop using `COPY_ARRAY()`
2025-01-28 8:28 ` [PATCH v2 04/20] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
@ 2025-01-29 15:46 ` Justin Tobler
2025-02-03 8:40 ` Patrick Steinhardt
0 siblings, 1 reply; 146+ messages in thread
From: Justin Tobler @ 2025-01-29 15:46 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson, Junio C Hamano
On 25/01/28 09:28AM, Patrick Steinhardt wrote:
> Drop our use of `COPY_ARRAY()`, replacing it with an open-coded variant
> thereof. This is done to reduce our dependency on the Git library.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> reftable/record.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/reftable/record.c b/reftable/record.c
> index 8919df8a4d..d1664c47ca 100644
> --- a/reftable/record.c
> +++ b/reftable/record.c
> @@ -508,7 +508,8 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
> if (!obj->offsets)
> return REFTABLE_OUT_OF_MEMORY_ERROR;
> obj->offset_len = src->offset_len;
> - COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
> + if (src->offset_len)
> + memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len);
The `COPY_ARRAY` version uses `st_mutl()` to protect against potential
overflows of the size parameter. Does this variant need to account for
such situations as well?
> return 0;
> }
>
> --
> 2.48.1.362.g079036d154.dirty
>
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v3 00/18] reftable: stop using "git-compat-util.h"
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (20 preceding siblings ...)
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
` (18 more replies)
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (2 subsequent siblings)
24 siblings, 19 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Hi,
this patch series is the final step to fully decouple the reftable
library from the rest of the Git codebase. The goal of this is to make
the library reusable by other projects like libgit2 by simply copying
over the source files, making Git the canonical upstream for reftable
functionality.
This patch series stops using all kinds of helpers exposed by our
"git-compat-util.h" header and open-codes them instead. In order to keep
us from using these helpers by accident the final step is to pull out
POSIX-related bits and pieces into a new "compat/posix.h" header, which
the reftable library then uses instead of "git-compat-util.h".
The series is built on top of master at 5f8f7081f7 (The third batch,
2025-01-23) with ps/reftable-sign-compare at 33319b0976 (reftable:
address trivial -Wsign-compare warnings, 2025-01-20) merged into it.
There is a trivial merge conflict with ps/zlib-ng that can be solved
like this:
diff --cc reftable/system.h
index e4a8944a70,d02eacea8f..0000000000
--- a/reftable/system.h
+++ b/reftable/system.h
@@@ -11,15 -11,9 +11,15 @@@ https://developers.google.com/open-sour
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "compat/posix.h"
- #include <zlib.h>
+ #include "compat/zlib-compat.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
Changes in v2:
- The splitup of Windows headers has broken compilation because some
of the headers couldn't be found anymore. I've fixed this more
generally by converting includes in "compat/" to always be relative
to the project source directory, dropping the platform-specific
`-Icompat/` include.
- Explain why we don't port over `EWOULDBLOCK` handling.
- Fix commit message typos.
- Link to v1: https://lore.kernel.org/r/20250127-pks-reftable-drop-git-compat-util-v1-0-6e280a564877@pks.im
Changes in v3:
- Fix type of `total_read` variable used to track how many bytes we
have read in `fd_read_lines()`.
- Drop the patch use root-relative includes again. Let's rather
discuss this outside of the scope of this series.
- Link to v2: https://lore.kernel.org/r/20250128-pks-reftable-drop-git-compat-util-v2-0-c85c20336317@pks.im
Thanks!
Patrick
---
Patrick Steinhardt (18):
reftable/stack: stop using `read_in_full()`
reftable/stack: stop using `write_in_full()`
reftable/blocksource: stop using `xmmap()`
reftable/record: stop using `COPY_ARRAY()`
reftable/record: stop using `BUG()` in `reftable_record_init()`
reftable/record: don't `BUG()` in `reftable_record_cmp()`
reftable: stop using `BUG()` in trivial cases
reftable/basics: stop using `st_mult()` in array allocators
reftable/basics: provide wrappers for big endian conversion
reftable/reader: stop using `ARRAY_SIZE()` macro
reftable/system: introduce `reftable_rand()`
reftable/stack: stop using `sleep_millisec()`
reftable/basics: stop using `SWAP()` macro
reftable/basics: stop using `UNUSED` annotation
compat/mingw: split out POSIX-related bits
git-compat-util.h: split out POSIX-emulating bits
reftable: decouple from Git codebase by pulling in "compat/posix.h"
Makefile: skip reftable library for Coccinelle
Makefile | 2 +-
compat/{mingw.c => mingw/compat-util.c} | 0
compat/mingw/compat-util.h | 220 +++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------
compat/{msvc.c => msvc/compat-util.c} | 2 +-
compat/msvc/compat-util.h | 7 +
compat/{msvc.h => msvc/posix.h} | 8 +-
compat/posix.h | 541 ++++++++++++++++++++++++++++++++
config.mak.uname | 6 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 535 +------------------------------
meson.build | 8 +-
reftable/basics.c | 19 --
reftable/basics.h | 123 +++++++-
reftable/block.c | 16 +-
reftable/blocksource.c | 21 +-
reftable/iter.c | 20 +-
reftable/merged.c | 27 +-
reftable/pq.c | 40 ++-
reftable/pq.h | 2 +-
reftable/reader.c | 33 +-
reftable/record.c | 109 ++++---
reftable/record.h | 6 +-
reftable/stack.c | 52 ++-
reftable/system.c | 7 +
reftable/system.h | 9 +-
reftable/writer.c | 29 +-
t/unit-tests/t-reftable-basics.c | 28 +-
t/unit-tests/t-reftable-pq.c | 22 +-
t/unit-tests/t-reftable-record.c | 42 ++-
30 files changed, 1223 insertions(+), 929 deletions(-)
Range-diff versus v2:
1: e9364a8d05 ! 1: 8488db3ac9 reftable/stack: stop using `read_in_full()`
@@ reftable/stack.c: static int fd_read_lines(int fd, char ***namesp)
- if (read_in_full(fd, buf, size) != size) {
- err = REFTABLE_IO_ERROR;
- goto done;
-+ for (size_t total_read = 0; total_read < (size_t) size; ) {
++ for (off_t total_read = 0; total_read < size; ) {
+ ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
+ if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
2: 41e411c00d = 2: 19db682279 reftable/stack: stop using `write_in_full()`
3: 1abf9a77e4 = 3: 17fa559a68 reftable/blocksource: stop using `xmmap()`
4: 458837e511 < -: ---------- reftable/record: stop using `COPY_ARRAY()`
-: ---------- > 4: 1667a37d38 reftable/record: stop using `COPY_ARRAY()`
5: a620950cb4 = 5: 1fe9563380 reftable/record: stop using `BUG()` in `reftable_record_init()`
6: 0590780f55 = 6: 12c1fdc125 reftable/record: don't `BUG()` in `reftable_record_cmp()`
7: adcba48303 = 7: 8cfb77ce2c reftable: stop using `BUG()` in trivial cases
8: 353d958e38 = 8: c7227123fa reftable/basics: stop using `st_mult()` in array allocators
9: c6abf6ca1e = 9: 204a7ffed7 reftable/basics: provide wrappers for big endian conversion
10: 095c6805d1 = 10: 533f2cdbd5 reftable/reader: stop using `ARRAY_SIZE()` macro
11: 816a984361 = 11: f5a9edc360 reftable/system: introduce `reftable_rand()`
12: eb09c1d79d = 12: 4b066d5be8 reftable/stack: stop using `sleep_millisec()`
13: 1595e4d771 = 13: 8580d01ee2 reftable/basics: stop using `SWAP()` macro
14: 448ec74479 = 14: 72847f6d69 reftable/basics: stop using `UNUSED` annotation
15: 838f2bcd3a < -: ---------- compat: consistently resolve headers via project root
16: cf6b915daf ! 15: 0348eed321 compat/mingw: split out POSIX-related bits
@@ compat/mingw/compat-util.h (new)
+#ifndef COMPAT_MINGW_COMPAT_UTIL_H
+#define COMPAT_MINGW_COMPAT_UTIL_H
+
-+#include "compat/mingw/posix.h"
++#include "posix.h"
+
+struct config_context;
+int mingw_core_config(const char *var, const char *value,
@@ compat/mingw/posix.h: char *mingw_query_user_email(void);
-#endif
+#endif /* COMPAT_MINGW_POSIX_H */
- ## compat/msvc.c ##
+ ## compat/msvc.c => compat/msvc/compat-util.c ##
@@
#include <conio.h>
- #include "strbuf.h"
+ #include "../strbuf.h"
--#include "compat/mingw.c"
-+#include "compat/mingw/compat-util.c"
+-#include "mingw.c"
++#include "mingw/compat-util.c"
- ## compat/msvc.h ##
-@@ compat/msvc.h: typedef int sigset_t;
+ ## compat/msvc/compat-util.h (new) ##
+@@
++#ifndef COMPAT_MSVC_COMPAT_UTIL_H
++#define COMPAT_MSVC_COMPAT_UTIL_H
++
++#include "posix.h"
++#include "../mingw/compat-util.h"
++
++#endif /* COMPAT_MSVC_COMPAT_UTIL_H */
+
+ ## compat/msvc.h => compat/msvc/posix.h ##
+@@
+-#ifndef __MSVC__HEAD
+-#define __MSVC__HEAD
++#ifndef COMPAT_MSVC_POSIX_H
++#define COMPAT_MSVC_POSIX_H
+
+ #include <direct.h>
+ #include <process.h>
+@@ compat/msvc/posix.h: typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-#include "compat/mingw.h"
-+#include "compat/mingw/compat-util.h"
++#include "../mingw/posix.h"
- #endif
+-#endif
++#endif /* COMPAT_MSVC_POSIX_H */
## config.mak.uname ##
@@ config.mak.uname: endif
+ AR = compat/vcbuild/scripts/lib.pl
+ CFLAGS =
+ BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
+- COMPAT_OBJS = compat/msvc.o compat/winansi.o \
++ COMPAT_OBJS = compat/msvc/compat-util.o compat/winansi.o \
+ compat/win32/flush.o \
+ compat/win32/path-utils.o \
+ compat/win32/pthread.o compat/win32/syslog.o \
+@@ config.mak.uname: endif
EXTRA_PROGRAMS += headless-git$X
-compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
-+compat/msvc.o: compat/msvc.c compat/mingw/compat-util.c GIT-CFLAGS
++compat/msvc/compat-util.o: compat/msvc/compat-util.c compat/mingw/compat-util.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease
@@ config.mak.uname: ifeq ($(uname_S),MINGW)
BASIC_LDFLAGS += -municode
- COMPAT_CFLAGS += -DNOGDI -Icompat/win32
+ COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/winansi.o \
+ COMPAT_OBJS += compat/mingw/compat-util.o compat/winansi.o \
@@ meson.build: if host_machine.system() == 'cygwin'
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw.c',
-+ 'compat/mingw/compat-util.c',
'compat/winansi.c',
'compat/win32/flush.c',
'compat/win32/path-utils.c',
+@@ meson.build: elif host_machine.system() == 'windows'
+ libgit_include_directories += 'compat/win32'
+ if compiler.get_id() == 'msvc'
+ libgit_include_directories += 'compat/vcbuild/include'
++ libgit_sources += 'compat/msvc/compat-util.c'
++ else
++ libgit_sources += 'compat/mingw/compat-util.c'
+ endif
+ endif
+
@@ meson.build: else
error('Native regex support requested but not found')
endif
17: ae57e3f391 < -: ---------- compat/msvc: split out POSIX-related bits
18: c32f39b777 ! 16: 141fd6a7cd git-compat-util.h: split out POSIX-emulating bits
@@ compat/posix.h (new)
+#endif
+
+#if defined(__MINGW32__)
-+#include "compat/mingw/posix.h"
++#include "mingw/posix.h"
+#elif defined(_MSC_VER)
-+#include "compat/msvc/posix.h"
++#include "msvc/posix.h"
+#else
+#include <sys/utsname.h>
+#include <sys/wait.h>
19: 496d30ee27 ! 17: 640f5e6376 reftable: decouple from Git codebase by pulling in "compat/posix.h"
@@ reftable/system.h: license that can be found in the LICENSE file or at
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
-+#include "compat/posix.h"
++#include "../compat/posix.h"
+#include <zlib.h>
/*
20: d257172bf7 = 18: 2f17a1963d Makefile: skip reftable library for Coccinelle
---
base-commit: 8047765d092881ec4aef7dfc57772161eee7f0f5
change-id: 20241119-pks-reftable-drop-git-compat-util-470f2bfde562
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v3 01/18] reftable/stack: stop using `read_in_full()`
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
` (17 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
There is a single callsite of `read_in_full()` in the reftable library.
Open-code the function to reduce our dependency on the Git library.
Note that we only partially port over the logic from `read_in_full()`
and its underlying `xread()` helper. Most importantly, the latter also
knows to handle `EWOULDBLOCK` via `handle_nonblock()`. This logic is
irrelevant for us though because the reftable library never sets the
`O_NONBLOCK` option in the first place.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index f7c1845e15..d57acd9540 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -115,13 +115,16 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
static int fd_read_lines(int fd, char ***namesp)
{
- off_t size = lseek(fd, 0, SEEK_END);
char *buf = NULL;
int err = 0;
+ off_t size;
+
+ size = lseek(fd, 0, SEEK_END);
if (size < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
+
err = lseek(fd, 0, SEEK_SET);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp)
goto done;
}
- if (read_in_full(fd, buf, size) != size) {
- err = REFTABLE_IO_ERROR;
- goto done;
+ for (off_t total_read = 0; total_read < size; ) {
+ ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
+ if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_read < 0 || !bytes_read) {
+ err = REFTABLE_IO_ERROR;
+ goto done;
+ }
+
+ total_read += bytes_read;
}
buf[size] = 0;
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 02/18] reftable/stack: stop using `write_in_full()`
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
` (16 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Similar to the preceding commit, drop our use of `write_in_full()` and
implement a new wrapper `reftable_write_full()` that handles this logic
for us. This is done to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index d57acd9540..46abf51ec5 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -48,6 +48,25 @@ static int stack_fsync(const struct reftable_write_options *opts, int fd)
return fsync(fd);
}
+static ssize_t reftable_write_data(int fd, const void *data, size_t size)
+{
+ size_t total_written = 0;
+ const char *p = data;
+
+ while (total_written < size) {
+ ssize_t bytes_written = write(fd, p, size - total_written);
+ if (bytes_written < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_written < 0)
+ return REFTABLE_IO_ERROR;
+
+ total_written += bytes_written;
+ p += bytes_written;
+ }
+
+ return total_written;
+}
+
struct fd_writer {
const struct reftable_write_options *opts;
int fd;
@@ -56,7 +75,7 @@ struct fd_writer {
static ssize_t fd_writer_write(void *arg, const void *data, size_t sz)
{
struct fd_writer *writer = arg;
- return write_in_full(writer->fd, data, sz);
+ return reftable_write_data(writer->fd, data, sz);
}
static int fd_writer_flush(void *arg)
@@ -784,7 +803,8 @@ int reftable_addition_commit(struct reftable_addition *add)
goto done;
}
- err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len);
+ err = reftable_write_data(add->tables_list_lock.fd,
+ table_list.buf, table_list.len);
reftable_buf_release(&table_list);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -1468,8 +1488,8 @@ static int stack_compact_range(struct reftable_stack *st,
goto done;
}
- err = write_in_full(tables_list_lock.fd,
- tables_list_buf.buf, tables_list_buf.len);
+ err = reftable_write_data(tables_list_lock.fd,
+ tables_list_buf.buf, tables_list_buf.len);
if (err < 0) {
err = REFTABLE_IO_ERROR;
unlink(new_table_path.buf);
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 03/18] reftable/blocksource: stop using `xmmap()`
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
` (15 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We use `xmmap()` to map reftables into memory. This function has two
problems:
- It causes us to die in case the mmap fails.
- It ties us to the Git codebase.
Refactor the code to use mmap(3p) instead with manual error checking.
Note that this function may not be the system-provided mmap(3p), but may
point to our `git_mmap()` wrapper that emulates the syscall on systems
that do not have mmap(3p) available.
Fix `reftable_block_source_from_file()` to properly bubble up the error
code in case the map(3p) call fails.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/blocksource.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index bba4a45b98..02972c46f4 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -98,7 +98,7 @@ static struct reftable_block_source_vtable file_vtable = {
int reftable_block_source_from_file(struct reftable_block_source *bs,
const char *name)
{
- struct file_block_source *p;
+ struct file_block_source *p = NULL;
struct stat st;
int fd, err;
@@ -122,7 +122,12 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
}
p->size = st.st_size;
- p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ p->data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p->data == MAP_FAILED) {
+ err = REFTABLE_IO_ERROR;
+ p->data = NULL;
+ goto out;
+ }
assert(!bs->ops);
bs->ops = &file_vtable;
@@ -135,5 +140,5 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
close(fd);
if (err < 0)
reftable_free(p);
- return 0;
+ return err;
}
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 04/18] reftable/record: stop using `COPY_ARRAY()`
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (2 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
` (14 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Drop our use of `COPY_ARRAY()`, replacing it with an open-coded variant
thereof. This is done to reduce our dependency on the Git library.
While at it, guard the whole array copy logic so that we only copy it in
case there actually is anything to be copied. Otherwise, we may end up
trying to allocate a zero-sized array, which will return a NULL pointer
and thus cause us to return an `REFTABLE_OUT_OF_MEMORY_ERROR`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/record.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/reftable/record.c b/reftable/record.c
index 8919df8a4d..2c0cc32cbd 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -504,11 +504,17 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
if (src->hash_prefix_len)
memcpy(obj->hash_prefix, src->hash_prefix, obj->hash_prefix_len);
- REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
- if (!obj->offsets)
- return REFTABLE_OUT_OF_MEMORY_ERROR;
- obj->offset_len = src->offset_len;
- COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
+ if (src->offset_len) {
+ if (sizeof(*src->offsets) > SIZE_MAX / src->offset_len)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
+ if (!obj->offsets)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len);
+ obj->offset_len = src->offset_len;
+ }
return 0;
}
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()`
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (3 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
` (13 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We're aborting the program via `BUG()` in case `reftable_record_init()`
was invoked with an unknown record type. This is bad because we may now
die in library code, and because it makes us depend on the Git codebase.
Refactor the code such that `reftable_record_init()` can return an error
code to the caller. Adapt any callers accordingly.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/block.c | 4 +++-
reftable/merged.c | 5 ++++-
reftable/reader.c | 5 ++++-
reftable/record.c | 8 ++++----
reftable/record.h | 4 ++--
t/unit-tests/t-reftable-pq.c | 6 +++---
t/unit-tests/t-reftable-record.c | 2 +-
7 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/reftable/block.c b/reftable/block.c
index 8ac865ce78..255d566854 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -509,7 +509,9 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,
it->block_len = br->block_len;
it->hash_size = br->hash_size;
- reftable_record_init(&rec, block_reader_type(br));
+ err = reftable_record_init(&rec, block_reader_type(br));
+ if (err < 0)
+ goto done;
/*
* We're looking for the last entry less than the wanted key so that
diff --git a/reftable/merged.c b/reftable/merged.c
index e72b39e178..4156eec07f 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -253,7 +253,10 @@ int merged_table_init_iter(struct reftable_merged_table *mt,
}
for (size_t i = 0; i < mt->readers_len; i++) {
- reftable_record_init(&subiters[i].rec, typ);
+ ret = reftable_record_init(&subiters[i].rec, typ);
+ if (ret < 0)
+ goto out;
+
ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
if (ret < 0)
goto out;
diff --git a/reftable/reader.c b/reftable/reader.c
index 3f2e4b2800..de6e6dd932 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -360,7 +360,10 @@ static int table_iter_seek_linear(struct table_iter *ti,
struct reftable_record rec;
int err;
- reftable_record_init(&rec, reftable_record_type(want));
+ err = reftable_record_init(&rec, reftable_record_type(want));
+ if (err < 0)
+ goto done;
+
err = reftable_record_key(want, &want_key);
if (err < 0)
goto done;
diff --git a/reftable/record.c b/reftable/record.c
index 2c0cc32cbd..1e18f8dffb 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1306,7 +1306,7 @@ reftable_record_vtable(struct reftable_record *rec)
abort();
}
-void reftable_record_init(struct reftable_record *rec, uint8_t typ)
+int reftable_record_init(struct reftable_record *rec, uint8_t typ)
{
memset(rec, 0, sizeof(*rec));
rec->type = typ;
@@ -1315,11 +1315,11 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)
case BLOCK_TYPE_REF:
case BLOCK_TYPE_LOG:
case BLOCK_TYPE_OBJ:
- return;
+ return 0;
case BLOCK_TYPE_INDEX:
reftable_buf_init(&rec->u.idx.last_key);
- return;
+ return 0;
default:
- BUG("unhandled record type");
+ return REFTABLE_API_ERROR;
}
}
diff --git a/reftable/record.h b/reftable/record.h
index c7755a4d75..e1846c294b 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -130,8 +130,8 @@ struct reftable_record {
} u;
};
-/* Initialize the reftable record for the given type */
-void reftable_record_init(struct reftable_record *rec, uint8_t typ);
+/* Initialize the reftable record for the given type. */
+int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index f3f8a0cdf3..d8a4c283a1 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -32,7 +32,7 @@ static void t_pq_record(void)
char *last = NULL;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
}
@@ -72,7 +72,7 @@ static void t_pq_index(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
@@ -111,7 +111,7 @@ static void t_merged_iter_pqueue_top(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index d49d2a2729..6540bd20e3 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -17,7 +17,7 @@ static void t_copy(struct reftable_record *rec)
uint8_t typ;
typ = reftable_record_type(rec);
- reftable_record_init(©, typ);
+ check(!reftable_record_init(©, typ));
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
/* do it twice to catch memory leaks */
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()`
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (4 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
` (12 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The reftable library aborts with a bug in case `reftable_record_cmp()`
is invoked with two records of differing types. This would cause the
program to die without the caller being able to handle the error, which
is not something we want in the context of library code. And it ties us
to the Git codebase.
Refactor the code such that `reftable_record_cmp()` returns an error
code separate from the actual comparison result. This requires us to
also adapt some callers up the callchain in a similar fashion.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/merged.c | 20 +++++++++++++++-----
reftable/pq.c | 36 +++++++++++++++++++++++++++++-------
reftable/pq.h | 2 +-
reftable/record.c | 10 ++++++----
reftable/record.h | 2 +-
t/unit-tests/t-reftable-pq.c | 16 ++++++++++++----
t/unit-tests/t-reftable-record.c | 40 ++++++++++++++++++++++++++++------------
7 files changed, 92 insertions(+), 34 deletions(-)
diff --git a/reftable/merged.c b/reftable/merged.c
index 4156eec07f..563864068c 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -66,8 +66,11 @@ static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want
int err;
mi->advance_index = -1;
- while (!merged_iter_pqueue_is_empty(mi->pq))
- merged_iter_pqueue_remove(&mi->pq);
+ while (!merged_iter_pqueue_is_empty(mi->pq)) {
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+ }
for (size_t i = 0; i < mi->subiters_len; i++) {
err = iterator_seek(&mi->subiters[i].iter, want);
@@ -120,7 +123,9 @@ static int merged_iter_next_entry(struct merged_iter *mi,
if (empty)
return 1;
- entry = merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, &entry);
+ if (err < 0)
+ return err;
/*
One can also use reftable as datacenter-local storage, where the ref
@@ -134,11 +139,16 @@ static int merged_iter_next_entry(struct merged_iter *mi,
struct pq_entry top = merged_iter_pqueue_top(mi->pq);
int cmp;
- cmp = reftable_record_cmp(top.rec, entry.rec);
+ err = reftable_record_cmp(top.rec, entry.rec, &cmp);
+ if (err < 0)
+ return err;
if (cmp > 0)
break;
- merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+
err = merged_iter_advance_subiter(mi, top.index);
if (err < 0)
return err;
diff --git a/reftable/pq.c b/reftable/pq.c
index 5591e875e1..ef8035cfd9 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -15,13 +15,18 @@ license that can be found in the LICENSE file or at
int pq_less(struct pq_entry *a, struct pq_entry *b)
{
- int cmp = reftable_record_cmp(a->rec, b->rec);
+ int cmp, err;
+
+ err = reftable_record_cmp(a->rec, b->rec, &cmp);
+ if (err < 0)
+ return err;
+
if (cmp == 0)
return a->index > b->index;
return cmp < 0;
}
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out)
{
size_t i = 0;
struct pq_entry e = pq->heap[0];
@@ -32,17 +37,34 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
size_t min = i;
size_t j = 2 * i + 1;
size_t k = 2 * i + 2;
- if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i]))
- min = j;
- if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min]))
- min = k;
+ int cmp;
+
+ if (j < pq->len) {
+ cmp = pq_less(&pq->heap[j], &pq->heap[i]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = j;
+ }
+
+ if (k < pq->len) {
+ cmp = pq_less(&pq->heap[k], &pq->heap[min]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = k;
+ }
+
if (min == i)
break;
SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
- return e;
+ if (out)
+ *out = e;
+
+ return 0;
}
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
diff --git a/reftable/pq.h b/reftable/pq.h
index 83c062eeca..ff39016445 100644
--- a/reftable/pq.h
+++ b/reftable/pq.h
@@ -22,7 +22,7 @@ struct merged_iter_pqueue {
size_t cap;
};
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out);
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
diff --git a/reftable/record.c b/reftable/record.c
index 1e18f8dffb..b39d99fcc7 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1195,12 +1195,14 @@ int reftable_record_is_deletion(struct reftable_record *rec)
reftable_record_data(rec));
}
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b)
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b,
+ int *cmp)
{
if (a->type != b->type)
- BUG("cannot compare reftable records of different type");
- return reftable_record_vtable(a)->cmp(
- reftable_record_data(a), reftable_record_data(b));
+ return -1;
+ *cmp = reftable_record_vtable(a)->cmp(reftable_record_data(a),
+ reftable_record_data(b));
+ return 0;
}
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size)
diff --git a/reftable/record.h b/reftable/record.h
index e1846c294b..867810a932 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -134,7 +134,7 @@ struct reftable_record {
int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b, int *cmp);
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size);
int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);
int reftable_record_copy_from(struct reftable_record *rec,
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index d8a4c283a1..c128fe8616 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -21,7 +21,9 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq)
static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b)
{
- return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index);
+ int cmp;
+ check(!reftable_record_cmp(a->rec, b->rec, &cmp));
+ return !cmp && (a->index == b->index);
}
static void t_pq_record(void)
@@ -49,7 +51,9 @@ static void t_pq_record(void)
while (!merged_iter_pqueue_is_empty(pq)) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -90,7 +94,9 @@ static void t_pq_index(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -129,7 +135,9 @@ static void t_merged_iter_pqueue_top(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index 6540bd20e3..5954966373 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -100,16 +100,20 @@ static void t_reftable_ref_record_comparison(void)
.u.ref.value.symref = (char *) "refs/heads/master",
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.ref.value_type = in[0].u.ref.value_type;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_ref_record_compare_name(void)
@@ -209,17 +213,20 @@ static void t_reftable_log_record_comparison(void)
.u.log.update_index = 22,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
/* comparison should be reversed for equal keys, because
* comparison is now performed on the basis of update indices */
- check_int(reftable_record_cmp(&in[0], &in[1]), <, 0);
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check_int(cmp, <, 0);
in[1].u.log.update_index = in[0].u.log.update_index;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
}
static void t_reftable_log_record_compare_key(void)
@@ -396,16 +403,20 @@ static void t_reftable_obj_record_comparison(void)
.u.obj.hash_prefix_len = 5,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.obj.offset_len = in[0].u.obj.offset_len;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_obj_record_roundtrip(void)
@@ -486,19 +497,24 @@ static void t_reftable_index_record_comparison(void)
.u.idx.last_key = REFTABLE_BUF_INIT,
},
};
+ int cmp;
+
check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch"));
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.idx.offset = in[0].u.idx.offset;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
for (size_t i = 0; i < ARRAY_SIZE(in); i++)
reftable_record_release(&in[i]);
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 07/18] reftable: stop using `BUG()` in trivial cases
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (5 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
` (11 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Stop using `BUG()` in the remaining trivial cases that we still have in
the reftable library. Instead of aborting the program, we'll now bubble
up a `REFTABLE_API_ERROR` to indicate misuse of the calling conventions.
Note that in both `reftable_reader_{inc,dec}ref()` we simply stop
calling `BUG()` altogether. The only situation where the counter should
be zero is when the structure has already been free'd anyway, so we
would run into undefined behaviour regardless of whether we try to abort
the program or not.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/iter.c | 3 +--
reftable/reader.c | 4 ----
reftable/writer.c | 5 ++---
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/reftable/iter.c b/reftable/iter.c
index 86e801ca9f..b2ffb09c16 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -146,8 +146,7 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
static int indexed_table_ref_iter_seek(void *p UNUSED,
struct reftable_record *want UNUSED)
{
- BUG("seeking indexed table is not supported");
- return -1;
+ return REFTABLE_API_ERROR;
}
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
diff --git a/reftable/reader.c b/reftable/reader.c
index de6e6dd932..36a5633ede 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -677,8 +677,6 @@ int reftable_reader_new(struct reftable_reader **out,
void reftable_reader_incref(struct reftable_reader *r)
{
- if (!r->refcount)
- BUG("cannot increment ref counter of dead reader");
r->refcount++;
}
@@ -686,8 +684,6 @@ void reftable_reader_decref(struct reftable_reader *r)
{
if (!r)
return;
- if (!r->refcount)
- BUG("cannot decrement ref counter of dead reader");
if (--r->refcount)
return;
block_source_close(&r->source);
diff --git a/reftable/writer.c b/reftable/writer.c
index 91d6629486..155863ee5f 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -158,7 +158,7 @@ int reftable_writer_new(struct reftable_writer **out,
opts = *_opts;
options_set_defaults(&opts);
if (opts.block_size >= (1 << 24))
- BUG("configured block size exceeds 16MB");
+ return REFTABLE_API_ERROR;
reftable_buf_init(&wp->block_writer_data.last_key);
reftable_buf_init(&wp->last_key);
@@ -289,8 +289,7 @@ static int writer_add_record(struct reftable_writer *w,
}
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
- BUG("record of type %d added to writer of type %d",
- reftable_record_type(rec), block_writer_type(w->block_writer));
+ return REFTABLE_API_ERROR;
/*
* Try to add the record to the writer. If this succeeds then we're
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 08/18] reftable/basics: stop using `st_mult()` in array allocators
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (6 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
` (10 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We're using `st_mult()` as part of our macro helpers that allocate
arrays. This is bad due two two reasons:
- `st_mult()` causes us to die in case the multiplication overflows.
- `st_mult()` ties us to the Git codebase.
Refactor the code to instead detect overflows manually and return an
error in such cases.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index a2a010a0e1..646f8d67f2 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -117,18 +117,46 @@ void reftable_free(void *p);
void *reftable_calloc(size_t nelem, size_t elsize);
char *reftable_strdup(const char *str);
-#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
+static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out)
+{
+ if (nelem && elsize > SIZE_MAX / nelem)
+ return -1;
+ *out = nelem * elsize;
+ return 0;
+}
+
+#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_malloc(alloc_size); \
+ } \
+ } while (0)
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
-#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc)))
+#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_realloc((x), alloc_size); \
+ } \
+ } while (0)
static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
size_t *allocp)
{
void *new_p;
- size_t alloc = *allocp * 2 + 1;
+ size_t alloc = *allocp * 2 + 1, alloc_bytes;
if (alloc < nelem)
alloc = nelem;
- new_p = reftable_realloc(p, st_mult(elsize, alloc));
+ if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) {
+ errno = ENOMEM;
+ return p;
+ }
+ new_p = reftable_realloc(p, alloc_bytes);
if (!new_p)
return p;
*allocp = alloc;
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 09/18] reftable/basics: provide wrappers for big endian conversion
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (7 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
` (9 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We're using a mixture of big endian conversion functions provided by
both the reftable library, but also by the Git codebase. Refactor the
code so that we exclusively use reftable-provided wrappers in order to
untangle us from the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.c | 19 ----------
reftable/basics.h | 76 ++++++++++++++++++++++++++++++++++++++--
reftable/block.c | 12 +++----
reftable/reader.c | 22 ++++++------
reftable/record.c | 8 ++---
reftable/writer.c | 20 +++++------
t/unit-tests/t-reftable-basics.c | 28 ++++++++++++---
7 files changed, 127 insertions(+), 58 deletions(-)
diff --git a/reftable/basics.c b/reftable/basics.c
index 3b5ea27bbd..8c4a4433e4 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -147,25 +147,6 @@ char *reftable_buf_detach(struct reftable_buf *buf)
return result;
}
-void put_be24(uint8_t *out, uint32_t i)
-{
- out[0] = (uint8_t)((i >> 16) & 0xff);
- out[1] = (uint8_t)((i >> 8) & 0xff);
- out[2] = (uint8_t)(i & 0xff);
-}
-
-uint32_t get_be24(uint8_t *in)
-{
- return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 |
- (uint32_t)(in[2]);
-}
-
-void put_be16(uint8_t *out, uint16_t i)
-{
- out[0] = (uint8_t)((i >> 8) & 0xff);
- out[1] = (uint8_t)(i & 0xff);
-}
-
size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
{
size_t lo = 0;
diff --git a/reftable/basics.h b/reftable/basics.h
index 646f8d67f2..c1ddbaec3f 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -76,9 +76,79 @@ char *reftable_buf_detach(struct reftable_buf *buf);
/* Bigendian en/decoding of integers */
-void put_be24(uint8_t *out, uint32_t i);
-uint32_t get_be24(uint8_t *in);
-void put_be16(uint8_t *out, uint16_t i);
+static inline void reftable_put_be16(void *out, uint16_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 8) & 0xff);
+ p[1] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be24(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 16) & 0xff);
+ p[1] = (uint8_t)((i >> 8) & 0xff);
+ p[2] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be32(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 24) & 0xff);
+ p[1] = (uint8_t)((i >> 16) & 0xff);
+ p[2] = (uint8_t)((i >> 8) & 0xff);
+ p[3] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be64(void *out, uint64_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 56) & 0xff);
+ p[1] = (uint8_t)((i >> 48) & 0xff);
+ p[2] = (uint8_t)((i >> 40) & 0xff);
+ p[3] = (uint8_t)((i >> 32) & 0xff);
+ p[4] = (uint8_t)((i >> 24) & 0xff);
+ p[5] = (uint8_t)((i >> 16) & 0xff);
+ p[6] = (uint8_t)((i >> 8) & 0xff);
+ p[7] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline uint16_t reftable_get_be16(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint16_t)(p[0]) << 8 |
+ (uint16_t)(p[1]) << 0;
+}
+
+static inline uint32_t reftable_get_be24(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 16 |
+ (uint32_t)(p[1]) << 8 |
+ (uint32_t)(p[2]) << 0;
+}
+
+static inline uint32_t reftable_get_be32(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 24 |
+ (uint32_t)(p[1]) << 16 |
+ (uint32_t)(p[2]) << 8|
+ (uint32_t)(p[3]) << 0;
+}
+
+static inline uint64_t reftable_get_be64(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint64_t)(p[0]) << 56 |
+ (uint64_t)(p[1]) << 48 |
+ (uint64_t)(p[2]) << 40 |
+ (uint64_t)(p[3]) << 32 |
+ (uint64_t)(p[4]) << 24 |
+ (uint64_t)(p[5]) << 16 |
+ (uint64_t)(p[6]) << 8 |
+ (uint64_t)(p[7]) << 0;
+}
/*
* find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is
diff --git a/reftable/block.c b/reftable/block.c
index 255d566854..373908807e 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -148,13 +148,13 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
int block_writer_finish(struct block_writer *w)
{
for (uint32_t i = 0; i < w->restart_len; i++) {
- put_be24(w->block + w->next, w->restarts[i]);
+ reftable_put_be24(w->block + w->next, w->restarts[i]);
w->next += 3;
}
- put_be16(w->block + w->next, w->restart_len);
+ reftable_put_be16(w->block + w->next, w->restart_len);
w->next += 2;
- put_be24(w->block + 1 + w->header_off, w->next);
+ reftable_put_be24(w->block + 1 + w->header_off, w->next);
/*
* Log records are stored zlib-compressed. Note that the compression
@@ -216,7 +216,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
{
uint32_t full_block_size = table_block_size;
uint8_t typ = block->data[header_off];
- uint32_t sz = get_be24(block->data + header_off + 1);
+ uint32_t sz = reftable_get_be24(block->data + header_off + 1);
int err = 0;
uint16_t restart_count = 0;
uint32_t restart_start = 0;
@@ -300,7 +300,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
full_block_size = sz;
}
- restart_count = get_be16(block->data + sz - 2);
+ restart_count = reftable_get_be16(block->data + sz - 2);
restart_start = sz - 2 - 3 * restart_count;
restart_bytes = block->data + restart_start;
@@ -355,7 +355,7 @@ int block_reader_first_key(const struct block_reader *br, struct reftable_buf *k
static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx)
{
- return get_be24(br->restart_bytes + 3 * idx);
+ return reftable_get_be24(br->restart_bytes + 3 * idx);
}
void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)
diff --git a/reftable/reader.c b/reftable/reader.c
index 36a5633ede..bf07a0a586 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -101,18 +101,18 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
}
f++;
- r->block_size = get_be24(f);
+ r->block_size = reftable_get_be24(f);
f += 3;
- r->min_update_index = get_be64(f);
+ r->min_update_index = reftable_get_be64(f);
f += 8;
- r->max_update_index = get_be64(f);
+ r->max_update_index = reftable_get_be64(f);
f += 8;
if (r->version == 1) {
r->hash_id = REFTABLE_HASH_SHA1;
} else {
- switch (get_be32(f)) {
+ switch (reftable_get_be32(f)) {
case REFTABLE_FORMAT_ID_SHA1:
r->hash_id = REFTABLE_HASH_SHA1;
break;
@@ -127,24 +127,24 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
f += 4;
}
- r->ref_offsets.index_offset = get_be64(f);
+ r->ref_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->obj_offsets.offset = get_be64(f);
+ r->obj_offsets.offset = reftable_get_be64(f);
f += 8;
r->object_id_len = r->obj_offsets.offset & ((1 << 5) - 1);
r->obj_offsets.offset >>= 5;
- r->obj_offsets.index_offset = get_be64(f);
+ r->obj_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.offset = get_be64(f);
+ r->log_offsets.offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.index_offset = get_be64(f);
+ r->log_offsets.index_offset = reftable_get_be64(f);
f += 8;
computed_crc = crc32(0, footer, f - footer);
- file_crc = get_be32(f);
+ file_crc = reftable_get_be32(f);
f += 4;
if (computed_crc != file_crc) {
err = REFTABLE_FORMAT_ERROR;
@@ -214,7 +214,7 @@ static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
*typ = data[0];
if (reftable_is_block_type(*typ)) {
- result = get_be24(data + 1);
+ result = reftable_get_be24(data + 1);
}
return result;
}
diff --git a/reftable/record.c b/reftable/record.c
index b39d99fcc7..3552bafa99 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -689,7 +689,7 @@ static int reftable_log_record_key(const void *r, struct reftable_buf *dest)
return err;
ts = (~ts) - rec->update_index;
- put_be64(&i64[0], ts);
+ reftable_put_be64(&i64[0], ts);
err = reftable_buf_add(dest, i64, sizeof(i64));
if (err < 0)
@@ -814,7 +814,7 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,
if (s.len < 2)
return -1;
- put_be16(s.buf, r->value.update.tz_offset);
+ reftable_put_be16(s.buf, r->value.update.tz_offset);
string_view_consume(&s, 2);
n = encode_string(
@@ -846,7 +846,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
}
memcpy(r->refname, key.buf, key.len - 8);
- ts = get_be64(key.buf + key.len - 8);
+ ts = reftable_get_be64((unsigned char *)key.buf + key.len - 8);
r->update_index = (~max) - ts;
@@ -937,7 +937,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
goto done;
}
- r->value.update.tz_offset = get_be16(in.buf);
+ r->value.update.tz_offset = reftable_get_be16(in.buf);
string_view_consume(&in, 2);
n = decode_string(scratch, in);
diff --git a/reftable/writer.c b/reftable/writer.c
index 155863ee5f..5961698311 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -99,9 +99,9 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
dest[4] = writer_version(w);
- put_be24(dest + 5, w->opts.block_size);
- put_be64(dest + 8, w->min_update_index);
- put_be64(dest + 16, w->max_update_index);
+ reftable_put_be24(dest + 5, w->opts.block_size);
+ reftable_put_be64(dest + 8, w->min_update_index);
+ reftable_put_be64(dest + 16, w->max_update_index);
if (writer_version(w) == 2) {
uint32_t hash_id;
@@ -116,7 +116,7 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
return -1;
}
- put_be32(dest + 24, hash_id);
+ reftable_put_be32(dest + 24, hash_id);
}
return header_size(writer_version(w));
@@ -717,19 +717,19 @@ int reftable_writer_close(struct reftable_writer *w)
}
p += writer_write_header(w, footer);
- put_be64(p, w->stats.ref_stats.index_offset);
+ reftable_put_be64(p, w->stats.ref_stats.index_offset);
p += 8;
- put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
+ reftable_put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
p += 8;
- put_be64(p, w->stats.obj_stats.index_offset);
+ reftable_put_be64(p, w->stats.obj_stats.index_offset);
p += 8;
- put_be64(p, w->stats.log_stats.offset);
+ reftable_put_be64(p, w->stats.log_stats.offset);
p += 8;
- put_be64(p, w->stats.log_stats.index_offset);
+ reftable_put_be64(p, w->stats.log_stats.index_offset);
p += 8;
- put_be32(p, crc32(0, footer, p - footer));
+ reftable_put_be32(p, crc32(0, footer, p - footer));
p += 4;
err = w->flush(w->write_arg);
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
index 9ba7eb05ad..c9e751e49e 100644
--- a/t/unit-tests/t-reftable-basics.c
+++ b/t/unit-tests/t-reftable-basics.c
@@ -128,12 +128,30 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
reftable_buf_release(&b);
}
- if_test ("put_be24 and get_be24 work") {
+ if_test ("reftable_put_be64 and reftable_get_be64 work") {
+ uint64_t in = 0x1122334455667788;
+ uint8_t dest[8];
+ uint64_t out;
+ reftable_put_be64(dest, in);
+ out = reftable_get_be64(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be32 and reftable_get_be32 work") {
+ uint32_t in = 0x11223344;
+ uint8_t dest[4];
+ uint32_t out;
+ reftable_put_be32(dest, in);
+ out = reftable_get_be32(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be24 and reftable_get_be24 work") {
uint32_t in = 0x112233;
uint8_t dest[3];
uint32_t out;
- put_be24(dest, in);
- out = get_be24(dest);
+ reftable_put_be24(dest, in);
+ out = reftable_get_be24(dest);
check_int(in, ==, out);
}
@@ -141,8 +159,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
uint32_t in = 0xfef1;
uint8_t dest[3];
uint32_t out;
- put_be16(dest, in);
- out = get_be16(dest);
+ reftable_put_be16(dest, in);
+ out = reftable_get_be16(dest);
check_int(in, ==, out);
}
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (8 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
` (8 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
We have a single user of the `ARRAY_SIZE()` macro in the reftable
reader. Drop its use to reduce our dependence on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/reader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/reader.c b/reftable/reader.c
index bf07a0a586..c3a3674665 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -849,7 +849,7 @@ int reftable_reader_print_blocks(const char *tablename)
printf("header:\n");
printf(" block_size: %d\n", r->block_size);
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
+ for (i = 0; i < sizeof(sections) / sizeof(*sections); i++) {
err = table_iter_seek_start(&ti, sections[i].type, 0);
if (err < 0)
goto done;
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 11/18] reftable/system: introduce `reftable_rand()`
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (9 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
` (7 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Introduce a new system-level `reftable_rand()` function that generates a
single unsigned integer for us. The implementation of this function is
to be provided by the calling codebase, which allows us to more easily
hook into pre-seeded random number generators.
Adapt the two callsites where we generated random data.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 4 ++--
reftable/system.c | 5 +++++
reftable/system.h | 6 ++++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 46abf51ec5..e22577ec77 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -523,7 +523,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
close(fd);
fd = -1;
- delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1;
+ delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
sleep_millisec(delay);
}
@@ -688,7 +688,7 @@ int reftable_stack_add(struct reftable_stack *st,
static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
{
char buf[100];
- uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE);
+ uint32_t rnd = reftable_rand();
snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
min, max, rnd);
reftable_buf_reset(dest);
diff --git a/reftable/system.c b/reftable/system.c
index adf8e4d30b..e25ccc0da3 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -4,6 +4,11 @@
#include "../lockfile.h"
#include "../tempfile.h"
+uint32_t reftable_rand(void)
+{
+ return git_rand(CSPRNG_BYTES_INSECURE);
+}
+
int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern)
{
struct tempfile *tempfile;
diff --git a/reftable/system.h b/reftable/system.h
index 7d5f803eeb..3bd4a4e322 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -13,6 +13,12 @@ license that can be found in the LICENSE file or at
#include "git-compat-util.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 12/18] reftable/stack: stop using `sleep_millisec()`
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (10 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
` (6 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Refactor our use of `sleep_millisec()` by open-coding it with poll(3p),
which is the current implementation of this function. Ideally, we'd use
a more direct way to sleep, but there is no equivalent to sleep(3p) that
would accept milliseconds as input.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index e22577ec77..7b0b10cd38 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -524,7 +524,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
fd = -1;
delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
- sleep_millisec(delay);
+ poll(NULL, 0, delay);
}
out:
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 13/18] reftable/basics: stop using `SWAP()` macro
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (11 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 14/18] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
` (5 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Stop using `SWAP()` macro in favor of an open-coded variant of it. Note
that this also requires us to open-code the build assert that `SWAP()`
itself uses to verify that the size of both variables matches.
This is done to reduce our dependency on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 9 +++++++++
reftable/merged.c | 2 +-
reftable/pq.c | 4 ++--
reftable/record.c | 16 ++++++++--------
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index c1ddbaec3f..59000798f0 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -266,6 +266,15 @@ static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
# define strdup(str) REFTABLE_BANNED(strdup)
#endif
+#define REFTABLE_SWAP(a, b) do { \
+ void *_swap_a_ptr = &(a); \
+ void *_swap_b_ptr = &(b); \
+ unsigned char _swap_buffer[sizeof(a) - 2 * sizeof(a) * (sizeof(a) != sizeof(b))]; \
+ memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \
+ memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a)); \
+ memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
+} while (0)
+
/* Find the longest shared prefix size of `a` and `b` */
size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);
diff --git a/reftable/merged.c b/reftable/merged.c
index 563864068c..4ff1553772 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -155,7 +155,7 @@ static int merged_iter_next_entry(struct merged_iter *mi,
}
mi->advance_index = entry.index;
- SWAP(*rec, *entry.rec);
+ REFTABLE_SWAP(*rec, *entry.rec);
return 0;
}
diff --git a/reftable/pq.c b/reftable/pq.c
index ef8035cfd9..82394a972d 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -57,7 +57,7 @@ int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *ou
if (min == i)
break;
- SWAP(pq->heap[i], pq->heap[min]);
+ REFTABLE_SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
@@ -81,7 +81,7 @@ int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry
size_t j = (i - 1) / 2;
if (pq_less(&pq->heap[j], &pq->heap[i]))
break;
- SWAP(pq->heap[j], pq->heap[i]);
+ REFTABLE_SWAP(pq->heap[j], pq->heap[i]);
i = j;
}
diff --git a/reftable/record.c b/reftable/record.c
index 3552bafa99..9a1edf39a0 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -237,11 +237,11 @@ static int reftable_ref_record_copy_from(void *rec, const void *src_rec,
size_t refname_cap = 0;
int err;
- SWAP(refname, ref->refname);
- SWAP(refname_cap, ref->refname_cap);
+ REFTABLE_SWAP(refname, ref->refname);
+ REFTABLE_SWAP(refname_cap, ref->refname_cap);
reftable_ref_record_release(ref);
- SWAP(ref->refname, refname);
- SWAP(ref->refname_cap, refname_cap);
+ REFTABLE_SWAP(ref->refname, refname);
+ REFTABLE_SWAP(ref->refname_cap, refname_cap);
if (src->refname) {
size_t refname_len = strlen(src->refname);
@@ -376,11 +376,11 @@ static int reftable_ref_record_decode(void *rec, struct reftable_buf key,
return n;
string_view_consume(&in, n);
- SWAP(refname, r->refname);
- SWAP(refname_cap, r->refname_cap);
+ REFTABLE_SWAP(refname, r->refname);
+ REFTABLE_SWAP(refname_cap, r->refname_cap);
reftable_ref_record_release(r);
- SWAP(r->refname, refname);
- SWAP(r->refname_cap, refname_cap);
+ REFTABLE_SWAP(r->refname, refname);
+ REFTABLE_SWAP(r->refname_cap, refname_cap);
REFTABLE_ALLOC_GROW_OR_NULL(r->refname, key.len + 1, r->refname_cap);
if (!r->refname) {
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 14/18] reftable/basics: stop using `UNUSED` annotation
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (12 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
` (4 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Stop using the `UNUSED` annotation and replace it with a new
`REFTABLE_UNUSED` macro. The latter is a weaker guarantee compared to
`UNUSED` as it only suppresses unused parameters without generating a
warning in case a parameter marked as unused is in fact used. But it's
good enough, and by relaxing the behaviour a bit we avoid having to wire
up compiler-specific logic.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 2 ++
reftable/blocksource.c | 10 +++++++---
reftable/iter.c | 17 ++++++++++++-----
reftable/record.c | 51 ++++++++++++++++++++++++++++++++++++--------------
reftable/writer.c | 4 +++-
5 files changed, 61 insertions(+), 23 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index 59000798f0..4d0645a4e9 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -16,6 +16,8 @@ license that can be found in the LICENSE file or at
#include "system.h"
#include "reftable-basics.h"
+#define REFTABLE_UNUSED(x) (void)(x)
+
struct reftable_buf {
size_t alloc;
size_t len;
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index 02972c46f4..bfd64b0e48 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -13,15 +13,17 @@ license that can be found in the LICENSE file or at
#include "reftable-blocksource.h"
#include "reftable-error.h"
-static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)
+static void reftable_buf_return_block(void *b, struct reftable_block *dest)
{
+ REFTABLE_UNUSED(b);
if (dest->len)
memset(dest->data, 0xff, dest->len);
reftable_free(dest->data);
}
-static void reftable_buf_close(void *b UNUSED)
+static void reftable_buf_close(void *b)
{
+ REFTABLE_UNUSED(b);
}
static ssize_t reftable_buf_read_block(void *v, struct reftable_block *dest,
@@ -67,8 +69,10 @@ static uint64_t file_size(void *b)
return ((struct file_block_source *)b)->size;
}
-static void file_return_block(void *b UNUSED, struct reftable_block *dest UNUSED)
+static void file_return_block(void *b, struct reftable_block *dest)
{
+ REFTABLE_UNUSED(b);
+ REFTABLE_UNUSED(dest);
}
static void file_close(void *v)
diff --git a/reftable/iter.c b/reftable/iter.c
index b2ffb09c16..452add2705 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -25,18 +25,23 @@ int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
return it->ops->next(it->iter_arg, rec);
}
-static int empty_iterator_seek(void *arg UNUSED, struct reftable_record *want UNUSED)
+static int empty_iterator_seek(void *arg, struct reftable_record *want)
{
+ REFTABLE_UNUSED(arg);
+ REFTABLE_UNUSED(want);
return 0;
}
-static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED)
+static int empty_iterator_next(void *arg, struct reftable_record *rec)
{
+ REFTABLE_UNUSED(arg);
+ REFTABLE_UNUSED(rec);
return 1;
}
-static void empty_iterator_close(void *arg UNUSED)
+static void empty_iterator_close(void *arg)
{
+ REFTABLE_UNUSED(arg);
}
static struct reftable_iterator_vtable empty_vtable = {
@@ -143,9 +148,11 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
return 0;
}
-static int indexed_table_ref_iter_seek(void *p UNUSED,
- struct reftable_record *want UNUSED)
+static int indexed_table_ref_iter_seek(void *p,
+ struct reftable_record *want)
{
+ REFTABLE_UNUSED(p);
+ REFTABLE_UNUSED(want);
return REFTABLE_API_ERROR;
}
diff --git a/reftable/record.c b/reftable/record.c
index 9a1edf39a0..5ee2fe44a7 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -490,11 +490,13 @@ static void reftable_obj_record_release(void *rec)
}
static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_obj_record *obj = rec;
const struct reftable_obj_record *src = src_rec;
+ REFTABLE_UNUSED(hash_size);
+
reftable_obj_record_release(obj);
REFTABLE_ALLOC_ARRAY(obj->hash_prefix, src->hash_prefix_len);
@@ -528,13 +530,16 @@ static uint8_t reftable_obj_record_val_type(const void *rec)
}
static int reftable_obj_record_encode(const void *rec, struct string_view s,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
const struct reftable_obj_record *r = rec;
struct string_view start = s;
int i = 0;
int n = 0;
uint64_t last = 0;
+
+ REFTABLE_UNUSED(hash_size);
+
if (r->offset_len == 0 || r->offset_len >= 8) {
n = put_var_int(&s, r->offset_len);
if (n < 0) {
@@ -563,8 +568,8 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,
static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
uint8_t val_type, struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size,
+ struct reftable_buf *scratch)
{
struct string_view start = in;
struct reftable_obj_record *r = rec;
@@ -572,6 +577,9 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
int n = 0;
uint64_t last;
+ REFTABLE_UNUSED(hash_size);
+ REFTABLE_UNUSED(scratch);
+
reftable_obj_record_release(r);
REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len);
@@ -618,17 +626,20 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
return start.len - in.len;
}
-static int not_a_deletion(const void *p UNUSED)
+static int not_a_deletion(const void *p)
{
+ REFTABLE_UNUSED(p);
return 0;
}
static int reftable_obj_record_equal_void(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_obj_record *ra = (struct reftable_obj_record *) a;
struct reftable_obj_record *rb = (struct reftable_obj_record *) b;
+ REFTABLE_UNUSED(hash_size);
+
if (ra->hash_prefix_len != rb->hash_prefix_len
|| ra->offset_len != rb->offset_len)
return 0;
@@ -1054,12 +1065,14 @@ static int reftable_index_record_key(const void *r, struct reftable_buf *dest)
}
static int reftable_index_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_index_record *dst = rec;
const struct reftable_index_record *src = src_rec;
int err;
+ REFTABLE_UNUSED(hash_size);
+
reftable_buf_reset(&dst->last_key);
err = reftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);
if (err < 0)
@@ -1075,19 +1088,23 @@ static void reftable_index_record_release(void *rec)
reftable_buf_release(&idx->last_key);
}
-static uint8_t reftable_index_record_val_type(const void *rec UNUSED)
+static uint8_t reftable_index_record_val_type(const void *rec)
{
+ REFTABLE_UNUSED(rec);
return 0;
}
static int reftable_index_record_encode(const void *rec, struct string_view out,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
const struct reftable_index_record *r =
(const struct reftable_index_record *)rec;
struct string_view start = out;
+ int n;
- int n = put_var_int(&out, r->offset);
+ REFTABLE_UNUSED(hash_size);
+
+ n = put_var_int(&out, r->offset);
if (n < 0)
return n;
@@ -1097,15 +1114,19 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,
}
static int reftable_index_record_decode(void *rec, struct reftable_buf key,
- uint8_t val_type UNUSED,
+ uint8_t val_type,
struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size,
+ struct reftable_buf *scratch)
{
struct string_view start = in;
struct reftable_index_record *r = rec;
int err, n = 0;
+ REFTABLE_UNUSED(val_type);
+ REFTABLE_UNUSED(hash_size);
+ REFTABLE_UNUSED(scratch);
+
reftable_buf_reset(&r->last_key);
err = reftable_buf_add(&r->last_key, key.buf, key.len);
if (err < 0)
@@ -1120,11 +1141,13 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,
}
static int reftable_index_record_equal(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_index_record *ia = (struct reftable_index_record *) a;
struct reftable_index_record *ib = (struct reftable_index_record *) b;
+ REFTABLE_UNUSED(hash_size);
+
return ia->offset == ib->offset && !reftable_buf_cmp(&ia->last_key, &ib->last_key);
}
diff --git a/reftable/writer.c b/reftable/writer.c
index 5961698311..0040a1b1c4 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -636,10 +636,12 @@ static void write_object_record(void *void_arg, void *key)
done:;
}
-static void object_record_free(void *void_arg UNUSED, void *key)
+static void object_record_free(void *void_arg, void *key)
{
struct obj_index_tree_node *entry = key;
+ REFTABLE_UNUSED(void_arg);
+
REFTABLE_FREE_AND_NULL(entry->offsets);
reftable_buf_release(&entry->hash);
reftable_free(entry);
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 15/18] compat/mingw: split out POSIX-related bits
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (13 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 14/18] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
` (3 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
Split out the POSIX-related bits from "compat/mingw.h". This is in
preparation for splitting up "git-compat-utils.h" into a header that
provides POSIX-compatibility and a header that provides common wrappers
used by the Git project.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/{mingw.c => mingw/compat-util.c} | 0
compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
compat/{msvc.c => msvc/compat-util.c} | 2 +-
compat/msvc/compat-util.h | 7 +
compat/{msvc.h => msvc/posix.h} | 8 +-
config.mak.uname | 6 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 4 +-
meson.build | 8 +-
10 files changed, 247 insertions(+), 226 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw/compat-util.c
similarity index 100%
rename from compat/mingw.c
rename to compat/mingw/compat-util.c
diff --git a/compat/mingw/compat-util.h b/compat/mingw/compat-util.h
new file mode 100644
index 0000000000..470542d309
--- /dev/null
+++ b/compat/mingw/compat-util.h
@@ -0,0 +1,220 @@
+#ifndef COMPAT_MINGW_COMPAT_UTIL_H
+#define COMPAT_MINGW_COMPAT_UTIL_H
+
+#include "posix.h"
+
+struct config_context;
+int mingw_core_config(const char *var, const char *value,
+ const struct config_context *ctx, void *cb);
+#define platform_core_config mingw_core_config
+
+#ifndef NO_OPENSSL
+#include <openssl/ssl.h>
+static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
+{
+ return SSL_set_fd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_fd mingw_SSL_set_fd
+
+static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
+{
+ return SSL_set_rfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_rfd mingw_SSL_set_rfd
+
+static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
+{
+ return SSL_set_wfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_wfd mingw_SSL_set_wfd
+#endif
+
+/*
+ * git specific compatibility
+ */
+
+static inline void convert_slashes(char *path)
+{
+ for (; *path; path++)
+ if (*path == '\\')
+ *path = '/';
+}
+#define PATH_SEP ';'
+char *mingw_query_user_email(void);
+#define query_user_email mingw_query_user_email
+
+/**
+ * Verifies that the specified path is owned by the user running the
+ * current process.
+ */
+int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
+#define is_path_owned_by_current_user is_path_owned_by_current_sid
+
+/**
+ * Verifies that the given path is a valid one on Windows.
+ *
+ * In particular, path segments are disallowed which
+ *
+ * - end in a period or a space (except the special directories `.` and `..`).
+ *
+ * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
+ *
+ * - correspond to reserved names (such as `AUX`, `PRN`, etc)
+ *
+ * The `allow_literal_nul` parameter controls whether the path `NUL` should
+ * be considered valid (this makes sense e.g. before opening files, as it is
+ * perfectly legitimate to open `NUL` on Windows, just as it is to open
+ * `/dev/null` on Unix/Linux).
+ *
+ * Returns 1 upon success, otherwise 0.
+ */
+int is_valid_win32_path(const char *path, int allow_literal_nul);
+#define is_valid_path(path) is_valid_win32_path(path, 0)
+
+/**
+ * Converts UTF-8 encoded string to UTF-16LE.
+ *
+ * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
+ * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
+ * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
+ * Unicode) are converted to hex-code.
+ *
+ * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
+ * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
+ *
+ * Maximum space requirement for the target buffer is two wide chars per UTF-8
+ * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
+ *
+ * | | UTF-8 | UTF-16 |
+ * Code point | UTF-8 sequence | bytes | words | ratio
+ * --------------+-------------------+-------+--------+-------
+ * 000000-00007f | 0-7f | 1 | 1 | 1
+ * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
+ * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
+ * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
+ * invalid | 80-9f | 1 | 2 (b) | 2
+ * invalid | a0-ff | 1 | 1 | 1
+ *
+ * (a) encoded as UTF-16 surrogate pair
+ * (b) encoded as two hex digits
+ *
+ * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
+ * or even indefinite-byte sequences, the largest valid code point \u10ffff
+ * encodes as only 4 UTF-8 bytes.
+ *
+ * Parameters:
+ * wcs: wide char target buffer
+ * utf: string to convert
+ * wcslen: size of target buffer (in wchar_t's)
+ * utflen: size of string to convert, or -1 if 0-terminated
+ *
+ * Returns:
+ * length of converted string (_wcslen(wcs)), or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
+
+/**
+ * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
+ */
+static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
+{
+ return xutftowcsn(wcs, utf, wcslen, -1);
+}
+
+/**
+ * Simplified file system specific variant of xutftowcsn, assumes output
+ * buffer size is MAX_PATH wide chars and input string is \0-terminated,
+ * fails with ENAMETOOLONG if input string is too long.
+ */
+static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
+{
+ int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
+ if (result < 0 && errno == ERANGE)
+ errno = ENAMETOOLONG;
+ return result;
+}
+
+/**
+ * Converts UTF-16LE encoded string to UTF-8.
+ *
+ * Maximum space requirement for the target buffer is three UTF-8 chars per
+ * wide char ((_wcslen(wcs) * 3) + 1).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
+ * modulo surrogate pairs), as per the following table:
+ *
+ * | | UTF-16 | UTF-8 |
+ * Code point | UTF-16 sequence | words | bytes | ratio
+ * --------------+-----------------------+--------+-------+-------
+ * 000000-00007f | 0000-007f | 1 | 1 | 1
+ * 000080-0007ff | 0080-07ff | 1 | 2 | 2
+ * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
+ * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
+ *
+ * Note that invalid code points > 10ffff cannot be represented in UTF-16.
+ *
+ * Parameters:
+ * utf: target buffer
+ * wcs: wide string to convert
+ * utflen: size of target buffer
+ *
+ * Returns:
+ * length of converted string, or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
+
+/*
+ * A critical section used in the implementation of the spawn
+ * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
+ * the replacement main() macro below.
+ */
+extern CRITICAL_SECTION pinfo_cs;
+
+/*
+ * Git, like most portable C applications, implements a main() function. On
+ * Windows, this main() function would receive parameters encoded in the
+ * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
+ *
+ * To make that happen, we still declare main() here, and then declare and
+ * implement wmain() (which is the Unicode variant of main()) and compile with
+ * -municode. This wmain() function reencodes the parameters from UTF-16 to
+ * UTF-8 format, sets up a couple of other things as required on Windows, and
+ * then hands off to the main() function.
+ */
+int wmain(int argc, const wchar_t **w_argv);
+int main(int argc, const char **argv);
+
+/*
+ * For debugging: if a problem occurs, say, in a Git process that is spawned
+ * from another Git process which in turn is spawned from yet another Git
+ * process, it can be quite daunting to figure out what is going on.
+ *
+ * Call this function to open a new MinTTY (this assumes you are in Git for
+ * Windows' SDK) with a GDB that attaches to the current process right away.
+ */
+void open_in_gdb(void);
+
+/*
+ * Used by Pthread API implementation for Windows
+ */
+int err_win_to_posix(DWORD winerr);
+
+#ifndef NO_UNIX_SOCKETS
+int mingw_have_unix_sockets(void);
+#undef have_unix_sockets
+#define have_unix_sockets mingw_have_unix_sockets
+#endif
+
+#endif /* COMPAT_MINGW_COMPAT_UTIL_H */
diff --git a/compat/mingw.h b/compat/mingw/posix.h
similarity index 59%
rename from compat/mingw.h
rename to compat/mingw/posix.h
index ebfb8ba423..8dddfa818d 100644
--- a/compat/mingw.h
+++ b/compat/mingw/posix.h
@@ -1,3 +1,6 @@
+#ifndef COMPAT_MINGW_POSIX_H
+#define COMPAT_MINGW_POSIX_H
+
#ifdef __MINGW64_VERSION_MAJOR
#include <stdint.h>
#include <wchar.h>
@@ -11,11 +14,6 @@ typedef _sigset_t sigset_t;
#undef _POSIX_THREAD_SAFE_FUNCTIONS
#endif
-struct config_context;
-int mingw_core_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb);
-#define platform_core_config mingw_core_config
-
/*
* things that are not available in header files
*/
@@ -180,27 +178,6 @@ int mingw_kill(pid_t pid, int sig);
#define locate_in_PATH mingw_locate_in_PATH
char *mingw_locate_in_PATH(const char *cmd);
-#ifndef NO_OPENSSL
-#include <openssl/ssl.h>
-static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
-{
- return SSL_set_fd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_fd mingw_SSL_set_fd
-
-static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
-{
- return SSL_set_rfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_rfd mingw_SSL_set_rfd
-
-static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
-{
- return SSL_set_wfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_wfd mingw_SSL_set_wfd
-#endif
-
/*
* implementations of missing functions
*/
@@ -444,19 +421,6 @@ int winansi_dup2(int oldfd, int newfd);
void winansi_init(void);
HANDLE winansi_get_osfhandle(int fd);
-/*
- * git specific compatibility
- */
-
-static inline void convert_slashes(char *path)
-{
- for (; *path; path++)
- if (*path == '\\')
- *path = '/';
-}
-#define PATH_SEP ';'
-char *mingw_query_user_email(void);
-#define query_user_email mingw_query_user_email
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
#define PRIuMAX "I64u"
#define PRId64 "I64d"
@@ -464,176 +428,4 @@ char *mingw_query_user_email(void);
#include <inttypes.h>
#endif
-/**
- * Verifies that the specified path is owned by the user running the
- * current process.
- */
-int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
-#define is_path_owned_by_current_user is_path_owned_by_current_sid
-
-/**
- * Verifies that the given path is a valid one on Windows.
- *
- * In particular, path segments are disallowed which
- *
- * - end in a period or a space (except the special directories `.` and `..`).
- *
- * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
- *
- * - correspond to reserved names (such as `AUX`, `PRN`, etc)
- *
- * The `allow_literal_nul` parameter controls whether the path `NUL` should
- * be considered valid (this makes sense e.g. before opening files, as it is
- * perfectly legitimate to open `NUL` on Windows, just as it is to open
- * `/dev/null` on Unix/Linux).
- *
- * Returns 1 upon success, otherwise 0.
- */
-int is_valid_win32_path(const char *path, int allow_literal_nul);
-#define is_valid_path(path) is_valid_win32_path(path, 0)
-
-/**
- * Converts UTF-8 encoded string to UTF-16LE.
- *
- * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
- * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
- * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
- * Unicode) are converted to hex-code.
- *
- * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
- * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
- *
- * Maximum space requirement for the target buffer is two wide chars per UTF-8
- * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
- *
- * The maximum space is needed only if the entire input string consists of
- * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
- *
- * | | UTF-8 | UTF-16 |
- * Code point | UTF-8 sequence | bytes | words | ratio
- * --------------+-------------------+-------+--------+-------
- * 000000-00007f | 0-7f | 1 | 1 | 1
- * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
- * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
- * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
- * invalid | 80-9f | 1 | 2 (b) | 2
- * invalid | a0-ff | 1 | 1 | 1
- *
- * (a) encoded as UTF-16 surrogate pair
- * (b) encoded as two hex digits
- *
- * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
- * or even indefinite-byte sequences, the largest valid code point \u10ffff
- * encodes as only 4 UTF-8 bytes.
- *
- * Parameters:
- * wcs: wide char target buffer
- * utf: string to convert
- * wcslen: size of target buffer (in wchar_t's)
- * utflen: size of string to convert, or -1 if 0-terminated
- *
- * Returns:
- * length of converted string (_wcslen(wcs)), or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
-
-/**
- * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
- */
-static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
-{
- return xutftowcsn(wcs, utf, wcslen, -1);
-}
-
-/**
- * Simplified file system specific variant of xutftowcsn, assumes output
- * buffer size is MAX_PATH wide chars and input string is \0-terminated,
- * fails with ENAMETOOLONG if input string is too long.
- */
-static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
-{
- int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
- if (result < 0 && errno == ERANGE)
- errno = ENAMETOOLONG;
- return result;
-}
-
-/**
- * Converts UTF-16LE encoded string to UTF-8.
- *
- * Maximum space requirement for the target buffer is three UTF-8 chars per
- * wide char ((_wcslen(wcs) * 3) + 1).
- *
- * The maximum space is needed only if the entire input string consists of
- * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
- * modulo surrogate pairs), as per the following table:
- *
- * | | UTF-16 | UTF-8 |
- * Code point | UTF-16 sequence | words | bytes | ratio
- * --------------+-----------------------+--------+-------+-------
- * 000000-00007f | 0000-007f | 1 | 1 | 1
- * 000080-0007ff | 0080-07ff | 1 | 2 | 2
- * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
- * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
- *
- * Note that invalid code points > 10ffff cannot be represented in UTF-16.
- *
- * Parameters:
- * utf: target buffer
- * wcs: wide string to convert
- * utflen: size of target buffer
- *
- * Returns:
- * length of converted string, or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
-
-/*
- * A critical section used in the implementation of the spawn
- * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
- * the replacement main() macro below.
- */
-extern CRITICAL_SECTION pinfo_cs;
-
-/*
- * Git, like most portable C applications, implements a main() function. On
- * Windows, this main() function would receive parameters encoded in the
- * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
- *
- * To make that happen, we still declare main() here, and then declare and
- * implement wmain() (which is the Unicode variant of main()) and compile with
- * -municode. This wmain() function reencodes the parameters from UTF-16 to
- * UTF-8 format, sets up a couple of other things as required on Windows, and
- * then hands off to the main() function.
- */
-int wmain(int argc, const wchar_t **w_argv);
-int main(int argc, const char **argv);
-
-/*
- * For debugging: if a problem occurs, say, in a Git process that is spawned
- * from another Git process which in turn is spawned from yet another Git
- * process, it can be quite daunting to figure out what is going on.
- *
- * Call this function to open a new MinTTY (this assumes you are in Git for
- * Windows' SDK) with a GDB that attaches to the current process right away.
- */
-void open_in_gdb(void);
-
-/*
- * Used by Pthread API implementation for Windows
- */
-int err_win_to_posix(DWORD winerr);
-
-#ifndef NO_UNIX_SOCKETS
-int mingw_have_unix_sockets(void);
-#undef have_unix_sockets
-#define have_unix_sockets mingw_have_unix_sockets
-#endif
+#endif /* COMPAT_MINGW_POSIX_H */
diff --git a/compat/msvc.c b/compat/msvc/compat-util.c
similarity index 75%
rename from compat/msvc.c
rename to compat/msvc/compat-util.c
index 71843d7eef..7f228a6399 100644
--- a/compat/msvc.c
+++ b/compat/msvc/compat-util.c
@@ -3,4 +3,4 @@
#include <conio.h>
#include "../strbuf.h"
-#include "mingw.c"
+#include "mingw/compat-util.c"
diff --git a/compat/msvc/compat-util.h b/compat/msvc/compat-util.h
new file mode 100644
index 0000000000..404af236b5
--- /dev/null
+++ b/compat/msvc/compat-util.h
@@ -0,0 +1,7 @@
+#ifndef COMPAT_MSVC_COMPAT_UTIL_H
+#define COMPAT_MSVC_COMPAT_UTIL_H
+
+#include "posix.h"
+#include "../mingw/compat-util.h"
+
+#endif /* COMPAT_MSVC_COMPAT_UTIL_H */
diff --git a/compat/msvc.h b/compat/msvc/posix.h
similarity index 86%
rename from compat/msvc.h
rename to compat/msvc/posix.h
index 1d7a8c6145..703a7c2067 100644
--- a/compat/msvc.h
+++ b/compat/msvc/posix.h
@@ -1,5 +1,5 @@
-#ifndef __MSVC__HEAD
-#define __MSVC__HEAD
+#ifndef COMPAT_MSVC_POSIX_H
+#define COMPAT_MSVC_POSIX_H
#include <direct.h>
#include <process.h>
@@ -28,6 +28,6 @@ typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-#include "compat/mingw.h"
+#include "../mingw/posix.h"
-#endif
+#endif /* COMPAT_MSVC_POSIX_H */
diff --git a/config.mak.uname b/config.mak.uname
index b12d4e168a..dbd05adb5d 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -495,7 +495,7 @@ endif
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
- COMPAT_OBJS = compat/msvc.o compat/winansi.o \
+ COMPAT_OBJS = compat/msvc/compat-util.o compat/winansi.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
compat/win32/pthread.o compat/win32/syslog.o \
@@ -541,7 +541,7 @@ endif
EXTRA_PROGRAMS += headless-git$X
-compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
+compat/msvc/compat-util.o: compat/msvc/compat-util.c compat/mingw/compat-util.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease
@@ -694,7 +694,7 @@ ifeq ($(uname_S),MINGW)
BASIC_LDFLAGS += -municode
COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/winansi.o \
+ COMPAT_OBJS += compat/mingw/compat-util.o compat/winansi.o \
compat/win32/trace2_win32_process_info.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 10dc54fdcb..65ce8705f0 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -258,7 +258,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET HAVE_RTLGENRANDOM)
list(APPEND compat_SOURCES
- compat/mingw.c
+ compat/mingw/compat-util.c
compat/winansi.c
compat/win32/flush.c
compat/win32/path-utils.c
diff --git a/git-compat-util.h b/git-compat-util.h
index e283c46c6f..b96fb98e1e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -304,10 +304,10 @@ static inline int is_xplatform_dir_sep(int c)
#if defined(__MINGW32__)
/* pull in Windows compatibility stuff */
#include "compat/win32/path-utils.h"
-#include "compat/mingw.h"
+#include "compat/mingw/compat-util.h"
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
-#include "compat/msvc.h"
+#include "compat/msvc/compat-util.h"
#else
#include <sys/utsname.h>
#include <sys/wait.h>
diff --git a/meson.build b/meson.build
index 2297f5e9dd..e8abf798f5 100644
--- a/meson.build
+++ b/meson.build
@@ -1054,7 +1054,6 @@ if host_machine.system() == 'cygwin'
]
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw.c',
'compat/winansi.c',
'compat/win32/flush.c',
'compat/win32/path-utils.c',
@@ -1081,6 +1080,9 @@ elif host_machine.system() == 'windows'
libgit_include_directories += 'compat/win32'
if compiler.get_id() == 'msvc'
libgit_include_directories += 'compat/vcbuild/include'
+ libgit_sources += 'compat/msvc/compat-util.c'
+ else
+ libgit_sources += 'compat/mingw/compat-util.c'
endif
endif
@@ -1157,7 +1159,7 @@ else
error('Native regex support requested but not found')
endif
-# setitimer and friends are provided by compat/mingw.c.
+# setitimer and friends are provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows'
if not compiler.compiles('''
#include <sys/time.h>
@@ -1237,7 +1239,7 @@ if not compiler.has_function('qsort')
endif
libgit_sources += 'compat/qsort_s.c'
-# unsetenv is provided by compat/mingw.c.
+# unsetenv is provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows' and not compiler.has_function('unsetenv')
libgit_c_args += '-DNO_UNSETENV'
libgit_sources += 'compat/unsetenv.c'
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 16/18] git-compat-util.h: split out POSIX-emulating bits
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (14 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
` (2 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The "git-compat-util.h" header is a treasure trove of various bits and
pieces used throughout the project. It basically mixes two different
things into one:
- Providing a POSIX-like interface even on platforms that aren't
POSIX-compliant.
- Providing low-level functionality that is specific to Git.
This intermixing is a bit of a problem for the reftable library as we
don't want to recreate the POSIX-like interface there. But neither do we
want to pull in the Git-specific functionality, as it is otherwise quite
easy to start depending on the Git codebase again.
Split out a new header "compat/posix.h" that only contains the bits and
pieces relevant for the emulation of POSIX, which we will start using in
the next commit.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/posix.h | 541 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
git-compat-util.h | 531 +----------------------------------------------------
2 files changed, 543 insertions(+), 529 deletions(-)
diff --git a/compat/posix.h b/compat/posix.h
new file mode 100644
index 0000000000..8aa41f7183
--- /dev/null
+++ b/compat/posix.h
@@ -0,0 +1,541 @@
+#ifndef COMPAT_POSIX_H
+#define COMPAT_POSIX_H
+
+#define _FILE_OFFSET_BITS 64
+
+/*
+ * Derived from Linux "Features Test Macro" header
+ * Convenience macros to test the versions of gcc (or
+ * a compatible compiler).
+ * Use them like this:
+ * #if GIT_GNUC_PREREQ (2,8)
+ * ... code requiring gcc 2.8 or later ...
+ * #endif
+ *
+ * This macro of course is not part of POSIX, but we need it for the UNUSED
+ * macro which is used by some of our POSIX compatibility wrappers.
+*/
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define GIT_GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+ #define GIT_GNUC_PREREQ(maj, min) 0
+#endif
+
+/*
+ * UNUSED marks a function parameter that is always unused. It also
+ * can be used to annotate a function, a variable, or a type that is
+ * always unused.
+ *
+ * A callback interface may dictate that a function accepts a
+ * parameter at that position, but the implementation of the function
+ * may not need to use the parameter. In such a case, mark the parameter
+ * with UNUSED.
+ *
+ * When a parameter may be used or unused, depending on conditional
+ * compilation, consider using MAYBE_UNUSED instead.
+ */
+#if GIT_GNUC_PREREQ(4, 5)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated ("parameter declared as UNUSED")))
+#elif defined(__GNUC__)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated))
+#else
+#define UNUSED
+#endif
+
+#ifdef __MINGW64__
+#define _POSIX_C_SOURCE 1
+#elif defined(__sun__)
+ /*
+ * On Solaris, when _XOPEN_EXTENDED is set, its header file
+ * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
+ * setting to say we are XPG5 or XPG6. Also on Solaris,
+ * XPG6 programs must be compiled with a c99 compiler, while
+ * non XPG6 programs must be compiled with a pre-c99 compiler.
+ */
+# if __STDC_VERSION__ - 0 >= 199901L
+# define _XOPEN_SOURCE 600
+# else
+# define _XOPEN_SOURCE 500
+# endif
+#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
+ !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
+ !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
+ !defined(__CYGWIN__)
+#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
+#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
+#endif
+#define _ALL_SOURCE 1
+#define _GNU_SOURCE 1
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+#define _NETBSD_SOURCE 1
+#define _SGI_SOURCE 1
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
+# if !defined(_WIN32_WINNT)
+# define _WIN32_WINNT 0x0600
+# endif
+#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
+#include <winsock2.h>
+#ifndef NO_UNIX_SOCKETS
+#include <afunix.h>
+#endif
+#include <windows.h>
+#define GIT_WINDOWS_NATIVE
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h> /* for strcasecmp() */
+#endif
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#ifdef NEEDS_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#include <syslog.h>
+#if !defined(NO_POLL_H)
+#include <poll.h>
+#elif !defined(NO_SYS_POLL_H)
+#include <sys/poll.h>
+#else
+/* Pull the compat stuff */
+#include <poll.h>
+#endif
+#ifdef HAVE_BSD_SYSCTL
+#include <sys/sysctl.h>
+#endif
+
+#if defined(__MINGW32__)
+#include "mingw/posix.h"
+#elif defined(_MSC_VER)
+#include "msvc/posix.h"
+#else
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/statvfs.h>
+#include <termios.h>
+#ifndef NO_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/un.h>
+#ifndef NO_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+#ifdef HAVE_ARC4RANDOM_LIBBSD
+#include <bsd/stdlib.h>
+#endif
+#ifdef HAVE_GETRANDOM
+#include <sys/random.h>
+#endif
+#ifdef NO_INTPTR_T
+/*
+ * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
+ * on LLP86, IL33LLP64 and P64 it needs to be "long long",
+ * while on IP16 and IP16L32 it is "int" (resp. "short")
+ * Size needs to match (or exceed) 'sizeof(void *)'.
+ * We can't take "long long" here as not everybody has it.
+ */
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+#endif
+#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
+#include <grp.h>
+#define _ALL_SOURCE 1
+#endif
+
+#ifdef MKDIR_WO_TRAILING_SLASH
+#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
+int compat_mkdir_wo_trailing_slash(const char*, mode_t);
+#endif
+
+#ifdef time
+#undef time
+#endif
+static inline time_t git_time(time_t *tloc)
+{
+ struct timeval tv;
+
+ /*
+ * Avoid time(NULL), which can disagree with gettimeofday(2)
+ * and filesystem timestamps.
+ */
+ gettimeofday(&tv, NULL);
+
+ if (tloc)
+ *tloc = tv.tv_sec;
+ return tv.tv_sec;
+}
+#define time git_time
+
+#ifdef NO_STRUCT_ITIMERVAL
+struct itimerval {
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+#endif
+
+#ifdef NO_SETITIMER
+static inline int git_setitimer(int which UNUSED,
+ const struct itimerval *value UNUSED,
+ struct itimerval *newvalue UNUSED) {
+ return 0; /* pretend success */
+}
+#undef setitimer
+#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
+#endif
+
+#ifndef NO_LIBGEN_H
+#include <libgen.h>
+#else
+#define basename gitbasename
+char *gitbasename(char *);
+#define dirname gitdirname
+char *gitdirname(char *);
+#endif
+
+#ifndef NO_ICONV
+#include <iconv.h>
+#endif
+
+/* On most systems <netdb.h> would have given us this, but
+ * not on some systems (e.g. z/OS).
+ */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+/* On most systems <limits.h> would have given us this, but
+ * not on some systems (e.g. GNU/Hurd).
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+typedef uintmax_t timestamp_t;
+#define PRItime PRIuMAX
+#define parse_timestamp strtoumax
+#define TIME_MAX UINTMAX_MAX
+#define TIME_MIN 0
+
+int lstat_cache_aware_rmdir(const char *path);
+#if !defined(__MINGW32__) && !defined(_MSC_VER)
+#define rmdir lstat_cache_aware_rmdir
+#endif
+
+#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
+
+#ifndef PROT_READ
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define MAP_PRIVATE 1
+#endif
+
+#define mmap git_mmap
+#define munmap git_munmap
+void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int git_munmap(void *start, size_t length);
+
+#else /* NO_MMAP || USE_WIN32_MMAP */
+
+#include <sys/mman.h>
+
+#endif /* NO_MMAP || USE_WIN32_MMAP */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#ifdef NEEDS_MODE_TRANSLATION
+#undef S_IFMT
+#undef S_IFREG
+#undef S_IFDIR
+#undef S_IFLNK
+#undef S_IFBLK
+#undef S_IFCHR
+#undef S_IFIFO
+#undef S_IFSOCK
+#define S_IFMT 0170000
+#define S_IFREG 0100000
+#define S_IFDIR 0040000
+#define S_IFLNK 0120000
+#define S_IFBLK 0060000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_IFSOCK 0140000
+#ifdef stat
+#undef stat
+#endif
+#define stat(path, buf) git_stat(path, buf)
+int git_stat(const char *, struct stat *);
+#ifdef fstat
+#undef fstat
+#endif
+#define fstat(fd, buf) git_fstat(fd, buf)
+int git_fstat(int, struct stat *);
+#ifdef lstat
+#undef lstat
+#endif
+#define lstat(path, buf) git_lstat(path, buf)
+int git_lstat(const char *, struct stat *);
+#endif
+
+#ifdef NO_PREAD
+#define pread git_pread
+ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+
+#ifdef NO_SETENV
+#define setenv gitsetenv
+int gitsetenv(const char *, const char *, int);
+#endif
+
+#ifdef NO_MKDTEMP
+#define mkdtemp gitmkdtemp
+char *gitmkdtemp(char *);
+#endif
+
+#ifdef NO_UNSETENV
+#define unsetenv gitunsetenv
+int gitunsetenv(const char *);
+#endif
+
+#ifdef NO_STRCASESTR
+#define strcasestr gitstrcasestr
+char *gitstrcasestr(const char *haystack, const char *needle);
+#endif
+
+#ifdef NO_STRLCPY
+#define strlcpy gitstrlcpy
+size_t gitstrlcpy(char *, const char *, size_t);
+#endif
+
+#ifdef NO_STRTOUMAX
+#define strtoumax gitstrtoumax
+uintmax_t gitstrtoumax(const char *, char **, int);
+#define strtoimax gitstrtoimax
+intmax_t gitstrtoimax(const char *, char **, int);
+#endif
+
+#ifdef NO_HSTRERROR
+#define hstrerror githstrerror
+const char *githstrerror(int herror);
+#endif
+
+#ifdef NO_MEMMEM
+#define memmem gitmemmem
+void *gitmemmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+#endif
+
+#ifdef OVERRIDE_STRDUP
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup gitstrdup
+char *gitstrdup(const char *s);
+#endif
+
+#ifdef NO_GETPAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifdef FREAD_READS_DIRECTORIES
+# if !defined(SUPPRESS_FOPEN_REDEFINITION)
+# ifdef fopen
+# undef fopen
+# endif
+# define fopen(a,b) git_fopen(a,b)
+# endif
+FILE *git_fopen(const char*, const char*);
+#endif
+
+#ifdef SNPRINTF_RETURNS_BOGUS
+#ifdef snprintf
+#undef snprintf
+#endif
+#define snprintf git_snprintf
+int git_snprintf(char *str, size_t maxsize,
+ const char *format, ...);
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#define vsnprintf git_vsnprintf
+int git_vsnprintf(char *str, size_t maxsize,
+ const char *format, va_list ap);
+#endif
+
+#ifdef OPEN_RETURNS_EINTR
+#undef open
+#define open git_open_with_retry
+int git_open_with_retry(const char *path, int flag, ...);
+#endif
+
+#ifdef __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2, 1)
+#define HAVE_STRCHRNUL
+#endif
+#endif
+
+#ifndef HAVE_STRCHRNUL
+#define strchrnul gitstrchrnul
+static inline char *gitstrchrnul(const char *s, int c)
+{
+ while (*s && *s != c)
+ s++;
+ return (char *)s;
+}
+#endif
+
+#ifdef NO_INET_PTON
+int inet_pton(int af, const char *src, void *dst);
+#endif
+
+#ifdef NO_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
+#ifdef NO_PTHREADS
+#define atexit git_atexit
+int git_atexit(void (*handler)(void));
+#endif
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
+#include "sane-ctype.h"
+
+void git_stable_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
+#ifdef INTERNAL_QSORT
+#define qsort git_stable_qsort
+#endif
+
+#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
+static inline void sane_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *))
+{
+ if (nmemb > 1)
+ qsort(base, nmemb, size, compar);
+}
+
+#define STABLE_QSORT(base, n, compar) \
+ git_stable_qsort((base), (n), sizeof(*(base)), compar)
+
+#ifndef HAVE_ISO_QSORT_S
+int git_qsort_s(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *), void *ctx);
+#define qsort_s git_qsort_s
+#endif
+
+#define QSORT_S(base, n, compar, ctx) do { \
+ if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
+ BUG("qsort_s() failed"); \
+} while (0)
+
+#ifdef NO_NSEC
+#undef USE_NSEC
+#define ST_CTIME_NSEC(st) 0
+#define ST_MTIME_NSEC(st) 0
+#else
+#ifdef USE_ST_TIMESPEC
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
+#else
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
+#endif
+#endif
+
+#ifndef va_copy
+/*
+ * Since an obvious implementation of va_list would be to make it a
+ * pointer into the stack frame, a simple assignment will work on
+ * many systems. But let's try to be more portable.
+ */
+#ifdef __va_copy
+#define va_copy(dst, src) __va_copy(dst, src)
+#else
+#define va_copy(dst, src) ((dst) = (src))
+#endif
+#endif
+
+#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+static inline void git_flockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+static inline void git_funlockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+#undef flockfile
+#undef funlockfile
+#undef getc_unlocked
+#define flockfile(fh) git_flockfile(fh)
+#define funlockfile(fh) git_funlockfile(fh)
+#define getc_unlocked(fh) getc(fh)
+#endif
+
+#ifdef FILENO_IS_A_MACRO
+int git_fileno(FILE *stream);
+# ifndef COMPAT_CODE_FILENO
+# undef fileno
+# define fileno(p) git_fileno(p)
+# endif
+#endif
+
+#ifdef NEED_ACCESS_ROOT_HANDLER
+int git_access(const char *path, int mode);
+# ifndef COMPAT_CODE_ACCESS
+# ifdef access
+# undef access
+# endif
+# define access(path, mode) git_access(path, mode)
+# endif
+#endif
+
+#endif /* COMPAT_POSIX_H */
diff --git a/git-compat-util.h b/git-compat-util.h
index b96fb98e1e..30ad0725fb 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -23,26 +23,9 @@
#include <crtdbg.h>
#endif
-struct strbuf;
-
-
-#define _FILE_OFFSET_BITS 64
+#include "compat/posix.h"
-
-/* Derived from Linux "Features Test Macro" header
- * Convenience macros to test the versions of gcc (or
- * a compatible compiler).
- * Use them like this:
- * #if GIT_GNUC_PREREQ (2,8)
- * ... code requiring gcc 2.8 or later ...
- * #endif
-*/
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define GIT_GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-#else
- #define GIT_GNUC_PREREQ(maj, min) 0
-#endif
+struct strbuf;
#if defined(__GNUC__) || defined(__clang__)
# define PRAGMA(pragma) _Pragma(#pragma)
@@ -176,71 +159,6 @@ DISABLE_WARNING(-Wsign-compare)
/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-#ifdef __MINGW64__
-#define _POSIX_C_SOURCE 1
-#elif defined(__sun__)
- /*
- * On Solaris, when _XOPEN_EXTENDED is set, its header file
- * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
- * setting to say we are XPG5 or XPG6. Also on Solaris,
- * XPG6 programs must be compiled with a c99 compiler, while
- * non XPG6 programs must be compiled with a pre-c99 compiler.
- */
-# if __STDC_VERSION__ - 0 >= 199901L
-# define _XOPEN_SOURCE 600
-# else
-# define _XOPEN_SOURCE 500
-# endif
-#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
- !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
- !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
- !defined(__CYGWIN__)
-#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
-#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
-#endif
-#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
-#define _BSD_SOURCE 1
-#define _DEFAULT_SOURCE 1
-#define _NETBSD_SOURCE 1
-#define _SGI_SOURCE 1
-
-/*
- * UNUSED marks a function parameter that is always unused. It also
- * can be used to annotate a function, a variable, or a type that is
- * always unused.
- *
- * A callback interface may dictate that a function accepts a
- * parameter at that position, but the implementation of the function
- * may not need to use the parameter. In such a case, mark the parameter
- * with UNUSED.
- *
- * When a parameter may be used or unused, depending on conditional
- * compilation, consider using MAYBE_UNUSED instead.
- */
-#if GIT_GNUC_PREREQ(4, 5)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated ("parameter declared as UNUSED")))
-#elif defined(__GNUC__)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated))
-#else
-#define UNUSED
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
-# if !defined(_WIN32_WINNT)
-# define _WIN32_WINNT 0x0600
-# endif
-#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
-#include <winsock2.h>
-#ifndef NO_UNIX_SOCKETS
-#include <afunix.h>
-#endif
-#include <windows.h>
-#define GIT_WINDOWS_NATIVE
-#endif
-
#if defined(NO_UNIX_SOCKETS) || !defined(GIT_WINDOWS_NATIVE)
static inline int _have_unix_sockets(void)
{
@@ -253,45 +171,6 @@ static inline int _have_unix_sockets(void)
#define have_unix_sockets _have_unix_sockets
#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h> /* for strcasecmp() */
-#endif
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#ifdef NEEDS_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <time.h>
-#include <signal.h>
-#include <assert.h>
-#include <regex.h>
-#include <utime.h>
-#include <syslog.h>
-#if !defined(NO_POLL_H)
-#include <poll.h>
-#elif !defined(NO_SYS_POLL_H)
-#include <sys/poll.h>
-#else
-/* Pull the compat stuff */
-#include <poll.h>
-#endif
-#ifdef HAVE_BSD_SYSCTL
-#include <sys/sysctl.h>
-#endif
-
/* Used by compat/win32/path-utils.h, and more */
static inline int is_xplatform_dir_sep(int c)
{
@@ -308,48 +187,6 @@ static inline int is_xplatform_dir_sep(int c)
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
#include "compat/msvc/compat-util.h"
-#else
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/statvfs.h>
-#include <termios.h>
-#ifndef NO_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <sys/un.h>
-#ifndef NO_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <stdint.h>
-#endif
-#ifdef HAVE_ARC4RANDOM_LIBBSD
-#include <bsd/stdlib.h>
-#endif
-#ifdef HAVE_GETRANDOM
-#include <sys/random.h>
-#endif
-#ifdef NO_INTPTR_T
-/*
- * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
- * on LLP86, IL33LLP64 and P64 it needs to be "long long",
- * while on IP16 and IP16L32 it is "int" (resp. "short")
- * Size needs to match (or exceed) 'sizeof(void *)'.
- * We can't take "long long" here as not everybody has it.
- */
-typedef long intptr_t;
-typedef unsigned long uintptr_t;
-#endif
-#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
-#include <grp.h>
-#define _ALL_SOURCE 1
#endif
/* used on Mac OS X */
@@ -370,60 +207,6 @@ static inline const char *precompose_string_if_needed(const char *in)
#define probe_utf8_pathname_composition()
#endif
-#ifdef MKDIR_WO_TRAILING_SLASH
-#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
-int compat_mkdir_wo_trailing_slash(const char*, mode_t);
-#endif
-
-#ifdef time
-#undef time
-#endif
-static inline time_t git_time(time_t *tloc)
-{
- struct timeval tv;
-
- /*
- * Avoid time(NULL), which can disagree with gettimeofday(2)
- * and filesystem timestamps.
- */
- gettimeofday(&tv, NULL);
-
- if (tloc)
- *tloc = tv.tv_sec;
- return tv.tv_sec;
-}
-#define time git_time
-
-#ifdef NO_STRUCT_ITIMERVAL
-struct itimerval {
- struct timeval it_interval;
- struct timeval it_value;
-};
-#endif
-
-#ifdef NO_SETITIMER
-static inline int git_setitimer(int which UNUSED,
- const struct itimerval *value UNUSED,
- struct itimerval *newvalue UNUSED) {
- return 0; /* pretend success */
-}
-#undef setitimer
-#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
-#endif
-
-#ifndef NO_LIBGEN_H
-#include <libgen.h>
-#else
-#define basename gitbasename
-char *gitbasename(char *);
-#define dirname gitdirname
-char *gitdirname(char *);
-#endif
-
-#ifndef NO_ICONV
-#include <iconv.h>
-#endif
-
#ifndef NO_OPENSSL
#ifdef __APPLE__
#undef __AVAILABILITY_MACROS_USES_AVAILABILITY
@@ -441,34 +224,6 @@ char *gitdirname(char *);
# include <sys/sysinfo.h>
#endif
-/* On most systems <netdb.h> would have given us this, but
- * not on some systems (e.g. z/OS).
- */
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
-
-/* On most systems <limits.h> would have given us this, but
- * not on some systems (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-typedef uintmax_t timestamp_t;
-#define PRItime PRIuMAX
-#define parse_timestamp strtoumax
-#define TIME_MAX UINTMAX_MAX
-#define TIME_MIN 0
-
#ifndef PATH_SEP
#define PATH_SEP ':'
#endif
@@ -492,11 +247,6 @@ static inline int noop_core_config(const char *var UNUSED,
#define platform_core_config noop_core_config
#endif
-int lstat_cache_aware_rmdir(const char *path);
-#if !defined(__MINGW32__) && !defined(_MSC_VER)
-#define rmdir lstat_cache_aware_rmdir
-#endif
-
#ifndef has_dos_drive_prefix
static inline int git_has_dos_drive_prefix(const char *path UNUSED)
{
@@ -822,25 +572,6 @@ static inline bool strip_suffix(const char *str, const char *suffix,
memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
} while (0)
-#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-
-#ifndef PROT_READ
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define MAP_PRIVATE 1
-#endif
-
-#define mmap git_mmap
-#define munmap git_munmap
-void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-int git_munmap(void *start, size_t length);
-
-#else /* NO_MMAP || USE_WIN32_MMAP */
-
-#include <sys/mman.h>
-
-#endif /* NO_MMAP || USE_WIN32_MMAP */
-
#ifdef NO_MMAP
/* This value must be multiple of (pagesize * 2) */
@@ -856,177 +587,15 @@ int git_munmap(void *start, size_t length);
#endif /* NO_MMAP */
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
#define on_disk_bytes(st) ((st).st_size)
#else
#define on_disk_bytes(st) ((st).st_blocks * 512)
#endif
-#ifdef NEEDS_MODE_TRANSLATION
-#undef S_IFMT
-#undef S_IFREG
-#undef S_IFDIR
-#undef S_IFLNK
-#undef S_IFBLK
-#undef S_IFCHR
-#undef S_IFIFO
-#undef S_IFSOCK
-#define S_IFMT 0170000
-#define S_IFREG 0100000
-#define S_IFDIR 0040000
-#define S_IFLNK 0120000
-#define S_IFBLK 0060000
-#define S_IFCHR 0020000
-#define S_IFIFO 0010000
-#define S_IFSOCK 0140000
-#ifdef stat
-#undef stat
-#endif
-#define stat(path, buf) git_stat(path, buf)
-int git_stat(const char *, struct stat *);
-#ifdef fstat
-#undef fstat
-#endif
-#define fstat(fd, buf) git_fstat(fd, buf)
-int git_fstat(int, struct stat *);
-#ifdef lstat
-#undef lstat
-#endif
-#define lstat(path, buf) git_lstat(path, buf)
-int git_lstat(const char *, struct stat *);
-#endif
-
#define DEFAULT_PACKED_GIT_LIMIT \
((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))
-#ifdef NO_PREAD
-#define pread git_pread
-ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
-#endif
-
-#ifdef NO_SETENV
-#define setenv gitsetenv
-int gitsetenv(const char *, const char *, int);
-#endif
-
-#ifdef NO_MKDTEMP
-#define mkdtemp gitmkdtemp
-char *gitmkdtemp(char *);
-#endif
-
-#ifdef NO_UNSETENV
-#define unsetenv gitunsetenv
-int gitunsetenv(const char *);
-#endif
-
-#ifdef NO_STRCASESTR
-#define strcasestr gitstrcasestr
-char *gitstrcasestr(const char *haystack, const char *needle);
-#endif
-
-#ifdef NO_STRLCPY
-#define strlcpy gitstrlcpy
-size_t gitstrlcpy(char *, const char *, size_t);
-#endif
-
-#ifdef NO_STRTOUMAX
-#define strtoumax gitstrtoumax
-uintmax_t gitstrtoumax(const char *, char **, int);
-#define strtoimax gitstrtoimax
-intmax_t gitstrtoimax(const char *, char **, int);
-#endif
-
-#ifdef NO_HSTRERROR
-#define hstrerror githstrerror
-const char *githstrerror(int herror);
-#endif
-
-#ifdef NO_MEMMEM
-#define memmem gitmemmem
-void *gitmemmem(const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen);
-#endif
-
-#ifdef OVERRIDE_STRDUP
-#ifdef strdup
-#undef strdup
-#endif
-#define strdup gitstrdup
-char *gitstrdup(const char *s);
-#endif
-
-#ifdef NO_GETPAGESIZE
-#define getpagesize() sysconf(_SC_PAGESIZE)
-#endif
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
-#endif
-
-#ifdef FREAD_READS_DIRECTORIES
-# if !defined(SUPPRESS_FOPEN_REDEFINITION)
-# ifdef fopen
-# undef fopen
-# endif
-# define fopen(a,b) git_fopen(a,b)
-# endif
-FILE *git_fopen(const char*, const char*);
-#endif
-
-#ifdef SNPRINTF_RETURNS_BOGUS
-#ifdef snprintf
-#undef snprintf
-#endif
-#define snprintf git_snprintf
-int git_snprintf(char *str, size_t maxsize,
- const char *format, ...);
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#define vsnprintf git_vsnprintf
-int git_vsnprintf(char *str, size_t maxsize,
- const char *format, va_list ap);
-#endif
-
-#ifdef OPEN_RETURNS_EINTR
-#undef open
-#define open git_open_with_retry
-int git_open_with_retry(const char *path, int flag, ...);
-#endif
-
-#ifdef __GLIBC_PREREQ
-#if __GLIBC_PREREQ(2, 1)
-#define HAVE_STRCHRNUL
-#endif
-#endif
-
-#ifndef HAVE_STRCHRNUL
-#define strchrnul gitstrchrnul
-static inline char *gitstrchrnul(const char *s, int c)
-{
- while (*s && *s != c)
- s++;
- return (char *)s;
-}
-#endif
-
-#ifdef NO_INET_PTON
-int inet_pton(int af, const char *src, void *dst);
-#endif
-
-#ifdef NO_INET_NTOP
-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-#endif
-
-#ifdef NO_PTHREADS
-#define atexit git_atexit
-int git_atexit(void (*handler)(void));
-#endif
-
static inline size_t st_add(size_t a, size_t b)
{
if (unsigned_add_overflows(a, b))
@@ -1293,12 +862,6 @@ static inline size_t xsize_t(off_t len)
return (size_t) len;
}
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
-#endif
-
-#include "sane-ctype.h"
-
/*
* Like skip_prefix, but compare case-insensitively. Note that the comparison
* is done via tolower(), so it is strictly ASCII (no multi-byte characters or
@@ -1364,34 +927,6 @@ static inline int strtol_i(char const *s, int base, int *result)
return 0;
}
-void git_stable_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *));
-#ifdef INTERNAL_QSORT
-#define qsort git_stable_qsort
-#endif
-
-#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
-static inline void sane_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *))
-{
- if (nmemb > 1)
- qsort(base, nmemb, size, compar);
-}
-
-#define STABLE_QSORT(base, n, compar) \
- git_stable_qsort((base), (n), sizeof(*(base)), compar)
-
-#ifndef HAVE_ISO_QSORT_S
-int git_qsort_s(void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *, void *), void *ctx);
-#define qsort_s git_qsort_s
-#endif
-
-#define QSORT_S(base, n, compar, ctx) do { \
- if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
- BUG("qsort_s() failed"); \
-} while (0)
-
#ifndef REG_STARTEND
#error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd"
#endif
@@ -1416,39 +951,12 @@ int git_regcomp(regex_t *preg, const char *pattern, int cflags);
# define FORCE_DIR_SET_GID 0
#endif
-#ifdef NO_NSEC
-#undef USE_NSEC
-#define ST_CTIME_NSEC(st) 0
-#define ST_MTIME_NSEC(st) 0
-#else
-#ifdef USE_ST_TIMESPEC
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
-#else
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
-#endif
-#endif
-
#ifdef UNRELIABLE_FSTAT
#define fstat_is_reliable() 0
#else
#define fstat_is_reliable() 1
#endif
-#ifndef va_copy
-/*
- * Since an obvious implementation of va_list would be to make it a
- * pointer into the stack frame, a simple assignment will work on
- * many systems. But let's try to be more portable.
- */
-#ifdef __va_copy
-#define va_copy(dst, src) __va_copy(dst, src)
-#else
-#define va_copy(dst, src) ((dst) = (src))
-#endif
-#endif
-
/* usage.c: only to be used for testing BUG() implementation (see test-tool) */
extern int BUG_exit_code;
@@ -1478,41 +986,6 @@ void bug_fl(const char *file, int line, const char *fmt, ...);
# define SHELL_PATH "/bin/sh"
#endif
-#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
-static inline void git_flockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-static inline void git_funlockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-#undef flockfile
-#undef funlockfile
-#undef getc_unlocked
-#define flockfile(fh) git_flockfile(fh)
-#define funlockfile(fh) git_funlockfile(fh)
-#define getc_unlocked(fh) getc(fh)
-#endif
-
-#ifdef FILENO_IS_A_MACRO
-int git_fileno(FILE *stream);
-# ifndef COMPAT_CODE_FILENO
-# undef fileno
-# define fileno(p) git_fileno(p)
-# endif
-#endif
-
-#ifdef NEED_ACCESS_ROOT_HANDLER
-int git_access(const char *path, int mode);
-# ifndef COMPAT_CODE_ACCESS
-# ifdef access
-# undef access
-# endif
-# define access(path, mode) git_access(path, mode)
-# endif
-#endif
-
/*
* Our code often opens a path to an optional file, to work on its
* contents when we can successfully open it. We can ignore a failure
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h"
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (15 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-02-06 4:04 ` [PATCH v3 00/18] reftable: stop using "git-compat-util.h" Justin Tobler
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The reftable library includes "git-compat-util.h" in order to get a
POSIX-like programming environment that papers over various differences
between platforms. The header also brings with it a couple of helpers
specific to the Git codebase though, and over time we have started to
use these helpers in the reftable library, as well.
This makes it very hard to use the reftable library as a standalone
library without the rest of the Git codebase, so other libraries like
e.g. libgit2 cannot easily use it. But now that we have removed all
calls to Git-specific functionality and have split out "compat/posix.h"
as a separate header we can address this.
Stop including "git-compat-util.h" and instead include "compat/posix.h"
to finalize the decoupling of the reftable library from the rest of the
Git codebase. The only bits which remain specific to Git are "system.h"
and "system.c", which projects will have to provide.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/system.c | 2 ++
reftable/system.h | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/reftable/system.c b/reftable/system.c
index e25ccc0da3..1ee268b125 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -1,3 +1,5 @@
+#include "../git-compat-util.h"
+
#include "system.h"
#include "basics.h"
#include "reftable-error.h"
diff --git a/reftable/system.h b/reftable/system.h
index 3bd4a4e322..dccdf11f76 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -11,7 +11,8 @@ license that can be found in the LICENSE file or at
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "../compat/posix.h"
+#include <zlib.h>
/*
* Return a random 32 bit integer. This function is expected to return
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v3 18/18] Makefile: skip reftable library for Coccinelle
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (16 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
@ 2025-02-03 8:03 ` Patrick Steinhardt
2025-02-06 4:04 ` [PATCH v3 00/18] reftable: stop using "git-compat-util.h" Justin Tobler
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:03 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano
The reftable library does not use any of the common helpers that the Git
project has. Consequently, most of the rules that we have in Coccinelle
do not apply to the library at all and may even generate false positives
when a pattern can be converted to use a Git helper function.
Exclude reftable library sources from being checked by Coccinelle to
avoid such false positives.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index d3011e30f7..dc2ac32e4a 100644
--- a/Makefile
+++ b/Makefile
@@ -946,7 +946,7 @@ FOUND_SOURCE_FILES := $(filter-out $(GENERATED_H),$(shell $(SOURCES_CMD)))
FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES))
FOUND_H_SOURCES = $(filter %.h,$(FOUND_SOURCE_FILES))
-COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
+COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES) reftable/%,$(FOUND_C_SOURCES))
LIB_H = $(FOUND_H_SOURCES)
--
2.48.1.502.g6dc24dfdaf.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* Re: [PATCH v2 04/20] reftable/record: stop using `COPY_ARRAY()`
2025-01-29 15:46 ` Justin Tobler
@ 2025-02-03 8:40 ` Patrick Steinhardt
0 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:40 UTC (permalink / raw)
To: Justin Tobler; +Cc: git, Edward Thomson, Junio C Hamano
On Wed, Jan 29, 2025 at 09:46:54AM -0600, Justin Tobler wrote:
> On 25/01/28 09:28AM, Patrick Steinhardt wrote:
> > Drop our use of `COPY_ARRAY()`, replacing it with an open-coded variant
> > thereof. This is done to reduce our dependency on the Git library.
> >
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
> > reftable/record.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/reftable/record.c b/reftable/record.c
> > index 8919df8a4d..d1664c47ca 100644
> > --- a/reftable/record.c
> > +++ b/reftable/record.c
> > @@ -508,7 +508,8 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
> > if (!obj->offsets)
> > return REFTABLE_OUT_OF_MEMORY_ERROR;
> > obj->offset_len = src->offset_len;
> > - COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
> > + if (src->offset_len)
> > + memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len);
>
> The `COPY_ARRAY` version uses `st_mutl()` to protect against potential
> overflows of the size parameter. Does this variant need to account for
> such situations as well?
It shouldn't be needed as we already know that the allocation was
successful in the source record, and we're basically just copying things
over. But better be safe than sorry, so I'll add it in.
Patrick
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v2 15/20] compat: consistently resolve headers via project root
2025-01-29 14:23 ` Junio C Hamano
@ 2025-02-03 8:40 ` Patrick Steinhardt
0 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-03 8:40 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, Edward Thomson, Justin Tobler, git
On Wed, Jan 29, 2025 at 06:23:36AM -0800, Junio C Hamano wrote:
> Johannes Sixt <j6t@kdbg.org> writes:
>
> > Depending on the desired goal, is it perhaps better to use <> brackets
> > more liberally?
>
> I'd be in general in favor of that direction, as the semantics of <>
> is more clear than "" from the point of view of the standard ;-)
Hm. Semantics are indeed clearer when using <>, but I think that in this
context "" still conveys more about where a specific header comes from.
I know it's not the whole truth, but "" is typically taken to mean "the
header comes from our own sources", whereas <> is typically taken to
mean that it is provided by the system.
So if we now e.g. started to `#include <compat/msvc.h>` I wonder whether
this would really result in code that is easier to understand, even if
it is technically correct.
I dunno -- I think I'll punt on the issue for now and drop the commit,
because I'd rather want to not start discussing this in the context of
this series here. I'm happy to discuss this as a subsequent step though.
Patrick
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v3 00/18] reftable: stop using "git-compat-util.h"
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
` (17 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
@ 2025-02-06 4:04 ` Justin Tobler
18 siblings, 0 replies; 146+ messages in thread
From: Justin Tobler @ 2025-02-06 4:04 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Edward Thomson, Junio C Hamano
On 25/02/03 09:03AM, Patrick Steinhardt wrote:
> Changes in v3:
> - Fix type of `total_read` variable used to track how many bytes we
> have read in `fd_read_lines()`.
> - Drop the patch use root-relative includes again. Let's rather
> discuss this outside of the scope of this series.
> - Link to v2: https://lore.kernel.org/r/20250128-pks-reftable-drop-git-compat-util-v2-0-c85c20336317@pks.im
Thanks Patrick. This version looks good to me!
-Justin
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v4 00/18] reftable: stop using "git-compat-util.h"
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (21 preceding siblings ...)
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
` (17 more replies)
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
24 siblings, 18 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Hi,
this patch series is the final step to fully decouple the reftable
library from the rest of the Git codebase. The goal of this is to make
the library reusable by other projects like libgit2 by simply copying
over the source files, making Git the canonical upstream for reftable
functionality.
This patch series stops using all kinds of helpers exposed by our
"git-compat-util.h" header and open-codes them instead. In order to keep
us from using these helpers by accident the final step is to pull out
POSIX-related bits and pieces into a new "compat/posix.h" header, which
the reftable library then uses instead of "git-compat-util.h".
The series is built on top of master at 5f8f7081f7 (The third batch,
2025-01-23) with ps/reftable-sign-compare at 33319b0976 (reftable:
address trivial -Wsign-compare warnings, 2025-01-20) merged into it.
There is a trivial merge conflict with ps/zlib-ng that can be solved
like this:
diff --cc reftable/system.h
index e4a8944a70,d02eacea8f..0000000000
--- a/reftable/system.h
+++ b/reftable/system.h
@@@ -11,15 -11,9 +11,15 @@@ https://developers.google.com/open-sour
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "compat/posix.h"
- #include <zlib.h>
+ #include "compat/zlib-compat.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
Changes in v2:
- The splitup of Windows headers has broken compilation because some
of the headers couldn't be found anymore. I've fixed this more
generally by converting includes in "compat/" to always be relative
to the project source directory, dropping the platform-specific
`-Icompat/` include.
- Explain why we don't port over `EWOULDBLOCK` handling.
- Fix commit message typos.
- Link to v1: https://lore.kernel.org/r/20250127-pks-reftable-drop-git-compat-util-v1-0-6e280a564877@pks.im
Changes in v3:
- Fix type of `total_read` variable used to track how many bytes we
have read in `fd_read_lines()`.
- Drop the patch use root-relative includes again. Let's rather
discuss this outside of the scope of this series.
- Link to v2: https://lore.kernel.org/r/20250128-pks-reftable-drop-git-compat-util-v2-0-c85c20336317@pks.im
Changes in v4:
- Fix a couple of now-invalid relative includes that I missed. This
fixes the build issue in "seen" with Meson.
- Link to v3: https://lore.kernel.org/r/20250203-pks-reftable-drop-git-compat-util-v3-0-446c9ed4ee9e@pks.im
Thanks!
Patrick
---
Patrick Steinhardt (18):
reftable/stack: stop using `read_in_full()`
reftable/stack: stop using `write_in_full()`
reftable/blocksource: stop using `xmmap()`
reftable/record: stop using `COPY_ARRAY()`
reftable/record: stop using `BUG()` in `reftable_record_init()`
reftable/record: don't `BUG()` in `reftable_record_cmp()`
reftable: stop using `BUG()` in trivial cases
reftable/basics: stop using `st_mult()` in array allocators
reftable/basics: provide wrappers for big endian conversion
reftable/reader: stop using `ARRAY_SIZE()` macro
reftable/system: introduce `reftable_rand()`
reftable/stack: stop using `sleep_millisec()`
reftable/basics: stop using `SWAP()` macro
reftable/basics: stop using `UNUSED` annotation
compat/mingw: split out POSIX-related bits
git-compat-util.h: split out POSIX-emulating bits
reftable: decouple from Git codebase by pulling in "compat/posix.h"
Makefile: skip reftable library for Coccinelle
Makefile | 2 +-
compat/{mingw.c => mingw/compat-util.c} | 28 +-
compat/mingw/compat-util.h | 220 +++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------
compat/msvc.c | 6 -
compat/msvc/compat-util.c | 6 +
compat/msvc/compat-util.h | 7 +
compat/{msvc.h => msvc/posix.h} | 8 +-
compat/posix.h | 541 ++++++++++++++++++++++++++++++++
config.mak.uname | 6 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 535 +------------------------------
meson.build | 8 +-
reftable/basics.c | 19 --
reftable/basics.h | 123 +++++++-
reftable/block.c | 16 +-
reftable/blocksource.c | 21 +-
reftable/iter.c | 20 +-
reftable/merged.c | 27 +-
reftable/pq.c | 40 ++-
reftable/pq.h | 2 +-
reftable/reader.c | 33 +-
reftable/record.c | 109 ++++---
reftable/record.h | 6 +-
reftable/stack.c | 52 ++-
reftable/system.c | 7 +
reftable/system.h | 9 +-
reftable/writer.c | 29 +-
t/unit-tests/t-reftable-basics.c | 28 +-
t/unit-tests/t-reftable-pq.c | 22 +-
t/unit-tests/t-reftable-record.c | 42 ++-
31 files changed, 1242 insertions(+), 948 deletions(-)
Range-diff versus v3:
1: 801e7bb30c = 1: 07f44927f1 reftable/stack: stop using `read_in_full()`
2: 9b1b778a28 = 2: c62404d62e reftable/stack: stop using `write_in_full()`
3: 336b5ca3e1 = 3: f936b06d4b reftable/blocksource: stop using `xmmap()`
4: ec74201d8d = 4: ea203b9060 reftable/record: stop using `COPY_ARRAY()`
5: 853740bd10 = 5: c13aaeca16 reftable/record: stop using `BUG()` in `reftable_record_init()`
6: c6003aa731 = 6: 397b5321bf reftable/record: don't `BUG()` in `reftable_record_cmp()`
7: afbb02bdc7 = 7: 921d4ba9f0 reftable: stop using `BUG()` in trivial cases
8: fe34e5e425 = 8: 0c4396cc16 reftable/basics: stop using `st_mult()` in array allocators
9: 405b6bdac7 = 9: af50906b6d reftable/basics: provide wrappers for big endian conversion
10: f0ca7a5f13 = 10: 1e931c747b reftable/reader: stop using `ARRAY_SIZE()` macro
11: 2e8152c509 = 11: f66900df08 reftable/system: introduce `reftable_rand()`
12: bdb708349d = 12: 99af9a50da reftable/stack: stop using `sleep_millisec()`
13: 6e59462638 = 13: bdcd8744df reftable/basics: stop using `SWAP()` macro
14: 7c4e2eeb9b = 14: 41f637bd3f reftable/basics: stop using `UNUSED` annotation
15: 942eeca014 ! 15: 4dbbc71e11 compat/mingw: split out POSIX-related bits
@@ Commit message
Signed-off-by: Patrick Steinhardt <ps@pks.im>
## compat/mingw.c => compat/mingw/compat-util.c ##
+@@
+ #define USE_THE_REPOSITORY_VARIABLE
+ #define DISABLE_SIGN_COMPARE_WARNINGS
+
+-#include "../git-compat-util.h"
+-#include "win32.h"
++#include "../../git-compat-util.h"
++#include "../win32.h"
+ #include <aclapi.h>
+ #include <sddl.h>
+ #include <conio.h>
+ #include <wchar.h>
+-#include "../strbuf.h"
+-#include "../run-command.h"
+-#include "../abspath.h"
+-#include "../alloc.h"
+-#include "win32/lazyload.h"
+-#include "../config.h"
+-#include "../environment.h"
+-#include "../trace2.h"
+-#include "../symlinks.h"
+-#include "../wrapper.h"
+-#include "dir.h"
+-#include "gettext.h"
++#include "../../strbuf.h"
++#include "../../run-command.h"
++#include "../../abspath.h"
++#include "../../alloc.h"
++#include "../win32/lazyload.h"
++#include "../../config.h"
++#include "../../environment.h"
++#include "../../trace2.h"
++#include "../../symlinks.h"
++#include "../../wrapper.h"
++#include "../../dir.h"
++#include "../../gettext.h"
+ #define SECURITY_WIN32
+ #include <sspi.h>
+
## compat/mingw/compat-util.h (new) ##
@@
@@ compat/mingw/posix.h: char *mingw_query_user_email(void);
-#endif
+#endif /* COMPAT_MINGW_POSIX_H */
- ## compat/msvc.c => compat/msvc/compat-util.c ##
+ ## compat/msvc.c (deleted) ##
@@
- #include <conio.h>
- #include "../strbuf.h"
-
+-#include "../git-compat-util.h"
+-#include "win32.h"
+-#include <conio.h>
+-#include "../strbuf.h"
+-
-#include "mingw.c"
-+#include "mingw/compat-util.c"
+
+ ## compat/msvc/compat-util.c (new) ##
+@@
++#include "../../git-compat-util.h"
++#include "../win32.h"
++#include <conio.h>
++#include "../../strbuf.h"
++
++#include "../mingw/compat-util.c"
## compat/msvc/compat-util.h (new) ##
@@
16: 53151b2649 ! 16: f0e9c6d3ee git-compat-util.h: split out POSIX-emulating bits
@@ compat/posix.h (new)
+#define HOST_NAME_MAX 256
+#endif
+
-+#include "sane-ctype.h"
++#include "../sane-ctype.h"
+
+void git_stable_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
17: b63a798513 = 17: 35a975dfe2 reftable: decouple from Git codebase by pulling in "compat/posix.h"
18: f9edb54708 = 18: 1dde84b32c Makefile: skip reftable library for Coccinelle
---
base-commit: 8047765d092881ec4aef7dfc57772161eee7f0f5
change-id: 20241119-pks-reftable-drop-git-compat-util-470f2bfde562
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v4 01/18] reftable/stack: stop using `read_in_full()`
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
` (16 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
There is a single callsite of `read_in_full()` in the reftable library.
Open-code the function to reduce our dependency on the Git library.
Note that we only partially port over the logic from `read_in_full()`
and its underlying `xread()` helper. Most importantly, the latter also
knows to handle `EWOULDBLOCK` via `handle_nonblock()`. This logic is
irrelevant for us though because the reftable library never sets the
`O_NONBLOCK` option in the first place.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index f7c1845e15..d57acd9540 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -115,13 +115,16 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
static int fd_read_lines(int fd, char ***namesp)
{
- off_t size = lseek(fd, 0, SEEK_END);
char *buf = NULL;
int err = 0;
+ off_t size;
+
+ size = lseek(fd, 0, SEEK_END);
if (size < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
+
err = lseek(fd, 0, SEEK_SET);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp)
goto done;
}
- if (read_in_full(fd, buf, size) != size) {
- err = REFTABLE_IO_ERROR;
- goto done;
+ for (off_t total_read = 0; total_read < size; ) {
+ ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
+ if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_read < 0 || !bytes_read) {
+ err = REFTABLE_IO_ERROR;
+ goto done;
+ }
+
+ total_read += bytes_read;
}
buf[size] = 0;
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 02/18] reftable/stack: stop using `write_in_full()`
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
` (15 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Similar to the preceding commit, drop our use of `write_in_full()` and
implement a new wrapper `reftable_write_full()` that handles this logic
for us. This is done to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index d57acd9540..46abf51ec5 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -48,6 +48,25 @@ static int stack_fsync(const struct reftable_write_options *opts, int fd)
return fsync(fd);
}
+static ssize_t reftable_write_data(int fd, const void *data, size_t size)
+{
+ size_t total_written = 0;
+ const char *p = data;
+
+ while (total_written < size) {
+ ssize_t bytes_written = write(fd, p, size - total_written);
+ if (bytes_written < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_written < 0)
+ return REFTABLE_IO_ERROR;
+
+ total_written += bytes_written;
+ p += bytes_written;
+ }
+
+ return total_written;
+}
+
struct fd_writer {
const struct reftable_write_options *opts;
int fd;
@@ -56,7 +75,7 @@ struct fd_writer {
static ssize_t fd_writer_write(void *arg, const void *data, size_t sz)
{
struct fd_writer *writer = arg;
- return write_in_full(writer->fd, data, sz);
+ return reftable_write_data(writer->fd, data, sz);
}
static int fd_writer_flush(void *arg)
@@ -784,7 +803,8 @@ int reftable_addition_commit(struct reftable_addition *add)
goto done;
}
- err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len);
+ err = reftable_write_data(add->tables_list_lock.fd,
+ table_list.buf, table_list.len);
reftable_buf_release(&table_list);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -1468,8 +1488,8 @@ static int stack_compact_range(struct reftable_stack *st,
goto done;
}
- err = write_in_full(tables_list_lock.fd,
- tables_list_buf.buf, tables_list_buf.len);
+ err = reftable_write_data(tables_list_lock.fd,
+ tables_list_buf.buf, tables_list_buf.len);
if (err < 0) {
err = REFTABLE_IO_ERROR;
unlink(new_table_path.buf);
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 03/18] reftable/blocksource: stop using `xmmap()`
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
` (14 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We use `xmmap()` to map reftables into memory. This function has two
problems:
- It causes us to die in case the mmap fails.
- It ties us to the Git codebase.
Refactor the code to use mmap(3p) instead with manual error checking.
Note that this function may not be the system-provided mmap(3p), but may
point to our `git_mmap()` wrapper that emulates the syscall on systems
that do not have mmap(3p) available.
Fix `reftable_block_source_from_file()` to properly bubble up the error
code in case the map(3p) call fails.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/blocksource.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index bba4a45b98..02972c46f4 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -98,7 +98,7 @@ static struct reftable_block_source_vtable file_vtable = {
int reftable_block_source_from_file(struct reftable_block_source *bs,
const char *name)
{
- struct file_block_source *p;
+ struct file_block_source *p = NULL;
struct stat st;
int fd, err;
@@ -122,7 +122,12 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
}
p->size = st.st_size;
- p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ p->data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p->data == MAP_FAILED) {
+ err = REFTABLE_IO_ERROR;
+ p->data = NULL;
+ goto out;
+ }
assert(!bs->ops);
bs->ops = &file_vtable;
@@ -135,5 +140,5 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
close(fd);
if (err < 0)
reftable_free(p);
- return 0;
+ return err;
}
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 04/18] reftable/record: stop using `COPY_ARRAY()`
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (2 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
` (13 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Drop our use of `COPY_ARRAY()`, replacing it with an open-coded variant
thereof. This is done to reduce our dependency on the Git library.
While at it, guard the whole array copy logic so that we only copy it in
case there actually is anything to be copied. Otherwise, we may end up
trying to allocate a zero-sized array, which will return a NULL pointer
and thus cause us to return an `REFTABLE_OUT_OF_MEMORY_ERROR`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/record.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/reftable/record.c b/reftable/record.c
index 8919df8a4d..2c0cc32cbd 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -504,11 +504,17 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
if (src->hash_prefix_len)
memcpy(obj->hash_prefix, src->hash_prefix, obj->hash_prefix_len);
- REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
- if (!obj->offsets)
- return REFTABLE_OUT_OF_MEMORY_ERROR;
- obj->offset_len = src->offset_len;
- COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
+ if (src->offset_len) {
+ if (sizeof(*src->offsets) > SIZE_MAX / src->offset_len)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
+ if (!obj->offsets)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len);
+ obj->offset_len = src->offset_len;
+ }
return 0;
}
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()`
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (3 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
` (12 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We're aborting the program via `BUG()` in case `reftable_record_init()`
was invoked with an unknown record type. This is bad because we may now
die in library code, and because it makes us depend on the Git codebase.
Refactor the code such that `reftable_record_init()` can return an error
code to the caller. Adapt any callers accordingly.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/block.c | 4 +++-
reftable/merged.c | 5 ++++-
reftable/reader.c | 5 ++++-
reftable/record.c | 8 ++++----
reftable/record.h | 4 ++--
t/unit-tests/t-reftable-pq.c | 6 +++---
t/unit-tests/t-reftable-record.c | 2 +-
7 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/reftable/block.c b/reftable/block.c
index 8ac865ce78..255d566854 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -509,7 +509,9 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,
it->block_len = br->block_len;
it->hash_size = br->hash_size;
- reftable_record_init(&rec, block_reader_type(br));
+ err = reftable_record_init(&rec, block_reader_type(br));
+ if (err < 0)
+ goto done;
/*
* We're looking for the last entry less than the wanted key so that
diff --git a/reftable/merged.c b/reftable/merged.c
index e72b39e178..4156eec07f 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -253,7 +253,10 @@ int merged_table_init_iter(struct reftable_merged_table *mt,
}
for (size_t i = 0; i < mt->readers_len; i++) {
- reftable_record_init(&subiters[i].rec, typ);
+ ret = reftable_record_init(&subiters[i].rec, typ);
+ if (ret < 0)
+ goto out;
+
ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
if (ret < 0)
goto out;
diff --git a/reftable/reader.c b/reftable/reader.c
index 3f2e4b2800..de6e6dd932 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -360,7 +360,10 @@ static int table_iter_seek_linear(struct table_iter *ti,
struct reftable_record rec;
int err;
- reftable_record_init(&rec, reftable_record_type(want));
+ err = reftable_record_init(&rec, reftable_record_type(want));
+ if (err < 0)
+ goto done;
+
err = reftable_record_key(want, &want_key);
if (err < 0)
goto done;
diff --git a/reftable/record.c b/reftable/record.c
index 2c0cc32cbd..1e18f8dffb 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1306,7 +1306,7 @@ reftable_record_vtable(struct reftable_record *rec)
abort();
}
-void reftable_record_init(struct reftable_record *rec, uint8_t typ)
+int reftable_record_init(struct reftable_record *rec, uint8_t typ)
{
memset(rec, 0, sizeof(*rec));
rec->type = typ;
@@ -1315,11 +1315,11 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)
case BLOCK_TYPE_REF:
case BLOCK_TYPE_LOG:
case BLOCK_TYPE_OBJ:
- return;
+ return 0;
case BLOCK_TYPE_INDEX:
reftable_buf_init(&rec->u.idx.last_key);
- return;
+ return 0;
default:
- BUG("unhandled record type");
+ return REFTABLE_API_ERROR;
}
}
diff --git a/reftable/record.h b/reftable/record.h
index c7755a4d75..e1846c294b 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -130,8 +130,8 @@ struct reftable_record {
} u;
};
-/* Initialize the reftable record for the given type */
-void reftable_record_init(struct reftable_record *rec, uint8_t typ);
+/* Initialize the reftable record for the given type. */
+int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index f3f8a0cdf3..d8a4c283a1 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -32,7 +32,7 @@ static void t_pq_record(void)
char *last = NULL;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
}
@@ -72,7 +72,7 @@ static void t_pq_index(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
@@ -111,7 +111,7 @@ static void t_merged_iter_pqueue_top(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index d49d2a2729..6540bd20e3 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -17,7 +17,7 @@ static void t_copy(struct reftable_record *rec)
uint8_t typ;
typ = reftable_record_type(rec);
- reftable_record_init(©, typ);
+ check(!reftable_record_init(©, typ));
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
/* do it twice to catch memory leaks */
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()`
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (4 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
` (11 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
The reftable library aborts with a bug in case `reftable_record_cmp()`
is invoked with two records of differing types. This would cause the
program to die without the caller being able to handle the error, which
is not something we want in the context of library code. And it ties us
to the Git codebase.
Refactor the code such that `reftable_record_cmp()` returns an error
code separate from the actual comparison result. This requires us to
also adapt some callers up the callchain in a similar fashion.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/merged.c | 20 +++++++++++++++-----
reftable/pq.c | 36 +++++++++++++++++++++++++++++-------
reftable/pq.h | 2 +-
reftable/record.c | 10 ++++++----
reftable/record.h | 2 +-
t/unit-tests/t-reftable-pq.c | 16 ++++++++++++----
t/unit-tests/t-reftable-record.c | 40 ++++++++++++++++++++++++++++------------
7 files changed, 92 insertions(+), 34 deletions(-)
diff --git a/reftable/merged.c b/reftable/merged.c
index 4156eec07f..563864068c 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -66,8 +66,11 @@ static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want
int err;
mi->advance_index = -1;
- while (!merged_iter_pqueue_is_empty(mi->pq))
- merged_iter_pqueue_remove(&mi->pq);
+ while (!merged_iter_pqueue_is_empty(mi->pq)) {
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+ }
for (size_t i = 0; i < mi->subiters_len; i++) {
err = iterator_seek(&mi->subiters[i].iter, want);
@@ -120,7 +123,9 @@ static int merged_iter_next_entry(struct merged_iter *mi,
if (empty)
return 1;
- entry = merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, &entry);
+ if (err < 0)
+ return err;
/*
One can also use reftable as datacenter-local storage, where the ref
@@ -134,11 +139,16 @@ static int merged_iter_next_entry(struct merged_iter *mi,
struct pq_entry top = merged_iter_pqueue_top(mi->pq);
int cmp;
- cmp = reftable_record_cmp(top.rec, entry.rec);
+ err = reftable_record_cmp(top.rec, entry.rec, &cmp);
+ if (err < 0)
+ return err;
if (cmp > 0)
break;
- merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+
err = merged_iter_advance_subiter(mi, top.index);
if (err < 0)
return err;
diff --git a/reftable/pq.c b/reftable/pq.c
index 5591e875e1..ef8035cfd9 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -15,13 +15,18 @@ license that can be found in the LICENSE file or at
int pq_less(struct pq_entry *a, struct pq_entry *b)
{
- int cmp = reftable_record_cmp(a->rec, b->rec);
+ int cmp, err;
+
+ err = reftable_record_cmp(a->rec, b->rec, &cmp);
+ if (err < 0)
+ return err;
+
if (cmp == 0)
return a->index > b->index;
return cmp < 0;
}
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out)
{
size_t i = 0;
struct pq_entry e = pq->heap[0];
@@ -32,17 +37,34 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
size_t min = i;
size_t j = 2 * i + 1;
size_t k = 2 * i + 2;
- if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i]))
- min = j;
- if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min]))
- min = k;
+ int cmp;
+
+ if (j < pq->len) {
+ cmp = pq_less(&pq->heap[j], &pq->heap[i]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = j;
+ }
+
+ if (k < pq->len) {
+ cmp = pq_less(&pq->heap[k], &pq->heap[min]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = k;
+ }
+
if (min == i)
break;
SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
- return e;
+ if (out)
+ *out = e;
+
+ return 0;
}
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
diff --git a/reftable/pq.h b/reftable/pq.h
index 83c062eeca..ff39016445 100644
--- a/reftable/pq.h
+++ b/reftable/pq.h
@@ -22,7 +22,7 @@ struct merged_iter_pqueue {
size_t cap;
};
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out);
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
diff --git a/reftable/record.c b/reftable/record.c
index 1e18f8dffb..b39d99fcc7 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1195,12 +1195,14 @@ int reftable_record_is_deletion(struct reftable_record *rec)
reftable_record_data(rec));
}
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b)
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b,
+ int *cmp)
{
if (a->type != b->type)
- BUG("cannot compare reftable records of different type");
- return reftable_record_vtable(a)->cmp(
- reftable_record_data(a), reftable_record_data(b));
+ return -1;
+ *cmp = reftable_record_vtable(a)->cmp(reftable_record_data(a),
+ reftable_record_data(b));
+ return 0;
}
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size)
diff --git a/reftable/record.h b/reftable/record.h
index e1846c294b..867810a932 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -134,7 +134,7 @@ struct reftable_record {
int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b, int *cmp);
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size);
int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);
int reftable_record_copy_from(struct reftable_record *rec,
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index d8a4c283a1..c128fe8616 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -21,7 +21,9 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq)
static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b)
{
- return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index);
+ int cmp;
+ check(!reftable_record_cmp(a->rec, b->rec, &cmp));
+ return !cmp && (a->index == b->index);
}
static void t_pq_record(void)
@@ -49,7 +51,9 @@ static void t_pq_record(void)
while (!merged_iter_pqueue_is_empty(pq)) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -90,7 +94,9 @@ static void t_pq_index(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -129,7 +135,9 @@ static void t_merged_iter_pqueue_top(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index 6540bd20e3..5954966373 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -100,16 +100,20 @@ static void t_reftable_ref_record_comparison(void)
.u.ref.value.symref = (char *) "refs/heads/master",
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.ref.value_type = in[0].u.ref.value_type;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_ref_record_compare_name(void)
@@ -209,17 +213,20 @@ static void t_reftable_log_record_comparison(void)
.u.log.update_index = 22,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
/* comparison should be reversed for equal keys, because
* comparison is now performed on the basis of update indices */
- check_int(reftable_record_cmp(&in[0], &in[1]), <, 0);
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check_int(cmp, <, 0);
in[1].u.log.update_index = in[0].u.log.update_index;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
}
static void t_reftable_log_record_compare_key(void)
@@ -396,16 +403,20 @@ static void t_reftable_obj_record_comparison(void)
.u.obj.hash_prefix_len = 5,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.obj.offset_len = in[0].u.obj.offset_len;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_obj_record_roundtrip(void)
@@ -486,19 +497,24 @@ static void t_reftable_index_record_comparison(void)
.u.idx.last_key = REFTABLE_BUF_INIT,
},
};
+ int cmp;
+
check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch"));
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.idx.offset = in[0].u.idx.offset;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
for (size_t i = 0; i < ARRAY_SIZE(in); i++)
reftable_record_release(&in[i]);
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 07/18] reftable: stop using `BUG()` in trivial cases
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (5 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
` (10 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Stop using `BUG()` in the remaining trivial cases that we still have in
the reftable library. Instead of aborting the program, we'll now bubble
up a `REFTABLE_API_ERROR` to indicate misuse of the calling conventions.
Note that in both `reftable_reader_{inc,dec}ref()` we simply stop
calling `BUG()` altogether. The only situation where the counter should
be zero is when the structure has already been free'd anyway, so we
would run into undefined behaviour regardless of whether we try to abort
the program or not.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/iter.c | 3 +--
reftable/reader.c | 4 ----
reftable/writer.c | 5 ++---
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/reftable/iter.c b/reftable/iter.c
index 86e801ca9f..b2ffb09c16 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -146,8 +146,7 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
static int indexed_table_ref_iter_seek(void *p UNUSED,
struct reftable_record *want UNUSED)
{
- BUG("seeking indexed table is not supported");
- return -1;
+ return REFTABLE_API_ERROR;
}
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
diff --git a/reftable/reader.c b/reftable/reader.c
index de6e6dd932..36a5633ede 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -677,8 +677,6 @@ int reftable_reader_new(struct reftable_reader **out,
void reftable_reader_incref(struct reftable_reader *r)
{
- if (!r->refcount)
- BUG("cannot increment ref counter of dead reader");
r->refcount++;
}
@@ -686,8 +684,6 @@ void reftable_reader_decref(struct reftable_reader *r)
{
if (!r)
return;
- if (!r->refcount)
- BUG("cannot decrement ref counter of dead reader");
if (--r->refcount)
return;
block_source_close(&r->source);
diff --git a/reftable/writer.c b/reftable/writer.c
index 91d6629486..155863ee5f 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -158,7 +158,7 @@ int reftable_writer_new(struct reftable_writer **out,
opts = *_opts;
options_set_defaults(&opts);
if (opts.block_size >= (1 << 24))
- BUG("configured block size exceeds 16MB");
+ return REFTABLE_API_ERROR;
reftable_buf_init(&wp->block_writer_data.last_key);
reftable_buf_init(&wp->last_key);
@@ -289,8 +289,7 @@ static int writer_add_record(struct reftable_writer *w,
}
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
- BUG("record of type %d added to writer of type %d",
- reftable_record_type(rec), block_writer_type(w->block_writer));
+ return REFTABLE_API_ERROR;
/*
* Try to add the record to the writer. If this succeeds then we're
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 08/18] reftable/basics: stop using `st_mult()` in array allocators
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (6 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
` (9 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We're using `st_mult()` as part of our macro helpers that allocate
arrays. This is bad due two two reasons:
- `st_mult()` causes us to die in case the multiplication overflows.
- `st_mult()` ties us to the Git codebase.
Refactor the code to instead detect overflows manually and return an
error in such cases.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index a2a010a0e1..646f8d67f2 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -117,18 +117,46 @@ void reftable_free(void *p);
void *reftable_calloc(size_t nelem, size_t elsize);
char *reftable_strdup(const char *str);
-#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
+static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out)
+{
+ if (nelem && elsize > SIZE_MAX / nelem)
+ return -1;
+ *out = nelem * elsize;
+ return 0;
+}
+
+#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_malloc(alloc_size); \
+ } \
+ } while (0)
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
-#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc)))
+#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_realloc((x), alloc_size); \
+ } \
+ } while (0)
static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
size_t *allocp)
{
void *new_p;
- size_t alloc = *allocp * 2 + 1;
+ size_t alloc = *allocp * 2 + 1, alloc_bytes;
if (alloc < nelem)
alloc = nelem;
- new_p = reftable_realloc(p, st_mult(elsize, alloc));
+ if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) {
+ errno = ENOMEM;
+ return p;
+ }
+ new_p = reftable_realloc(p, alloc_bytes);
if (!new_p)
return p;
*allocp = alloc;
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 09/18] reftable/basics: provide wrappers for big endian conversion
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (7 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
` (8 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We're using a mixture of big endian conversion functions provided by
both the reftable library, but also by the Git codebase. Refactor the
code so that we exclusively use reftable-provided wrappers in order to
untangle us from the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.c | 19 ----------
reftable/basics.h | 76 ++++++++++++++++++++++++++++++++++++++--
reftable/block.c | 12 +++----
reftable/reader.c | 22 ++++++------
reftable/record.c | 8 ++---
reftable/writer.c | 20 +++++------
t/unit-tests/t-reftable-basics.c | 28 ++++++++++++---
7 files changed, 127 insertions(+), 58 deletions(-)
diff --git a/reftable/basics.c b/reftable/basics.c
index 3b5ea27bbd..8c4a4433e4 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -147,25 +147,6 @@ char *reftable_buf_detach(struct reftable_buf *buf)
return result;
}
-void put_be24(uint8_t *out, uint32_t i)
-{
- out[0] = (uint8_t)((i >> 16) & 0xff);
- out[1] = (uint8_t)((i >> 8) & 0xff);
- out[2] = (uint8_t)(i & 0xff);
-}
-
-uint32_t get_be24(uint8_t *in)
-{
- return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 |
- (uint32_t)(in[2]);
-}
-
-void put_be16(uint8_t *out, uint16_t i)
-{
- out[0] = (uint8_t)((i >> 8) & 0xff);
- out[1] = (uint8_t)(i & 0xff);
-}
-
size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
{
size_t lo = 0;
diff --git a/reftable/basics.h b/reftable/basics.h
index 646f8d67f2..c1ddbaec3f 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -76,9 +76,79 @@ char *reftable_buf_detach(struct reftable_buf *buf);
/* Bigendian en/decoding of integers */
-void put_be24(uint8_t *out, uint32_t i);
-uint32_t get_be24(uint8_t *in);
-void put_be16(uint8_t *out, uint16_t i);
+static inline void reftable_put_be16(void *out, uint16_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 8) & 0xff);
+ p[1] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be24(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 16) & 0xff);
+ p[1] = (uint8_t)((i >> 8) & 0xff);
+ p[2] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be32(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 24) & 0xff);
+ p[1] = (uint8_t)((i >> 16) & 0xff);
+ p[2] = (uint8_t)((i >> 8) & 0xff);
+ p[3] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be64(void *out, uint64_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 56) & 0xff);
+ p[1] = (uint8_t)((i >> 48) & 0xff);
+ p[2] = (uint8_t)((i >> 40) & 0xff);
+ p[3] = (uint8_t)((i >> 32) & 0xff);
+ p[4] = (uint8_t)((i >> 24) & 0xff);
+ p[5] = (uint8_t)((i >> 16) & 0xff);
+ p[6] = (uint8_t)((i >> 8) & 0xff);
+ p[7] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline uint16_t reftable_get_be16(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint16_t)(p[0]) << 8 |
+ (uint16_t)(p[1]) << 0;
+}
+
+static inline uint32_t reftable_get_be24(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 16 |
+ (uint32_t)(p[1]) << 8 |
+ (uint32_t)(p[2]) << 0;
+}
+
+static inline uint32_t reftable_get_be32(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 24 |
+ (uint32_t)(p[1]) << 16 |
+ (uint32_t)(p[2]) << 8|
+ (uint32_t)(p[3]) << 0;
+}
+
+static inline uint64_t reftable_get_be64(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint64_t)(p[0]) << 56 |
+ (uint64_t)(p[1]) << 48 |
+ (uint64_t)(p[2]) << 40 |
+ (uint64_t)(p[3]) << 32 |
+ (uint64_t)(p[4]) << 24 |
+ (uint64_t)(p[5]) << 16 |
+ (uint64_t)(p[6]) << 8 |
+ (uint64_t)(p[7]) << 0;
+}
/*
* find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is
diff --git a/reftable/block.c b/reftable/block.c
index 255d566854..373908807e 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -148,13 +148,13 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
int block_writer_finish(struct block_writer *w)
{
for (uint32_t i = 0; i < w->restart_len; i++) {
- put_be24(w->block + w->next, w->restarts[i]);
+ reftable_put_be24(w->block + w->next, w->restarts[i]);
w->next += 3;
}
- put_be16(w->block + w->next, w->restart_len);
+ reftable_put_be16(w->block + w->next, w->restart_len);
w->next += 2;
- put_be24(w->block + 1 + w->header_off, w->next);
+ reftable_put_be24(w->block + 1 + w->header_off, w->next);
/*
* Log records are stored zlib-compressed. Note that the compression
@@ -216,7 +216,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
{
uint32_t full_block_size = table_block_size;
uint8_t typ = block->data[header_off];
- uint32_t sz = get_be24(block->data + header_off + 1);
+ uint32_t sz = reftable_get_be24(block->data + header_off + 1);
int err = 0;
uint16_t restart_count = 0;
uint32_t restart_start = 0;
@@ -300,7 +300,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
full_block_size = sz;
}
- restart_count = get_be16(block->data + sz - 2);
+ restart_count = reftable_get_be16(block->data + sz - 2);
restart_start = sz - 2 - 3 * restart_count;
restart_bytes = block->data + restart_start;
@@ -355,7 +355,7 @@ int block_reader_first_key(const struct block_reader *br, struct reftable_buf *k
static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx)
{
- return get_be24(br->restart_bytes + 3 * idx);
+ return reftable_get_be24(br->restart_bytes + 3 * idx);
}
void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)
diff --git a/reftable/reader.c b/reftable/reader.c
index 36a5633ede..bf07a0a586 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -101,18 +101,18 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
}
f++;
- r->block_size = get_be24(f);
+ r->block_size = reftable_get_be24(f);
f += 3;
- r->min_update_index = get_be64(f);
+ r->min_update_index = reftable_get_be64(f);
f += 8;
- r->max_update_index = get_be64(f);
+ r->max_update_index = reftable_get_be64(f);
f += 8;
if (r->version == 1) {
r->hash_id = REFTABLE_HASH_SHA1;
} else {
- switch (get_be32(f)) {
+ switch (reftable_get_be32(f)) {
case REFTABLE_FORMAT_ID_SHA1:
r->hash_id = REFTABLE_HASH_SHA1;
break;
@@ -127,24 +127,24 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
f += 4;
}
- r->ref_offsets.index_offset = get_be64(f);
+ r->ref_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->obj_offsets.offset = get_be64(f);
+ r->obj_offsets.offset = reftable_get_be64(f);
f += 8;
r->object_id_len = r->obj_offsets.offset & ((1 << 5) - 1);
r->obj_offsets.offset >>= 5;
- r->obj_offsets.index_offset = get_be64(f);
+ r->obj_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.offset = get_be64(f);
+ r->log_offsets.offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.index_offset = get_be64(f);
+ r->log_offsets.index_offset = reftable_get_be64(f);
f += 8;
computed_crc = crc32(0, footer, f - footer);
- file_crc = get_be32(f);
+ file_crc = reftable_get_be32(f);
f += 4;
if (computed_crc != file_crc) {
err = REFTABLE_FORMAT_ERROR;
@@ -214,7 +214,7 @@ static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
*typ = data[0];
if (reftable_is_block_type(*typ)) {
- result = get_be24(data + 1);
+ result = reftable_get_be24(data + 1);
}
return result;
}
diff --git a/reftable/record.c b/reftable/record.c
index b39d99fcc7..3552bafa99 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -689,7 +689,7 @@ static int reftable_log_record_key(const void *r, struct reftable_buf *dest)
return err;
ts = (~ts) - rec->update_index;
- put_be64(&i64[0], ts);
+ reftable_put_be64(&i64[0], ts);
err = reftable_buf_add(dest, i64, sizeof(i64));
if (err < 0)
@@ -814,7 +814,7 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,
if (s.len < 2)
return -1;
- put_be16(s.buf, r->value.update.tz_offset);
+ reftable_put_be16(s.buf, r->value.update.tz_offset);
string_view_consume(&s, 2);
n = encode_string(
@@ -846,7 +846,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
}
memcpy(r->refname, key.buf, key.len - 8);
- ts = get_be64(key.buf + key.len - 8);
+ ts = reftable_get_be64((unsigned char *)key.buf + key.len - 8);
r->update_index = (~max) - ts;
@@ -937,7 +937,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
goto done;
}
- r->value.update.tz_offset = get_be16(in.buf);
+ r->value.update.tz_offset = reftable_get_be16(in.buf);
string_view_consume(&in, 2);
n = decode_string(scratch, in);
diff --git a/reftable/writer.c b/reftable/writer.c
index 155863ee5f..5961698311 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -99,9 +99,9 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
dest[4] = writer_version(w);
- put_be24(dest + 5, w->opts.block_size);
- put_be64(dest + 8, w->min_update_index);
- put_be64(dest + 16, w->max_update_index);
+ reftable_put_be24(dest + 5, w->opts.block_size);
+ reftable_put_be64(dest + 8, w->min_update_index);
+ reftable_put_be64(dest + 16, w->max_update_index);
if (writer_version(w) == 2) {
uint32_t hash_id;
@@ -116,7 +116,7 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
return -1;
}
- put_be32(dest + 24, hash_id);
+ reftable_put_be32(dest + 24, hash_id);
}
return header_size(writer_version(w));
@@ -717,19 +717,19 @@ int reftable_writer_close(struct reftable_writer *w)
}
p += writer_write_header(w, footer);
- put_be64(p, w->stats.ref_stats.index_offset);
+ reftable_put_be64(p, w->stats.ref_stats.index_offset);
p += 8;
- put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
+ reftable_put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
p += 8;
- put_be64(p, w->stats.obj_stats.index_offset);
+ reftable_put_be64(p, w->stats.obj_stats.index_offset);
p += 8;
- put_be64(p, w->stats.log_stats.offset);
+ reftable_put_be64(p, w->stats.log_stats.offset);
p += 8;
- put_be64(p, w->stats.log_stats.index_offset);
+ reftable_put_be64(p, w->stats.log_stats.index_offset);
p += 8;
- put_be32(p, crc32(0, footer, p - footer));
+ reftable_put_be32(p, crc32(0, footer, p - footer));
p += 4;
err = w->flush(w->write_arg);
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
index 9ba7eb05ad..c9e751e49e 100644
--- a/t/unit-tests/t-reftable-basics.c
+++ b/t/unit-tests/t-reftable-basics.c
@@ -128,12 +128,30 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
reftable_buf_release(&b);
}
- if_test ("put_be24 and get_be24 work") {
+ if_test ("reftable_put_be64 and reftable_get_be64 work") {
+ uint64_t in = 0x1122334455667788;
+ uint8_t dest[8];
+ uint64_t out;
+ reftable_put_be64(dest, in);
+ out = reftable_get_be64(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be32 and reftable_get_be32 work") {
+ uint32_t in = 0x11223344;
+ uint8_t dest[4];
+ uint32_t out;
+ reftable_put_be32(dest, in);
+ out = reftable_get_be32(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be24 and reftable_get_be24 work") {
uint32_t in = 0x112233;
uint8_t dest[3];
uint32_t out;
- put_be24(dest, in);
- out = get_be24(dest);
+ reftable_put_be24(dest, in);
+ out = reftable_get_be24(dest);
check_int(in, ==, out);
}
@@ -141,8 +159,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
uint32_t in = 0xfef1;
uint8_t dest[3];
uint32_t out;
- put_be16(dest, in);
- out = get_be16(dest);
+ reftable_put_be16(dest, in);
+ out = reftable_get_be16(dest);
check_int(in, ==, out);
}
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (8 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
` (7 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We have a single user of the `ARRAY_SIZE()` macro in the reftable
reader. Drop its use to reduce our dependence on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/reader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/reader.c b/reftable/reader.c
index bf07a0a586..c3a3674665 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -849,7 +849,7 @@ int reftable_reader_print_blocks(const char *tablename)
printf("header:\n");
printf(" block_size: %d\n", r->block_size);
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
+ for (i = 0; i < sizeof(sections) / sizeof(*sections); i++) {
err = table_iter_seek_start(&ti, sections[i].type, 0);
if (err < 0)
goto done;
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 11/18] reftable/system: introduce `reftable_rand()`
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (9 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
` (6 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Introduce a new system-level `reftable_rand()` function that generates a
single unsigned integer for us. The implementation of this function is
to be provided by the calling codebase, which allows us to more easily
hook into pre-seeded random number generators.
Adapt the two callsites where we generated random data.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 4 ++--
reftable/system.c | 5 +++++
reftable/system.h | 6 ++++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 46abf51ec5..e22577ec77 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -523,7 +523,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
close(fd);
fd = -1;
- delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1;
+ delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
sleep_millisec(delay);
}
@@ -688,7 +688,7 @@ int reftable_stack_add(struct reftable_stack *st,
static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
{
char buf[100];
- uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE);
+ uint32_t rnd = reftable_rand();
snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
min, max, rnd);
reftable_buf_reset(dest);
diff --git a/reftable/system.c b/reftable/system.c
index adf8e4d30b..e25ccc0da3 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -4,6 +4,11 @@
#include "../lockfile.h"
#include "../tempfile.h"
+uint32_t reftable_rand(void)
+{
+ return git_rand(CSPRNG_BYTES_INSECURE);
+}
+
int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern)
{
struct tempfile *tempfile;
diff --git a/reftable/system.h b/reftable/system.h
index 7d5f803eeb..3bd4a4e322 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -13,6 +13,12 @@ license that can be found in the LICENSE file or at
#include "git-compat-util.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 12/18] reftable/stack: stop using `sleep_millisec()`
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (10 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
` (5 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Refactor our use of `sleep_millisec()` by open-coding it with poll(3p),
which is the current implementation of this function. Ideally, we'd use
a more direct way to sleep, but there is no equivalent to sleep(3p) that
would accept milliseconds as input.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index e22577ec77..7b0b10cd38 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -524,7 +524,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
fd = -1;
delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
- sleep_millisec(delay);
+ poll(NULL, 0, delay);
}
out:
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 13/18] reftable/basics: stop using `SWAP()` macro
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (11 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 14/18] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
` (4 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Stop using `SWAP()` macro in favor of an open-coded variant of it. Note
that this also requires us to open-code the build assert that `SWAP()`
itself uses to verify that the size of both variables matches.
This is done to reduce our dependency on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 9 +++++++++
reftable/merged.c | 2 +-
reftable/pq.c | 4 ++--
reftable/record.c | 16 ++++++++--------
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index c1ddbaec3f..59000798f0 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -266,6 +266,15 @@ static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
# define strdup(str) REFTABLE_BANNED(strdup)
#endif
+#define REFTABLE_SWAP(a, b) do { \
+ void *_swap_a_ptr = &(a); \
+ void *_swap_b_ptr = &(b); \
+ unsigned char _swap_buffer[sizeof(a) - 2 * sizeof(a) * (sizeof(a) != sizeof(b))]; \
+ memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \
+ memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a)); \
+ memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
+} while (0)
+
/* Find the longest shared prefix size of `a` and `b` */
size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);
diff --git a/reftable/merged.c b/reftable/merged.c
index 563864068c..4ff1553772 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -155,7 +155,7 @@ static int merged_iter_next_entry(struct merged_iter *mi,
}
mi->advance_index = entry.index;
- SWAP(*rec, *entry.rec);
+ REFTABLE_SWAP(*rec, *entry.rec);
return 0;
}
diff --git a/reftable/pq.c b/reftable/pq.c
index ef8035cfd9..82394a972d 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -57,7 +57,7 @@ int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *ou
if (min == i)
break;
- SWAP(pq->heap[i], pq->heap[min]);
+ REFTABLE_SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
@@ -81,7 +81,7 @@ int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry
size_t j = (i - 1) / 2;
if (pq_less(&pq->heap[j], &pq->heap[i]))
break;
- SWAP(pq->heap[j], pq->heap[i]);
+ REFTABLE_SWAP(pq->heap[j], pq->heap[i]);
i = j;
}
diff --git a/reftable/record.c b/reftable/record.c
index 3552bafa99..9a1edf39a0 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -237,11 +237,11 @@ static int reftable_ref_record_copy_from(void *rec, const void *src_rec,
size_t refname_cap = 0;
int err;
- SWAP(refname, ref->refname);
- SWAP(refname_cap, ref->refname_cap);
+ REFTABLE_SWAP(refname, ref->refname);
+ REFTABLE_SWAP(refname_cap, ref->refname_cap);
reftable_ref_record_release(ref);
- SWAP(ref->refname, refname);
- SWAP(ref->refname_cap, refname_cap);
+ REFTABLE_SWAP(ref->refname, refname);
+ REFTABLE_SWAP(ref->refname_cap, refname_cap);
if (src->refname) {
size_t refname_len = strlen(src->refname);
@@ -376,11 +376,11 @@ static int reftable_ref_record_decode(void *rec, struct reftable_buf key,
return n;
string_view_consume(&in, n);
- SWAP(refname, r->refname);
- SWAP(refname_cap, r->refname_cap);
+ REFTABLE_SWAP(refname, r->refname);
+ REFTABLE_SWAP(refname_cap, r->refname_cap);
reftable_ref_record_release(r);
- SWAP(r->refname, refname);
- SWAP(r->refname_cap, refname_cap);
+ REFTABLE_SWAP(r->refname, refname);
+ REFTABLE_SWAP(r->refname_cap, refname_cap);
REFTABLE_ALLOC_GROW_OR_NULL(r->refname, key.len + 1, r->refname_cap);
if (!r->refname) {
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 14/18] reftable/basics: stop using `UNUSED` annotation
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (12 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-07 10:03 ` Toon Claes
2025-02-06 7:52 ` [PATCH v4 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
` (3 subsequent siblings)
17 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Stop using the `UNUSED` annotation and replace it with a new
`REFTABLE_UNUSED` macro. The latter is a weaker guarantee compared to
`UNUSED` as it only suppresses unused parameters without generating a
warning in case a parameter marked as unused is in fact used. But it's
good enough, and by relaxing the behaviour a bit we avoid having to wire
up compiler-specific logic.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 2 ++
reftable/blocksource.c | 10 +++++++---
reftable/iter.c | 17 ++++++++++++-----
reftable/record.c | 51 ++++++++++++++++++++++++++++++++++++--------------
reftable/writer.c | 4 +++-
5 files changed, 61 insertions(+), 23 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index 59000798f0..4d0645a4e9 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -16,6 +16,8 @@ license that can be found in the LICENSE file or at
#include "system.h"
#include "reftable-basics.h"
+#define REFTABLE_UNUSED(x) (void)(x)
+
struct reftable_buf {
size_t alloc;
size_t len;
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index 02972c46f4..bfd64b0e48 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -13,15 +13,17 @@ license that can be found in the LICENSE file or at
#include "reftable-blocksource.h"
#include "reftable-error.h"
-static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)
+static void reftable_buf_return_block(void *b, struct reftable_block *dest)
{
+ REFTABLE_UNUSED(b);
if (dest->len)
memset(dest->data, 0xff, dest->len);
reftable_free(dest->data);
}
-static void reftable_buf_close(void *b UNUSED)
+static void reftable_buf_close(void *b)
{
+ REFTABLE_UNUSED(b);
}
static ssize_t reftable_buf_read_block(void *v, struct reftable_block *dest,
@@ -67,8 +69,10 @@ static uint64_t file_size(void *b)
return ((struct file_block_source *)b)->size;
}
-static void file_return_block(void *b UNUSED, struct reftable_block *dest UNUSED)
+static void file_return_block(void *b, struct reftable_block *dest)
{
+ REFTABLE_UNUSED(b);
+ REFTABLE_UNUSED(dest);
}
static void file_close(void *v)
diff --git a/reftable/iter.c b/reftable/iter.c
index b2ffb09c16..452add2705 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -25,18 +25,23 @@ int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
return it->ops->next(it->iter_arg, rec);
}
-static int empty_iterator_seek(void *arg UNUSED, struct reftable_record *want UNUSED)
+static int empty_iterator_seek(void *arg, struct reftable_record *want)
{
+ REFTABLE_UNUSED(arg);
+ REFTABLE_UNUSED(want);
return 0;
}
-static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED)
+static int empty_iterator_next(void *arg, struct reftable_record *rec)
{
+ REFTABLE_UNUSED(arg);
+ REFTABLE_UNUSED(rec);
return 1;
}
-static void empty_iterator_close(void *arg UNUSED)
+static void empty_iterator_close(void *arg)
{
+ REFTABLE_UNUSED(arg);
}
static struct reftable_iterator_vtable empty_vtable = {
@@ -143,9 +148,11 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
return 0;
}
-static int indexed_table_ref_iter_seek(void *p UNUSED,
- struct reftable_record *want UNUSED)
+static int indexed_table_ref_iter_seek(void *p,
+ struct reftable_record *want)
{
+ REFTABLE_UNUSED(p);
+ REFTABLE_UNUSED(want);
return REFTABLE_API_ERROR;
}
diff --git a/reftable/record.c b/reftable/record.c
index 9a1edf39a0..5ee2fe44a7 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -490,11 +490,13 @@ static void reftable_obj_record_release(void *rec)
}
static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_obj_record *obj = rec;
const struct reftable_obj_record *src = src_rec;
+ REFTABLE_UNUSED(hash_size);
+
reftable_obj_record_release(obj);
REFTABLE_ALLOC_ARRAY(obj->hash_prefix, src->hash_prefix_len);
@@ -528,13 +530,16 @@ static uint8_t reftable_obj_record_val_type(const void *rec)
}
static int reftable_obj_record_encode(const void *rec, struct string_view s,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
const struct reftable_obj_record *r = rec;
struct string_view start = s;
int i = 0;
int n = 0;
uint64_t last = 0;
+
+ REFTABLE_UNUSED(hash_size);
+
if (r->offset_len == 0 || r->offset_len >= 8) {
n = put_var_int(&s, r->offset_len);
if (n < 0) {
@@ -563,8 +568,8 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,
static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
uint8_t val_type, struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size,
+ struct reftable_buf *scratch)
{
struct string_view start = in;
struct reftable_obj_record *r = rec;
@@ -572,6 +577,9 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
int n = 0;
uint64_t last;
+ REFTABLE_UNUSED(hash_size);
+ REFTABLE_UNUSED(scratch);
+
reftable_obj_record_release(r);
REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len);
@@ -618,17 +626,20 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
return start.len - in.len;
}
-static int not_a_deletion(const void *p UNUSED)
+static int not_a_deletion(const void *p)
{
+ REFTABLE_UNUSED(p);
return 0;
}
static int reftable_obj_record_equal_void(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_obj_record *ra = (struct reftable_obj_record *) a;
struct reftable_obj_record *rb = (struct reftable_obj_record *) b;
+ REFTABLE_UNUSED(hash_size);
+
if (ra->hash_prefix_len != rb->hash_prefix_len
|| ra->offset_len != rb->offset_len)
return 0;
@@ -1054,12 +1065,14 @@ static int reftable_index_record_key(const void *r, struct reftable_buf *dest)
}
static int reftable_index_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_index_record *dst = rec;
const struct reftable_index_record *src = src_rec;
int err;
+ REFTABLE_UNUSED(hash_size);
+
reftable_buf_reset(&dst->last_key);
err = reftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);
if (err < 0)
@@ -1075,19 +1088,23 @@ static void reftable_index_record_release(void *rec)
reftable_buf_release(&idx->last_key);
}
-static uint8_t reftable_index_record_val_type(const void *rec UNUSED)
+static uint8_t reftable_index_record_val_type(const void *rec)
{
+ REFTABLE_UNUSED(rec);
return 0;
}
static int reftable_index_record_encode(const void *rec, struct string_view out,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
const struct reftable_index_record *r =
(const struct reftable_index_record *)rec;
struct string_view start = out;
+ int n;
- int n = put_var_int(&out, r->offset);
+ REFTABLE_UNUSED(hash_size);
+
+ n = put_var_int(&out, r->offset);
if (n < 0)
return n;
@@ -1097,15 +1114,19 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,
}
static int reftable_index_record_decode(void *rec, struct reftable_buf key,
- uint8_t val_type UNUSED,
+ uint8_t val_type,
struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size,
+ struct reftable_buf *scratch)
{
struct string_view start = in;
struct reftable_index_record *r = rec;
int err, n = 0;
+ REFTABLE_UNUSED(val_type);
+ REFTABLE_UNUSED(hash_size);
+ REFTABLE_UNUSED(scratch);
+
reftable_buf_reset(&r->last_key);
err = reftable_buf_add(&r->last_key, key.buf, key.len);
if (err < 0)
@@ -1120,11 +1141,13 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,
}
static int reftable_index_record_equal(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size)
{
struct reftable_index_record *ia = (struct reftable_index_record *) a;
struct reftable_index_record *ib = (struct reftable_index_record *) b;
+ REFTABLE_UNUSED(hash_size);
+
return ia->offset == ib->offset && !reftable_buf_cmp(&ia->last_key, &ib->last_key);
}
diff --git a/reftable/writer.c b/reftable/writer.c
index 5961698311..0040a1b1c4 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -636,10 +636,12 @@ static void write_object_record(void *void_arg, void *key)
done:;
}
-static void object_record_free(void *void_arg UNUSED, void *key)
+static void object_record_free(void *void_arg, void *key)
{
struct obj_index_tree_node *entry = key;
+ REFTABLE_UNUSED(void_arg);
+
REFTABLE_FREE_AND_NULL(entry->offsets);
reftable_buf_release(&entry->hash);
reftable_free(entry);
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 15/18] compat/mingw: split out POSIX-related bits
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (13 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 14/18] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
` (2 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Split out the POSIX-related bits from "compat/mingw.h". This is in
preparation for splitting up "git-compat-utils.h" into a header that
provides POSIX-compatibility and a header that provides common wrappers
used by the Git project.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/{mingw.c => mingw/compat-util.c} | 28 ++--
compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
compat/msvc.c | 6 -
compat/msvc/compat-util.c | 6 +
compat/msvc/compat-util.h | 7 +
compat/{msvc.h => msvc/posix.h} | 8 +-
config.mak.uname | 6 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 4 +-
meson.build | 8 +-
11 files changed, 266 insertions(+), 245 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw/compat-util.c
similarity index 99%
rename from compat/mingw.c
rename to compat/mingw/compat-util.c
index 1d5b211b54..aeb569bcea 100644
--- a/compat/mingw.c
+++ b/compat/mingw/compat-util.c
@@ -1,24 +1,24 @@
#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS
-#include "../git-compat-util.h"
-#include "win32.h"
+#include "../../git-compat-util.h"
+#include "../win32.h"
#include <aclapi.h>
#include <sddl.h>
#include <conio.h>
#include <wchar.h>
-#include "../strbuf.h"
-#include "../run-command.h"
-#include "../abspath.h"
-#include "../alloc.h"
-#include "win32/lazyload.h"
-#include "../config.h"
-#include "../environment.h"
-#include "../trace2.h"
-#include "../symlinks.h"
-#include "../wrapper.h"
-#include "dir.h"
-#include "gettext.h"
+#include "../../strbuf.h"
+#include "../../run-command.h"
+#include "../../abspath.h"
+#include "../../alloc.h"
+#include "../win32/lazyload.h"
+#include "../../config.h"
+#include "../../environment.h"
+#include "../../trace2.h"
+#include "../../symlinks.h"
+#include "../../wrapper.h"
+#include "../../dir.h"
+#include "../../gettext.h"
#define SECURITY_WIN32
#include <sspi.h>
diff --git a/compat/mingw/compat-util.h b/compat/mingw/compat-util.h
new file mode 100644
index 0000000000..470542d309
--- /dev/null
+++ b/compat/mingw/compat-util.h
@@ -0,0 +1,220 @@
+#ifndef COMPAT_MINGW_COMPAT_UTIL_H
+#define COMPAT_MINGW_COMPAT_UTIL_H
+
+#include "posix.h"
+
+struct config_context;
+int mingw_core_config(const char *var, const char *value,
+ const struct config_context *ctx, void *cb);
+#define platform_core_config mingw_core_config
+
+#ifndef NO_OPENSSL
+#include <openssl/ssl.h>
+static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
+{
+ return SSL_set_fd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_fd mingw_SSL_set_fd
+
+static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
+{
+ return SSL_set_rfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_rfd mingw_SSL_set_rfd
+
+static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
+{
+ return SSL_set_wfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_wfd mingw_SSL_set_wfd
+#endif
+
+/*
+ * git specific compatibility
+ */
+
+static inline void convert_slashes(char *path)
+{
+ for (; *path; path++)
+ if (*path == '\\')
+ *path = '/';
+}
+#define PATH_SEP ';'
+char *mingw_query_user_email(void);
+#define query_user_email mingw_query_user_email
+
+/**
+ * Verifies that the specified path is owned by the user running the
+ * current process.
+ */
+int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
+#define is_path_owned_by_current_user is_path_owned_by_current_sid
+
+/**
+ * Verifies that the given path is a valid one on Windows.
+ *
+ * In particular, path segments are disallowed which
+ *
+ * - end in a period or a space (except the special directories `.` and `..`).
+ *
+ * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
+ *
+ * - correspond to reserved names (such as `AUX`, `PRN`, etc)
+ *
+ * The `allow_literal_nul` parameter controls whether the path `NUL` should
+ * be considered valid (this makes sense e.g. before opening files, as it is
+ * perfectly legitimate to open `NUL` on Windows, just as it is to open
+ * `/dev/null` on Unix/Linux).
+ *
+ * Returns 1 upon success, otherwise 0.
+ */
+int is_valid_win32_path(const char *path, int allow_literal_nul);
+#define is_valid_path(path) is_valid_win32_path(path, 0)
+
+/**
+ * Converts UTF-8 encoded string to UTF-16LE.
+ *
+ * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
+ * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
+ * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
+ * Unicode) are converted to hex-code.
+ *
+ * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
+ * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
+ *
+ * Maximum space requirement for the target buffer is two wide chars per UTF-8
+ * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
+ *
+ * | | UTF-8 | UTF-16 |
+ * Code point | UTF-8 sequence | bytes | words | ratio
+ * --------------+-------------------+-------+--------+-------
+ * 000000-00007f | 0-7f | 1 | 1 | 1
+ * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
+ * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
+ * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
+ * invalid | 80-9f | 1 | 2 (b) | 2
+ * invalid | a0-ff | 1 | 1 | 1
+ *
+ * (a) encoded as UTF-16 surrogate pair
+ * (b) encoded as two hex digits
+ *
+ * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
+ * or even indefinite-byte sequences, the largest valid code point \u10ffff
+ * encodes as only 4 UTF-8 bytes.
+ *
+ * Parameters:
+ * wcs: wide char target buffer
+ * utf: string to convert
+ * wcslen: size of target buffer (in wchar_t's)
+ * utflen: size of string to convert, or -1 if 0-terminated
+ *
+ * Returns:
+ * length of converted string (_wcslen(wcs)), or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
+
+/**
+ * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
+ */
+static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
+{
+ return xutftowcsn(wcs, utf, wcslen, -1);
+}
+
+/**
+ * Simplified file system specific variant of xutftowcsn, assumes output
+ * buffer size is MAX_PATH wide chars and input string is \0-terminated,
+ * fails with ENAMETOOLONG if input string is too long.
+ */
+static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
+{
+ int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
+ if (result < 0 && errno == ERANGE)
+ errno = ENAMETOOLONG;
+ return result;
+}
+
+/**
+ * Converts UTF-16LE encoded string to UTF-8.
+ *
+ * Maximum space requirement for the target buffer is three UTF-8 chars per
+ * wide char ((_wcslen(wcs) * 3) + 1).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
+ * modulo surrogate pairs), as per the following table:
+ *
+ * | | UTF-16 | UTF-8 |
+ * Code point | UTF-16 sequence | words | bytes | ratio
+ * --------------+-----------------------+--------+-------+-------
+ * 000000-00007f | 0000-007f | 1 | 1 | 1
+ * 000080-0007ff | 0080-07ff | 1 | 2 | 2
+ * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
+ * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
+ *
+ * Note that invalid code points > 10ffff cannot be represented in UTF-16.
+ *
+ * Parameters:
+ * utf: target buffer
+ * wcs: wide string to convert
+ * utflen: size of target buffer
+ *
+ * Returns:
+ * length of converted string, or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
+
+/*
+ * A critical section used in the implementation of the spawn
+ * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
+ * the replacement main() macro below.
+ */
+extern CRITICAL_SECTION pinfo_cs;
+
+/*
+ * Git, like most portable C applications, implements a main() function. On
+ * Windows, this main() function would receive parameters encoded in the
+ * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
+ *
+ * To make that happen, we still declare main() here, and then declare and
+ * implement wmain() (which is the Unicode variant of main()) and compile with
+ * -municode. This wmain() function reencodes the parameters from UTF-16 to
+ * UTF-8 format, sets up a couple of other things as required on Windows, and
+ * then hands off to the main() function.
+ */
+int wmain(int argc, const wchar_t **w_argv);
+int main(int argc, const char **argv);
+
+/*
+ * For debugging: if a problem occurs, say, in a Git process that is spawned
+ * from another Git process which in turn is spawned from yet another Git
+ * process, it can be quite daunting to figure out what is going on.
+ *
+ * Call this function to open a new MinTTY (this assumes you are in Git for
+ * Windows' SDK) with a GDB that attaches to the current process right away.
+ */
+void open_in_gdb(void);
+
+/*
+ * Used by Pthread API implementation for Windows
+ */
+int err_win_to_posix(DWORD winerr);
+
+#ifndef NO_UNIX_SOCKETS
+int mingw_have_unix_sockets(void);
+#undef have_unix_sockets
+#define have_unix_sockets mingw_have_unix_sockets
+#endif
+
+#endif /* COMPAT_MINGW_COMPAT_UTIL_H */
diff --git a/compat/mingw.h b/compat/mingw/posix.h
similarity index 59%
rename from compat/mingw.h
rename to compat/mingw/posix.h
index ebfb8ba423..8dddfa818d 100644
--- a/compat/mingw.h
+++ b/compat/mingw/posix.h
@@ -1,3 +1,6 @@
+#ifndef COMPAT_MINGW_POSIX_H
+#define COMPAT_MINGW_POSIX_H
+
#ifdef __MINGW64_VERSION_MAJOR
#include <stdint.h>
#include <wchar.h>
@@ -11,11 +14,6 @@ typedef _sigset_t sigset_t;
#undef _POSIX_THREAD_SAFE_FUNCTIONS
#endif
-struct config_context;
-int mingw_core_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb);
-#define platform_core_config mingw_core_config
-
/*
* things that are not available in header files
*/
@@ -180,27 +178,6 @@ int mingw_kill(pid_t pid, int sig);
#define locate_in_PATH mingw_locate_in_PATH
char *mingw_locate_in_PATH(const char *cmd);
-#ifndef NO_OPENSSL
-#include <openssl/ssl.h>
-static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
-{
- return SSL_set_fd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_fd mingw_SSL_set_fd
-
-static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
-{
- return SSL_set_rfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_rfd mingw_SSL_set_rfd
-
-static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
-{
- return SSL_set_wfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_wfd mingw_SSL_set_wfd
-#endif
-
/*
* implementations of missing functions
*/
@@ -444,19 +421,6 @@ int winansi_dup2(int oldfd, int newfd);
void winansi_init(void);
HANDLE winansi_get_osfhandle(int fd);
-/*
- * git specific compatibility
- */
-
-static inline void convert_slashes(char *path)
-{
- for (; *path; path++)
- if (*path == '\\')
- *path = '/';
-}
-#define PATH_SEP ';'
-char *mingw_query_user_email(void);
-#define query_user_email mingw_query_user_email
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
#define PRIuMAX "I64u"
#define PRId64 "I64d"
@@ -464,176 +428,4 @@ char *mingw_query_user_email(void);
#include <inttypes.h>
#endif
-/**
- * Verifies that the specified path is owned by the user running the
- * current process.
- */
-int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
-#define is_path_owned_by_current_user is_path_owned_by_current_sid
-
-/**
- * Verifies that the given path is a valid one on Windows.
- *
- * In particular, path segments are disallowed which
- *
- * - end in a period or a space (except the special directories `.` and `..`).
- *
- * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
- *
- * - correspond to reserved names (such as `AUX`, `PRN`, etc)
- *
- * The `allow_literal_nul` parameter controls whether the path `NUL` should
- * be considered valid (this makes sense e.g. before opening files, as it is
- * perfectly legitimate to open `NUL` on Windows, just as it is to open
- * `/dev/null` on Unix/Linux).
- *
- * Returns 1 upon success, otherwise 0.
- */
-int is_valid_win32_path(const char *path, int allow_literal_nul);
-#define is_valid_path(path) is_valid_win32_path(path, 0)
-
-/**
- * Converts UTF-8 encoded string to UTF-16LE.
- *
- * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
- * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
- * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
- * Unicode) are converted to hex-code.
- *
- * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
- * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
- *
- * Maximum space requirement for the target buffer is two wide chars per UTF-8
- * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
- *
- * The maximum space is needed only if the entire input string consists of
- * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
- *
- * | | UTF-8 | UTF-16 |
- * Code point | UTF-8 sequence | bytes | words | ratio
- * --------------+-------------------+-------+--------+-------
- * 000000-00007f | 0-7f | 1 | 1 | 1
- * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
- * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
- * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
- * invalid | 80-9f | 1 | 2 (b) | 2
- * invalid | a0-ff | 1 | 1 | 1
- *
- * (a) encoded as UTF-16 surrogate pair
- * (b) encoded as two hex digits
- *
- * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
- * or even indefinite-byte sequences, the largest valid code point \u10ffff
- * encodes as only 4 UTF-8 bytes.
- *
- * Parameters:
- * wcs: wide char target buffer
- * utf: string to convert
- * wcslen: size of target buffer (in wchar_t's)
- * utflen: size of string to convert, or -1 if 0-terminated
- *
- * Returns:
- * length of converted string (_wcslen(wcs)), or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
-
-/**
- * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
- */
-static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
-{
- return xutftowcsn(wcs, utf, wcslen, -1);
-}
-
-/**
- * Simplified file system specific variant of xutftowcsn, assumes output
- * buffer size is MAX_PATH wide chars and input string is \0-terminated,
- * fails with ENAMETOOLONG if input string is too long.
- */
-static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
-{
- int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
- if (result < 0 && errno == ERANGE)
- errno = ENAMETOOLONG;
- return result;
-}
-
-/**
- * Converts UTF-16LE encoded string to UTF-8.
- *
- * Maximum space requirement for the target buffer is three UTF-8 chars per
- * wide char ((_wcslen(wcs) * 3) + 1).
- *
- * The maximum space is needed only if the entire input string consists of
- * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
- * modulo surrogate pairs), as per the following table:
- *
- * | | UTF-16 | UTF-8 |
- * Code point | UTF-16 sequence | words | bytes | ratio
- * --------------+-----------------------+--------+-------+-------
- * 000000-00007f | 0000-007f | 1 | 1 | 1
- * 000080-0007ff | 0080-07ff | 1 | 2 | 2
- * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
- * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
- *
- * Note that invalid code points > 10ffff cannot be represented in UTF-16.
- *
- * Parameters:
- * utf: target buffer
- * wcs: wide string to convert
- * utflen: size of target buffer
- *
- * Returns:
- * length of converted string, or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
-
-/*
- * A critical section used in the implementation of the spawn
- * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
- * the replacement main() macro below.
- */
-extern CRITICAL_SECTION pinfo_cs;
-
-/*
- * Git, like most portable C applications, implements a main() function. On
- * Windows, this main() function would receive parameters encoded in the
- * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
- *
- * To make that happen, we still declare main() here, and then declare and
- * implement wmain() (which is the Unicode variant of main()) and compile with
- * -municode. This wmain() function reencodes the parameters from UTF-16 to
- * UTF-8 format, sets up a couple of other things as required on Windows, and
- * then hands off to the main() function.
- */
-int wmain(int argc, const wchar_t **w_argv);
-int main(int argc, const char **argv);
-
-/*
- * For debugging: if a problem occurs, say, in a Git process that is spawned
- * from another Git process which in turn is spawned from yet another Git
- * process, it can be quite daunting to figure out what is going on.
- *
- * Call this function to open a new MinTTY (this assumes you are in Git for
- * Windows' SDK) with a GDB that attaches to the current process right away.
- */
-void open_in_gdb(void);
-
-/*
- * Used by Pthread API implementation for Windows
- */
-int err_win_to_posix(DWORD winerr);
-
-#ifndef NO_UNIX_SOCKETS
-int mingw_have_unix_sockets(void);
-#undef have_unix_sockets
-#define have_unix_sockets mingw_have_unix_sockets
-#endif
+#endif /* COMPAT_MINGW_POSIX_H */
diff --git a/compat/msvc.c b/compat/msvc.c
deleted file mode 100644
index 71843d7eef..0000000000
--- a/compat/msvc.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "../git-compat-util.h"
-#include "win32.h"
-#include <conio.h>
-#include "../strbuf.h"
-
-#include "mingw.c"
diff --git a/compat/msvc/compat-util.c b/compat/msvc/compat-util.c
new file mode 100644
index 0000000000..b92e52b8b8
--- /dev/null
+++ b/compat/msvc/compat-util.c
@@ -0,0 +1,6 @@
+#include "../../git-compat-util.h"
+#include "../win32.h"
+#include <conio.h>
+#include "../../strbuf.h"
+
+#include "../mingw/compat-util.c"
diff --git a/compat/msvc/compat-util.h b/compat/msvc/compat-util.h
new file mode 100644
index 0000000000..404af236b5
--- /dev/null
+++ b/compat/msvc/compat-util.h
@@ -0,0 +1,7 @@
+#ifndef COMPAT_MSVC_COMPAT_UTIL_H
+#define COMPAT_MSVC_COMPAT_UTIL_H
+
+#include "posix.h"
+#include "../mingw/compat-util.h"
+
+#endif /* COMPAT_MSVC_COMPAT_UTIL_H */
diff --git a/compat/msvc.h b/compat/msvc/posix.h
similarity index 86%
rename from compat/msvc.h
rename to compat/msvc/posix.h
index 1d7a8c6145..703a7c2067 100644
--- a/compat/msvc.h
+++ b/compat/msvc/posix.h
@@ -1,5 +1,5 @@
-#ifndef __MSVC__HEAD
-#define __MSVC__HEAD
+#ifndef COMPAT_MSVC_POSIX_H
+#define COMPAT_MSVC_POSIX_H
#include <direct.h>
#include <process.h>
@@ -28,6 +28,6 @@ typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-#include "compat/mingw.h"
+#include "../mingw/posix.h"
-#endif
+#endif /* COMPAT_MSVC_POSIX_H */
diff --git a/config.mak.uname b/config.mak.uname
index b12d4e168a..dbd05adb5d 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -495,7 +495,7 @@ endif
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
- COMPAT_OBJS = compat/msvc.o compat/winansi.o \
+ COMPAT_OBJS = compat/msvc/compat-util.o compat/winansi.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
compat/win32/pthread.o compat/win32/syslog.o \
@@ -541,7 +541,7 @@ endif
EXTRA_PROGRAMS += headless-git$X
-compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
+compat/msvc/compat-util.o: compat/msvc/compat-util.c compat/mingw/compat-util.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease
@@ -694,7 +694,7 @@ ifeq ($(uname_S),MINGW)
BASIC_LDFLAGS += -municode
COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/winansi.o \
+ COMPAT_OBJS += compat/mingw/compat-util.o compat/winansi.o \
compat/win32/trace2_win32_process_info.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 10dc54fdcb..65ce8705f0 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -258,7 +258,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET HAVE_RTLGENRANDOM)
list(APPEND compat_SOURCES
- compat/mingw.c
+ compat/mingw/compat-util.c
compat/winansi.c
compat/win32/flush.c
compat/win32/path-utils.c
diff --git a/git-compat-util.h b/git-compat-util.h
index e283c46c6f..b96fb98e1e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -304,10 +304,10 @@ static inline int is_xplatform_dir_sep(int c)
#if defined(__MINGW32__)
/* pull in Windows compatibility stuff */
#include "compat/win32/path-utils.h"
-#include "compat/mingw.h"
+#include "compat/mingw/compat-util.h"
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
-#include "compat/msvc.h"
+#include "compat/msvc/compat-util.h"
#else
#include <sys/utsname.h>
#include <sys/wait.h>
diff --git a/meson.build b/meson.build
index 2297f5e9dd..e8abf798f5 100644
--- a/meson.build
+++ b/meson.build
@@ -1054,7 +1054,6 @@ if host_machine.system() == 'cygwin'
]
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw.c',
'compat/winansi.c',
'compat/win32/flush.c',
'compat/win32/path-utils.c',
@@ -1081,6 +1080,9 @@ elif host_machine.system() == 'windows'
libgit_include_directories += 'compat/win32'
if compiler.get_id() == 'msvc'
libgit_include_directories += 'compat/vcbuild/include'
+ libgit_sources += 'compat/msvc/compat-util.c'
+ else
+ libgit_sources += 'compat/mingw/compat-util.c'
endif
endif
@@ -1157,7 +1159,7 @@ else
error('Native regex support requested but not found')
endif
-# setitimer and friends are provided by compat/mingw.c.
+# setitimer and friends are provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows'
if not compiler.compiles('''
#include <sys/time.h>
@@ -1237,7 +1239,7 @@ if not compiler.has_function('qsort')
endif
libgit_sources += 'compat/qsort_s.c'
-# unsetenv is provided by compat/mingw.c.
+# unsetenv is provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows' and not compiler.has_function('unsetenv')
libgit_c_args += '-DNO_UNSETENV'
libgit_sources += 'compat/unsetenv.c'
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 16/18] git-compat-util.h: split out POSIX-emulating bits
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (14 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
The "git-compat-util.h" header is a treasure trove of various bits and
pieces used throughout the project. It basically mixes two different
things into one:
- Providing a POSIX-like interface even on platforms that aren't
POSIX-compliant.
- Providing low-level functionality that is specific to Git.
This intermixing is a bit of a problem for the reftable library as we
don't want to recreate the POSIX-like interface there. But neither do we
want to pull in the Git-specific functionality, as it is otherwise quite
easy to start depending on the Git codebase again.
Split out a new header "compat/posix.h" that only contains the bits and
pieces relevant for the emulation of POSIX, which we will start using in
the next commit.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/posix.h | 541 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
git-compat-util.h | 531 +----------------------------------------------------
2 files changed, 543 insertions(+), 529 deletions(-)
diff --git a/compat/posix.h b/compat/posix.h
new file mode 100644
index 0000000000..7e6c4c1a1f
--- /dev/null
+++ b/compat/posix.h
@@ -0,0 +1,541 @@
+#ifndef COMPAT_POSIX_H
+#define COMPAT_POSIX_H
+
+#define _FILE_OFFSET_BITS 64
+
+/*
+ * Derived from Linux "Features Test Macro" header
+ * Convenience macros to test the versions of gcc (or
+ * a compatible compiler).
+ * Use them like this:
+ * #if GIT_GNUC_PREREQ (2,8)
+ * ... code requiring gcc 2.8 or later ...
+ * #endif
+ *
+ * This macro of course is not part of POSIX, but we need it for the UNUSED
+ * macro which is used by some of our POSIX compatibility wrappers.
+*/
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define GIT_GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+ #define GIT_GNUC_PREREQ(maj, min) 0
+#endif
+
+/*
+ * UNUSED marks a function parameter that is always unused. It also
+ * can be used to annotate a function, a variable, or a type that is
+ * always unused.
+ *
+ * A callback interface may dictate that a function accepts a
+ * parameter at that position, but the implementation of the function
+ * may not need to use the parameter. In such a case, mark the parameter
+ * with UNUSED.
+ *
+ * When a parameter may be used or unused, depending on conditional
+ * compilation, consider using MAYBE_UNUSED instead.
+ */
+#if GIT_GNUC_PREREQ(4, 5)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated ("parameter declared as UNUSED")))
+#elif defined(__GNUC__)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated))
+#else
+#define UNUSED
+#endif
+
+#ifdef __MINGW64__
+#define _POSIX_C_SOURCE 1
+#elif defined(__sun__)
+ /*
+ * On Solaris, when _XOPEN_EXTENDED is set, its header file
+ * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
+ * setting to say we are XPG5 or XPG6. Also on Solaris,
+ * XPG6 programs must be compiled with a c99 compiler, while
+ * non XPG6 programs must be compiled with a pre-c99 compiler.
+ */
+# if __STDC_VERSION__ - 0 >= 199901L
+# define _XOPEN_SOURCE 600
+# else
+# define _XOPEN_SOURCE 500
+# endif
+#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
+ !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
+ !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
+ !defined(__CYGWIN__)
+#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
+#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
+#endif
+#define _ALL_SOURCE 1
+#define _GNU_SOURCE 1
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+#define _NETBSD_SOURCE 1
+#define _SGI_SOURCE 1
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
+# if !defined(_WIN32_WINNT)
+# define _WIN32_WINNT 0x0600
+# endif
+#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
+#include <winsock2.h>
+#ifndef NO_UNIX_SOCKETS
+#include <afunix.h>
+#endif
+#include <windows.h>
+#define GIT_WINDOWS_NATIVE
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h> /* for strcasecmp() */
+#endif
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#ifdef NEEDS_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#include <syslog.h>
+#if !defined(NO_POLL_H)
+#include <poll.h>
+#elif !defined(NO_SYS_POLL_H)
+#include <sys/poll.h>
+#else
+/* Pull the compat stuff */
+#include <poll.h>
+#endif
+#ifdef HAVE_BSD_SYSCTL
+#include <sys/sysctl.h>
+#endif
+
+#if defined(__MINGW32__)
+#include "mingw/posix.h"
+#elif defined(_MSC_VER)
+#include "msvc/posix.h"
+#else
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/statvfs.h>
+#include <termios.h>
+#ifndef NO_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/un.h>
+#ifndef NO_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+#ifdef HAVE_ARC4RANDOM_LIBBSD
+#include <bsd/stdlib.h>
+#endif
+#ifdef HAVE_GETRANDOM
+#include <sys/random.h>
+#endif
+#ifdef NO_INTPTR_T
+/*
+ * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
+ * on LLP86, IL33LLP64 and P64 it needs to be "long long",
+ * while on IP16 and IP16L32 it is "int" (resp. "short")
+ * Size needs to match (or exceed) 'sizeof(void *)'.
+ * We can't take "long long" here as not everybody has it.
+ */
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+#endif
+#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
+#include <grp.h>
+#define _ALL_SOURCE 1
+#endif
+
+#ifdef MKDIR_WO_TRAILING_SLASH
+#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
+int compat_mkdir_wo_trailing_slash(const char*, mode_t);
+#endif
+
+#ifdef time
+#undef time
+#endif
+static inline time_t git_time(time_t *tloc)
+{
+ struct timeval tv;
+
+ /*
+ * Avoid time(NULL), which can disagree with gettimeofday(2)
+ * and filesystem timestamps.
+ */
+ gettimeofday(&tv, NULL);
+
+ if (tloc)
+ *tloc = tv.tv_sec;
+ return tv.tv_sec;
+}
+#define time git_time
+
+#ifdef NO_STRUCT_ITIMERVAL
+struct itimerval {
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+#endif
+
+#ifdef NO_SETITIMER
+static inline int git_setitimer(int which UNUSED,
+ const struct itimerval *value UNUSED,
+ struct itimerval *newvalue UNUSED) {
+ return 0; /* pretend success */
+}
+#undef setitimer
+#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
+#endif
+
+#ifndef NO_LIBGEN_H
+#include <libgen.h>
+#else
+#define basename gitbasename
+char *gitbasename(char *);
+#define dirname gitdirname
+char *gitdirname(char *);
+#endif
+
+#ifndef NO_ICONV
+#include <iconv.h>
+#endif
+
+/* On most systems <netdb.h> would have given us this, but
+ * not on some systems (e.g. z/OS).
+ */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+/* On most systems <limits.h> would have given us this, but
+ * not on some systems (e.g. GNU/Hurd).
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+typedef uintmax_t timestamp_t;
+#define PRItime PRIuMAX
+#define parse_timestamp strtoumax
+#define TIME_MAX UINTMAX_MAX
+#define TIME_MIN 0
+
+int lstat_cache_aware_rmdir(const char *path);
+#if !defined(__MINGW32__) && !defined(_MSC_VER)
+#define rmdir lstat_cache_aware_rmdir
+#endif
+
+#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
+
+#ifndef PROT_READ
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define MAP_PRIVATE 1
+#endif
+
+#define mmap git_mmap
+#define munmap git_munmap
+void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int git_munmap(void *start, size_t length);
+
+#else /* NO_MMAP || USE_WIN32_MMAP */
+
+#include <sys/mman.h>
+
+#endif /* NO_MMAP || USE_WIN32_MMAP */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#ifdef NEEDS_MODE_TRANSLATION
+#undef S_IFMT
+#undef S_IFREG
+#undef S_IFDIR
+#undef S_IFLNK
+#undef S_IFBLK
+#undef S_IFCHR
+#undef S_IFIFO
+#undef S_IFSOCK
+#define S_IFMT 0170000
+#define S_IFREG 0100000
+#define S_IFDIR 0040000
+#define S_IFLNK 0120000
+#define S_IFBLK 0060000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_IFSOCK 0140000
+#ifdef stat
+#undef stat
+#endif
+#define stat(path, buf) git_stat(path, buf)
+int git_stat(const char *, struct stat *);
+#ifdef fstat
+#undef fstat
+#endif
+#define fstat(fd, buf) git_fstat(fd, buf)
+int git_fstat(int, struct stat *);
+#ifdef lstat
+#undef lstat
+#endif
+#define lstat(path, buf) git_lstat(path, buf)
+int git_lstat(const char *, struct stat *);
+#endif
+
+#ifdef NO_PREAD
+#define pread git_pread
+ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+
+#ifdef NO_SETENV
+#define setenv gitsetenv
+int gitsetenv(const char *, const char *, int);
+#endif
+
+#ifdef NO_MKDTEMP
+#define mkdtemp gitmkdtemp
+char *gitmkdtemp(char *);
+#endif
+
+#ifdef NO_UNSETENV
+#define unsetenv gitunsetenv
+int gitunsetenv(const char *);
+#endif
+
+#ifdef NO_STRCASESTR
+#define strcasestr gitstrcasestr
+char *gitstrcasestr(const char *haystack, const char *needle);
+#endif
+
+#ifdef NO_STRLCPY
+#define strlcpy gitstrlcpy
+size_t gitstrlcpy(char *, const char *, size_t);
+#endif
+
+#ifdef NO_STRTOUMAX
+#define strtoumax gitstrtoumax
+uintmax_t gitstrtoumax(const char *, char **, int);
+#define strtoimax gitstrtoimax
+intmax_t gitstrtoimax(const char *, char **, int);
+#endif
+
+#ifdef NO_HSTRERROR
+#define hstrerror githstrerror
+const char *githstrerror(int herror);
+#endif
+
+#ifdef NO_MEMMEM
+#define memmem gitmemmem
+void *gitmemmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+#endif
+
+#ifdef OVERRIDE_STRDUP
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup gitstrdup
+char *gitstrdup(const char *s);
+#endif
+
+#ifdef NO_GETPAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifdef FREAD_READS_DIRECTORIES
+# if !defined(SUPPRESS_FOPEN_REDEFINITION)
+# ifdef fopen
+# undef fopen
+# endif
+# define fopen(a,b) git_fopen(a,b)
+# endif
+FILE *git_fopen(const char*, const char*);
+#endif
+
+#ifdef SNPRINTF_RETURNS_BOGUS
+#ifdef snprintf
+#undef snprintf
+#endif
+#define snprintf git_snprintf
+int git_snprintf(char *str, size_t maxsize,
+ const char *format, ...);
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#define vsnprintf git_vsnprintf
+int git_vsnprintf(char *str, size_t maxsize,
+ const char *format, va_list ap);
+#endif
+
+#ifdef OPEN_RETURNS_EINTR
+#undef open
+#define open git_open_with_retry
+int git_open_with_retry(const char *path, int flag, ...);
+#endif
+
+#ifdef __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2, 1)
+#define HAVE_STRCHRNUL
+#endif
+#endif
+
+#ifndef HAVE_STRCHRNUL
+#define strchrnul gitstrchrnul
+static inline char *gitstrchrnul(const char *s, int c)
+{
+ while (*s && *s != c)
+ s++;
+ return (char *)s;
+}
+#endif
+
+#ifdef NO_INET_PTON
+int inet_pton(int af, const char *src, void *dst);
+#endif
+
+#ifdef NO_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
+#ifdef NO_PTHREADS
+#define atexit git_atexit
+int git_atexit(void (*handler)(void));
+#endif
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
+#include "../sane-ctype.h"
+
+void git_stable_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
+#ifdef INTERNAL_QSORT
+#define qsort git_stable_qsort
+#endif
+
+#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
+static inline void sane_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *))
+{
+ if (nmemb > 1)
+ qsort(base, nmemb, size, compar);
+}
+
+#define STABLE_QSORT(base, n, compar) \
+ git_stable_qsort((base), (n), sizeof(*(base)), compar)
+
+#ifndef HAVE_ISO_QSORT_S
+int git_qsort_s(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *), void *ctx);
+#define qsort_s git_qsort_s
+#endif
+
+#define QSORT_S(base, n, compar, ctx) do { \
+ if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
+ BUG("qsort_s() failed"); \
+} while (0)
+
+#ifdef NO_NSEC
+#undef USE_NSEC
+#define ST_CTIME_NSEC(st) 0
+#define ST_MTIME_NSEC(st) 0
+#else
+#ifdef USE_ST_TIMESPEC
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
+#else
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
+#endif
+#endif
+
+#ifndef va_copy
+/*
+ * Since an obvious implementation of va_list would be to make it a
+ * pointer into the stack frame, a simple assignment will work on
+ * many systems. But let's try to be more portable.
+ */
+#ifdef __va_copy
+#define va_copy(dst, src) __va_copy(dst, src)
+#else
+#define va_copy(dst, src) ((dst) = (src))
+#endif
+#endif
+
+#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+static inline void git_flockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+static inline void git_funlockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+#undef flockfile
+#undef funlockfile
+#undef getc_unlocked
+#define flockfile(fh) git_flockfile(fh)
+#define funlockfile(fh) git_funlockfile(fh)
+#define getc_unlocked(fh) getc(fh)
+#endif
+
+#ifdef FILENO_IS_A_MACRO
+int git_fileno(FILE *stream);
+# ifndef COMPAT_CODE_FILENO
+# undef fileno
+# define fileno(p) git_fileno(p)
+# endif
+#endif
+
+#ifdef NEED_ACCESS_ROOT_HANDLER
+int git_access(const char *path, int mode);
+# ifndef COMPAT_CODE_ACCESS
+# ifdef access
+# undef access
+# endif
+# define access(path, mode) git_access(path, mode)
+# endif
+#endif
+
+#endif /* COMPAT_POSIX_H */
diff --git a/git-compat-util.h b/git-compat-util.h
index b96fb98e1e..30ad0725fb 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -23,26 +23,9 @@
#include <crtdbg.h>
#endif
-struct strbuf;
-
-
-#define _FILE_OFFSET_BITS 64
+#include "compat/posix.h"
-
-/* Derived from Linux "Features Test Macro" header
- * Convenience macros to test the versions of gcc (or
- * a compatible compiler).
- * Use them like this:
- * #if GIT_GNUC_PREREQ (2,8)
- * ... code requiring gcc 2.8 or later ...
- * #endif
-*/
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define GIT_GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-#else
- #define GIT_GNUC_PREREQ(maj, min) 0
-#endif
+struct strbuf;
#if defined(__GNUC__) || defined(__clang__)
# define PRAGMA(pragma) _Pragma(#pragma)
@@ -176,71 +159,6 @@ DISABLE_WARNING(-Wsign-compare)
/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-#ifdef __MINGW64__
-#define _POSIX_C_SOURCE 1
-#elif defined(__sun__)
- /*
- * On Solaris, when _XOPEN_EXTENDED is set, its header file
- * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
- * setting to say we are XPG5 or XPG6. Also on Solaris,
- * XPG6 programs must be compiled with a c99 compiler, while
- * non XPG6 programs must be compiled with a pre-c99 compiler.
- */
-# if __STDC_VERSION__ - 0 >= 199901L
-# define _XOPEN_SOURCE 600
-# else
-# define _XOPEN_SOURCE 500
-# endif
-#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
- !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
- !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
- !defined(__CYGWIN__)
-#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
-#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
-#endif
-#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
-#define _BSD_SOURCE 1
-#define _DEFAULT_SOURCE 1
-#define _NETBSD_SOURCE 1
-#define _SGI_SOURCE 1
-
-/*
- * UNUSED marks a function parameter that is always unused. It also
- * can be used to annotate a function, a variable, or a type that is
- * always unused.
- *
- * A callback interface may dictate that a function accepts a
- * parameter at that position, but the implementation of the function
- * may not need to use the parameter. In such a case, mark the parameter
- * with UNUSED.
- *
- * When a parameter may be used or unused, depending on conditional
- * compilation, consider using MAYBE_UNUSED instead.
- */
-#if GIT_GNUC_PREREQ(4, 5)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated ("parameter declared as UNUSED")))
-#elif defined(__GNUC__)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated))
-#else
-#define UNUSED
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
-# if !defined(_WIN32_WINNT)
-# define _WIN32_WINNT 0x0600
-# endif
-#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
-#include <winsock2.h>
-#ifndef NO_UNIX_SOCKETS
-#include <afunix.h>
-#endif
-#include <windows.h>
-#define GIT_WINDOWS_NATIVE
-#endif
-
#if defined(NO_UNIX_SOCKETS) || !defined(GIT_WINDOWS_NATIVE)
static inline int _have_unix_sockets(void)
{
@@ -253,45 +171,6 @@ static inline int _have_unix_sockets(void)
#define have_unix_sockets _have_unix_sockets
#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h> /* for strcasecmp() */
-#endif
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#ifdef NEEDS_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <time.h>
-#include <signal.h>
-#include <assert.h>
-#include <regex.h>
-#include <utime.h>
-#include <syslog.h>
-#if !defined(NO_POLL_H)
-#include <poll.h>
-#elif !defined(NO_SYS_POLL_H)
-#include <sys/poll.h>
-#else
-/* Pull the compat stuff */
-#include <poll.h>
-#endif
-#ifdef HAVE_BSD_SYSCTL
-#include <sys/sysctl.h>
-#endif
-
/* Used by compat/win32/path-utils.h, and more */
static inline int is_xplatform_dir_sep(int c)
{
@@ -308,48 +187,6 @@ static inline int is_xplatform_dir_sep(int c)
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
#include "compat/msvc/compat-util.h"
-#else
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/statvfs.h>
-#include <termios.h>
-#ifndef NO_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <sys/un.h>
-#ifndef NO_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <stdint.h>
-#endif
-#ifdef HAVE_ARC4RANDOM_LIBBSD
-#include <bsd/stdlib.h>
-#endif
-#ifdef HAVE_GETRANDOM
-#include <sys/random.h>
-#endif
-#ifdef NO_INTPTR_T
-/*
- * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
- * on LLP86, IL33LLP64 and P64 it needs to be "long long",
- * while on IP16 and IP16L32 it is "int" (resp. "short")
- * Size needs to match (or exceed) 'sizeof(void *)'.
- * We can't take "long long" here as not everybody has it.
- */
-typedef long intptr_t;
-typedef unsigned long uintptr_t;
-#endif
-#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
-#include <grp.h>
-#define _ALL_SOURCE 1
#endif
/* used on Mac OS X */
@@ -370,60 +207,6 @@ static inline const char *precompose_string_if_needed(const char *in)
#define probe_utf8_pathname_composition()
#endif
-#ifdef MKDIR_WO_TRAILING_SLASH
-#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
-int compat_mkdir_wo_trailing_slash(const char*, mode_t);
-#endif
-
-#ifdef time
-#undef time
-#endif
-static inline time_t git_time(time_t *tloc)
-{
- struct timeval tv;
-
- /*
- * Avoid time(NULL), which can disagree with gettimeofday(2)
- * and filesystem timestamps.
- */
- gettimeofday(&tv, NULL);
-
- if (tloc)
- *tloc = tv.tv_sec;
- return tv.tv_sec;
-}
-#define time git_time
-
-#ifdef NO_STRUCT_ITIMERVAL
-struct itimerval {
- struct timeval it_interval;
- struct timeval it_value;
-};
-#endif
-
-#ifdef NO_SETITIMER
-static inline int git_setitimer(int which UNUSED,
- const struct itimerval *value UNUSED,
- struct itimerval *newvalue UNUSED) {
- return 0; /* pretend success */
-}
-#undef setitimer
-#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
-#endif
-
-#ifndef NO_LIBGEN_H
-#include <libgen.h>
-#else
-#define basename gitbasename
-char *gitbasename(char *);
-#define dirname gitdirname
-char *gitdirname(char *);
-#endif
-
-#ifndef NO_ICONV
-#include <iconv.h>
-#endif
-
#ifndef NO_OPENSSL
#ifdef __APPLE__
#undef __AVAILABILITY_MACROS_USES_AVAILABILITY
@@ -441,34 +224,6 @@ char *gitdirname(char *);
# include <sys/sysinfo.h>
#endif
-/* On most systems <netdb.h> would have given us this, but
- * not on some systems (e.g. z/OS).
- */
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
-
-/* On most systems <limits.h> would have given us this, but
- * not on some systems (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-typedef uintmax_t timestamp_t;
-#define PRItime PRIuMAX
-#define parse_timestamp strtoumax
-#define TIME_MAX UINTMAX_MAX
-#define TIME_MIN 0
-
#ifndef PATH_SEP
#define PATH_SEP ':'
#endif
@@ -492,11 +247,6 @@ static inline int noop_core_config(const char *var UNUSED,
#define platform_core_config noop_core_config
#endif
-int lstat_cache_aware_rmdir(const char *path);
-#if !defined(__MINGW32__) && !defined(_MSC_VER)
-#define rmdir lstat_cache_aware_rmdir
-#endif
-
#ifndef has_dos_drive_prefix
static inline int git_has_dos_drive_prefix(const char *path UNUSED)
{
@@ -822,25 +572,6 @@ static inline bool strip_suffix(const char *str, const char *suffix,
memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
} while (0)
-#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-
-#ifndef PROT_READ
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define MAP_PRIVATE 1
-#endif
-
-#define mmap git_mmap
-#define munmap git_munmap
-void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-int git_munmap(void *start, size_t length);
-
-#else /* NO_MMAP || USE_WIN32_MMAP */
-
-#include <sys/mman.h>
-
-#endif /* NO_MMAP || USE_WIN32_MMAP */
-
#ifdef NO_MMAP
/* This value must be multiple of (pagesize * 2) */
@@ -856,177 +587,15 @@ int git_munmap(void *start, size_t length);
#endif /* NO_MMAP */
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
#define on_disk_bytes(st) ((st).st_size)
#else
#define on_disk_bytes(st) ((st).st_blocks * 512)
#endif
-#ifdef NEEDS_MODE_TRANSLATION
-#undef S_IFMT
-#undef S_IFREG
-#undef S_IFDIR
-#undef S_IFLNK
-#undef S_IFBLK
-#undef S_IFCHR
-#undef S_IFIFO
-#undef S_IFSOCK
-#define S_IFMT 0170000
-#define S_IFREG 0100000
-#define S_IFDIR 0040000
-#define S_IFLNK 0120000
-#define S_IFBLK 0060000
-#define S_IFCHR 0020000
-#define S_IFIFO 0010000
-#define S_IFSOCK 0140000
-#ifdef stat
-#undef stat
-#endif
-#define stat(path, buf) git_stat(path, buf)
-int git_stat(const char *, struct stat *);
-#ifdef fstat
-#undef fstat
-#endif
-#define fstat(fd, buf) git_fstat(fd, buf)
-int git_fstat(int, struct stat *);
-#ifdef lstat
-#undef lstat
-#endif
-#define lstat(path, buf) git_lstat(path, buf)
-int git_lstat(const char *, struct stat *);
-#endif
-
#define DEFAULT_PACKED_GIT_LIMIT \
((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))
-#ifdef NO_PREAD
-#define pread git_pread
-ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
-#endif
-
-#ifdef NO_SETENV
-#define setenv gitsetenv
-int gitsetenv(const char *, const char *, int);
-#endif
-
-#ifdef NO_MKDTEMP
-#define mkdtemp gitmkdtemp
-char *gitmkdtemp(char *);
-#endif
-
-#ifdef NO_UNSETENV
-#define unsetenv gitunsetenv
-int gitunsetenv(const char *);
-#endif
-
-#ifdef NO_STRCASESTR
-#define strcasestr gitstrcasestr
-char *gitstrcasestr(const char *haystack, const char *needle);
-#endif
-
-#ifdef NO_STRLCPY
-#define strlcpy gitstrlcpy
-size_t gitstrlcpy(char *, const char *, size_t);
-#endif
-
-#ifdef NO_STRTOUMAX
-#define strtoumax gitstrtoumax
-uintmax_t gitstrtoumax(const char *, char **, int);
-#define strtoimax gitstrtoimax
-intmax_t gitstrtoimax(const char *, char **, int);
-#endif
-
-#ifdef NO_HSTRERROR
-#define hstrerror githstrerror
-const char *githstrerror(int herror);
-#endif
-
-#ifdef NO_MEMMEM
-#define memmem gitmemmem
-void *gitmemmem(const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen);
-#endif
-
-#ifdef OVERRIDE_STRDUP
-#ifdef strdup
-#undef strdup
-#endif
-#define strdup gitstrdup
-char *gitstrdup(const char *s);
-#endif
-
-#ifdef NO_GETPAGESIZE
-#define getpagesize() sysconf(_SC_PAGESIZE)
-#endif
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
-#endif
-
-#ifdef FREAD_READS_DIRECTORIES
-# if !defined(SUPPRESS_FOPEN_REDEFINITION)
-# ifdef fopen
-# undef fopen
-# endif
-# define fopen(a,b) git_fopen(a,b)
-# endif
-FILE *git_fopen(const char*, const char*);
-#endif
-
-#ifdef SNPRINTF_RETURNS_BOGUS
-#ifdef snprintf
-#undef snprintf
-#endif
-#define snprintf git_snprintf
-int git_snprintf(char *str, size_t maxsize,
- const char *format, ...);
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#define vsnprintf git_vsnprintf
-int git_vsnprintf(char *str, size_t maxsize,
- const char *format, va_list ap);
-#endif
-
-#ifdef OPEN_RETURNS_EINTR
-#undef open
-#define open git_open_with_retry
-int git_open_with_retry(const char *path, int flag, ...);
-#endif
-
-#ifdef __GLIBC_PREREQ
-#if __GLIBC_PREREQ(2, 1)
-#define HAVE_STRCHRNUL
-#endif
-#endif
-
-#ifndef HAVE_STRCHRNUL
-#define strchrnul gitstrchrnul
-static inline char *gitstrchrnul(const char *s, int c)
-{
- while (*s && *s != c)
- s++;
- return (char *)s;
-}
-#endif
-
-#ifdef NO_INET_PTON
-int inet_pton(int af, const char *src, void *dst);
-#endif
-
-#ifdef NO_INET_NTOP
-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-#endif
-
-#ifdef NO_PTHREADS
-#define atexit git_atexit
-int git_atexit(void (*handler)(void));
-#endif
-
static inline size_t st_add(size_t a, size_t b)
{
if (unsigned_add_overflows(a, b))
@@ -1293,12 +862,6 @@ static inline size_t xsize_t(off_t len)
return (size_t) len;
}
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
-#endif
-
-#include "sane-ctype.h"
-
/*
* Like skip_prefix, but compare case-insensitively. Note that the comparison
* is done via tolower(), so it is strictly ASCII (no multi-byte characters or
@@ -1364,34 +927,6 @@ static inline int strtol_i(char const *s, int base, int *result)
return 0;
}
-void git_stable_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *));
-#ifdef INTERNAL_QSORT
-#define qsort git_stable_qsort
-#endif
-
-#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
-static inline void sane_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *))
-{
- if (nmemb > 1)
- qsort(base, nmemb, size, compar);
-}
-
-#define STABLE_QSORT(base, n, compar) \
- git_stable_qsort((base), (n), sizeof(*(base)), compar)
-
-#ifndef HAVE_ISO_QSORT_S
-int git_qsort_s(void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *, void *), void *ctx);
-#define qsort_s git_qsort_s
-#endif
-
-#define QSORT_S(base, n, compar, ctx) do { \
- if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
- BUG("qsort_s() failed"); \
-} while (0)
-
#ifndef REG_STARTEND
#error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd"
#endif
@@ -1416,39 +951,12 @@ int git_regcomp(regex_t *preg, const char *pattern, int cflags);
# define FORCE_DIR_SET_GID 0
#endif
-#ifdef NO_NSEC
-#undef USE_NSEC
-#define ST_CTIME_NSEC(st) 0
-#define ST_MTIME_NSEC(st) 0
-#else
-#ifdef USE_ST_TIMESPEC
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
-#else
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
-#endif
-#endif
-
#ifdef UNRELIABLE_FSTAT
#define fstat_is_reliable() 0
#else
#define fstat_is_reliable() 1
#endif
-#ifndef va_copy
-/*
- * Since an obvious implementation of va_list would be to make it a
- * pointer into the stack frame, a simple assignment will work on
- * many systems. But let's try to be more portable.
- */
-#ifdef __va_copy
-#define va_copy(dst, src) __va_copy(dst, src)
-#else
-#define va_copy(dst, src) ((dst) = (src))
-#endif
-#endif
-
/* usage.c: only to be used for testing BUG() implementation (see test-tool) */
extern int BUG_exit_code;
@@ -1478,41 +986,6 @@ void bug_fl(const char *file, int line, const char *fmt, ...);
# define SHELL_PATH "/bin/sh"
#endif
-#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
-static inline void git_flockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-static inline void git_funlockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-#undef flockfile
-#undef funlockfile
-#undef getc_unlocked
-#define flockfile(fh) git_flockfile(fh)
-#define funlockfile(fh) git_funlockfile(fh)
-#define getc_unlocked(fh) getc(fh)
-#endif
-
-#ifdef FILENO_IS_A_MACRO
-int git_fileno(FILE *stream);
-# ifndef COMPAT_CODE_FILENO
-# undef fileno
-# define fileno(p) git_fileno(p)
-# endif
-#endif
-
-#ifdef NEED_ACCESS_ROOT_HANDLER
-int git_access(const char *path, int mode);
-# ifndef COMPAT_CODE_ACCESS
-# ifdef access
-# undef access
-# endif
-# define access(path, mode) git_access(path, mode)
-# endif
-#endif
-
/*
* Our code often opens a path to an optional file, to work on its
* contents when we can successfully open it. We can ignore a failure
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h"
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (15 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
The reftable library includes "git-compat-util.h" in order to get a
POSIX-like programming environment that papers over various differences
between platforms. The header also brings with it a couple of helpers
specific to the Git codebase though, and over time we have started to
use these helpers in the reftable library, as well.
This makes it very hard to use the reftable library as a standalone
library without the rest of the Git codebase, so other libraries like
e.g. libgit2 cannot easily use it. But now that we have removed all
calls to Git-specific functionality and have split out "compat/posix.h"
as a separate header we can address this.
Stop including "git-compat-util.h" and instead include "compat/posix.h"
to finalize the decoupling of the reftable library from the rest of the
Git codebase. The only bits which remain specific to Git are "system.h"
and "system.c", which projects will have to provide.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/system.c | 2 ++
reftable/system.h | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/reftable/system.c b/reftable/system.c
index e25ccc0da3..1ee268b125 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -1,3 +1,5 @@
+#include "../git-compat-util.h"
+
#include "system.h"
#include "basics.h"
#include "reftable-error.h"
diff --git a/reftable/system.h b/reftable/system.h
index 3bd4a4e322..dccdf11f76 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -11,7 +11,8 @@ license that can be found in the LICENSE file or at
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "../compat/posix.h"
+#include <zlib.h>
/*
* Return a random 32 bit integer. This function is expected to return
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v4 18/18] Makefile: skip reftable library for Coccinelle
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
` (16 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
@ 2025-02-06 7:52 ` Patrick Steinhardt
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-06 7:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
The reftable library does not use any of the common helpers that the Git
project has. Consequently, most of the rules that we have in Coccinelle
do not apply to the library at all and may even generate false positives
when a pattern can be converted to use a Git helper function.
Exclude reftable library sources from being checked by Coccinelle to
avoid such false positives.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index d3011e30f7..dc2ac32e4a 100644
--- a/Makefile
+++ b/Makefile
@@ -946,7 +946,7 @@ FOUND_SOURCE_FILES := $(filter-out $(GENERATED_H),$(shell $(SOURCES_CMD)))
FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES))
FOUND_H_SOURCES = $(filter %.h,$(FOUND_SOURCE_FILES))
-COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
+COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES) reftable/%,$(FOUND_C_SOURCES))
LIB_H = $(FOUND_H_SOURCES)
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* Re: [PATCH v4 14/18] reftable/basics: stop using `UNUSED` annotation
2025-02-06 7:52 ` [PATCH v4 14/18] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
@ 2025-02-07 10:03 ` Toon Claes
2025-02-07 11:50 ` Patrick Steinhardt
0 siblings, 1 reply; 146+ messages in thread
From: Toon Claes @ 2025-02-07 10:03 UTC (permalink / raw)
To: Patrick Steinhardt, git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Patrick Steinhardt <ps@pks.im> writes:
> Stop using the `UNUSED` annotation and replace it with a new
> `REFTABLE_UNUSED` macro. The latter is a weaker guarantee compared to
> `UNUSED` as it only suppresses unused parameters without generating a
> warning in case a parameter marked as unused is in fact used. But it's
> good enough, and by relaxing the behaviour a bit we avoid having to wire
> up compiler-specific logic.
I see MAYBE_UNUSED is defined as `__attribute__((__unused__))`, which as
far as I can tell is independent on the compiler, and has the same
effect as the implementation in this patch. Would it make sense to use
that defition instead? Or did you intentionally choose a statement that
will sit on a separate line so it's more obviously that line needs to be
deleted whenever the parameter is put in use?
--
Toon
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v4 14/18] reftable/basics: stop using `UNUSED` annotation
2025-02-07 10:03 ` Toon Claes
@ 2025-02-07 11:50 ` Patrick Steinhardt
0 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:50 UTC (permalink / raw)
To: Toon Claes
Cc: git, Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
On Fri, Feb 07, 2025 at 11:03:15AM +0100, Toon Claes wrote:
> Patrick Steinhardt <ps@pks.im> writes:
>
> > Stop using the `UNUSED` annotation and replace it with a new
> > `REFTABLE_UNUSED` macro. The latter is a weaker guarantee compared to
> > `UNUSED` as it only suppresses unused parameters without generating a
> > warning in case a parameter marked as unused is in fact used. But it's
> > good enough, and by relaxing the behaviour a bit we avoid having to wire
> > up compiler-specific logic.
>
> I see MAYBE_UNUSED is defined as `__attribute__((__unused__))`, which as
> far as I can tell is independent on the compiler, and has the same
> effect as the implementation in this patch. Would it make sense to use
> that defition instead? Or did you intentionally choose a statement that
> will sit on a separate line so it's more obviously that line needs to be
> deleted whenever the parameter is put in use?
Interesting. I was checking the definition of `UNUSED`, which depends on
the actual compiler we're using. But you're right, `MAYBE_UNUSED` is
defined unconditionally, so by that reasoning we should be able to use
it on all supported platforms indeed.
I'll revise this patch, thanks for noticing!
Patrick
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v5 00/18] reftable: stop using "git-compat-util.h"
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (22 preceding siblings ...)
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
@ 2025-02-07 11:51 ` Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
` (17 more replies)
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
24 siblings, 18 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:51 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Toon Claes
Hi,
this patch series is the final step to fully decouple the reftable
library from the rest of the Git codebase. The goal of this is to make
the library reusable by other projects like libgit2 by simply copying
over the source files, making Git the canonical upstream for reftable
functionality.
This patch series stops using all kinds of helpers exposed by our
"git-compat-util.h" header and open-codes them instead. In order to keep
us from using these helpers by accident the final step is to pull out
POSIX-related bits and pieces into a new "compat/posix.h" header, which
the reftable library then uses instead of "git-compat-util.h".
The series is built on top of master at 5f8f7081f7 (The third batch,
2025-01-23) with ps/reftable-sign-compare at 33319b0976 (reftable:
address trivial -Wsign-compare warnings, 2025-01-20) merged into it.
There is a trivial merge conflict with ps/zlib-ng that can be solved
like this:
diff --cc reftable/system.h
index e4a8944a70,d02eacea8f..0000000000
--- a/reftable/system.h
+++ b/reftable/system.h
@@@ -11,15 -11,9 +11,15 @@@ https://developers.google.com/open-sour
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "compat/posix.h"
- #include <zlib.h>
+ #include "compat/zlib-compat.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
Changes in v2:
- The splitup of Windows headers has broken compilation because some
of the headers couldn't be found anymore. I've fixed this more
generally by converting includes in "compat/" to always be relative
to the project source directory, dropping the platform-specific
`-Icompat/` include.
- Explain why we don't port over `EWOULDBLOCK` handling.
- Fix commit message typos.
- Link to v1: https://lore.kernel.org/r/20250127-pks-reftable-drop-git-compat-util-v1-0-6e280a564877@pks.im
Changes in v3:
- Fix type of `total_read` variable used to track how many bytes we
have read in `fd_read_lines()`.
- Drop the patch use root-relative includes again. Let's rather
discuss this outside of the scope of this series.
- Link to v2: https://lore.kernel.org/r/20250128-pks-reftable-drop-git-compat-util-v2-0-c85c20336317@pks.im
Changes in v4:
- Fix a couple of now-invalid relative includes that I missed. This
fixes the build issue in "seen" with Meson.
- Link to v3: https://lore.kernel.org/r/20250203-pks-reftable-drop-git-compat-util-v3-0-446c9ed4ee9e@pks.im
Changes in v5:
- Rework the implementation of `REFTABLE_UNUSED` to use
`__attribute__((__unused__))`.
- Link to v4: https://lore.kernel.org/r/20250206-pks-reftable-drop-git-compat-util-v4-0-603d276d5f95@pks.im
Thanks!
Patrick
---
Patrick Steinhardt (18):
reftable/stack: stop using `read_in_full()`
reftable/stack: stop using `write_in_full()`
reftable/blocksource: stop using `xmmap()`
reftable/record: stop using `COPY_ARRAY()`
reftable/record: stop using `BUG()` in `reftable_record_init()`
reftable/record: don't `BUG()` in `reftable_record_cmp()`
reftable: stop using `BUG()` in trivial cases
reftable/basics: stop using `st_mult()` in array allocators
reftable/basics: provide wrappers for big endian conversion
reftable/reader: stop using `ARRAY_SIZE()` macro
reftable/system: introduce `reftable_rand()`
reftable/stack: stop using `sleep_millisec()`
reftable/basics: stop using `SWAP()` macro
reftable/basics: introduce `REFTABLE_UNUSED` annotation
compat/mingw: split out POSIX-related bits
git-compat-util.h: split out POSIX-emulating bits
reftable: decouple from Git codebase by pulling in "compat/posix.h"
Makefile: skip reftable library for Coccinelle
Makefile | 2 +-
compat/{mingw.c => mingw/compat-util.c} | 28 +-
compat/mingw/compat-util.h | 220 +++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------
compat/msvc.c | 6 -
compat/msvc/compat-util.c | 6 +
compat/msvc/compat-util.h | 7 +
compat/{msvc.h => msvc/posix.h} | 8 +-
compat/posix.h | 541 ++++++++++++++++++++++++++++++++
config.mak.uname | 6 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 535 +------------------------------
meson.build | 8 +-
reftable/basics.c | 19 --
reftable/basics.h | 123 +++++++-
reftable/block.c | 16 +-
reftable/blocksource.c | 17 +-
reftable/iter.c | 13 +-
reftable/merged.c | 27 +-
reftable/pq.c | 40 ++-
reftable/pq.h | 2 +-
reftable/reader.c | 33 +-
reftable/record.c | 84 ++---
reftable/record.h | 6 +-
reftable/stack.c | 52 ++-
reftable/system.c | 7 +
reftable/system.h | 9 +-
reftable/writer.c | 27 +-
t/unit-tests/t-reftable-basics.c | 28 +-
t/unit-tests/t-reftable-pq.c | 22 +-
t/unit-tests/t-reftable-record.c | 42 ++-
31 files changed, 1205 insertions(+), 947 deletions(-)
Range-diff versus v4:
1: 7db7704c24 = 1: 74f576c975 reftable/stack: stop using `read_in_full()`
2: 3ddd26284d = 2: acd5854f56 reftable/stack: stop using `write_in_full()`
3: 5f4a747da9 = 3: 25aab5acc1 reftable/blocksource: stop using `xmmap()`
4: 64b87dd35f = 4: 5ea4f2d8ea reftable/record: stop using `COPY_ARRAY()`
5: 49ab3789ac = 5: 2ca248c1cc reftable/record: stop using `BUG()` in `reftable_record_init()`
6: 47aacb4064 = 6: 590b9097e3 reftable/record: don't `BUG()` in `reftable_record_cmp()`
7: 4a777111bb = 7: 461cb30e1c reftable: stop using `BUG()` in trivial cases
8: 743e70374d = 8: 72f672b731 reftable/basics: stop using `st_mult()` in array allocators
9: 2a7cba7ec7 = 9: c597bd1621 reftable/basics: provide wrappers for big endian conversion
10: fd741883d7 = 10: 643b70b67e reftable/reader: stop using `ARRAY_SIZE()` macro
11: 2a4e188e96 = 11: dc809eefbf reftable/system: introduce `reftable_rand()`
12: 57014b3de7 = 12: bf59b53b60 reftable/stack: stop using `sleep_millisec()`
13: 7daddddd0d = 13: 68ffa9306f reftable/basics: stop using `SWAP()` macro
14: e7556a7d53 < -: ---------- reftable/basics: stop using `UNUSED` annotation
-: ---------- > 14: b444c64faf reftable/basics: introduce `REFTABLE_UNUSED` annotation
15: 4628c8a98e = 15: 2043277fb1 compat/mingw: split out POSIX-related bits
16: 055b865078 = 16: f496f30aa2 git-compat-util.h: split out POSIX-emulating bits
17: ae323e3b8d = 17: 3e4564d927 reftable: decouple from Git codebase by pulling in "compat/posix.h"
18: 6c3360b76a = 18: 63d85e0ace Makefile: skip reftable library for Coccinelle
---
base-commit: 8047765d092881ec4aef7dfc57772161eee7f0f5
change-id: 20241119-pks-reftable-drop-git-compat-util-470f2bfde562
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v5 01/18] reftable/stack: stop using `read_in_full()`
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
@ 2025-02-07 11:51 ` Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
` (16 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:51 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
There is a single callsite of `read_in_full()` in the reftable library.
Open-code the function to reduce our dependency on the Git library.
Note that we only partially port over the logic from `read_in_full()`
and its underlying `xread()` helper. Most importantly, the latter also
knows to handle `EWOULDBLOCK` via `handle_nonblock()`. This logic is
irrelevant for us though because the reftable library never sets the
`O_NONBLOCK` option in the first place.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index f7c1845e15..d57acd9540 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -115,13 +115,16 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
static int fd_read_lines(int fd, char ***namesp)
{
- off_t size = lseek(fd, 0, SEEK_END);
char *buf = NULL;
int err = 0;
+ off_t size;
+
+ size = lseek(fd, 0, SEEK_END);
if (size < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
+
err = lseek(fd, 0, SEEK_SET);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp)
goto done;
}
- if (read_in_full(fd, buf, size) != size) {
- err = REFTABLE_IO_ERROR;
- goto done;
+ for (off_t total_read = 0; total_read < size; ) {
+ ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
+ if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_read < 0 || !bytes_read) {
+ err = REFTABLE_IO_ERROR;
+ goto done;
+ }
+
+ total_read += bytes_read;
}
buf[size] = 0;
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 02/18] reftable/stack: stop using `write_in_full()`
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
@ 2025-02-07 11:51 ` Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
` (15 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:51 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Similar to the preceding commit, drop our use of `write_in_full()` and
implement a new wrapper `reftable_write_full()` that handles this logic
for us. This is done to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index d57acd9540..46abf51ec5 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -48,6 +48,25 @@ static int stack_fsync(const struct reftable_write_options *opts, int fd)
return fsync(fd);
}
+static ssize_t reftable_write_data(int fd, const void *data, size_t size)
+{
+ size_t total_written = 0;
+ const char *p = data;
+
+ while (total_written < size) {
+ ssize_t bytes_written = write(fd, p, size - total_written);
+ if (bytes_written < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_written < 0)
+ return REFTABLE_IO_ERROR;
+
+ total_written += bytes_written;
+ p += bytes_written;
+ }
+
+ return total_written;
+}
+
struct fd_writer {
const struct reftable_write_options *opts;
int fd;
@@ -56,7 +75,7 @@ struct fd_writer {
static ssize_t fd_writer_write(void *arg, const void *data, size_t sz)
{
struct fd_writer *writer = arg;
- return write_in_full(writer->fd, data, sz);
+ return reftable_write_data(writer->fd, data, sz);
}
static int fd_writer_flush(void *arg)
@@ -784,7 +803,8 @@ int reftable_addition_commit(struct reftable_addition *add)
goto done;
}
- err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len);
+ err = reftable_write_data(add->tables_list_lock.fd,
+ table_list.buf, table_list.len);
reftable_buf_release(&table_list);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -1468,8 +1488,8 @@ static int stack_compact_range(struct reftable_stack *st,
goto done;
}
- err = write_in_full(tables_list_lock.fd,
- tables_list_buf.buf, tables_list_buf.len);
+ err = reftable_write_data(tables_list_lock.fd,
+ tables_list_buf.buf, tables_list_buf.len);
if (err < 0) {
err = REFTABLE_IO_ERROR;
unlink(new_table_path.buf);
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 03/18] reftable/blocksource: stop using `xmmap()`
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
@ 2025-02-07 11:51 ` Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
` (14 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:51 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We use `xmmap()` to map reftables into memory. This function has two
problems:
- It causes us to die in case the mmap fails.
- It ties us to the Git codebase.
Refactor the code to use mmap(3p) instead with manual error checking.
Note that this function may not be the system-provided mmap(3p), but may
point to our `git_mmap()` wrapper that emulates the syscall on systems
that do not have mmap(3p) available.
Fix `reftable_block_source_from_file()` to properly bubble up the error
code in case the map(3p) call fails.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/blocksource.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index bba4a45b98..02972c46f4 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -98,7 +98,7 @@ static struct reftable_block_source_vtable file_vtable = {
int reftable_block_source_from_file(struct reftable_block_source *bs,
const char *name)
{
- struct file_block_source *p;
+ struct file_block_source *p = NULL;
struct stat st;
int fd, err;
@@ -122,7 +122,12 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
}
p->size = st.st_size;
- p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ p->data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p->data == MAP_FAILED) {
+ err = REFTABLE_IO_ERROR;
+ p->data = NULL;
+ goto out;
+ }
assert(!bs->ops);
bs->ops = &file_vtable;
@@ -135,5 +140,5 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
close(fd);
if (err < 0)
reftable_free(p);
- return 0;
+ return err;
}
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 04/18] reftable/record: stop using `COPY_ARRAY()`
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (2 preceding siblings ...)
2025-02-07 11:51 ` [PATCH v5 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
@ 2025-02-07 11:51 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
` (13 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:51 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Drop our use of `COPY_ARRAY()`, replacing it with an open-coded variant
thereof. This is done to reduce our dependency on the Git library.
While at it, guard the whole array copy logic so that we only copy it in
case there actually is anything to be copied. Otherwise, we may end up
trying to allocate a zero-sized array, which will return a NULL pointer
and thus cause us to return an `REFTABLE_OUT_OF_MEMORY_ERROR`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/record.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/reftable/record.c b/reftable/record.c
index 8919df8a4d..2c0cc32cbd 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -504,11 +504,17 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
if (src->hash_prefix_len)
memcpy(obj->hash_prefix, src->hash_prefix, obj->hash_prefix_len);
- REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
- if (!obj->offsets)
- return REFTABLE_OUT_OF_MEMORY_ERROR;
- obj->offset_len = src->offset_len;
- COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
+ if (src->offset_len) {
+ if (sizeof(*src->offsets) > SIZE_MAX / src->offset_len)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
+ if (!obj->offsets)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len);
+ obj->offset_len = src->offset_len;
+ }
return 0;
}
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()`
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (3 preceding siblings ...)
2025-02-07 11:51 ` [PATCH v5 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
` (12 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We're aborting the program via `BUG()` in case `reftable_record_init()`
was invoked with an unknown record type. This is bad because we may now
die in library code, and because it makes us depend on the Git codebase.
Refactor the code such that `reftable_record_init()` can return an error
code to the caller. Adapt any callers accordingly.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/block.c | 4 +++-
reftable/merged.c | 5 ++++-
reftable/reader.c | 5 ++++-
reftable/record.c | 8 ++++----
reftable/record.h | 4 ++--
t/unit-tests/t-reftable-pq.c | 6 +++---
t/unit-tests/t-reftable-record.c | 2 +-
7 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/reftable/block.c b/reftable/block.c
index 8ac865ce78..255d566854 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -509,7 +509,9 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,
it->block_len = br->block_len;
it->hash_size = br->hash_size;
- reftable_record_init(&rec, block_reader_type(br));
+ err = reftable_record_init(&rec, block_reader_type(br));
+ if (err < 0)
+ goto done;
/*
* We're looking for the last entry less than the wanted key so that
diff --git a/reftable/merged.c b/reftable/merged.c
index e72b39e178..4156eec07f 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -253,7 +253,10 @@ int merged_table_init_iter(struct reftable_merged_table *mt,
}
for (size_t i = 0; i < mt->readers_len; i++) {
- reftable_record_init(&subiters[i].rec, typ);
+ ret = reftable_record_init(&subiters[i].rec, typ);
+ if (ret < 0)
+ goto out;
+
ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
if (ret < 0)
goto out;
diff --git a/reftable/reader.c b/reftable/reader.c
index 3f2e4b2800..de6e6dd932 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -360,7 +360,10 @@ static int table_iter_seek_linear(struct table_iter *ti,
struct reftable_record rec;
int err;
- reftable_record_init(&rec, reftable_record_type(want));
+ err = reftable_record_init(&rec, reftable_record_type(want));
+ if (err < 0)
+ goto done;
+
err = reftable_record_key(want, &want_key);
if (err < 0)
goto done;
diff --git a/reftable/record.c b/reftable/record.c
index 2c0cc32cbd..1e18f8dffb 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1306,7 +1306,7 @@ reftable_record_vtable(struct reftable_record *rec)
abort();
}
-void reftable_record_init(struct reftable_record *rec, uint8_t typ)
+int reftable_record_init(struct reftable_record *rec, uint8_t typ)
{
memset(rec, 0, sizeof(*rec));
rec->type = typ;
@@ -1315,11 +1315,11 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)
case BLOCK_TYPE_REF:
case BLOCK_TYPE_LOG:
case BLOCK_TYPE_OBJ:
- return;
+ return 0;
case BLOCK_TYPE_INDEX:
reftable_buf_init(&rec->u.idx.last_key);
- return;
+ return 0;
default:
- BUG("unhandled record type");
+ return REFTABLE_API_ERROR;
}
}
diff --git a/reftable/record.h b/reftable/record.h
index c7755a4d75..e1846c294b 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -130,8 +130,8 @@ struct reftable_record {
} u;
};
-/* Initialize the reftable record for the given type */
-void reftable_record_init(struct reftable_record *rec, uint8_t typ);
+/* Initialize the reftable record for the given type. */
+int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index f3f8a0cdf3..d8a4c283a1 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -32,7 +32,7 @@ static void t_pq_record(void)
char *last = NULL;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
}
@@ -72,7 +72,7 @@ static void t_pq_index(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
@@ -111,7 +111,7 @@ static void t_merged_iter_pqueue_top(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index d49d2a2729..6540bd20e3 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -17,7 +17,7 @@ static void t_copy(struct reftable_record *rec)
uint8_t typ;
typ = reftable_record_type(rec);
- reftable_record_init(©, typ);
+ check(!reftable_record_init(©, typ));
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
/* do it twice to catch memory leaks */
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()`
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (4 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
` (11 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
The reftable library aborts with a bug in case `reftable_record_cmp()`
is invoked with two records of differing types. This would cause the
program to die without the caller being able to handle the error, which
is not something we want in the context of library code. And it ties us
to the Git codebase.
Refactor the code such that `reftable_record_cmp()` returns an error
code separate from the actual comparison result. This requires us to
also adapt some callers up the callchain in a similar fashion.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/merged.c | 20 +++++++++++++++-----
reftable/pq.c | 36 +++++++++++++++++++++++++++++-------
reftable/pq.h | 2 +-
reftable/record.c | 10 ++++++----
reftable/record.h | 2 +-
t/unit-tests/t-reftable-pq.c | 16 ++++++++++++----
t/unit-tests/t-reftable-record.c | 40 ++++++++++++++++++++++++++++------------
7 files changed, 92 insertions(+), 34 deletions(-)
diff --git a/reftable/merged.c b/reftable/merged.c
index 4156eec07f..563864068c 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -66,8 +66,11 @@ static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want
int err;
mi->advance_index = -1;
- while (!merged_iter_pqueue_is_empty(mi->pq))
- merged_iter_pqueue_remove(&mi->pq);
+ while (!merged_iter_pqueue_is_empty(mi->pq)) {
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+ }
for (size_t i = 0; i < mi->subiters_len; i++) {
err = iterator_seek(&mi->subiters[i].iter, want);
@@ -120,7 +123,9 @@ static int merged_iter_next_entry(struct merged_iter *mi,
if (empty)
return 1;
- entry = merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, &entry);
+ if (err < 0)
+ return err;
/*
One can also use reftable as datacenter-local storage, where the ref
@@ -134,11 +139,16 @@ static int merged_iter_next_entry(struct merged_iter *mi,
struct pq_entry top = merged_iter_pqueue_top(mi->pq);
int cmp;
- cmp = reftable_record_cmp(top.rec, entry.rec);
+ err = reftable_record_cmp(top.rec, entry.rec, &cmp);
+ if (err < 0)
+ return err;
if (cmp > 0)
break;
- merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+
err = merged_iter_advance_subiter(mi, top.index);
if (err < 0)
return err;
diff --git a/reftable/pq.c b/reftable/pq.c
index 5591e875e1..ef8035cfd9 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -15,13 +15,18 @@ license that can be found in the LICENSE file or at
int pq_less(struct pq_entry *a, struct pq_entry *b)
{
- int cmp = reftable_record_cmp(a->rec, b->rec);
+ int cmp, err;
+
+ err = reftable_record_cmp(a->rec, b->rec, &cmp);
+ if (err < 0)
+ return err;
+
if (cmp == 0)
return a->index > b->index;
return cmp < 0;
}
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out)
{
size_t i = 0;
struct pq_entry e = pq->heap[0];
@@ -32,17 +37,34 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
size_t min = i;
size_t j = 2 * i + 1;
size_t k = 2 * i + 2;
- if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i]))
- min = j;
- if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min]))
- min = k;
+ int cmp;
+
+ if (j < pq->len) {
+ cmp = pq_less(&pq->heap[j], &pq->heap[i]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = j;
+ }
+
+ if (k < pq->len) {
+ cmp = pq_less(&pq->heap[k], &pq->heap[min]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = k;
+ }
+
if (min == i)
break;
SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
- return e;
+ if (out)
+ *out = e;
+
+ return 0;
}
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
diff --git a/reftable/pq.h b/reftable/pq.h
index 83c062eeca..ff39016445 100644
--- a/reftable/pq.h
+++ b/reftable/pq.h
@@ -22,7 +22,7 @@ struct merged_iter_pqueue {
size_t cap;
};
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out);
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
diff --git a/reftable/record.c b/reftable/record.c
index 1e18f8dffb..b39d99fcc7 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1195,12 +1195,14 @@ int reftable_record_is_deletion(struct reftable_record *rec)
reftable_record_data(rec));
}
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b)
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b,
+ int *cmp)
{
if (a->type != b->type)
- BUG("cannot compare reftable records of different type");
- return reftable_record_vtable(a)->cmp(
- reftable_record_data(a), reftable_record_data(b));
+ return -1;
+ *cmp = reftable_record_vtable(a)->cmp(reftable_record_data(a),
+ reftable_record_data(b));
+ return 0;
}
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size)
diff --git a/reftable/record.h b/reftable/record.h
index e1846c294b..867810a932 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -134,7 +134,7 @@ struct reftable_record {
int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b, int *cmp);
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size);
int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);
int reftable_record_copy_from(struct reftable_record *rec,
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index d8a4c283a1..c128fe8616 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -21,7 +21,9 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq)
static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b)
{
- return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index);
+ int cmp;
+ check(!reftable_record_cmp(a->rec, b->rec, &cmp));
+ return !cmp && (a->index == b->index);
}
static void t_pq_record(void)
@@ -49,7 +51,9 @@ static void t_pq_record(void)
while (!merged_iter_pqueue_is_empty(pq)) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -90,7 +94,9 @@ static void t_pq_index(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -129,7 +135,9 @@ static void t_merged_iter_pqueue_top(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index 6540bd20e3..5954966373 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -100,16 +100,20 @@ static void t_reftable_ref_record_comparison(void)
.u.ref.value.symref = (char *) "refs/heads/master",
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.ref.value_type = in[0].u.ref.value_type;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_ref_record_compare_name(void)
@@ -209,17 +213,20 @@ static void t_reftable_log_record_comparison(void)
.u.log.update_index = 22,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
/* comparison should be reversed for equal keys, because
* comparison is now performed on the basis of update indices */
- check_int(reftable_record_cmp(&in[0], &in[1]), <, 0);
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check_int(cmp, <, 0);
in[1].u.log.update_index = in[0].u.log.update_index;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
}
static void t_reftable_log_record_compare_key(void)
@@ -396,16 +403,20 @@ static void t_reftable_obj_record_comparison(void)
.u.obj.hash_prefix_len = 5,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.obj.offset_len = in[0].u.obj.offset_len;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_obj_record_roundtrip(void)
@@ -486,19 +497,24 @@ static void t_reftable_index_record_comparison(void)
.u.idx.last_key = REFTABLE_BUF_INIT,
},
};
+ int cmp;
+
check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch"));
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.idx.offset = in[0].u.idx.offset;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
for (size_t i = 0; i < ARRAY_SIZE(in); i++)
reftable_record_release(&in[i]);
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 07/18] reftable: stop using `BUG()` in trivial cases
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (5 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
` (10 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Stop using `BUG()` in the remaining trivial cases that we still have in
the reftable library. Instead of aborting the program, we'll now bubble
up a `REFTABLE_API_ERROR` to indicate misuse of the calling conventions.
Note that in both `reftable_reader_{inc,dec}ref()` we simply stop
calling `BUG()` altogether. The only situation where the counter should
be zero is when the structure has already been free'd anyway, so we
would run into undefined behaviour regardless of whether we try to abort
the program or not.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/iter.c | 3 +--
reftable/reader.c | 4 ----
reftable/writer.c | 5 ++---
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/reftable/iter.c b/reftable/iter.c
index 86e801ca9f..b2ffb09c16 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -146,8 +146,7 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
static int indexed_table_ref_iter_seek(void *p UNUSED,
struct reftable_record *want UNUSED)
{
- BUG("seeking indexed table is not supported");
- return -1;
+ return REFTABLE_API_ERROR;
}
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
diff --git a/reftable/reader.c b/reftable/reader.c
index de6e6dd932..36a5633ede 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -677,8 +677,6 @@ int reftable_reader_new(struct reftable_reader **out,
void reftable_reader_incref(struct reftable_reader *r)
{
- if (!r->refcount)
- BUG("cannot increment ref counter of dead reader");
r->refcount++;
}
@@ -686,8 +684,6 @@ void reftable_reader_decref(struct reftable_reader *r)
{
if (!r)
return;
- if (!r->refcount)
- BUG("cannot decrement ref counter of dead reader");
if (--r->refcount)
return;
block_source_close(&r->source);
diff --git a/reftable/writer.c b/reftable/writer.c
index 91d6629486..155863ee5f 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -158,7 +158,7 @@ int reftable_writer_new(struct reftable_writer **out,
opts = *_opts;
options_set_defaults(&opts);
if (opts.block_size >= (1 << 24))
- BUG("configured block size exceeds 16MB");
+ return REFTABLE_API_ERROR;
reftable_buf_init(&wp->block_writer_data.last_key);
reftable_buf_init(&wp->last_key);
@@ -289,8 +289,7 @@ static int writer_add_record(struct reftable_writer *w,
}
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
- BUG("record of type %d added to writer of type %d",
- reftable_record_type(rec), block_writer_type(w->block_writer));
+ return REFTABLE_API_ERROR;
/*
* Try to add the record to the writer. If this succeeds then we're
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 08/18] reftable/basics: stop using `st_mult()` in array allocators
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (6 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
` (9 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We're using `st_mult()` as part of our macro helpers that allocate
arrays. This is bad due two two reasons:
- `st_mult()` causes us to die in case the multiplication overflows.
- `st_mult()` ties us to the Git codebase.
Refactor the code to instead detect overflows manually and return an
error in such cases.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index a2a010a0e1..646f8d67f2 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -117,18 +117,46 @@ void reftable_free(void *p);
void *reftable_calloc(size_t nelem, size_t elsize);
char *reftable_strdup(const char *str);
-#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
+static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out)
+{
+ if (nelem && elsize > SIZE_MAX / nelem)
+ return -1;
+ *out = nelem * elsize;
+ return 0;
+}
+
+#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_malloc(alloc_size); \
+ } \
+ } while (0)
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
-#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc)))
+#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_realloc((x), alloc_size); \
+ } \
+ } while (0)
static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
size_t *allocp)
{
void *new_p;
- size_t alloc = *allocp * 2 + 1;
+ size_t alloc = *allocp * 2 + 1, alloc_bytes;
if (alloc < nelem)
alloc = nelem;
- new_p = reftable_realloc(p, st_mult(elsize, alloc));
+ if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) {
+ errno = ENOMEM;
+ return p;
+ }
+ new_p = reftable_realloc(p, alloc_bytes);
if (!new_p)
return p;
*allocp = alloc;
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 09/18] reftable/basics: provide wrappers for big endian conversion
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (7 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
` (8 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We're using a mixture of big endian conversion functions provided by
both the reftable library, but also by the Git codebase. Refactor the
code so that we exclusively use reftable-provided wrappers in order to
untangle us from the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.c | 19 ----------
reftable/basics.h | 76 ++++++++++++++++++++++++++++++++++++++--
reftable/block.c | 12 +++----
reftable/reader.c | 22 ++++++------
reftable/record.c | 8 ++---
reftable/writer.c | 20 +++++------
t/unit-tests/t-reftable-basics.c | 28 ++++++++++++---
7 files changed, 127 insertions(+), 58 deletions(-)
diff --git a/reftable/basics.c b/reftable/basics.c
index 3b5ea27bbd..8c4a4433e4 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -147,25 +147,6 @@ char *reftable_buf_detach(struct reftable_buf *buf)
return result;
}
-void put_be24(uint8_t *out, uint32_t i)
-{
- out[0] = (uint8_t)((i >> 16) & 0xff);
- out[1] = (uint8_t)((i >> 8) & 0xff);
- out[2] = (uint8_t)(i & 0xff);
-}
-
-uint32_t get_be24(uint8_t *in)
-{
- return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 |
- (uint32_t)(in[2]);
-}
-
-void put_be16(uint8_t *out, uint16_t i)
-{
- out[0] = (uint8_t)((i >> 8) & 0xff);
- out[1] = (uint8_t)(i & 0xff);
-}
-
size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
{
size_t lo = 0;
diff --git a/reftable/basics.h b/reftable/basics.h
index 646f8d67f2..c1ddbaec3f 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -76,9 +76,79 @@ char *reftable_buf_detach(struct reftable_buf *buf);
/* Bigendian en/decoding of integers */
-void put_be24(uint8_t *out, uint32_t i);
-uint32_t get_be24(uint8_t *in);
-void put_be16(uint8_t *out, uint16_t i);
+static inline void reftable_put_be16(void *out, uint16_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 8) & 0xff);
+ p[1] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be24(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 16) & 0xff);
+ p[1] = (uint8_t)((i >> 8) & 0xff);
+ p[2] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be32(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 24) & 0xff);
+ p[1] = (uint8_t)((i >> 16) & 0xff);
+ p[2] = (uint8_t)((i >> 8) & 0xff);
+ p[3] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be64(void *out, uint64_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 56) & 0xff);
+ p[1] = (uint8_t)((i >> 48) & 0xff);
+ p[2] = (uint8_t)((i >> 40) & 0xff);
+ p[3] = (uint8_t)((i >> 32) & 0xff);
+ p[4] = (uint8_t)((i >> 24) & 0xff);
+ p[5] = (uint8_t)((i >> 16) & 0xff);
+ p[6] = (uint8_t)((i >> 8) & 0xff);
+ p[7] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline uint16_t reftable_get_be16(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint16_t)(p[0]) << 8 |
+ (uint16_t)(p[1]) << 0;
+}
+
+static inline uint32_t reftable_get_be24(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 16 |
+ (uint32_t)(p[1]) << 8 |
+ (uint32_t)(p[2]) << 0;
+}
+
+static inline uint32_t reftable_get_be32(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 24 |
+ (uint32_t)(p[1]) << 16 |
+ (uint32_t)(p[2]) << 8|
+ (uint32_t)(p[3]) << 0;
+}
+
+static inline uint64_t reftable_get_be64(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint64_t)(p[0]) << 56 |
+ (uint64_t)(p[1]) << 48 |
+ (uint64_t)(p[2]) << 40 |
+ (uint64_t)(p[3]) << 32 |
+ (uint64_t)(p[4]) << 24 |
+ (uint64_t)(p[5]) << 16 |
+ (uint64_t)(p[6]) << 8 |
+ (uint64_t)(p[7]) << 0;
+}
/*
* find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is
diff --git a/reftable/block.c b/reftable/block.c
index 255d566854..373908807e 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -148,13 +148,13 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
int block_writer_finish(struct block_writer *w)
{
for (uint32_t i = 0; i < w->restart_len; i++) {
- put_be24(w->block + w->next, w->restarts[i]);
+ reftable_put_be24(w->block + w->next, w->restarts[i]);
w->next += 3;
}
- put_be16(w->block + w->next, w->restart_len);
+ reftable_put_be16(w->block + w->next, w->restart_len);
w->next += 2;
- put_be24(w->block + 1 + w->header_off, w->next);
+ reftable_put_be24(w->block + 1 + w->header_off, w->next);
/*
* Log records are stored zlib-compressed. Note that the compression
@@ -216,7 +216,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
{
uint32_t full_block_size = table_block_size;
uint8_t typ = block->data[header_off];
- uint32_t sz = get_be24(block->data + header_off + 1);
+ uint32_t sz = reftable_get_be24(block->data + header_off + 1);
int err = 0;
uint16_t restart_count = 0;
uint32_t restart_start = 0;
@@ -300,7 +300,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
full_block_size = sz;
}
- restart_count = get_be16(block->data + sz - 2);
+ restart_count = reftable_get_be16(block->data + sz - 2);
restart_start = sz - 2 - 3 * restart_count;
restart_bytes = block->data + restart_start;
@@ -355,7 +355,7 @@ int block_reader_first_key(const struct block_reader *br, struct reftable_buf *k
static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx)
{
- return get_be24(br->restart_bytes + 3 * idx);
+ return reftable_get_be24(br->restart_bytes + 3 * idx);
}
void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)
diff --git a/reftable/reader.c b/reftable/reader.c
index 36a5633ede..bf07a0a586 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -101,18 +101,18 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
}
f++;
- r->block_size = get_be24(f);
+ r->block_size = reftable_get_be24(f);
f += 3;
- r->min_update_index = get_be64(f);
+ r->min_update_index = reftable_get_be64(f);
f += 8;
- r->max_update_index = get_be64(f);
+ r->max_update_index = reftable_get_be64(f);
f += 8;
if (r->version == 1) {
r->hash_id = REFTABLE_HASH_SHA1;
} else {
- switch (get_be32(f)) {
+ switch (reftable_get_be32(f)) {
case REFTABLE_FORMAT_ID_SHA1:
r->hash_id = REFTABLE_HASH_SHA1;
break;
@@ -127,24 +127,24 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
f += 4;
}
- r->ref_offsets.index_offset = get_be64(f);
+ r->ref_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->obj_offsets.offset = get_be64(f);
+ r->obj_offsets.offset = reftable_get_be64(f);
f += 8;
r->object_id_len = r->obj_offsets.offset & ((1 << 5) - 1);
r->obj_offsets.offset >>= 5;
- r->obj_offsets.index_offset = get_be64(f);
+ r->obj_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.offset = get_be64(f);
+ r->log_offsets.offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.index_offset = get_be64(f);
+ r->log_offsets.index_offset = reftable_get_be64(f);
f += 8;
computed_crc = crc32(0, footer, f - footer);
- file_crc = get_be32(f);
+ file_crc = reftable_get_be32(f);
f += 4;
if (computed_crc != file_crc) {
err = REFTABLE_FORMAT_ERROR;
@@ -214,7 +214,7 @@ static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
*typ = data[0];
if (reftable_is_block_type(*typ)) {
- result = get_be24(data + 1);
+ result = reftable_get_be24(data + 1);
}
return result;
}
diff --git a/reftable/record.c b/reftable/record.c
index b39d99fcc7..3552bafa99 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -689,7 +689,7 @@ static int reftable_log_record_key(const void *r, struct reftable_buf *dest)
return err;
ts = (~ts) - rec->update_index;
- put_be64(&i64[0], ts);
+ reftable_put_be64(&i64[0], ts);
err = reftable_buf_add(dest, i64, sizeof(i64));
if (err < 0)
@@ -814,7 +814,7 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,
if (s.len < 2)
return -1;
- put_be16(s.buf, r->value.update.tz_offset);
+ reftable_put_be16(s.buf, r->value.update.tz_offset);
string_view_consume(&s, 2);
n = encode_string(
@@ -846,7 +846,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
}
memcpy(r->refname, key.buf, key.len - 8);
- ts = get_be64(key.buf + key.len - 8);
+ ts = reftable_get_be64((unsigned char *)key.buf + key.len - 8);
r->update_index = (~max) - ts;
@@ -937,7 +937,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
goto done;
}
- r->value.update.tz_offset = get_be16(in.buf);
+ r->value.update.tz_offset = reftable_get_be16(in.buf);
string_view_consume(&in, 2);
n = decode_string(scratch, in);
diff --git a/reftable/writer.c b/reftable/writer.c
index 155863ee5f..5961698311 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -99,9 +99,9 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
dest[4] = writer_version(w);
- put_be24(dest + 5, w->opts.block_size);
- put_be64(dest + 8, w->min_update_index);
- put_be64(dest + 16, w->max_update_index);
+ reftable_put_be24(dest + 5, w->opts.block_size);
+ reftable_put_be64(dest + 8, w->min_update_index);
+ reftable_put_be64(dest + 16, w->max_update_index);
if (writer_version(w) == 2) {
uint32_t hash_id;
@@ -116,7 +116,7 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
return -1;
}
- put_be32(dest + 24, hash_id);
+ reftable_put_be32(dest + 24, hash_id);
}
return header_size(writer_version(w));
@@ -717,19 +717,19 @@ int reftable_writer_close(struct reftable_writer *w)
}
p += writer_write_header(w, footer);
- put_be64(p, w->stats.ref_stats.index_offset);
+ reftable_put_be64(p, w->stats.ref_stats.index_offset);
p += 8;
- put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
+ reftable_put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
p += 8;
- put_be64(p, w->stats.obj_stats.index_offset);
+ reftable_put_be64(p, w->stats.obj_stats.index_offset);
p += 8;
- put_be64(p, w->stats.log_stats.offset);
+ reftable_put_be64(p, w->stats.log_stats.offset);
p += 8;
- put_be64(p, w->stats.log_stats.index_offset);
+ reftable_put_be64(p, w->stats.log_stats.index_offset);
p += 8;
- put_be32(p, crc32(0, footer, p - footer));
+ reftable_put_be32(p, crc32(0, footer, p - footer));
p += 4;
err = w->flush(w->write_arg);
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
index 9ba7eb05ad..c9e751e49e 100644
--- a/t/unit-tests/t-reftable-basics.c
+++ b/t/unit-tests/t-reftable-basics.c
@@ -128,12 +128,30 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
reftable_buf_release(&b);
}
- if_test ("put_be24 and get_be24 work") {
+ if_test ("reftable_put_be64 and reftable_get_be64 work") {
+ uint64_t in = 0x1122334455667788;
+ uint8_t dest[8];
+ uint64_t out;
+ reftable_put_be64(dest, in);
+ out = reftable_get_be64(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be32 and reftable_get_be32 work") {
+ uint32_t in = 0x11223344;
+ uint8_t dest[4];
+ uint32_t out;
+ reftable_put_be32(dest, in);
+ out = reftable_get_be32(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be24 and reftable_get_be24 work") {
uint32_t in = 0x112233;
uint8_t dest[3];
uint32_t out;
- put_be24(dest, in);
- out = get_be24(dest);
+ reftable_put_be24(dest, in);
+ out = reftable_get_be24(dest);
check_int(in, ==, out);
}
@@ -141,8 +159,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
uint32_t in = 0xfef1;
uint8_t dest[3];
uint32_t out;
- put_be16(dest, in);
- out = get_be16(dest);
+ reftable_put_be16(dest, in);
+ out = reftable_get_be16(dest);
check_int(in, ==, out);
}
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (8 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
` (7 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
We have a single user of the `ARRAY_SIZE()` macro in the reftable
reader. Drop its use to reduce our dependence on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/reader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/reader.c b/reftable/reader.c
index bf07a0a586..c3a3674665 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -849,7 +849,7 @@ int reftable_reader_print_blocks(const char *tablename)
printf("header:\n");
printf(" block_size: %d\n", r->block_size);
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
+ for (i = 0; i < sizeof(sections) / sizeof(*sections); i++) {
err = table_iter_seek_start(&ti, sections[i].type, 0);
if (err < 0)
goto done;
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 11/18] reftable/system: introduce `reftable_rand()`
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (9 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
` (6 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Introduce a new system-level `reftable_rand()` function that generates a
single unsigned integer for us. The implementation of this function is
to be provided by the calling codebase, which allows us to more easily
hook into pre-seeded random number generators.
Adapt the two callsites where we generated random data.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 4 ++--
reftable/system.c | 5 +++++
reftable/system.h | 6 ++++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 46abf51ec5..e22577ec77 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -523,7 +523,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
close(fd);
fd = -1;
- delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1;
+ delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
sleep_millisec(delay);
}
@@ -688,7 +688,7 @@ int reftable_stack_add(struct reftable_stack *st,
static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
{
char buf[100];
- uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE);
+ uint32_t rnd = reftable_rand();
snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
min, max, rnd);
reftable_buf_reset(dest);
diff --git a/reftable/system.c b/reftable/system.c
index adf8e4d30b..e25ccc0da3 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -4,6 +4,11 @@
#include "../lockfile.h"
#include "../tempfile.h"
+uint32_t reftable_rand(void)
+{
+ return git_rand(CSPRNG_BYTES_INSECURE);
+}
+
int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern)
{
struct tempfile *tempfile;
diff --git a/reftable/system.h b/reftable/system.h
index 7d5f803eeb..3bd4a4e322 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -13,6 +13,12 @@ license that can be found in the LICENSE file or at
#include "git-compat-util.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 12/18] reftable/stack: stop using `sleep_millisec()`
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (10 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
` (5 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Refactor our use of `sleep_millisec()` by open-coding it with poll(3p),
which is the current implementation of this function. Ideally, we'd use
a more direct way to sleep, but there is no equivalent to sleep(3p) that
would accept milliseconds as input.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index e22577ec77..7b0b10cd38 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -524,7 +524,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
fd = -1;
delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
- sleep_millisec(delay);
+ poll(NULL, 0, delay);
}
out:
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 13/18] reftable/basics: stop using `SWAP()` macro
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (11 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 14/18] reftable/basics: introduce `REFTABLE_UNUSED` annotation Patrick Steinhardt
` (4 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Stop using `SWAP()` macro in favor of an open-coded variant of it. Note
that this also requires us to open-code the build assert that `SWAP()`
itself uses to verify that the size of both variables matches.
This is done to reduce our dependency on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 9 +++++++++
reftable/merged.c | 2 +-
reftable/pq.c | 4 ++--
reftable/record.c | 16 ++++++++--------
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index c1ddbaec3f..59000798f0 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -266,6 +266,15 @@ static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
# define strdup(str) REFTABLE_BANNED(strdup)
#endif
+#define REFTABLE_SWAP(a, b) do { \
+ void *_swap_a_ptr = &(a); \
+ void *_swap_b_ptr = &(b); \
+ unsigned char _swap_buffer[sizeof(a) - 2 * sizeof(a) * (sizeof(a) != sizeof(b))]; \
+ memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \
+ memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a)); \
+ memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
+} while (0)
+
/* Find the longest shared prefix size of `a` and `b` */
size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);
diff --git a/reftable/merged.c b/reftable/merged.c
index 563864068c..4ff1553772 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -155,7 +155,7 @@ static int merged_iter_next_entry(struct merged_iter *mi,
}
mi->advance_index = entry.index;
- SWAP(*rec, *entry.rec);
+ REFTABLE_SWAP(*rec, *entry.rec);
return 0;
}
diff --git a/reftable/pq.c b/reftable/pq.c
index ef8035cfd9..82394a972d 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -57,7 +57,7 @@ int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *ou
if (min == i)
break;
- SWAP(pq->heap[i], pq->heap[min]);
+ REFTABLE_SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
@@ -81,7 +81,7 @@ int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry
size_t j = (i - 1) / 2;
if (pq_less(&pq->heap[j], &pq->heap[i]))
break;
- SWAP(pq->heap[j], pq->heap[i]);
+ REFTABLE_SWAP(pq->heap[j], pq->heap[i]);
i = j;
}
diff --git a/reftable/record.c b/reftable/record.c
index 3552bafa99..9a1edf39a0 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -237,11 +237,11 @@ static int reftable_ref_record_copy_from(void *rec, const void *src_rec,
size_t refname_cap = 0;
int err;
- SWAP(refname, ref->refname);
- SWAP(refname_cap, ref->refname_cap);
+ REFTABLE_SWAP(refname, ref->refname);
+ REFTABLE_SWAP(refname_cap, ref->refname_cap);
reftable_ref_record_release(ref);
- SWAP(ref->refname, refname);
- SWAP(ref->refname_cap, refname_cap);
+ REFTABLE_SWAP(ref->refname, refname);
+ REFTABLE_SWAP(ref->refname_cap, refname_cap);
if (src->refname) {
size_t refname_len = strlen(src->refname);
@@ -376,11 +376,11 @@ static int reftable_ref_record_decode(void *rec, struct reftable_buf key,
return n;
string_view_consume(&in, n);
- SWAP(refname, r->refname);
- SWAP(refname_cap, r->refname_cap);
+ REFTABLE_SWAP(refname, r->refname);
+ REFTABLE_SWAP(refname_cap, r->refname_cap);
reftable_ref_record_release(r);
- SWAP(r->refname, refname);
- SWAP(r->refname_cap, refname_cap);
+ REFTABLE_SWAP(r->refname, refname);
+ REFTABLE_SWAP(r->refname_cap, refname_cap);
REFTABLE_ALLOC_GROW_OR_NULL(r->refname, key.len + 1, r->refname_cap);
if (!r->refname) {
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 14/18] reftable/basics: introduce `REFTABLE_UNUSED` annotation
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (12 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
` (3 subsequent siblings)
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Toon Claes
Introduce the `REFTABLE_UNUSED` annotation and replace all existing
users of `UNUSED` in the reftable library to use the new macro instead.
Note that we unconditionally define `MAYBE_UNUSED` in the exact same
way, so doing so unconditionally for `REFTABLE_UNUSED` should be fine,
too.
Suggested-by: Toon Claes <toon@iotcl.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 2 ++
reftable/blocksource.c | 6 +++---
reftable/iter.c | 10 +++++-----
reftable/record.c | 26 +++++++++++++-------------
reftable/writer.c | 2 +-
5 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index 59000798f0..fd59cbb772 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -16,6 +16,8 @@ license that can be found in the LICENSE file or at
#include "system.h"
#include "reftable-basics.h"
+#define REFTABLE_UNUSED __attribute__((__unused__))
+
struct reftable_buf {
size_t alloc;
size_t len;
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index 02972c46f4..78c1be2337 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -13,14 +13,14 @@ license that can be found in the LICENSE file or at
#include "reftable-blocksource.h"
#include "reftable-error.h"
-static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)
+static void reftable_buf_return_block(void *b REFTABLE_UNUSED, struct reftable_block *dest)
{
if (dest->len)
memset(dest->data, 0xff, dest->len);
reftable_free(dest->data);
}
-static void reftable_buf_close(void *b UNUSED)
+static void reftable_buf_close(void *b REFTABLE_UNUSED)
{
}
@@ -67,7 +67,7 @@ static uint64_t file_size(void *b)
return ((struct file_block_source *)b)->size;
}
-static void file_return_block(void *b UNUSED, struct reftable_block *dest UNUSED)
+static void file_return_block(void *b REFTABLE_UNUSED, struct reftable_block *dest REFTABLE_UNUSED)
{
}
diff --git a/reftable/iter.c b/reftable/iter.c
index b2ffb09c16..f520382e70 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -25,17 +25,17 @@ int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
return it->ops->next(it->iter_arg, rec);
}
-static int empty_iterator_seek(void *arg UNUSED, struct reftable_record *want UNUSED)
+static int empty_iterator_seek(void *arg REFTABLE_UNUSED, struct reftable_record *want REFTABLE_UNUSED)
{
return 0;
}
-static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED)
+static int empty_iterator_next(void *arg REFTABLE_UNUSED, struct reftable_record *rec REFTABLE_UNUSED)
{
return 1;
}
-static void empty_iterator_close(void *arg UNUSED)
+static void empty_iterator_close(void *arg REFTABLE_UNUSED)
{
}
@@ -143,8 +143,8 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
return 0;
}
-static int indexed_table_ref_iter_seek(void *p UNUSED,
- struct reftable_record *want UNUSED)
+static int indexed_table_ref_iter_seek(void *p REFTABLE_UNUSED,
+ struct reftable_record *want REFTABLE_UNUSED)
{
return REFTABLE_API_ERROR;
}
diff --git a/reftable/record.c b/reftable/record.c
index 9a1edf39a0..142853d507 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -490,7 +490,7 @@ static void reftable_obj_record_release(void *rec)
}
static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
struct reftable_obj_record *obj = rec;
const struct reftable_obj_record *src = src_rec;
@@ -528,7 +528,7 @@ static uint8_t reftable_obj_record_val_type(const void *rec)
}
static int reftable_obj_record_encode(const void *rec, struct string_view s,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
const struct reftable_obj_record *r = rec;
struct string_view start = s;
@@ -563,8 +563,8 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,
static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
uint8_t val_type, struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED,
+ struct reftable_buf *scratch REFTABLE_UNUSED)
{
struct string_view start = in;
struct reftable_obj_record *r = rec;
@@ -618,13 +618,13 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
return start.len - in.len;
}
-static int not_a_deletion(const void *p UNUSED)
+static int not_a_deletion(const void *p REFTABLE_UNUSED)
{
return 0;
}
static int reftable_obj_record_equal_void(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
struct reftable_obj_record *ra = (struct reftable_obj_record *) a;
struct reftable_obj_record *rb = (struct reftable_obj_record *) b;
@@ -1054,7 +1054,7 @@ static int reftable_index_record_key(const void *r, struct reftable_buf *dest)
}
static int reftable_index_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
struct reftable_index_record *dst = rec;
const struct reftable_index_record *src = src_rec;
@@ -1075,13 +1075,13 @@ static void reftable_index_record_release(void *rec)
reftable_buf_release(&idx->last_key);
}
-static uint8_t reftable_index_record_val_type(const void *rec UNUSED)
+static uint8_t reftable_index_record_val_type(const void *rec REFTABLE_UNUSED)
{
return 0;
}
static int reftable_index_record_encode(const void *rec, struct string_view out,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
const struct reftable_index_record *r =
(const struct reftable_index_record *)rec;
@@ -1097,10 +1097,10 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,
}
static int reftable_index_record_decode(void *rec, struct reftable_buf key,
- uint8_t val_type UNUSED,
+ uint8_t val_type REFTABLE_UNUSED,
struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED,
+ struct reftable_buf *scratch REFTABLE_UNUSED)
{
struct string_view start = in;
struct reftable_index_record *r = rec;
@@ -1120,7 +1120,7 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,
}
static int reftable_index_record_equal(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
struct reftable_index_record *ia = (struct reftable_index_record *) a;
struct reftable_index_record *ib = (struct reftable_index_record *) b;
diff --git a/reftable/writer.c b/reftable/writer.c
index 5961698311..bb00e89f53 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -636,7 +636,7 @@ static void write_object_record(void *void_arg, void *key)
done:;
}
-static void object_record_free(void *void_arg UNUSED, void *key)
+static void object_record_free(void *void_arg REFTABLE_UNUSED, void *key)
{
struct obj_index_tree_node *entry = key;
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 15/18] compat/mingw: split out POSIX-related bits
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (13 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 14/18] reftable/basics: introduce `REFTABLE_UNUSED` annotation Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-09 13:14 ` Johannes Sixt
2025-02-07 11:52 ` [PATCH v5 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
` (2 subsequent siblings)
17 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
Split out the POSIX-related bits from "compat/mingw.h". This is in
preparation for splitting up "git-compat-utils.h" into a header that
provides POSIX-compatibility and a header that provides common wrappers
used by the Git project.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/{mingw.c => mingw/compat-util.c} | 28 ++--
compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
compat/msvc.c | 6 -
compat/msvc/compat-util.c | 6 +
compat/msvc/compat-util.h | 7 +
compat/{msvc.h => msvc/posix.h} | 8 +-
config.mak.uname | 6 +-
contrib/buildsystems/CMakeLists.txt | 2 +-
git-compat-util.h | 4 +-
meson.build | 8 +-
11 files changed, 266 insertions(+), 245 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw/compat-util.c
similarity index 99%
rename from compat/mingw.c
rename to compat/mingw/compat-util.c
index 1d5b211b54..aeb569bcea 100644
--- a/compat/mingw.c
+++ b/compat/mingw/compat-util.c
@@ -1,24 +1,24 @@
#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS
-#include "../git-compat-util.h"
-#include "win32.h"
+#include "../../git-compat-util.h"
+#include "../win32.h"
#include <aclapi.h>
#include <sddl.h>
#include <conio.h>
#include <wchar.h>
-#include "../strbuf.h"
-#include "../run-command.h"
-#include "../abspath.h"
-#include "../alloc.h"
-#include "win32/lazyload.h"
-#include "../config.h"
-#include "../environment.h"
-#include "../trace2.h"
-#include "../symlinks.h"
-#include "../wrapper.h"
-#include "dir.h"
-#include "gettext.h"
+#include "../../strbuf.h"
+#include "../../run-command.h"
+#include "../../abspath.h"
+#include "../../alloc.h"
+#include "../win32/lazyload.h"
+#include "../../config.h"
+#include "../../environment.h"
+#include "../../trace2.h"
+#include "../../symlinks.h"
+#include "../../wrapper.h"
+#include "../../dir.h"
+#include "../../gettext.h"
#define SECURITY_WIN32
#include <sspi.h>
diff --git a/compat/mingw/compat-util.h b/compat/mingw/compat-util.h
new file mode 100644
index 0000000000..470542d309
--- /dev/null
+++ b/compat/mingw/compat-util.h
@@ -0,0 +1,220 @@
+#ifndef COMPAT_MINGW_COMPAT_UTIL_H
+#define COMPAT_MINGW_COMPAT_UTIL_H
+
+#include "posix.h"
+
+struct config_context;
+int mingw_core_config(const char *var, const char *value,
+ const struct config_context *ctx, void *cb);
+#define platform_core_config mingw_core_config
+
+#ifndef NO_OPENSSL
+#include <openssl/ssl.h>
+static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
+{
+ return SSL_set_fd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_fd mingw_SSL_set_fd
+
+static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
+{
+ return SSL_set_rfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_rfd mingw_SSL_set_rfd
+
+static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
+{
+ return SSL_set_wfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_wfd mingw_SSL_set_wfd
+#endif
+
+/*
+ * git specific compatibility
+ */
+
+static inline void convert_slashes(char *path)
+{
+ for (; *path; path++)
+ if (*path == '\\')
+ *path = '/';
+}
+#define PATH_SEP ';'
+char *mingw_query_user_email(void);
+#define query_user_email mingw_query_user_email
+
+/**
+ * Verifies that the specified path is owned by the user running the
+ * current process.
+ */
+int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
+#define is_path_owned_by_current_user is_path_owned_by_current_sid
+
+/**
+ * Verifies that the given path is a valid one on Windows.
+ *
+ * In particular, path segments are disallowed which
+ *
+ * - end in a period or a space (except the special directories `.` and `..`).
+ *
+ * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
+ *
+ * - correspond to reserved names (such as `AUX`, `PRN`, etc)
+ *
+ * The `allow_literal_nul` parameter controls whether the path `NUL` should
+ * be considered valid (this makes sense e.g. before opening files, as it is
+ * perfectly legitimate to open `NUL` on Windows, just as it is to open
+ * `/dev/null` on Unix/Linux).
+ *
+ * Returns 1 upon success, otherwise 0.
+ */
+int is_valid_win32_path(const char *path, int allow_literal_nul);
+#define is_valid_path(path) is_valid_win32_path(path, 0)
+
+/**
+ * Converts UTF-8 encoded string to UTF-16LE.
+ *
+ * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
+ * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
+ * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
+ * Unicode) are converted to hex-code.
+ *
+ * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
+ * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
+ *
+ * Maximum space requirement for the target buffer is two wide chars per UTF-8
+ * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
+ *
+ * | | UTF-8 | UTF-16 |
+ * Code point | UTF-8 sequence | bytes | words | ratio
+ * --------------+-------------------+-------+--------+-------
+ * 000000-00007f | 0-7f | 1 | 1 | 1
+ * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
+ * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
+ * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
+ * invalid | 80-9f | 1 | 2 (b) | 2
+ * invalid | a0-ff | 1 | 1 | 1
+ *
+ * (a) encoded as UTF-16 surrogate pair
+ * (b) encoded as two hex digits
+ *
+ * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
+ * or even indefinite-byte sequences, the largest valid code point \u10ffff
+ * encodes as only 4 UTF-8 bytes.
+ *
+ * Parameters:
+ * wcs: wide char target buffer
+ * utf: string to convert
+ * wcslen: size of target buffer (in wchar_t's)
+ * utflen: size of string to convert, or -1 if 0-terminated
+ *
+ * Returns:
+ * length of converted string (_wcslen(wcs)), or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
+
+/**
+ * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
+ */
+static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
+{
+ return xutftowcsn(wcs, utf, wcslen, -1);
+}
+
+/**
+ * Simplified file system specific variant of xutftowcsn, assumes output
+ * buffer size is MAX_PATH wide chars and input string is \0-terminated,
+ * fails with ENAMETOOLONG if input string is too long.
+ */
+static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
+{
+ int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
+ if (result < 0 && errno == ERANGE)
+ errno = ENAMETOOLONG;
+ return result;
+}
+
+/**
+ * Converts UTF-16LE encoded string to UTF-8.
+ *
+ * Maximum space requirement for the target buffer is three UTF-8 chars per
+ * wide char ((_wcslen(wcs) * 3) + 1).
+ *
+ * The maximum space is needed only if the entire input string consists of
+ * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
+ * modulo surrogate pairs), as per the following table:
+ *
+ * | | UTF-16 | UTF-8 |
+ * Code point | UTF-16 sequence | words | bytes | ratio
+ * --------------+-----------------------+--------+-------+-------
+ * 000000-00007f | 0000-007f | 1 | 1 | 1
+ * 000080-0007ff | 0080-07ff | 1 | 2 | 2
+ * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
+ * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
+ *
+ * Note that invalid code points > 10ffff cannot be represented in UTF-16.
+ *
+ * Parameters:
+ * utf: target buffer
+ * wcs: wide string to convert
+ * utflen: size of target buffer
+ *
+ * Returns:
+ * length of converted string, or -1 on failure
+ *
+ * Errors:
+ * EINVAL: one of the input parameters is invalid (e.g. NULL)
+ * ERANGE: the output buffer is too small
+ */
+int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
+
+/*
+ * A critical section used in the implementation of the spawn
+ * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
+ * the replacement main() macro below.
+ */
+extern CRITICAL_SECTION pinfo_cs;
+
+/*
+ * Git, like most portable C applications, implements a main() function. On
+ * Windows, this main() function would receive parameters encoded in the
+ * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
+ *
+ * To make that happen, we still declare main() here, and then declare and
+ * implement wmain() (which is the Unicode variant of main()) and compile with
+ * -municode. This wmain() function reencodes the parameters from UTF-16 to
+ * UTF-8 format, sets up a couple of other things as required on Windows, and
+ * then hands off to the main() function.
+ */
+int wmain(int argc, const wchar_t **w_argv);
+int main(int argc, const char **argv);
+
+/*
+ * For debugging: if a problem occurs, say, in a Git process that is spawned
+ * from another Git process which in turn is spawned from yet another Git
+ * process, it can be quite daunting to figure out what is going on.
+ *
+ * Call this function to open a new MinTTY (this assumes you are in Git for
+ * Windows' SDK) with a GDB that attaches to the current process right away.
+ */
+void open_in_gdb(void);
+
+/*
+ * Used by Pthread API implementation for Windows
+ */
+int err_win_to_posix(DWORD winerr);
+
+#ifndef NO_UNIX_SOCKETS
+int mingw_have_unix_sockets(void);
+#undef have_unix_sockets
+#define have_unix_sockets mingw_have_unix_sockets
+#endif
+
+#endif /* COMPAT_MINGW_COMPAT_UTIL_H */
diff --git a/compat/mingw.h b/compat/mingw/posix.h
similarity index 59%
rename from compat/mingw.h
rename to compat/mingw/posix.h
index ebfb8ba423..8dddfa818d 100644
--- a/compat/mingw.h
+++ b/compat/mingw/posix.h
@@ -1,3 +1,6 @@
+#ifndef COMPAT_MINGW_POSIX_H
+#define COMPAT_MINGW_POSIX_H
+
#ifdef __MINGW64_VERSION_MAJOR
#include <stdint.h>
#include <wchar.h>
@@ -11,11 +14,6 @@ typedef _sigset_t sigset_t;
#undef _POSIX_THREAD_SAFE_FUNCTIONS
#endif
-struct config_context;
-int mingw_core_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb);
-#define platform_core_config mingw_core_config
-
/*
* things that are not available in header files
*/
@@ -180,27 +178,6 @@ int mingw_kill(pid_t pid, int sig);
#define locate_in_PATH mingw_locate_in_PATH
char *mingw_locate_in_PATH(const char *cmd);
-#ifndef NO_OPENSSL
-#include <openssl/ssl.h>
-static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
-{
- return SSL_set_fd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_fd mingw_SSL_set_fd
-
-static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
-{
- return SSL_set_rfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_rfd mingw_SSL_set_rfd
-
-static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
-{
- return SSL_set_wfd(ssl, _get_osfhandle(fd));
-}
-#define SSL_set_wfd mingw_SSL_set_wfd
-#endif
-
/*
* implementations of missing functions
*/
@@ -444,19 +421,6 @@ int winansi_dup2(int oldfd, int newfd);
void winansi_init(void);
HANDLE winansi_get_osfhandle(int fd);
-/*
- * git specific compatibility
- */
-
-static inline void convert_slashes(char *path)
-{
- for (; *path; path++)
- if (*path == '\\')
- *path = '/';
-}
-#define PATH_SEP ';'
-char *mingw_query_user_email(void);
-#define query_user_email mingw_query_user_email
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
#define PRIuMAX "I64u"
#define PRId64 "I64d"
@@ -464,176 +428,4 @@ char *mingw_query_user_email(void);
#include <inttypes.h>
#endif
-/**
- * Verifies that the specified path is owned by the user running the
- * current process.
- */
-int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
-#define is_path_owned_by_current_user is_path_owned_by_current_sid
-
-/**
- * Verifies that the given path is a valid one on Windows.
- *
- * In particular, path segments are disallowed which
- *
- * - end in a period or a space (except the special directories `.` and `..`).
- *
- * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
- *
- * - correspond to reserved names (such as `AUX`, `PRN`, etc)
- *
- * The `allow_literal_nul` parameter controls whether the path `NUL` should
- * be considered valid (this makes sense e.g. before opening files, as it is
- * perfectly legitimate to open `NUL` on Windows, just as it is to open
- * `/dev/null` on Unix/Linux).
- *
- * Returns 1 upon success, otherwise 0.
- */
-int is_valid_win32_path(const char *path, int allow_literal_nul);
-#define is_valid_path(path) is_valid_win32_path(path, 0)
-
-/**
- * Converts UTF-8 encoded string to UTF-16LE.
- *
- * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
- * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
- * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
- * Unicode) are converted to hex-code.
- *
- * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
- * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
- *
- * Maximum space requirement for the target buffer is two wide chars per UTF-8
- * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
- *
- * The maximum space is needed only if the entire input string consists of
- * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
- *
- * | | UTF-8 | UTF-16 |
- * Code point | UTF-8 sequence | bytes | words | ratio
- * --------------+-------------------+-------+--------+-------
- * 000000-00007f | 0-7f | 1 | 1 | 1
- * 000080-0007ff | c2-df + 80-bf | 2 | 1 | 0.5
- * 000800-00ffff | e0-ef + 2 * 80-bf | 3 | 1 | 0.33
- * 010000-10ffff | f0-f4 + 3 * 80-bf | 4 | 2 (a) | 0.5
- * invalid | 80-9f | 1 | 2 (b) | 2
- * invalid | a0-ff | 1 | 1 | 1
- *
- * (a) encoded as UTF-16 surrogate pair
- * (b) encoded as two hex digits
- *
- * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
- * or even indefinite-byte sequences, the largest valid code point \u10ffff
- * encodes as only 4 UTF-8 bytes.
- *
- * Parameters:
- * wcs: wide char target buffer
- * utf: string to convert
- * wcslen: size of target buffer (in wchar_t's)
- * utflen: size of string to convert, or -1 if 0-terminated
- *
- * Returns:
- * length of converted string (_wcslen(wcs)), or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
-
-/**
- * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
- */
-static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
-{
- return xutftowcsn(wcs, utf, wcslen, -1);
-}
-
-/**
- * Simplified file system specific variant of xutftowcsn, assumes output
- * buffer size is MAX_PATH wide chars and input string is \0-terminated,
- * fails with ENAMETOOLONG if input string is too long.
- */
-static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
-{
- int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
- if (result < 0 && errno == ERANGE)
- errno = ENAMETOOLONG;
- return result;
-}
-
-/**
- * Converts UTF-16LE encoded string to UTF-8.
- *
- * Maximum space requirement for the target buffer is three UTF-8 chars per
- * wide char ((_wcslen(wcs) * 3) + 1).
- *
- * The maximum space is needed only if the entire input string consists of
- * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
- * modulo surrogate pairs), as per the following table:
- *
- * | | UTF-16 | UTF-8 |
- * Code point | UTF-16 sequence | words | bytes | ratio
- * --------------+-----------------------+--------+-------+-------
- * 000000-00007f | 0000-007f | 1 | 1 | 1
- * 000080-0007ff | 0080-07ff | 1 | 2 | 2
- * 000800-00ffff | 0800-d7ff / e000-ffff | 1 | 3 | 3
- * 010000-10ffff | d800-dbff + dc00-dfff | 2 | 4 | 2
- *
- * Note that invalid code points > 10ffff cannot be represented in UTF-16.
- *
- * Parameters:
- * utf: target buffer
- * wcs: wide string to convert
- * utflen: size of target buffer
- *
- * Returns:
- * length of converted string, or -1 on failure
- *
- * Errors:
- * EINVAL: one of the input parameters is invalid (e.g. NULL)
- * ERANGE: the output buffer is too small
- */
-int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
-
-/*
- * A critical section used in the implementation of the spawn
- * functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
- * the replacement main() macro below.
- */
-extern CRITICAL_SECTION pinfo_cs;
-
-/*
- * Git, like most portable C applications, implements a main() function. On
- * Windows, this main() function would receive parameters encoded in the
- * current locale, but Git for Windows would prefer UTF-8 encoded parameters.
- *
- * To make that happen, we still declare main() here, and then declare and
- * implement wmain() (which is the Unicode variant of main()) and compile with
- * -municode. This wmain() function reencodes the parameters from UTF-16 to
- * UTF-8 format, sets up a couple of other things as required on Windows, and
- * then hands off to the main() function.
- */
-int wmain(int argc, const wchar_t **w_argv);
-int main(int argc, const char **argv);
-
-/*
- * For debugging: if a problem occurs, say, in a Git process that is spawned
- * from another Git process which in turn is spawned from yet another Git
- * process, it can be quite daunting to figure out what is going on.
- *
- * Call this function to open a new MinTTY (this assumes you are in Git for
- * Windows' SDK) with a GDB that attaches to the current process right away.
- */
-void open_in_gdb(void);
-
-/*
- * Used by Pthread API implementation for Windows
- */
-int err_win_to_posix(DWORD winerr);
-
-#ifndef NO_UNIX_SOCKETS
-int mingw_have_unix_sockets(void);
-#undef have_unix_sockets
-#define have_unix_sockets mingw_have_unix_sockets
-#endif
+#endif /* COMPAT_MINGW_POSIX_H */
diff --git a/compat/msvc.c b/compat/msvc.c
deleted file mode 100644
index 71843d7eef..0000000000
--- a/compat/msvc.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "../git-compat-util.h"
-#include "win32.h"
-#include <conio.h>
-#include "../strbuf.h"
-
-#include "mingw.c"
diff --git a/compat/msvc/compat-util.c b/compat/msvc/compat-util.c
new file mode 100644
index 0000000000..b92e52b8b8
--- /dev/null
+++ b/compat/msvc/compat-util.c
@@ -0,0 +1,6 @@
+#include "../../git-compat-util.h"
+#include "../win32.h"
+#include <conio.h>
+#include "../../strbuf.h"
+
+#include "../mingw/compat-util.c"
diff --git a/compat/msvc/compat-util.h b/compat/msvc/compat-util.h
new file mode 100644
index 0000000000..404af236b5
--- /dev/null
+++ b/compat/msvc/compat-util.h
@@ -0,0 +1,7 @@
+#ifndef COMPAT_MSVC_COMPAT_UTIL_H
+#define COMPAT_MSVC_COMPAT_UTIL_H
+
+#include "posix.h"
+#include "../mingw/compat-util.h"
+
+#endif /* COMPAT_MSVC_COMPAT_UTIL_H */
diff --git a/compat/msvc.h b/compat/msvc/posix.h
similarity index 86%
rename from compat/msvc.h
rename to compat/msvc/posix.h
index 1d7a8c6145..703a7c2067 100644
--- a/compat/msvc.h
+++ b/compat/msvc/posix.h
@@ -1,5 +1,5 @@
-#ifndef __MSVC__HEAD
-#define __MSVC__HEAD
+#ifndef COMPAT_MSVC_POSIX_H
+#define COMPAT_MSVC_POSIX_H
#include <direct.h>
#include <process.h>
@@ -28,6 +28,6 @@ typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-#include "compat/mingw.h"
+#include "../mingw/posix.h"
-#endif
+#endif /* COMPAT_MSVC_POSIX_H */
diff --git a/config.mak.uname b/config.mak.uname
index b12d4e168a..dbd05adb5d 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -495,7 +495,7 @@ endif
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
- COMPAT_OBJS = compat/msvc.o compat/winansi.o \
+ COMPAT_OBJS = compat/msvc/compat-util.o compat/winansi.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
compat/win32/pthread.o compat/win32/syslog.o \
@@ -541,7 +541,7 @@ endif
EXTRA_PROGRAMS += headless-git$X
-compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
+compat/msvc/compat-util.o: compat/msvc/compat-util.c compat/mingw/compat-util.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease
@@ -694,7 +694,7 @@ ifeq ($(uname_S),MINGW)
BASIC_LDFLAGS += -municode
COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/winansi.o \
+ COMPAT_OBJS += compat/mingw/compat-util.o compat/winansi.o \
compat/win32/trace2_win32_process_info.o \
compat/win32/flush.o \
compat/win32/path-utils.o \
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 10dc54fdcb..65ce8705f0 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -258,7 +258,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET HAVE_RTLGENRANDOM)
list(APPEND compat_SOURCES
- compat/mingw.c
+ compat/mingw/compat-util.c
compat/winansi.c
compat/win32/flush.c
compat/win32/path-utils.c
diff --git a/git-compat-util.h b/git-compat-util.h
index e283c46c6f..b96fb98e1e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -304,10 +304,10 @@ static inline int is_xplatform_dir_sep(int c)
#if defined(__MINGW32__)
/* pull in Windows compatibility stuff */
#include "compat/win32/path-utils.h"
-#include "compat/mingw.h"
+#include "compat/mingw/compat-util.h"
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
-#include "compat/msvc.h"
+#include "compat/msvc/compat-util.h"
#else
#include <sys/utsname.h>
#include <sys/wait.h>
diff --git a/meson.build b/meson.build
index 2297f5e9dd..e8abf798f5 100644
--- a/meson.build
+++ b/meson.build
@@ -1054,7 +1054,6 @@ if host_machine.system() == 'cygwin'
]
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw.c',
'compat/winansi.c',
'compat/win32/flush.c',
'compat/win32/path-utils.c',
@@ -1081,6 +1080,9 @@ elif host_machine.system() == 'windows'
libgit_include_directories += 'compat/win32'
if compiler.get_id() == 'msvc'
libgit_include_directories += 'compat/vcbuild/include'
+ libgit_sources += 'compat/msvc/compat-util.c'
+ else
+ libgit_sources += 'compat/mingw/compat-util.c'
endif
endif
@@ -1157,7 +1159,7 @@ else
error('Native regex support requested but not found')
endif
-# setitimer and friends are provided by compat/mingw.c.
+# setitimer and friends are provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows'
if not compiler.compiles('''
#include <sys/time.h>
@@ -1237,7 +1239,7 @@ if not compiler.has_function('qsort')
endif
libgit_sources += 'compat/qsort_s.c'
-# unsetenv is provided by compat/mingw.c.
+# unsetenv is provided by compat/mingw/compat-util.c.
if host_machine.system() != 'windows' and not compiler.has_function('unsetenv')
libgit_c_args += '-DNO_UNSETENV'
libgit_sources += 'compat/unsetenv.c'
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 16/18] git-compat-util.h: split out POSIX-emulating bits
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (14 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
The "git-compat-util.h" header is a treasure trove of various bits and
pieces used throughout the project. It basically mixes two different
things into one:
- Providing a POSIX-like interface even on platforms that aren't
POSIX-compliant.
- Providing low-level functionality that is specific to Git.
This intermixing is a bit of a problem for the reftable library as we
don't want to recreate the POSIX-like interface there. But neither do we
want to pull in the Git-specific functionality, as it is otherwise quite
easy to start depending on the Git codebase again.
Split out a new header "compat/posix.h" that only contains the bits and
pieces relevant for the emulation of POSIX, which we will start using in
the next commit.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/posix.h | 541 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
git-compat-util.h | 531 +----------------------------------------------------
2 files changed, 543 insertions(+), 529 deletions(-)
diff --git a/compat/posix.h b/compat/posix.h
new file mode 100644
index 0000000000..7e6c4c1a1f
--- /dev/null
+++ b/compat/posix.h
@@ -0,0 +1,541 @@
+#ifndef COMPAT_POSIX_H
+#define COMPAT_POSIX_H
+
+#define _FILE_OFFSET_BITS 64
+
+/*
+ * Derived from Linux "Features Test Macro" header
+ * Convenience macros to test the versions of gcc (or
+ * a compatible compiler).
+ * Use them like this:
+ * #if GIT_GNUC_PREREQ (2,8)
+ * ... code requiring gcc 2.8 or later ...
+ * #endif
+ *
+ * This macro of course is not part of POSIX, but we need it for the UNUSED
+ * macro which is used by some of our POSIX compatibility wrappers.
+*/
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define GIT_GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+ #define GIT_GNUC_PREREQ(maj, min) 0
+#endif
+
+/*
+ * UNUSED marks a function parameter that is always unused. It also
+ * can be used to annotate a function, a variable, or a type that is
+ * always unused.
+ *
+ * A callback interface may dictate that a function accepts a
+ * parameter at that position, but the implementation of the function
+ * may not need to use the parameter. In such a case, mark the parameter
+ * with UNUSED.
+ *
+ * When a parameter may be used or unused, depending on conditional
+ * compilation, consider using MAYBE_UNUSED instead.
+ */
+#if GIT_GNUC_PREREQ(4, 5)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated ("parameter declared as UNUSED")))
+#elif defined(__GNUC__)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated))
+#else
+#define UNUSED
+#endif
+
+#ifdef __MINGW64__
+#define _POSIX_C_SOURCE 1
+#elif defined(__sun__)
+ /*
+ * On Solaris, when _XOPEN_EXTENDED is set, its header file
+ * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
+ * setting to say we are XPG5 or XPG6. Also on Solaris,
+ * XPG6 programs must be compiled with a c99 compiler, while
+ * non XPG6 programs must be compiled with a pre-c99 compiler.
+ */
+# if __STDC_VERSION__ - 0 >= 199901L
+# define _XOPEN_SOURCE 600
+# else
+# define _XOPEN_SOURCE 500
+# endif
+#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
+ !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
+ !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
+ !defined(__CYGWIN__)
+#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
+#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
+#endif
+#define _ALL_SOURCE 1
+#define _GNU_SOURCE 1
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+#define _NETBSD_SOURCE 1
+#define _SGI_SOURCE 1
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
+# if !defined(_WIN32_WINNT)
+# define _WIN32_WINNT 0x0600
+# endif
+#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
+#include <winsock2.h>
+#ifndef NO_UNIX_SOCKETS
+#include <afunix.h>
+#endif
+#include <windows.h>
+#define GIT_WINDOWS_NATIVE
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h> /* for strcasecmp() */
+#endif
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#ifdef NEEDS_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#include <syslog.h>
+#if !defined(NO_POLL_H)
+#include <poll.h>
+#elif !defined(NO_SYS_POLL_H)
+#include <sys/poll.h>
+#else
+/* Pull the compat stuff */
+#include <poll.h>
+#endif
+#ifdef HAVE_BSD_SYSCTL
+#include <sys/sysctl.h>
+#endif
+
+#if defined(__MINGW32__)
+#include "mingw/posix.h"
+#elif defined(_MSC_VER)
+#include "msvc/posix.h"
+#else
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/statvfs.h>
+#include <termios.h>
+#ifndef NO_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/un.h>
+#ifndef NO_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+#ifdef HAVE_ARC4RANDOM_LIBBSD
+#include <bsd/stdlib.h>
+#endif
+#ifdef HAVE_GETRANDOM
+#include <sys/random.h>
+#endif
+#ifdef NO_INTPTR_T
+/*
+ * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
+ * on LLP86, IL33LLP64 and P64 it needs to be "long long",
+ * while on IP16 and IP16L32 it is "int" (resp. "short")
+ * Size needs to match (or exceed) 'sizeof(void *)'.
+ * We can't take "long long" here as not everybody has it.
+ */
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+#endif
+#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
+#include <grp.h>
+#define _ALL_SOURCE 1
+#endif
+
+#ifdef MKDIR_WO_TRAILING_SLASH
+#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
+int compat_mkdir_wo_trailing_slash(const char*, mode_t);
+#endif
+
+#ifdef time
+#undef time
+#endif
+static inline time_t git_time(time_t *tloc)
+{
+ struct timeval tv;
+
+ /*
+ * Avoid time(NULL), which can disagree with gettimeofday(2)
+ * and filesystem timestamps.
+ */
+ gettimeofday(&tv, NULL);
+
+ if (tloc)
+ *tloc = tv.tv_sec;
+ return tv.tv_sec;
+}
+#define time git_time
+
+#ifdef NO_STRUCT_ITIMERVAL
+struct itimerval {
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+#endif
+
+#ifdef NO_SETITIMER
+static inline int git_setitimer(int which UNUSED,
+ const struct itimerval *value UNUSED,
+ struct itimerval *newvalue UNUSED) {
+ return 0; /* pretend success */
+}
+#undef setitimer
+#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
+#endif
+
+#ifndef NO_LIBGEN_H
+#include <libgen.h>
+#else
+#define basename gitbasename
+char *gitbasename(char *);
+#define dirname gitdirname
+char *gitdirname(char *);
+#endif
+
+#ifndef NO_ICONV
+#include <iconv.h>
+#endif
+
+/* On most systems <netdb.h> would have given us this, but
+ * not on some systems (e.g. z/OS).
+ */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+/* On most systems <limits.h> would have given us this, but
+ * not on some systems (e.g. GNU/Hurd).
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+typedef uintmax_t timestamp_t;
+#define PRItime PRIuMAX
+#define parse_timestamp strtoumax
+#define TIME_MAX UINTMAX_MAX
+#define TIME_MIN 0
+
+int lstat_cache_aware_rmdir(const char *path);
+#if !defined(__MINGW32__) && !defined(_MSC_VER)
+#define rmdir lstat_cache_aware_rmdir
+#endif
+
+#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
+
+#ifndef PROT_READ
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define MAP_PRIVATE 1
+#endif
+
+#define mmap git_mmap
+#define munmap git_munmap
+void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int git_munmap(void *start, size_t length);
+
+#else /* NO_MMAP || USE_WIN32_MMAP */
+
+#include <sys/mman.h>
+
+#endif /* NO_MMAP || USE_WIN32_MMAP */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#ifdef NEEDS_MODE_TRANSLATION
+#undef S_IFMT
+#undef S_IFREG
+#undef S_IFDIR
+#undef S_IFLNK
+#undef S_IFBLK
+#undef S_IFCHR
+#undef S_IFIFO
+#undef S_IFSOCK
+#define S_IFMT 0170000
+#define S_IFREG 0100000
+#define S_IFDIR 0040000
+#define S_IFLNK 0120000
+#define S_IFBLK 0060000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_IFSOCK 0140000
+#ifdef stat
+#undef stat
+#endif
+#define stat(path, buf) git_stat(path, buf)
+int git_stat(const char *, struct stat *);
+#ifdef fstat
+#undef fstat
+#endif
+#define fstat(fd, buf) git_fstat(fd, buf)
+int git_fstat(int, struct stat *);
+#ifdef lstat
+#undef lstat
+#endif
+#define lstat(path, buf) git_lstat(path, buf)
+int git_lstat(const char *, struct stat *);
+#endif
+
+#ifdef NO_PREAD
+#define pread git_pread
+ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+
+#ifdef NO_SETENV
+#define setenv gitsetenv
+int gitsetenv(const char *, const char *, int);
+#endif
+
+#ifdef NO_MKDTEMP
+#define mkdtemp gitmkdtemp
+char *gitmkdtemp(char *);
+#endif
+
+#ifdef NO_UNSETENV
+#define unsetenv gitunsetenv
+int gitunsetenv(const char *);
+#endif
+
+#ifdef NO_STRCASESTR
+#define strcasestr gitstrcasestr
+char *gitstrcasestr(const char *haystack, const char *needle);
+#endif
+
+#ifdef NO_STRLCPY
+#define strlcpy gitstrlcpy
+size_t gitstrlcpy(char *, const char *, size_t);
+#endif
+
+#ifdef NO_STRTOUMAX
+#define strtoumax gitstrtoumax
+uintmax_t gitstrtoumax(const char *, char **, int);
+#define strtoimax gitstrtoimax
+intmax_t gitstrtoimax(const char *, char **, int);
+#endif
+
+#ifdef NO_HSTRERROR
+#define hstrerror githstrerror
+const char *githstrerror(int herror);
+#endif
+
+#ifdef NO_MEMMEM
+#define memmem gitmemmem
+void *gitmemmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+#endif
+
+#ifdef OVERRIDE_STRDUP
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup gitstrdup
+char *gitstrdup(const char *s);
+#endif
+
+#ifdef NO_GETPAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifdef FREAD_READS_DIRECTORIES
+# if !defined(SUPPRESS_FOPEN_REDEFINITION)
+# ifdef fopen
+# undef fopen
+# endif
+# define fopen(a,b) git_fopen(a,b)
+# endif
+FILE *git_fopen(const char*, const char*);
+#endif
+
+#ifdef SNPRINTF_RETURNS_BOGUS
+#ifdef snprintf
+#undef snprintf
+#endif
+#define snprintf git_snprintf
+int git_snprintf(char *str, size_t maxsize,
+ const char *format, ...);
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#define vsnprintf git_vsnprintf
+int git_vsnprintf(char *str, size_t maxsize,
+ const char *format, va_list ap);
+#endif
+
+#ifdef OPEN_RETURNS_EINTR
+#undef open
+#define open git_open_with_retry
+int git_open_with_retry(const char *path, int flag, ...);
+#endif
+
+#ifdef __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2, 1)
+#define HAVE_STRCHRNUL
+#endif
+#endif
+
+#ifndef HAVE_STRCHRNUL
+#define strchrnul gitstrchrnul
+static inline char *gitstrchrnul(const char *s, int c)
+{
+ while (*s && *s != c)
+ s++;
+ return (char *)s;
+}
+#endif
+
+#ifdef NO_INET_PTON
+int inet_pton(int af, const char *src, void *dst);
+#endif
+
+#ifdef NO_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
+#ifdef NO_PTHREADS
+#define atexit git_atexit
+int git_atexit(void (*handler)(void));
+#endif
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
+#include "../sane-ctype.h"
+
+void git_stable_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
+#ifdef INTERNAL_QSORT
+#define qsort git_stable_qsort
+#endif
+
+#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
+static inline void sane_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *))
+{
+ if (nmemb > 1)
+ qsort(base, nmemb, size, compar);
+}
+
+#define STABLE_QSORT(base, n, compar) \
+ git_stable_qsort((base), (n), sizeof(*(base)), compar)
+
+#ifndef HAVE_ISO_QSORT_S
+int git_qsort_s(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *), void *ctx);
+#define qsort_s git_qsort_s
+#endif
+
+#define QSORT_S(base, n, compar, ctx) do { \
+ if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
+ BUG("qsort_s() failed"); \
+} while (0)
+
+#ifdef NO_NSEC
+#undef USE_NSEC
+#define ST_CTIME_NSEC(st) 0
+#define ST_MTIME_NSEC(st) 0
+#else
+#ifdef USE_ST_TIMESPEC
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
+#else
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
+#endif
+#endif
+
+#ifndef va_copy
+/*
+ * Since an obvious implementation of va_list would be to make it a
+ * pointer into the stack frame, a simple assignment will work on
+ * many systems. But let's try to be more portable.
+ */
+#ifdef __va_copy
+#define va_copy(dst, src) __va_copy(dst, src)
+#else
+#define va_copy(dst, src) ((dst) = (src))
+#endif
+#endif
+
+#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+static inline void git_flockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+static inline void git_funlockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+#undef flockfile
+#undef funlockfile
+#undef getc_unlocked
+#define flockfile(fh) git_flockfile(fh)
+#define funlockfile(fh) git_funlockfile(fh)
+#define getc_unlocked(fh) getc(fh)
+#endif
+
+#ifdef FILENO_IS_A_MACRO
+int git_fileno(FILE *stream);
+# ifndef COMPAT_CODE_FILENO
+# undef fileno
+# define fileno(p) git_fileno(p)
+# endif
+#endif
+
+#ifdef NEED_ACCESS_ROOT_HANDLER
+int git_access(const char *path, int mode);
+# ifndef COMPAT_CODE_ACCESS
+# ifdef access
+# undef access
+# endif
+# define access(path, mode) git_access(path, mode)
+# endif
+#endif
+
+#endif /* COMPAT_POSIX_H */
diff --git a/git-compat-util.h b/git-compat-util.h
index b96fb98e1e..30ad0725fb 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -23,26 +23,9 @@
#include <crtdbg.h>
#endif
-struct strbuf;
-
-
-#define _FILE_OFFSET_BITS 64
+#include "compat/posix.h"
-
-/* Derived from Linux "Features Test Macro" header
- * Convenience macros to test the versions of gcc (or
- * a compatible compiler).
- * Use them like this:
- * #if GIT_GNUC_PREREQ (2,8)
- * ... code requiring gcc 2.8 or later ...
- * #endif
-*/
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define GIT_GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-#else
- #define GIT_GNUC_PREREQ(maj, min) 0
-#endif
+struct strbuf;
#if defined(__GNUC__) || defined(__clang__)
# define PRAGMA(pragma) _Pragma(#pragma)
@@ -176,71 +159,6 @@ DISABLE_WARNING(-Wsign-compare)
/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-#ifdef __MINGW64__
-#define _POSIX_C_SOURCE 1
-#elif defined(__sun__)
- /*
- * On Solaris, when _XOPEN_EXTENDED is set, its header file
- * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
- * setting to say we are XPG5 or XPG6. Also on Solaris,
- * XPG6 programs must be compiled with a c99 compiler, while
- * non XPG6 programs must be compiled with a pre-c99 compiler.
- */
-# if __STDC_VERSION__ - 0 >= 199901L
-# define _XOPEN_SOURCE 600
-# else
-# define _XOPEN_SOURCE 500
-# endif
-#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
- !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
- !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
- !defined(__CYGWIN__)
-#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
-#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
-#endif
-#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
-#define _BSD_SOURCE 1
-#define _DEFAULT_SOURCE 1
-#define _NETBSD_SOURCE 1
-#define _SGI_SOURCE 1
-
-/*
- * UNUSED marks a function parameter that is always unused. It also
- * can be used to annotate a function, a variable, or a type that is
- * always unused.
- *
- * A callback interface may dictate that a function accepts a
- * parameter at that position, but the implementation of the function
- * may not need to use the parameter. In such a case, mark the parameter
- * with UNUSED.
- *
- * When a parameter may be used or unused, depending on conditional
- * compilation, consider using MAYBE_UNUSED instead.
- */
-#if GIT_GNUC_PREREQ(4, 5)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated ("parameter declared as UNUSED")))
-#elif defined(__GNUC__)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated))
-#else
-#define UNUSED
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
-# if !defined(_WIN32_WINNT)
-# define _WIN32_WINNT 0x0600
-# endif
-#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
-#include <winsock2.h>
-#ifndef NO_UNIX_SOCKETS
-#include <afunix.h>
-#endif
-#include <windows.h>
-#define GIT_WINDOWS_NATIVE
-#endif
-
#if defined(NO_UNIX_SOCKETS) || !defined(GIT_WINDOWS_NATIVE)
static inline int _have_unix_sockets(void)
{
@@ -253,45 +171,6 @@ static inline int _have_unix_sockets(void)
#define have_unix_sockets _have_unix_sockets
#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h> /* for strcasecmp() */
-#endif
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#ifdef NEEDS_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <time.h>
-#include <signal.h>
-#include <assert.h>
-#include <regex.h>
-#include <utime.h>
-#include <syslog.h>
-#if !defined(NO_POLL_H)
-#include <poll.h>
-#elif !defined(NO_SYS_POLL_H)
-#include <sys/poll.h>
-#else
-/* Pull the compat stuff */
-#include <poll.h>
-#endif
-#ifdef HAVE_BSD_SYSCTL
-#include <sys/sysctl.h>
-#endif
-
/* Used by compat/win32/path-utils.h, and more */
static inline int is_xplatform_dir_sep(int c)
{
@@ -308,48 +187,6 @@ static inline int is_xplatform_dir_sep(int c)
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
#include "compat/msvc/compat-util.h"
-#else
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/statvfs.h>
-#include <termios.h>
-#ifndef NO_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <sys/un.h>
-#ifndef NO_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <stdint.h>
-#endif
-#ifdef HAVE_ARC4RANDOM_LIBBSD
-#include <bsd/stdlib.h>
-#endif
-#ifdef HAVE_GETRANDOM
-#include <sys/random.h>
-#endif
-#ifdef NO_INTPTR_T
-/*
- * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
- * on LLP86, IL33LLP64 and P64 it needs to be "long long",
- * while on IP16 and IP16L32 it is "int" (resp. "short")
- * Size needs to match (or exceed) 'sizeof(void *)'.
- * We can't take "long long" here as not everybody has it.
- */
-typedef long intptr_t;
-typedef unsigned long uintptr_t;
-#endif
-#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
-#include <grp.h>
-#define _ALL_SOURCE 1
#endif
/* used on Mac OS X */
@@ -370,60 +207,6 @@ static inline const char *precompose_string_if_needed(const char *in)
#define probe_utf8_pathname_composition()
#endif
-#ifdef MKDIR_WO_TRAILING_SLASH
-#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
-int compat_mkdir_wo_trailing_slash(const char*, mode_t);
-#endif
-
-#ifdef time
-#undef time
-#endif
-static inline time_t git_time(time_t *tloc)
-{
- struct timeval tv;
-
- /*
- * Avoid time(NULL), which can disagree with gettimeofday(2)
- * and filesystem timestamps.
- */
- gettimeofday(&tv, NULL);
-
- if (tloc)
- *tloc = tv.tv_sec;
- return tv.tv_sec;
-}
-#define time git_time
-
-#ifdef NO_STRUCT_ITIMERVAL
-struct itimerval {
- struct timeval it_interval;
- struct timeval it_value;
-};
-#endif
-
-#ifdef NO_SETITIMER
-static inline int git_setitimer(int which UNUSED,
- const struct itimerval *value UNUSED,
- struct itimerval *newvalue UNUSED) {
- return 0; /* pretend success */
-}
-#undef setitimer
-#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
-#endif
-
-#ifndef NO_LIBGEN_H
-#include <libgen.h>
-#else
-#define basename gitbasename
-char *gitbasename(char *);
-#define dirname gitdirname
-char *gitdirname(char *);
-#endif
-
-#ifndef NO_ICONV
-#include <iconv.h>
-#endif
-
#ifndef NO_OPENSSL
#ifdef __APPLE__
#undef __AVAILABILITY_MACROS_USES_AVAILABILITY
@@ -441,34 +224,6 @@ char *gitdirname(char *);
# include <sys/sysinfo.h>
#endif
-/* On most systems <netdb.h> would have given us this, but
- * not on some systems (e.g. z/OS).
- */
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
-
-/* On most systems <limits.h> would have given us this, but
- * not on some systems (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-typedef uintmax_t timestamp_t;
-#define PRItime PRIuMAX
-#define parse_timestamp strtoumax
-#define TIME_MAX UINTMAX_MAX
-#define TIME_MIN 0
-
#ifndef PATH_SEP
#define PATH_SEP ':'
#endif
@@ -492,11 +247,6 @@ static inline int noop_core_config(const char *var UNUSED,
#define platform_core_config noop_core_config
#endif
-int lstat_cache_aware_rmdir(const char *path);
-#if !defined(__MINGW32__) && !defined(_MSC_VER)
-#define rmdir lstat_cache_aware_rmdir
-#endif
-
#ifndef has_dos_drive_prefix
static inline int git_has_dos_drive_prefix(const char *path UNUSED)
{
@@ -822,25 +572,6 @@ static inline bool strip_suffix(const char *str, const char *suffix,
memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
} while (0)
-#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-
-#ifndef PROT_READ
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define MAP_PRIVATE 1
-#endif
-
-#define mmap git_mmap
-#define munmap git_munmap
-void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-int git_munmap(void *start, size_t length);
-
-#else /* NO_MMAP || USE_WIN32_MMAP */
-
-#include <sys/mman.h>
-
-#endif /* NO_MMAP || USE_WIN32_MMAP */
-
#ifdef NO_MMAP
/* This value must be multiple of (pagesize * 2) */
@@ -856,177 +587,15 @@ int git_munmap(void *start, size_t length);
#endif /* NO_MMAP */
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
#define on_disk_bytes(st) ((st).st_size)
#else
#define on_disk_bytes(st) ((st).st_blocks * 512)
#endif
-#ifdef NEEDS_MODE_TRANSLATION
-#undef S_IFMT
-#undef S_IFREG
-#undef S_IFDIR
-#undef S_IFLNK
-#undef S_IFBLK
-#undef S_IFCHR
-#undef S_IFIFO
-#undef S_IFSOCK
-#define S_IFMT 0170000
-#define S_IFREG 0100000
-#define S_IFDIR 0040000
-#define S_IFLNK 0120000
-#define S_IFBLK 0060000
-#define S_IFCHR 0020000
-#define S_IFIFO 0010000
-#define S_IFSOCK 0140000
-#ifdef stat
-#undef stat
-#endif
-#define stat(path, buf) git_stat(path, buf)
-int git_stat(const char *, struct stat *);
-#ifdef fstat
-#undef fstat
-#endif
-#define fstat(fd, buf) git_fstat(fd, buf)
-int git_fstat(int, struct stat *);
-#ifdef lstat
-#undef lstat
-#endif
-#define lstat(path, buf) git_lstat(path, buf)
-int git_lstat(const char *, struct stat *);
-#endif
-
#define DEFAULT_PACKED_GIT_LIMIT \
((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))
-#ifdef NO_PREAD
-#define pread git_pread
-ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
-#endif
-
-#ifdef NO_SETENV
-#define setenv gitsetenv
-int gitsetenv(const char *, const char *, int);
-#endif
-
-#ifdef NO_MKDTEMP
-#define mkdtemp gitmkdtemp
-char *gitmkdtemp(char *);
-#endif
-
-#ifdef NO_UNSETENV
-#define unsetenv gitunsetenv
-int gitunsetenv(const char *);
-#endif
-
-#ifdef NO_STRCASESTR
-#define strcasestr gitstrcasestr
-char *gitstrcasestr(const char *haystack, const char *needle);
-#endif
-
-#ifdef NO_STRLCPY
-#define strlcpy gitstrlcpy
-size_t gitstrlcpy(char *, const char *, size_t);
-#endif
-
-#ifdef NO_STRTOUMAX
-#define strtoumax gitstrtoumax
-uintmax_t gitstrtoumax(const char *, char **, int);
-#define strtoimax gitstrtoimax
-intmax_t gitstrtoimax(const char *, char **, int);
-#endif
-
-#ifdef NO_HSTRERROR
-#define hstrerror githstrerror
-const char *githstrerror(int herror);
-#endif
-
-#ifdef NO_MEMMEM
-#define memmem gitmemmem
-void *gitmemmem(const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen);
-#endif
-
-#ifdef OVERRIDE_STRDUP
-#ifdef strdup
-#undef strdup
-#endif
-#define strdup gitstrdup
-char *gitstrdup(const char *s);
-#endif
-
-#ifdef NO_GETPAGESIZE
-#define getpagesize() sysconf(_SC_PAGESIZE)
-#endif
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
-#endif
-
-#ifdef FREAD_READS_DIRECTORIES
-# if !defined(SUPPRESS_FOPEN_REDEFINITION)
-# ifdef fopen
-# undef fopen
-# endif
-# define fopen(a,b) git_fopen(a,b)
-# endif
-FILE *git_fopen(const char*, const char*);
-#endif
-
-#ifdef SNPRINTF_RETURNS_BOGUS
-#ifdef snprintf
-#undef snprintf
-#endif
-#define snprintf git_snprintf
-int git_snprintf(char *str, size_t maxsize,
- const char *format, ...);
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#define vsnprintf git_vsnprintf
-int git_vsnprintf(char *str, size_t maxsize,
- const char *format, va_list ap);
-#endif
-
-#ifdef OPEN_RETURNS_EINTR
-#undef open
-#define open git_open_with_retry
-int git_open_with_retry(const char *path, int flag, ...);
-#endif
-
-#ifdef __GLIBC_PREREQ
-#if __GLIBC_PREREQ(2, 1)
-#define HAVE_STRCHRNUL
-#endif
-#endif
-
-#ifndef HAVE_STRCHRNUL
-#define strchrnul gitstrchrnul
-static inline char *gitstrchrnul(const char *s, int c)
-{
- while (*s && *s != c)
- s++;
- return (char *)s;
-}
-#endif
-
-#ifdef NO_INET_PTON
-int inet_pton(int af, const char *src, void *dst);
-#endif
-
-#ifdef NO_INET_NTOP
-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-#endif
-
-#ifdef NO_PTHREADS
-#define atexit git_atexit
-int git_atexit(void (*handler)(void));
-#endif
-
static inline size_t st_add(size_t a, size_t b)
{
if (unsigned_add_overflows(a, b))
@@ -1293,12 +862,6 @@ static inline size_t xsize_t(off_t len)
return (size_t) len;
}
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
-#endif
-
-#include "sane-ctype.h"
-
/*
* Like skip_prefix, but compare case-insensitively. Note that the comparison
* is done via tolower(), so it is strictly ASCII (no multi-byte characters or
@@ -1364,34 +927,6 @@ static inline int strtol_i(char const *s, int base, int *result)
return 0;
}
-void git_stable_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *));
-#ifdef INTERNAL_QSORT
-#define qsort git_stable_qsort
-#endif
-
-#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
-static inline void sane_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *))
-{
- if (nmemb > 1)
- qsort(base, nmemb, size, compar);
-}
-
-#define STABLE_QSORT(base, n, compar) \
- git_stable_qsort((base), (n), sizeof(*(base)), compar)
-
-#ifndef HAVE_ISO_QSORT_S
-int git_qsort_s(void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *, void *), void *ctx);
-#define qsort_s git_qsort_s
-#endif
-
-#define QSORT_S(base, n, compar, ctx) do { \
- if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
- BUG("qsort_s() failed"); \
-} while (0)
-
#ifndef REG_STARTEND
#error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd"
#endif
@@ -1416,39 +951,12 @@ int git_regcomp(regex_t *preg, const char *pattern, int cflags);
# define FORCE_DIR_SET_GID 0
#endif
-#ifdef NO_NSEC
-#undef USE_NSEC
-#define ST_CTIME_NSEC(st) 0
-#define ST_MTIME_NSEC(st) 0
-#else
-#ifdef USE_ST_TIMESPEC
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
-#else
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
-#endif
-#endif
-
#ifdef UNRELIABLE_FSTAT
#define fstat_is_reliable() 0
#else
#define fstat_is_reliable() 1
#endif
-#ifndef va_copy
-/*
- * Since an obvious implementation of va_list would be to make it a
- * pointer into the stack frame, a simple assignment will work on
- * many systems. But let's try to be more portable.
- */
-#ifdef __va_copy
-#define va_copy(dst, src) __va_copy(dst, src)
-#else
-#define va_copy(dst, src) ((dst) = (src))
-#endif
-#endif
-
/* usage.c: only to be used for testing BUG() implementation (see test-tool) */
extern int BUG_exit_code;
@@ -1478,41 +986,6 @@ void bug_fl(const char *file, int line, const char *fmt, ...);
# define SHELL_PATH "/bin/sh"
#endif
-#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
-static inline void git_flockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-static inline void git_funlockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-#undef flockfile
-#undef funlockfile
-#undef getc_unlocked
-#define flockfile(fh) git_flockfile(fh)
-#define funlockfile(fh) git_funlockfile(fh)
-#define getc_unlocked(fh) getc(fh)
-#endif
-
-#ifdef FILENO_IS_A_MACRO
-int git_fileno(FILE *stream);
-# ifndef COMPAT_CODE_FILENO
-# undef fileno
-# define fileno(p) git_fileno(p)
-# endif
-#endif
-
-#ifdef NEED_ACCESS_ROOT_HANDLER
-int git_access(const char *path, int mode);
-# ifndef COMPAT_CODE_ACCESS
-# ifdef access
-# undef access
-# endif
-# define access(path, mode) git_access(path, mode)
-# endif
-#endif
-
/*
* Our code often opens a path to an optional file, to work on its
* contents when we can successfully open it. We can ignore a failure
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h"
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (15 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
The reftable library includes "git-compat-util.h" in order to get a
POSIX-like programming environment that papers over various differences
between platforms. The header also brings with it a couple of helpers
specific to the Git codebase though, and over time we have started to
use these helpers in the reftable library, as well.
This makes it very hard to use the reftable library as a standalone
library without the rest of the Git codebase, so other libraries like
e.g. libgit2 cannot easily use it. But now that we have removed all
calls to Git-specific functionality and have split out "compat/posix.h"
as a separate header we can address this.
Stop including "git-compat-util.h" and instead include "compat/posix.h"
to finalize the decoupling of the reftable library from the rest of the
Git codebase. The only bits which remain specific to Git are "system.h"
and "system.c", which projects will have to provide.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/system.c | 2 ++
reftable/system.h | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/reftable/system.c b/reftable/system.c
index e25ccc0da3..1ee268b125 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -1,3 +1,5 @@
+#include "../git-compat-util.h"
+
#include "system.h"
#include "basics.h"
#include "reftable-error.h"
diff --git a/reftable/system.h b/reftable/system.h
index 3bd4a4e322..dccdf11f76 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -11,7 +11,8 @@ license that can be found in the LICENSE file or at
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "../compat/posix.h"
+#include <zlib.h>
/*
* Return a random 32 bit integer. This function is expected to return
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v5 18/18] Makefile: skip reftable library for Coccinelle
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (16 preceding siblings ...)
2025-02-07 11:52 ` [PATCH v5 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
@ 2025-02-07 11:52 ` Patrick Steinhardt
17 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-07 11:52 UTC (permalink / raw)
To: git; +Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt
The reftable library does not use any of the common helpers that the Git
project has. Consequently, most of the rules that we have in Coccinelle
do not apply to the library at all and may even generate false positives
when a pattern can be converted to use a Git helper function.
Exclude reftable library sources from being checked by Coccinelle to
avoid such false positives.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index d3011e30f7..dc2ac32e4a 100644
--- a/Makefile
+++ b/Makefile
@@ -946,7 +946,7 @@ FOUND_SOURCE_FILES := $(filter-out $(GENERATED_H),$(shell $(SOURCES_CMD)))
FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES))
FOUND_H_SOURCES = $(filter %.h,$(FOUND_SOURCE_FILES))
-COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
+COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES) reftable/%,$(FOUND_C_SOURCES))
LIB_H = $(FOUND_H_SOURCES)
--
2.48.1.538.gc4cfc42d60.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* Re: [PATCH v5 15/18] compat/mingw: split out POSIX-related bits
2025-02-07 11:52 ` [PATCH v5 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
@ 2025-02-09 13:14 ` Johannes Sixt
2025-02-10 15:50 ` Junio C Hamano
2025-02-13 18:22 ` Johannes Schindelin
0 siblings, 2 replies; 146+ messages in thread
From: Johannes Sixt @ 2025-02-09 13:14 UTC (permalink / raw)
To: Patrick Steinhardt
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, git,
Johannes Schindelin
Am 07.02.25 um 12:52 schrieb Patrick Steinhardt:
> Split out the POSIX-related bits from "compat/mingw.h". This is in
> preparation for splitting up "git-compat-utils.h" into a header that
> provides POSIX-compatibility and a header that provides common wrappers
> used by the Git project.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> compat/{mingw.c => mingw/compat-util.c} | 28 ++--
> compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
> compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
> compat/msvc.c | 6 -
> compat/msvc/compat-util.c | 6 +
> compat/msvc/compat-util.h | 7 +
> compat/{msvc.h => msvc/posix.h} | 8 +-
> config.mak.uname | 6 +-
> contrib/buildsystems/CMakeLists.txt | 2 +-
> git-compat-util.h | 4 +-
> meson.build | 8 +-
> 11 files changed, 266 insertions(+), 245 deletions(-)
I can agree with this rearrangement of compat/mingw.c. But the
Git-for-Windows repository has much higher stakes with all the
additional changes. I put Dscho on Cc.
-- Hannes
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v5 15/18] compat/mingw: split out POSIX-related bits
2025-02-09 13:14 ` Johannes Sixt
@ 2025-02-10 15:50 ` Junio C Hamano
2025-02-13 18:22 ` Johannes Schindelin
1 sibling, 0 replies; 146+ messages in thread
From: Junio C Hamano @ 2025-02-10 15:50 UTC (permalink / raw)
To: Johannes Sixt
Cc: Patrick Steinhardt, Edward Thomson, Justin Tobler, git,
Johannes Schindelin
Johannes Sixt <j6t@kdbg.org> writes:
> Am 07.02.25 um 12:52 schrieb Patrick Steinhardt:
>> Split out the POSIX-related bits from "compat/mingw.h". This is in
>> preparation for splitting up "git-compat-utils.h" into a header that
>> provides POSIX-compatibility and a header that provides common wrappers
>> used by the Git project.
>>
>> Signed-off-by: Patrick Steinhardt <ps@pks.im>
>> ---
>> compat/{mingw.c => mingw/compat-util.c} | 28 ++--
>> compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
>> compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
>> compat/msvc.c | 6 -
>> compat/msvc/compat-util.c | 6 +
>> compat/msvc/compat-util.h | 7 +
>> compat/{msvc.h => msvc/posix.h} | 8 +-
>> config.mak.uname | 6 +-
>> contrib/buildsystems/CMakeLists.txt | 2 +-
>> git-compat-util.h | 4 +-
>> meson.build | 8 +-
>> 11 files changed, 266 insertions(+), 245 deletions(-)
>
> I can agree with this rearrangement of compat/mingw.c. But the
> Git-for-Windows repository has much higher stakes with all the
> additional changes. I put Dscho on Cc.
Thanks. I agree that it is a very prudent and sensible thing to do
to ask for input from Dscho.
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v5 15/18] compat/mingw: split out POSIX-related bits
2025-02-09 13:14 ` Johannes Sixt
2025-02-10 15:50 ` Junio C Hamano
@ 2025-02-13 18:22 ` Johannes Schindelin
2025-02-17 12:47 ` Patrick Steinhardt
1 sibling, 1 reply; 146+ messages in thread
From: Johannes Schindelin @ 2025-02-13 18:22 UTC (permalink / raw)
To: Johannes Sixt
Cc: Patrick Steinhardt, Edward Thomson, Justin Tobler, Junio C Hamano,
git
Hi Hannes,
thank you for looping me in.
On Sun, 9 Feb 2025, Johannes Sixt wrote:
> Am 07.02.25 um 12:52 schrieb Patrick Steinhardt:
> > Split out the POSIX-related bits from "compat/mingw.h". This is in
> > preparation for splitting up "git-compat-utils.h" into a header that
> > provides POSIX-compatibility and a header that provides common wrappers
> > used by the Git project.
> >
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
> > compat/{mingw.c => mingw/compat-util.c} | 28 ++--
> > compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
> > compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
> > compat/msvc.c | 6 -
> > compat/msvc/compat-util.c | 6 +
> > compat/msvc/compat-util.h | 7 +
> > compat/{msvc.h => msvc/posix.h} | 8 +-
> > config.mak.uname | 6 +-
> > contrib/buildsystems/CMakeLists.txt | 2 +-
> > git-compat-util.h | 4 +-
> > meson.build | 8 +-
> > 11 files changed, 266 insertions(+), 245 deletions(-)
>
> I can agree with this rearrangement of compat/mingw.c. But the
> Git-for-Windows repository has much higher stakes with all the
> additional changes. I put Dscho on Cc.
This indeed causes massive friction. See for example
https://github.com/git-for-windows/git/actions/workflows/main.yml?query=branch%3Ashears%2Fseen,
which should ideally be updated with green builds as frequently as `seen`
is updated. It's dark red, and there are tons of gaps (which means that I
was not able to finish adapting to these changes).
Another problem introduced by this series is that now the same filename is
used in multiple directories, which makes it unnecessarily hard e.g. when
setting breakpoints in `gdb`, or when trying to follow `#include`s.
Granted, the problem already exists, e.g. with range-diff.c vs
builtin/range-diff.c, but I would hope that Git's source code would be
changed away from duplicate filenames instead of adding more.
Ciao,
Johannes
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v5 15/18] compat/mingw: split out POSIX-related bits
2025-02-13 18:22 ` Johannes Schindelin
@ 2025-02-17 12:47 ` Patrick Steinhardt
0 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-17 12:47 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Johannes Sixt, Edward Thomson, Justin Tobler, Junio C Hamano, git
On Thu, Feb 13, 2025 at 07:22:57PM +0100, Johannes Schindelin wrote:
> Hi Hannes,
>
> thank you for looping me in.
>
> On Sun, 9 Feb 2025, Johannes Sixt wrote:
>
> > Am 07.02.25 um 12:52 schrieb Patrick Steinhardt:
> > > Split out the POSIX-related bits from "compat/mingw.h". This is in
> > > preparation for splitting up "git-compat-utils.h" into a header that
> > > provides POSIX-compatibility and a header that provides common wrappers
> > > used by the Git project.
> > >
> > > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > > ---
> > > compat/{mingw.c => mingw/compat-util.c} | 28 ++--
> > > compat/mingw/compat-util.h | 220 ++++++++++++++++++++++++++++++++
> > > compat/{mingw.h => mingw/posix.h} | 216 +------------------------------
> > > compat/msvc.c | 6 -
> > > compat/msvc/compat-util.c | 6 +
> > > compat/msvc/compat-util.h | 7 +
> > > compat/{msvc.h => msvc/posix.h} | 8 +-
> > > config.mak.uname | 6 +-
> > > contrib/buildsystems/CMakeLists.txt | 2 +-
> > > git-compat-util.h | 4 +-
> > > meson.build | 8 +-
> > > 11 files changed, 266 insertions(+), 245 deletions(-)
> >
> > I can agree with this rearrangement of compat/mingw.c. But the
> > Git-for-Windows repository has much higher stakes with all the
> > additional changes. I put Dscho on Cc.
>
> This indeed causes massive friction. See for example
> https://github.com/git-for-windows/git/actions/workflows/main.yml?query=branch%3Ashears%2Fseen,
> which should ideally be updated with green builds as frequently as `seen`
> is updated. It's dark red, and there are tons of gaps (which means that I
> was not able to finish adapting to these changes).
>
> Another problem introduced by this series is that now the same filename is
> used in multiple directories, which makes it unnecessarily hard e.g. when
> setting breakpoints in `gdb`, or when trying to follow `#include`s.
>
> Granted, the problem already exists, e.g. with range-diff.c vs
> builtin/range-diff.c, but I would hope that Git's source code would be
> changed away from duplicate filenames instead of adding more.
The question is what ways we have to improve. Filenames being the same
can be avoided, e.g. by naming the split-out files e.g. "mingw-posix.h"
instead of "mingw/posix.h". But what alternatives do we have when it
comes to splitting out the logic in the first place to reduce the
conflicts on your side?
A couple of alternatives I see:
- Use `ifdef`s to conditionally only make POSIX bits available. I
think this would be quite awkward.
- Just ignore the issue on Windows altogether and expose non-POSIX
bits there. I don't think this is great either, as it means that
Windows becomes even more of an outlier than it already is.
Do you have any other ideas?
I can send a version that avoids moving stuff around and really only
splits out relevant functions into "compat/{mingw,msvc}-posix.h". But
I'm unsure whether that's enough of a help to you.
Patrick
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v6 00/18] reftable: stop using "git-compat-util.h"
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (23 preceding siblings ...)
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
` (18 more replies)
24 siblings, 19 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin, Toon Claes
Hi,
this patch series is the final step to fully decouple the reftable
library from the rest of the Git codebase. The goal of this is to make
the library reusable by other projects like libgit2 by simply copying
over the source files, making Git the canonical upstream for reftable
functionality.
This patch series stops using all kinds of helpers exposed by our
"git-compat-util.h" header and open-codes them instead. In order to keep
us from using these helpers by accident the final step is to pull out
POSIX-related bits and pieces into a new "compat/posix.h" header, which
the reftable library then uses instead of "git-compat-util.h".
Changes in v3:
- Fix type of `total_read` variable used to track how many bytes we
have read in `fd_read_lines()`.
- Drop the patch use root-relative includes again. Let's rather
discuss this outside of the scope of this series.
- Link to v2: https://lore.kernel.org/r/20250128-pks-reftable-drop-git-compat-util-v2-0-c85c20336317@pks.im
Changes in v4:
- Fix a couple of now-invalid relative includes that I missed. This
fixes the build issue in "seen" with Meson.
- Link to v3: https://lore.kernel.org/r/20250203-pks-reftable-drop-git-compat-util-v3-0-446c9ed4ee9e@pks.im
Changes in v5:
- Rework the implementation of `REFTABLE_UNUSED` to use
`__attribute__((__unused__))`.
- Link to v4: https://lore.kernel.org/r/20250206-pks-reftable-drop-git-compat-util-v4-0-603d276d5f95@pks.im
Changes in v6:
- I have rebased the patch series on top of "master" at 03944513488
(The eleventh batch, 2025-02-14). On the one hand this gets rid of
the conflict with the zlib-ng changes, which have meanwhile been
merged to that branch. And on the other hand it pulls in the new CI
build for MSVC+Meson, which allows me to have better test coverage
on Windows to better detect breakage there.
- Stop moving around Win32 files so that we do the minimum viable
change in this context. Hopefully, this makes it easier for Dscho to
integrate into Git for Windows. If it doesn't I don't really have
any other good ideas for how to do it, so the only alternative would
be to just ignore Windows altogether.
- Link to v5: https://lore.kernel.org/r/20250207-pks-reftable-drop-git-compat-util-v5-0-ba2adc79110f@pks.im
Thanks!
Patrick
---
Patrick Steinhardt (18):
reftable/stack: stop using `read_in_full()`
reftable/stack: stop using `write_in_full()`
reftable/blocksource: stop using `xmmap()`
reftable/record: stop using `COPY_ARRAY()`
reftable/record: stop using `BUG()` in `reftable_record_init()`
reftable/record: don't `BUG()` in `reftable_record_cmp()`
reftable: stop using `BUG()` in trivial cases
reftable/basics: stop using `st_mult()` in array allocators
reftable/basics: provide wrappers for big endian conversion
reftable/reader: stop using `ARRAY_SIZE()` macro
reftable/system: introduce `reftable_rand()`
reftable/stack: stop using `sleep_millisec()`
reftable/basics: stop using `SWAP()` macro
reftable/basics: introduce `REFTABLE_UNUSED` annotation
compat/mingw: split out POSIX-related bits
git-compat-util.h: split out POSIX-emulating bits
reftable: decouple from Git codebase by pulling in "compat/posix.h"
Makefile: skip reftable library for Coccinelle
Makefile | 2 +-
compat/mingw-posix.h | 431 +++++++++++++++++++++++++++++++
compat/mingw.h | 426 +-----------------------------
compat/msvc-posix.h | 33 +++
compat/msvc.h | 30 +--
compat/posix.h | 541 +++++++++++++++++++++++++++++++++++++++
git-compat-util.h | 531 +-------------------------------------
reftable/basics.c | 19 --
reftable/basics.h | 123 ++++++++-
reftable/block.c | 16 +-
reftable/blocksource.c | 17 +-
reftable/iter.c | 13 +-
reftable/merged.c | 27 +-
reftable/pq.c | 40 ++-
reftable/pq.h | 2 +-
reftable/reader.c | 33 ++-
reftable/record.c | 84 +++---
reftable/record.h | 6 +-
reftable/stack.c | 52 +++-
reftable/system.c | 7 +
reftable/system.h | 8 +-
reftable/writer.c | 27 +-
t/unit-tests/t-reftable-basics.c | 28 +-
t/unit-tests/t-reftable-pq.c | 22 +-
t/unit-tests/t-reftable-record.c | 42 ++-
25 files changed, 1405 insertions(+), 1155 deletions(-)
Range-diff versus v5:
1: 18b6360460f = 1: 3589d759e69 reftable/stack: stop using `read_in_full()`
2: 4426ec59a5e = 2: e9fb7b0821f reftable/stack: stop using `write_in_full()`
3: 4db9255d16d = 3: f509993ee13 reftable/blocksource: stop using `xmmap()`
4: 2752fb006c5 = 4: 48247ebf145 reftable/record: stop using `COPY_ARRAY()`
5: 3bdd13f015e = 5: 795e9650146 reftable/record: stop using `BUG()` in `reftable_record_init()`
6: 21529172e83 = 6: 8221aec91a9 reftable/record: don't `BUG()` in `reftable_record_cmp()`
7: e62c056f8e8 = 7: 8563af898e5 reftable: stop using `BUG()` in trivial cases
8: b506a862abc = 8: 447c7166c97 reftable/basics: stop using `st_mult()` in array allocators
9: b1749f88610 = 9: 108d40a63f5 reftable/basics: provide wrappers for big endian conversion
10: f583f0cfb03 = 10: 19068751b6c reftable/reader: stop using `ARRAY_SIZE()` macro
11: c59328f9299 ! 11: 316ca16a18c reftable/system: introduce `reftable_rand()`
@@ reftable/system.c
## reftable/system.h ##
@@ reftable/system.h: license that can be found in the LICENSE file or at
-
#include "git-compat-util.h"
+ #include "compat/zlib-compat.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
12: 0657d144327 = 12: 3cf2df99203 reftable/stack: stop using `sleep_millisec()`
13: 504ae579c30 = 13: 5184d4185a6 reftable/basics: stop using `SWAP()` macro
14: 34b0ae5f697 = 14: a108a876c9a reftable/basics: introduce `REFTABLE_UNUSED` annotation
15: 1552c1f45bf < -: ----------- compat/mingw: split out POSIX-related bits
-: ----------- > 15: 48186eb7aeb compat/mingw: split out POSIX-related bits
16: 7cebd3c3381 ! 16: 16f2371c868 git-compat-util.h: split out POSIX-emulating bits
@@ compat/posix.h (new)
+#endif
+
+#if defined(__MINGW32__)
-+#include "mingw/posix.h"
++#include "mingw-posix.h"
+#elif defined(_MSC_VER)
-+#include "msvc/posix.h"
++#include "msvc-posix.h"
+#else
+#include <sys/utsname.h>
+#include <sys/wait.h>
@@ git-compat-util.h: static inline int _have_unix_sockets(void)
@@ git-compat-util.h: static inline int is_xplatform_dir_sep(int c)
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
- #include "compat/msvc/compat-util.h"
+ #include "compat/msvc.h"
-#else
-#include <sys/utsname.h>
-#include <sys/wait.h>
17: dbb9b816d2e ! 17: 4461c8cf4a3 reftable: decouple from Git codebase by pulling in "compat/posix.h"
@@ reftable/system.h: license that can be found in the LICENSE file or at
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
-+#include "../compat/posix.h"
-+#include <zlib.h>
++#include "compat/posix.h"
+ #include "compat/zlib-compat.h"
/*
- * Return a random 32 bit integer. This function is expected to return
18: f7b470f3387 = 18: 3e70da1abc8 Makefile: skip reftable library for Coccinelle
---
base-commit: 03944513488db4a81fdb4c21c3b515e4cb260b05
change-id: 20241119-pks-reftable-drop-git-compat-util-470f2bfde562
^ permalink raw reply [flat|nested] 146+ messages in thread
* [PATCH v6 01/18] reftable/stack: stop using `read_in_full()`
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
` (17 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
There is a single callsite of `read_in_full()` in the reftable library.
Open-code the function to reduce our dependency on the Git library.
Note that we only partially port over the logic from `read_in_full()`
and its underlying `xread()` helper. Most importantly, the latter also
knows to handle `EWOULDBLOCK` via `handle_nonblock()`. This logic is
irrelevant for us though because the reftable library never sets the
`O_NONBLOCK` option in the first place.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 6c4e8be19b1..1cc47b94d9c 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -115,13 +115,16 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
static int fd_read_lines(int fd, char ***namesp)
{
- off_t size = lseek(fd, 0, SEEK_END);
char *buf = NULL;
int err = 0;
+ off_t size;
+
+ size = lseek(fd, 0, SEEK_END);
if (size < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
+
err = lseek(fd, 0, SEEK_SET);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp)
goto done;
}
- if (read_in_full(fd, buf, size) != size) {
- err = REFTABLE_IO_ERROR;
- goto done;
+ for (off_t total_read = 0; total_read < size; ) {
+ ssize_t bytes_read = read(fd, buf + total_read, size - total_read);
+ if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_read < 0 || !bytes_read) {
+ err = REFTABLE_IO_ERROR;
+ goto done;
+ }
+
+ total_read += bytes_read;
}
buf[size] = 0;
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 02/18] reftable/stack: stop using `write_in_full()`
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
` (16 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
Similar to the preceding commit, drop our use of `write_in_full()` and
implement a new wrapper `reftable_write_full()` that handles this logic
for us. This is done to reduce our dependency on the Git library.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 1cc47b94d9c..c33f0c3333a 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -48,6 +48,25 @@ static int stack_fsync(const struct reftable_write_options *opts, int fd)
return fsync(fd);
}
+static ssize_t reftable_write_data(int fd, const void *data, size_t size)
+{
+ size_t total_written = 0;
+ const char *p = data;
+
+ while (total_written < size) {
+ ssize_t bytes_written = write(fd, p, size - total_written);
+ if (bytes_written < 0 && (errno == EAGAIN || errno == EINTR))
+ continue;
+ if (bytes_written < 0)
+ return REFTABLE_IO_ERROR;
+
+ total_written += bytes_written;
+ p += bytes_written;
+ }
+
+ return total_written;
+}
+
struct fd_writer {
const struct reftable_write_options *opts;
int fd;
@@ -56,7 +75,7 @@ struct fd_writer {
static ssize_t fd_writer_write(void *arg, const void *data, size_t sz)
{
struct fd_writer *writer = arg;
- return write_in_full(writer->fd, data, sz);
+ return reftable_write_data(writer->fd, data, sz);
}
static int fd_writer_flush(void *arg)
@@ -784,7 +803,8 @@ int reftable_addition_commit(struct reftable_addition *add)
goto done;
}
- err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len);
+ err = reftable_write_data(add->tables_list_lock.fd,
+ table_list.buf, table_list.len);
reftable_buf_release(&table_list);
if (err < 0) {
err = REFTABLE_IO_ERROR;
@@ -1470,8 +1490,8 @@ static int stack_compact_range(struct reftable_stack *st,
goto done;
}
- err = write_in_full(tables_list_lock.fd,
- tables_list_buf.buf, tables_list_buf.len);
+ err = reftable_write_data(tables_list_lock.fd,
+ tables_list_buf.buf, tables_list_buf.len);
if (err < 0) {
err = REFTABLE_IO_ERROR;
unlink(new_table_path.buf);
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 03/18] reftable/blocksource: stop using `xmmap()`
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
` (15 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
We use `xmmap()` to map reftables into memory. This function has two
problems:
- It causes us to die in case the mmap fails.
- It ties us to the Git codebase.
Refactor the code to use mmap(3p) instead with manual error checking.
Note that this function may not be the system-provided mmap(3p), but may
point to our `git_mmap()` wrapper that emulates the syscall on systems
that do not have mmap(3p) available.
Fix `reftable_block_source_from_file()` to properly bubble up the error
code in case the map(3p) call fails.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/blocksource.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index bba4a45b98a..02972c46f4b 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -98,7 +98,7 @@ static struct reftable_block_source_vtable file_vtable = {
int reftable_block_source_from_file(struct reftable_block_source *bs,
const char *name)
{
- struct file_block_source *p;
+ struct file_block_source *p = NULL;
struct stat st;
int fd, err;
@@ -122,7 +122,12 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
}
p->size = st.st_size;
- p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ p->data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p->data == MAP_FAILED) {
+ err = REFTABLE_IO_ERROR;
+ p->data = NULL;
+ goto out;
+ }
assert(!bs->ops);
bs->ops = &file_vtable;
@@ -135,5 +140,5 @@ int reftable_block_source_from_file(struct reftable_block_source *bs,
close(fd);
if (err < 0)
reftable_free(p);
- return 0;
+ return err;
}
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 04/18] reftable/record: stop using `COPY_ARRAY()`
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (2 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
` (14 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
Drop our use of `COPY_ARRAY()`, replacing it with an open-coded variant
thereof. This is done to reduce our dependency on the Git library.
While at it, guard the whole array copy logic so that we only copy it in
case there actually is anything to be copied. Otherwise, we may end up
trying to allocate a zero-sized array, which will return a NULL pointer
and thus cause us to return an `REFTABLE_OUT_OF_MEMORY_ERROR`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/record.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/reftable/record.c b/reftable/record.c
index 8919df8a4d3..2c0cc32cbd3 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -504,11 +504,17 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
if (src->hash_prefix_len)
memcpy(obj->hash_prefix, src->hash_prefix, obj->hash_prefix_len);
- REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
- if (!obj->offsets)
- return REFTABLE_OUT_OF_MEMORY_ERROR;
- obj->offset_len = src->offset_len;
- COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
+ if (src->offset_len) {
+ if (sizeof(*src->offsets) > SIZE_MAX / src->offset_len)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
+ if (!obj->offsets)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+
+ memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len);
+ obj->offset_len = src->offset_len;
+ }
return 0;
}
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()`
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (3 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
` (13 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
We're aborting the program via `BUG()` in case `reftable_record_init()`
was invoked with an unknown record type. This is bad because we may now
die in library code, and because it makes us depend on the Git codebase.
Refactor the code such that `reftable_record_init()` can return an error
code to the caller. Adapt any callers accordingly.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/block.c | 4 +++-
reftable/merged.c | 5 ++++-
reftable/reader.c | 5 ++++-
reftable/record.c | 8 ++++----
reftable/record.h | 4 ++--
t/unit-tests/t-reftable-pq.c | 6 +++---
t/unit-tests/t-reftable-record.c | 2 +-
7 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/reftable/block.c b/reftable/block.c
index b14a8f1259a..999876826d1 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -508,7 +508,9 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,
it->block_len = br->block_len;
it->hash_size = br->hash_size;
- reftable_record_init(&rec, block_reader_type(br));
+ err = reftable_record_init(&rec, block_reader_type(br));
+ if (err < 0)
+ goto done;
/*
* We're looking for the last entry less than the wanted key so that
diff --git a/reftable/merged.c b/reftable/merged.c
index e72b39e178d..4156eec07fc 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -253,7 +253,10 @@ int merged_table_init_iter(struct reftable_merged_table *mt,
}
for (size_t i = 0; i < mt->readers_len; i++) {
- reftable_record_init(&subiters[i].rec, typ);
+ ret = reftable_record_init(&subiters[i].rec, typ);
+ if (ret < 0)
+ goto out;
+
ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
if (ret < 0)
goto out;
diff --git a/reftable/reader.c b/reftable/reader.c
index 3f2e4b28005..de6e6dd9322 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -360,7 +360,10 @@ static int table_iter_seek_linear(struct table_iter *ti,
struct reftable_record rec;
int err;
- reftable_record_init(&rec, reftable_record_type(want));
+ err = reftable_record_init(&rec, reftable_record_type(want));
+ if (err < 0)
+ goto done;
+
err = reftable_record_key(want, &want_key);
if (err < 0)
goto done;
diff --git a/reftable/record.c b/reftable/record.c
index 2c0cc32cbd3..1e18f8dffb1 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1306,7 +1306,7 @@ reftable_record_vtable(struct reftable_record *rec)
abort();
}
-void reftable_record_init(struct reftable_record *rec, uint8_t typ)
+int reftable_record_init(struct reftable_record *rec, uint8_t typ)
{
memset(rec, 0, sizeof(*rec));
rec->type = typ;
@@ -1315,11 +1315,11 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)
case BLOCK_TYPE_REF:
case BLOCK_TYPE_LOG:
case BLOCK_TYPE_OBJ:
- return;
+ return 0;
case BLOCK_TYPE_INDEX:
reftable_buf_init(&rec->u.idx.last_key);
- return;
+ return 0;
default:
- BUG("unhandled record type");
+ return REFTABLE_API_ERROR;
}
}
diff --git a/reftable/record.h b/reftable/record.h
index c7755a4d750..e1846c294ba 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -130,8 +130,8 @@ struct reftable_record {
} u;
};
-/* Initialize the reftable record for the given type */
-void reftable_record_init(struct reftable_record *rec, uint8_t typ);
+/* Initialize the reftable record for the given type. */
+int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index f3f8a0cdf38..d8a4c283a11 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -32,7 +32,7 @@ static void t_pq_record(void)
char *last = NULL;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
}
@@ -72,7 +72,7 @@ static void t_pq_index(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
@@ -111,7 +111,7 @@ static void t_merged_iter_pqueue_top(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index d49d2a2729c..6540bd20e37 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -17,7 +17,7 @@ static void t_copy(struct reftable_record *rec)
uint8_t typ;
typ = reftable_record_type(rec);
- reftable_record_init(©, typ);
+ check(!reftable_record_init(©, typ));
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
/* do it twice to catch memory leaks */
reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1);
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()`
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (4 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
` (12 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
The reftable library aborts with a bug in case `reftable_record_cmp()`
is invoked with two records of differing types. This would cause the
program to die without the caller being able to handle the error, which
is not something we want in the context of library code. And it ties us
to the Git codebase.
Refactor the code such that `reftable_record_cmp()` returns an error
code separate from the actual comparison result. This requires us to
also adapt some callers up the callchain in a similar fashion.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/merged.c | 20 +++++++++++++++-----
reftable/pq.c | 36 +++++++++++++++++++++++++++++-------
reftable/pq.h | 2 +-
reftable/record.c | 10 ++++++----
reftable/record.h | 2 +-
t/unit-tests/t-reftable-pq.c | 16 ++++++++++++----
t/unit-tests/t-reftable-record.c | 40 ++++++++++++++++++++++++++++------------
7 files changed, 92 insertions(+), 34 deletions(-)
diff --git a/reftable/merged.c b/reftable/merged.c
index 4156eec07fc..563864068c1 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -66,8 +66,11 @@ static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want
int err;
mi->advance_index = -1;
- while (!merged_iter_pqueue_is_empty(mi->pq))
- merged_iter_pqueue_remove(&mi->pq);
+ while (!merged_iter_pqueue_is_empty(mi->pq)) {
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+ }
for (size_t i = 0; i < mi->subiters_len; i++) {
err = iterator_seek(&mi->subiters[i].iter, want);
@@ -120,7 +123,9 @@ static int merged_iter_next_entry(struct merged_iter *mi,
if (empty)
return 1;
- entry = merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, &entry);
+ if (err < 0)
+ return err;
/*
One can also use reftable as datacenter-local storage, where the ref
@@ -134,11 +139,16 @@ static int merged_iter_next_entry(struct merged_iter *mi,
struct pq_entry top = merged_iter_pqueue_top(mi->pq);
int cmp;
- cmp = reftable_record_cmp(top.rec, entry.rec);
+ err = reftable_record_cmp(top.rec, entry.rec, &cmp);
+ if (err < 0)
+ return err;
if (cmp > 0)
break;
- merged_iter_pqueue_remove(&mi->pq);
+ err = merged_iter_pqueue_remove(&mi->pq, NULL);
+ if (err < 0)
+ return err;
+
err = merged_iter_advance_subiter(mi, top.index);
if (err < 0)
return err;
diff --git a/reftable/pq.c b/reftable/pq.c
index 5591e875e1e..ef8035cfd9b 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -15,13 +15,18 @@ license that can be found in the LICENSE file or at
int pq_less(struct pq_entry *a, struct pq_entry *b)
{
- int cmp = reftable_record_cmp(a->rec, b->rec);
+ int cmp, err;
+
+ err = reftable_record_cmp(a->rec, b->rec, &cmp);
+ if (err < 0)
+ return err;
+
if (cmp == 0)
return a->index > b->index;
return cmp < 0;
}
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out)
{
size_t i = 0;
struct pq_entry e = pq->heap[0];
@@ -32,17 +37,34 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
size_t min = i;
size_t j = 2 * i + 1;
size_t k = 2 * i + 2;
- if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i]))
- min = j;
- if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min]))
- min = k;
+ int cmp;
+
+ if (j < pq->len) {
+ cmp = pq_less(&pq->heap[j], &pq->heap[i]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = j;
+ }
+
+ if (k < pq->len) {
+ cmp = pq_less(&pq->heap[k], &pq->heap[min]);
+ if (cmp < 0)
+ return -1;
+ else if (cmp)
+ min = k;
+ }
+
if (min == i)
break;
SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
- return e;
+ if (out)
+ *out = e;
+
+ return 0;
}
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
diff --git a/reftable/pq.h b/reftable/pq.h
index 83c062eecac..ff39016445b 100644
--- a/reftable/pq.h
+++ b/reftable/pq.h
@@ -22,7 +22,7 @@ struct merged_iter_pqueue {
size_t cap;
};
-struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
+int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out);
int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
diff --git a/reftable/record.c b/reftable/record.c
index 1e18f8dffb1..b39d99fcc75 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -1195,12 +1195,14 @@ int reftable_record_is_deletion(struct reftable_record *rec)
reftable_record_data(rec));
}
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b)
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b,
+ int *cmp)
{
if (a->type != b->type)
- BUG("cannot compare reftable records of different type");
- return reftable_record_vtable(a)->cmp(
- reftable_record_data(a), reftable_record_data(b));
+ return -1;
+ *cmp = reftable_record_vtable(a)->cmp(reftable_record_data(a),
+ reftable_record_data(b));
+ return 0;
}
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size)
diff --git a/reftable/record.h b/reftable/record.h
index e1846c294ba..867810a9328 100644
--- a/reftable/record.h
+++ b/reftable/record.h
@@ -134,7 +134,7 @@ struct reftable_record {
int reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
-int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b, int *cmp);
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size);
int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);
int reftable_record_copy_from(struct reftable_record *rec,
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
index d8a4c283a11..c128fe8616a 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/t-reftable-pq.c
@@ -21,7 +21,9 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq)
static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b)
{
- return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index);
+ int cmp;
+ check(!reftable_record_cmp(a->rec, b->rec, &cmp));
+ return !cmp && (a->index == b->index);
}
static void t_pq_record(void)
@@ -49,7 +51,9 @@ static void t_pq_record(void)
while (!merged_iter_pqueue_is_empty(pq)) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -90,7 +94,9 @@ static void t_pq_index(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
@@ -129,7 +135,9 @@ static void t_merged_iter_pqueue_top(void)
for (i = N - 1; i > 0; i--) {
struct pq_entry top = merged_iter_pqueue_top(pq);
- struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ struct pq_entry e;
+
+ check(!merged_iter_pqueue_remove(&pq, &e));
merged_iter_pqueue_check(&pq);
check(pq_entry_equal(&top, &e));
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
index 6540bd20e37..59549663736 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/t-reftable-record.c
@@ -100,16 +100,20 @@ static void t_reftable_ref_record_comparison(void)
.u.ref.value.symref = (char *) "refs/heads/master",
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.ref.value_type = in[0].u.ref.value_type;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_ref_record_compare_name(void)
@@ -209,17 +213,20 @@ static void t_reftable_log_record_comparison(void)
.u.log.update_index = 22,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
/* comparison should be reversed for equal keys, because
* comparison is now performed on the basis of update indices */
- check_int(reftable_record_cmp(&in[0], &in[1]), <, 0);
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check_int(cmp, <, 0);
in[1].u.log.update_index = in[0].u.log.update_index;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
}
static void t_reftable_log_record_compare_key(void)
@@ -396,16 +403,20 @@ static void t_reftable_obj_record_comparison(void)
.u.obj.hash_prefix_len = 5,
},
};
+ int cmp;
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.obj.offset_len = in[0].u.obj.offset_len;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
}
static void t_reftable_obj_record_roundtrip(void)
@@ -486,19 +497,24 @@ static void t_reftable_index_record_comparison(void)
.u.idx.last_key = REFTABLE_BUF_INIT,
},
};
+ int cmp;
+
check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"));
check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch"));
check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ check(!reftable_record_cmp(&in[1], &in[2], &cmp));
+ check_int(cmp, >, 0);
in[1].u.idx.offset = in[0].u.idx.offset;
check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1]));
+ check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ check(!cmp);
for (size_t i = 0; i < ARRAY_SIZE(in); i++)
reftable_record_release(&in[i]);
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 07/18] reftable: stop using `BUG()` in trivial cases
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (5 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
` (11 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
Stop using `BUG()` in the remaining trivial cases that we still have in
the reftable library. Instead of aborting the program, we'll now bubble
up a `REFTABLE_API_ERROR` to indicate misuse of the calling conventions.
Note that in both `reftable_reader_{inc,dec}ref()` we simply stop
calling `BUG()` altogether. The only situation where the counter should
be zero is when the structure has already been free'd anyway, so we
would run into undefined behaviour regardless of whether we try to abort
the program or not.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/iter.c | 3 +--
reftable/reader.c | 4 ----
reftable/writer.c | 5 ++---
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/reftable/iter.c b/reftable/iter.c
index 86e801ca9fb..b2ffb09c16b 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -146,8 +146,7 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
static int indexed_table_ref_iter_seek(void *p UNUSED,
struct reftable_record *want UNUSED)
{
- BUG("seeking indexed table is not supported");
- return -1;
+ return REFTABLE_API_ERROR;
}
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
diff --git a/reftable/reader.c b/reftable/reader.c
index de6e6dd9322..36a5633eded 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -677,8 +677,6 @@ int reftable_reader_new(struct reftable_reader **out,
void reftable_reader_incref(struct reftable_reader *r)
{
- if (!r->refcount)
- BUG("cannot increment ref counter of dead reader");
r->refcount++;
}
@@ -686,8 +684,6 @@ void reftable_reader_decref(struct reftable_reader *r)
{
if (!r)
return;
- if (!r->refcount)
- BUG("cannot decrement ref counter of dead reader");
if (--r->refcount)
return;
block_source_close(&r->source);
diff --git a/reftable/writer.c b/reftable/writer.c
index f3ab1035d61..239573ade24 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -158,7 +158,7 @@ int reftable_writer_new(struct reftable_writer **out,
opts = *_opts;
options_set_defaults(&opts);
if (opts.block_size >= (1 << 24))
- BUG("configured block size exceeds 16MB");
+ return REFTABLE_API_ERROR;
reftable_buf_init(&wp->block_writer_data.last_key);
reftable_buf_init(&wp->last_key);
@@ -302,8 +302,7 @@ static int writer_add_record(struct reftable_writer *w,
}
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
- BUG("record of type %d added to writer of type %d",
- reftable_record_type(rec), block_writer_type(w->block_writer));
+ return REFTABLE_API_ERROR;
/*
* Try to add the record to the writer. If this succeeds then we're
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 08/18] reftable/basics: stop using `st_mult()` in array allocators
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (6 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
` (10 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
We're using `st_mult()` as part of our macro helpers that allocate
arrays. This is bad due two two reasons:
- `st_mult()` causes us to die in case the multiplication overflows.
- `st_mult()` ties us to the Git codebase.
Refactor the code to instead detect overflows manually and return an
error in such cases.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index a2a010a0e19..646f8d67f2d 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -117,18 +117,46 @@ void reftable_free(void *p);
void *reftable_calloc(size_t nelem, size_t elsize);
char *reftable_strdup(const char *str);
-#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
+static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out)
+{
+ if (nelem && elsize > SIZE_MAX / nelem)
+ return -1;
+ *out = nelem * elsize;
+ return 0;
+}
+
+#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_malloc(alloc_size); \
+ } \
+ } while (0)
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
-#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc)))
+#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \
+ size_t alloc_size; \
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
+ errno = ENOMEM; \
+ (x) = NULL; \
+ } else { \
+ (x) = reftable_realloc((x), alloc_size); \
+ } \
+ } while (0)
static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
size_t *allocp)
{
void *new_p;
- size_t alloc = *allocp * 2 + 1;
+ size_t alloc = *allocp * 2 + 1, alloc_bytes;
if (alloc < nelem)
alloc = nelem;
- new_p = reftable_realloc(p, st_mult(elsize, alloc));
+ if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) {
+ errno = ENOMEM;
+ return p;
+ }
+ new_p = reftable_realloc(p, alloc_bytes);
if (!new_p)
return p;
*allocp = alloc;
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 09/18] reftable/basics: provide wrappers for big endian conversion
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (7 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
` (9 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
We're using a mixture of big endian conversion functions provided by
both the reftable library, but also by the Git codebase. Refactor the
code so that we exclusively use reftable-provided wrappers in order to
untangle us from the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.c | 19 ----------
reftable/basics.h | 76 ++++++++++++++++++++++++++++++++++++++--
reftable/block.c | 12 +++----
reftable/reader.c | 22 ++++++------
reftable/record.c | 8 ++---
reftable/writer.c | 20 +++++------
t/unit-tests/t-reftable-basics.c | 28 ++++++++++++---
7 files changed, 127 insertions(+), 58 deletions(-)
diff --git a/reftable/basics.c b/reftable/basics.c
index 3b5ea27bbdc..8c4a4433e41 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -147,25 +147,6 @@ char *reftable_buf_detach(struct reftable_buf *buf)
return result;
}
-void put_be24(uint8_t *out, uint32_t i)
-{
- out[0] = (uint8_t)((i >> 16) & 0xff);
- out[1] = (uint8_t)((i >> 8) & 0xff);
- out[2] = (uint8_t)(i & 0xff);
-}
-
-uint32_t get_be24(uint8_t *in)
-{
- return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 |
- (uint32_t)(in[2]);
-}
-
-void put_be16(uint8_t *out, uint16_t i)
-{
- out[0] = (uint8_t)((i >> 8) & 0xff);
- out[1] = (uint8_t)(i & 0xff);
-}
-
size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
{
size_t lo = 0;
diff --git a/reftable/basics.h b/reftable/basics.h
index 646f8d67f2d..c1ddbaec3ff 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -76,9 +76,79 @@ char *reftable_buf_detach(struct reftable_buf *buf);
/* Bigendian en/decoding of integers */
-void put_be24(uint8_t *out, uint32_t i);
-uint32_t get_be24(uint8_t *in);
-void put_be16(uint8_t *out, uint16_t i);
+static inline void reftable_put_be16(void *out, uint16_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 8) & 0xff);
+ p[1] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be24(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 16) & 0xff);
+ p[1] = (uint8_t)((i >> 8) & 0xff);
+ p[2] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be32(void *out, uint32_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 24) & 0xff);
+ p[1] = (uint8_t)((i >> 16) & 0xff);
+ p[2] = (uint8_t)((i >> 8) & 0xff);
+ p[3] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline void reftable_put_be64(void *out, uint64_t i)
+{
+ unsigned char *p = out;
+ p[0] = (uint8_t)((i >> 56) & 0xff);
+ p[1] = (uint8_t)((i >> 48) & 0xff);
+ p[2] = (uint8_t)((i >> 40) & 0xff);
+ p[3] = (uint8_t)((i >> 32) & 0xff);
+ p[4] = (uint8_t)((i >> 24) & 0xff);
+ p[5] = (uint8_t)((i >> 16) & 0xff);
+ p[6] = (uint8_t)((i >> 8) & 0xff);
+ p[7] = (uint8_t)((i >> 0) & 0xff);
+}
+
+static inline uint16_t reftable_get_be16(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint16_t)(p[0]) << 8 |
+ (uint16_t)(p[1]) << 0;
+}
+
+static inline uint32_t reftable_get_be24(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 16 |
+ (uint32_t)(p[1]) << 8 |
+ (uint32_t)(p[2]) << 0;
+}
+
+static inline uint32_t reftable_get_be32(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint32_t)(p[0]) << 24 |
+ (uint32_t)(p[1]) << 16 |
+ (uint32_t)(p[2]) << 8|
+ (uint32_t)(p[3]) << 0;
+}
+
+static inline uint64_t reftable_get_be64(const void *in)
+{
+ const unsigned char *p = in;
+ return (uint64_t)(p[0]) << 56 |
+ (uint64_t)(p[1]) << 48 |
+ (uint64_t)(p[2]) << 40 |
+ (uint64_t)(p[3]) << 32 |
+ (uint64_t)(p[4]) << 24 |
+ (uint64_t)(p[5]) << 16 |
+ (uint64_t)(p[6]) << 8 |
+ (uint64_t)(p[7]) << 0;
+}
/*
* find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is
diff --git a/reftable/block.c b/reftable/block.c
index 999876826d1..53b5e044690 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -147,13 +147,13 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
int block_writer_finish(struct block_writer *w)
{
for (uint32_t i = 0; i < w->restart_len; i++) {
- put_be24(w->block + w->next, w->restarts[i]);
+ reftable_put_be24(w->block + w->next, w->restarts[i]);
w->next += 3;
}
- put_be16(w->block + w->next, w->restart_len);
+ reftable_put_be16(w->block + w->next, w->restart_len);
w->next += 2;
- put_be24(w->block + 1 + w->header_off, w->next);
+ reftable_put_be24(w->block + 1 + w->header_off, w->next);
/*
* Log records are stored zlib-compressed. Note that the compression
@@ -215,7 +215,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
{
uint32_t full_block_size = table_block_size;
uint8_t typ = block->data[header_off];
- uint32_t sz = get_be24(block->data + header_off + 1);
+ uint32_t sz = reftable_get_be24(block->data + header_off + 1);
int err = 0;
uint16_t restart_count = 0;
uint32_t restart_start = 0;
@@ -299,7 +299,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
full_block_size = sz;
}
- restart_count = get_be16(block->data + sz - 2);
+ restart_count = reftable_get_be16(block->data + sz - 2);
restart_start = sz - 2 - 3 * restart_count;
restart_bytes = block->data + restart_start;
@@ -354,7 +354,7 @@ int block_reader_first_key(const struct block_reader *br, struct reftable_buf *k
static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx)
{
- return get_be24(br->restart_bytes + 3 * idx);
+ return reftable_get_be24(br->restart_bytes + 3 * idx);
}
void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)
diff --git a/reftable/reader.c b/reftable/reader.c
index 36a5633eded..bf07a0a586f 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -101,18 +101,18 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
}
f++;
- r->block_size = get_be24(f);
+ r->block_size = reftable_get_be24(f);
f += 3;
- r->min_update_index = get_be64(f);
+ r->min_update_index = reftable_get_be64(f);
f += 8;
- r->max_update_index = get_be64(f);
+ r->max_update_index = reftable_get_be64(f);
f += 8;
if (r->version == 1) {
r->hash_id = REFTABLE_HASH_SHA1;
} else {
- switch (get_be32(f)) {
+ switch (reftable_get_be32(f)) {
case REFTABLE_FORMAT_ID_SHA1:
r->hash_id = REFTABLE_HASH_SHA1;
break;
@@ -127,24 +127,24 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
f += 4;
}
- r->ref_offsets.index_offset = get_be64(f);
+ r->ref_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->obj_offsets.offset = get_be64(f);
+ r->obj_offsets.offset = reftable_get_be64(f);
f += 8;
r->object_id_len = r->obj_offsets.offset & ((1 << 5) - 1);
r->obj_offsets.offset >>= 5;
- r->obj_offsets.index_offset = get_be64(f);
+ r->obj_offsets.index_offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.offset = get_be64(f);
+ r->log_offsets.offset = reftable_get_be64(f);
f += 8;
- r->log_offsets.index_offset = get_be64(f);
+ r->log_offsets.index_offset = reftable_get_be64(f);
f += 8;
computed_crc = crc32(0, footer, f - footer);
- file_crc = get_be32(f);
+ file_crc = reftable_get_be32(f);
f += 4;
if (computed_crc != file_crc) {
err = REFTABLE_FORMAT_ERROR;
@@ -214,7 +214,7 @@ static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
*typ = data[0];
if (reftable_is_block_type(*typ)) {
- result = get_be24(data + 1);
+ result = reftable_get_be24(data + 1);
}
return result;
}
diff --git a/reftable/record.c b/reftable/record.c
index b39d99fcc75..3552bafa994 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -689,7 +689,7 @@ static int reftable_log_record_key(const void *r, struct reftable_buf *dest)
return err;
ts = (~ts) - rec->update_index;
- put_be64(&i64[0], ts);
+ reftable_put_be64(&i64[0], ts);
err = reftable_buf_add(dest, i64, sizeof(i64));
if (err < 0)
@@ -814,7 +814,7 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,
if (s.len < 2)
return -1;
- put_be16(s.buf, r->value.update.tz_offset);
+ reftable_put_be16(s.buf, r->value.update.tz_offset);
string_view_consume(&s, 2);
n = encode_string(
@@ -846,7 +846,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
}
memcpy(r->refname, key.buf, key.len - 8);
- ts = get_be64(key.buf + key.len - 8);
+ ts = reftable_get_be64((unsigned char *)key.buf + key.len - 8);
r->update_index = (~max) - ts;
@@ -937,7 +937,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key,
goto done;
}
- r->value.update.tz_offset = get_be16(in.buf);
+ r->value.update.tz_offset = reftable_get_be16(in.buf);
string_view_consume(&in, 2);
n = decode_string(scratch, in);
diff --git a/reftable/writer.c b/reftable/writer.c
index 239573ade24..913b971b591 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -99,9 +99,9 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
dest[4] = writer_version(w);
- put_be24(dest + 5, w->opts.block_size);
- put_be64(dest + 8, w->min_update_index);
- put_be64(dest + 16, w->max_update_index);
+ reftable_put_be24(dest + 5, w->opts.block_size);
+ reftable_put_be64(dest + 8, w->min_update_index);
+ reftable_put_be64(dest + 16, w->max_update_index);
if (writer_version(w) == 2) {
uint32_t hash_id;
@@ -116,7 +116,7 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
return -1;
}
- put_be32(dest + 24, hash_id);
+ reftable_put_be32(dest + 24, hash_id);
}
return header_size(writer_version(w));
@@ -730,19 +730,19 @@ int reftable_writer_close(struct reftable_writer *w)
}
p += writer_write_header(w, footer);
- put_be64(p, w->stats.ref_stats.index_offset);
+ reftable_put_be64(p, w->stats.ref_stats.index_offset);
p += 8;
- put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
+ reftable_put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
p += 8;
- put_be64(p, w->stats.obj_stats.index_offset);
+ reftable_put_be64(p, w->stats.obj_stats.index_offset);
p += 8;
- put_be64(p, w->stats.log_stats.offset);
+ reftable_put_be64(p, w->stats.log_stats.offset);
p += 8;
- put_be64(p, w->stats.log_stats.index_offset);
+ reftable_put_be64(p, w->stats.log_stats.index_offset);
p += 8;
- put_be32(p, crc32(0, footer, p - footer));
+ reftable_put_be32(p, crc32(0, footer, p - footer));
p += 4;
err = w->flush(w->write_arg);
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
index 9ba7eb05ada..c9e751e49e9 100644
--- a/t/unit-tests/t-reftable-basics.c
+++ b/t/unit-tests/t-reftable-basics.c
@@ -128,12 +128,30 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
reftable_buf_release(&b);
}
- if_test ("put_be24 and get_be24 work") {
+ if_test ("reftable_put_be64 and reftable_get_be64 work") {
+ uint64_t in = 0x1122334455667788;
+ uint8_t dest[8];
+ uint64_t out;
+ reftable_put_be64(dest, in);
+ out = reftable_get_be64(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be32 and reftable_get_be32 work") {
+ uint32_t in = 0x11223344;
+ uint8_t dest[4];
+ uint32_t out;
+ reftable_put_be32(dest, in);
+ out = reftable_get_be32(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("reftable_put_be24 and reftable_get_be24 work") {
uint32_t in = 0x112233;
uint8_t dest[3];
uint32_t out;
- put_be24(dest, in);
- out = get_be24(dest);
+ reftable_put_be24(dest, in);
+ out = reftable_get_be24(dest);
check_int(in, ==, out);
}
@@ -141,8 +159,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
uint32_t in = 0xfef1;
uint8_t dest[3];
uint32_t out;
- put_be16(dest, in);
- out = get_be16(dest);
+ reftable_put_be16(dest, in);
+ out = reftable_get_be16(dest);
check_int(in, ==, out);
}
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (8 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
` (8 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
We have a single user of the `ARRAY_SIZE()` macro in the reftable
reader. Drop its use to reduce our dependence on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/reader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/reader.c b/reftable/reader.c
index bf07a0a586f..c3a36746652 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -849,7 +849,7 @@ int reftable_reader_print_blocks(const char *tablename)
printf("header:\n");
printf(" block_size: %d\n", r->block_size);
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
+ for (i = 0; i < sizeof(sections) / sizeof(*sections); i++) {
err = table_iter_seek_start(&ti, sections[i].type, 0);
if (err < 0)
goto done;
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 11/18] reftable/system: introduce `reftable_rand()`
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (9 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
` (7 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
Introduce a new system-level `reftable_rand()` function that generates a
single unsigned integer for us. The implementation of this function is
to be provided by the calling codebase, which allows us to more easily
hook into pre-seeded random number generators.
Adapt the two callsites where we generated random data.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 4 ++--
reftable/system.c | 5 +++++
reftable/system.h | 6 ++++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index c33f0c3333a..08893fd454f 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -523,7 +523,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
close(fd);
fd = -1;
- delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1;
+ delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
sleep_millisec(delay);
}
@@ -688,7 +688,7 @@ int reftable_stack_add(struct reftable_stack *st,
static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
{
char buf[100];
- uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE);
+ uint32_t rnd = reftable_rand();
snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
min, max, rnd);
reftable_buf_reset(dest);
diff --git a/reftable/system.c b/reftable/system.c
index adf8e4d30b8..e25ccc0da3c 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -4,6 +4,11 @@
#include "../lockfile.h"
#include "../tempfile.h"
+uint32_t reftable_rand(void)
+{
+ return git_rand(CSPRNG_BYTES_INSECURE);
+}
+
int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern)
{
struct tempfile *tempfile;
diff --git a/reftable/system.h b/reftable/system.h
index d02eacea8f0..bb6a7e6285b 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -14,6 +14,12 @@ license that can be found in the LICENSE file or at
#include "git-compat-util.h"
#include "compat/zlib-compat.h"
+/*
+ * Return a random 32 bit integer. This function is expected to return
+ * pre-seeded data.
+ */
+uint32_t reftable_rand(void);
+
/*
* An implementation-specific temporary file. By making this specific to the
* implementation it becomes possible to tie temporary files into any kind of
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 12/18] reftable/stack: stop using `sleep_millisec()`
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (10 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
` (6 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
Refactor our use of `sleep_millisec()` by open-coding it with poll(3p),
which is the current implementation of this function. Ideally, we'd use
a more direct way to sleep, but there is no equivalent to sleep(3p) that
would accept milliseconds as input.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/stack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/reftable/stack.c b/reftable/stack.c
index 08893fd454f..6dac015b473 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -524,7 +524,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
fd = -1;
delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1;
- sleep_millisec(delay);
+ poll(NULL, 0, delay);
}
out:
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 13/18] reftable/basics: stop using `SWAP()` macro
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (11 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 14/18] reftable/basics: introduce `REFTABLE_UNUSED` annotation Patrick Steinhardt
` (5 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
Stop using `SWAP()` macro in favor of an open-coded variant of it. Note
that this also requires us to open-code the build assert that `SWAP()`
itself uses to verify that the size of both variables matches.
This is done to reduce our dependency on the Git codebase.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 9 +++++++++
reftable/merged.c | 2 +-
reftable/pq.c | 4 ++--
reftable/record.c | 16 ++++++++--------
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index c1ddbaec3ff..59000798f0b 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -266,6 +266,15 @@ static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
# define strdup(str) REFTABLE_BANNED(strdup)
#endif
+#define REFTABLE_SWAP(a, b) do { \
+ void *_swap_a_ptr = &(a); \
+ void *_swap_b_ptr = &(b); \
+ unsigned char _swap_buffer[sizeof(a) - 2 * sizeof(a) * (sizeof(a) != sizeof(b))]; \
+ memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \
+ memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a)); \
+ memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
+} while (0)
+
/* Find the longest shared prefix size of `a` and `b` */
size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);
diff --git a/reftable/merged.c b/reftable/merged.c
index 563864068c1..4ff1553772a 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -155,7 +155,7 @@ static int merged_iter_next_entry(struct merged_iter *mi,
}
mi->advance_index = entry.index;
- SWAP(*rec, *entry.rec);
+ REFTABLE_SWAP(*rec, *entry.rec);
return 0;
}
diff --git a/reftable/pq.c b/reftable/pq.c
index ef8035cfd9b..82394a972db 100644
--- a/reftable/pq.c
+++ b/reftable/pq.c
@@ -57,7 +57,7 @@ int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *ou
if (min == i)
break;
- SWAP(pq->heap[i], pq->heap[min]);
+ REFTABLE_SWAP(pq->heap[i], pq->heap[min]);
i = min;
}
@@ -81,7 +81,7 @@ int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry
size_t j = (i - 1) / 2;
if (pq_less(&pq->heap[j], &pq->heap[i]))
break;
- SWAP(pq->heap[j], pq->heap[i]);
+ REFTABLE_SWAP(pq->heap[j], pq->heap[i]);
i = j;
}
diff --git a/reftable/record.c b/reftable/record.c
index 3552bafa994..9a1edf39a02 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -237,11 +237,11 @@ static int reftable_ref_record_copy_from(void *rec, const void *src_rec,
size_t refname_cap = 0;
int err;
- SWAP(refname, ref->refname);
- SWAP(refname_cap, ref->refname_cap);
+ REFTABLE_SWAP(refname, ref->refname);
+ REFTABLE_SWAP(refname_cap, ref->refname_cap);
reftable_ref_record_release(ref);
- SWAP(ref->refname, refname);
- SWAP(ref->refname_cap, refname_cap);
+ REFTABLE_SWAP(ref->refname, refname);
+ REFTABLE_SWAP(ref->refname_cap, refname_cap);
if (src->refname) {
size_t refname_len = strlen(src->refname);
@@ -376,11 +376,11 @@ static int reftable_ref_record_decode(void *rec, struct reftable_buf key,
return n;
string_view_consume(&in, n);
- SWAP(refname, r->refname);
- SWAP(refname_cap, r->refname_cap);
+ REFTABLE_SWAP(refname, r->refname);
+ REFTABLE_SWAP(refname_cap, r->refname_cap);
reftable_ref_record_release(r);
- SWAP(r->refname, refname);
- SWAP(r->refname_cap, refname_cap);
+ REFTABLE_SWAP(r->refname, refname);
+ REFTABLE_SWAP(r->refname_cap, refname_cap);
REFTABLE_ALLOC_GROW_OR_NULL(r->refname, key.len + 1, r->refname_cap);
if (!r->refname) {
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 14/18] reftable/basics: introduce `REFTABLE_UNUSED` annotation
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (12 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
` (4 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin, Toon Claes
Introduce the `REFTABLE_UNUSED` annotation and replace all existing
users of `UNUSED` in the reftable library to use the new macro instead.
Note that we unconditionally define `MAYBE_UNUSED` in the exact same
way, so doing so unconditionally for `REFTABLE_UNUSED` should be fine,
too.
Suggested-by: Toon Claes <toon@iotcl.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/basics.h | 2 ++
reftable/blocksource.c | 6 +++---
reftable/iter.c | 10 +++++-----
reftable/record.c | 26 +++++++++++++-------------
reftable/writer.c | 2 +-
5 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/reftable/basics.h b/reftable/basics.h
index 59000798f0b..fd59cbb7720 100644
--- a/reftable/basics.h
+++ b/reftable/basics.h
@@ -16,6 +16,8 @@ license that can be found in the LICENSE file or at
#include "system.h"
#include "reftable-basics.h"
+#define REFTABLE_UNUSED __attribute__((__unused__))
+
struct reftable_buf {
size_t alloc;
size_t len;
diff --git a/reftable/blocksource.c b/reftable/blocksource.c
index 02972c46f4b..78c1be23373 100644
--- a/reftable/blocksource.c
+++ b/reftable/blocksource.c
@@ -13,14 +13,14 @@ license that can be found in the LICENSE file or at
#include "reftable-blocksource.h"
#include "reftable-error.h"
-static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)
+static void reftable_buf_return_block(void *b REFTABLE_UNUSED, struct reftable_block *dest)
{
if (dest->len)
memset(dest->data, 0xff, dest->len);
reftable_free(dest->data);
}
-static void reftable_buf_close(void *b UNUSED)
+static void reftable_buf_close(void *b REFTABLE_UNUSED)
{
}
@@ -67,7 +67,7 @@ static uint64_t file_size(void *b)
return ((struct file_block_source *)b)->size;
}
-static void file_return_block(void *b UNUSED, struct reftable_block *dest UNUSED)
+static void file_return_block(void *b REFTABLE_UNUSED, struct reftable_block *dest REFTABLE_UNUSED)
{
}
diff --git a/reftable/iter.c b/reftable/iter.c
index b2ffb09c16b..f520382e700 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -25,17 +25,17 @@ int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
return it->ops->next(it->iter_arg, rec);
}
-static int empty_iterator_seek(void *arg UNUSED, struct reftable_record *want UNUSED)
+static int empty_iterator_seek(void *arg REFTABLE_UNUSED, struct reftable_record *want REFTABLE_UNUSED)
{
return 0;
}
-static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED)
+static int empty_iterator_next(void *arg REFTABLE_UNUSED, struct reftable_record *rec REFTABLE_UNUSED)
{
return 1;
}
-static void empty_iterator_close(void *arg UNUSED)
+static void empty_iterator_close(void *arg REFTABLE_UNUSED)
{
}
@@ -143,8 +143,8 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
return 0;
}
-static int indexed_table_ref_iter_seek(void *p UNUSED,
- struct reftable_record *want UNUSED)
+static int indexed_table_ref_iter_seek(void *p REFTABLE_UNUSED,
+ struct reftable_record *want REFTABLE_UNUSED)
{
return REFTABLE_API_ERROR;
}
diff --git a/reftable/record.c b/reftable/record.c
index 9a1edf39a02..142853d5070 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -490,7 +490,7 @@ static void reftable_obj_record_release(void *rec)
}
static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
struct reftable_obj_record *obj = rec;
const struct reftable_obj_record *src = src_rec;
@@ -528,7 +528,7 @@ static uint8_t reftable_obj_record_val_type(const void *rec)
}
static int reftable_obj_record_encode(const void *rec, struct string_view s,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
const struct reftable_obj_record *r = rec;
struct string_view start = s;
@@ -563,8 +563,8 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,
static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
uint8_t val_type, struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED,
+ struct reftable_buf *scratch REFTABLE_UNUSED)
{
struct string_view start = in;
struct reftable_obj_record *r = rec;
@@ -618,13 +618,13 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key,
return start.len - in.len;
}
-static int not_a_deletion(const void *p UNUSED)
+static int not_a_deletion(const void *p REFTABLE_UNUSED)
{
return 0;
}
static int reftable_obj_record_equal_void(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
struct reftable_obj_record *ra = (struct reftable_obj_record *) a;
struct reftable_obj_record *rb = (struct reftable_obj_record *) b;
@@ -1054,7 +1054,7 @@ static int reftable_index_record_key(const void *r, struct reftable_buf *dest)
}
static int reftable_index_record_copy_from(void *rec, const void *src_rec,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
struct reftable_index_record *dst = rec;
const struct reftable_index_record *src = src_rec;
@@ -1075,13 +1075,13 @@ static void reftable_index_record_release(void *rec)
reftable_buf_release(&idx->last_key);
}
-static uint8_t reftable_index_record_val_type(const void *rec UNUSED)
+static uint8_t reftable_index_record_val_type(const void *rec REFTABLE_UNUSED)
{
return 0;
}
static int reftable_index_record_encode(const void *rec, struct string_view out,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
const struct reftable_index_record *r =
(const struct reftable_index_record *)rec;
@@ -1097,10 +1097,10 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,
}
static int reftable_index_record_decode(void *rec, struct reftable_buf key,
- uint8_t val_type UNUSED,
+ uint8_t val_type REFTABLE_UNUSED,
struct string_view in,
- uint32_t hash_size UNUSED,
- struct reftable_buf *scratch UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED,
+ struct reftable_buf *scratch REFTABLE_UNUSED)
{
struct string_view start = in;
struct reftable_index_record *r = rec;
@@ -1120,7 +1120,7 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,
}
static int reftable_index_record_equal(const void *a, const void *b,
- uint32_t hash_size UNUSED)
+ uint32_t hash_size REFTABLE_UNUSED)
{
struct reftable_index_record *ia = (struct reftable_index_record *) a;
struct reftable_index_record *ib = (struct reftable_index_record *) b;
diff --git a/reftable/writer.c b/reftable/writer.c
index 913b971b591..ce55a1deb06 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -649,7 +649,7 @@ static void write_object_record(void *void_arg, void *key)
done:;
}
-static void object_record_free(void *void_arg UNUSED, void *key)
+static void object_record_free(void *void_arg REFTABLE_UNUSED, void *key)
{
struct obj_index_tree_node *entry = key;
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 15/18] compat/mingw: split out POSIX-related bits
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (13 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 14/18] reftable/basics: introduce `REFTABLE_UNUSED` annotation Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
` (3 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
Split out POSIX-related bits from "compat/mingw.h" and "compat/msvc.h".
This is in preparation for splitting up "git-compat-utils.h" into a
header that provides POSIX-compatibility and a header that provides
common wrappers used by the Git project.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/mingw-posix.h | 431 +++++++++++++++++++++++++++++++++++++++++++++++++++
compat/mingw.h | 426 +-------------------------------------------------
compat/msvc-posix.h | 33 ++++
compat/msvc.h | 30 +---
4 files changed, 467 insertions(+), 453 deletions(-)
diff --git a/compat/mingw-posix.h b/compat/mingw-posix.h
new file mode 100644
index 00000000000..8dddfa818d6
--- /dev/null
+++ b/compat/mingw-posix.h
@@ -0,0 +1,431 @@
+#ifndef COMPAT_MINGW_POSIX_H
+#define COMPAT_MINGW_POSIX_H
+
+#ifdef __MINGW64_VERSION_MAJOR
+#include <stdint.h>
+#include <wchar.h>
+typedef _sigset_t sigset_t;
+#endif
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+/* MinGW-w64 reports to have flockfile, but it does not actually have it. */
+#ifdef __MINGW64_VERSION_MAJOR
+#undef _POSIX_THREAD_SAFE_FUNCTIONS
+#endif
+
+/*
+ * things that are not available in header files
+ */
+
+typedef int uid_t;
+typedef int socklen_t;
+#ifndef __MINGW64_VERSION_MAJOR
+typedef int pid_t;
+#define hstrerror strerror
+#endif
+
+#define S_IFLNK 0120000 /* Symbolic link */
+#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
+#define S_ISSOCK(x) 0
+
+#ifndef S_IRWXG
+#define S_IRGRP 0
+#define S_IWGRP 0
+#define S_IXGRP 0
+#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+#endif
+#ifndef S_IRWXO
+#define S_IROTH 0
+#define S_IWOTH 0
+#define S_IXOTH 0
+#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#endif
+
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#define WIFEXITED(x) 1
+#define WIFSIGNALED(x) 0
+#define WEXITSTATUS(x) ((x) & 0xff)
+#define WTERMSIG(x) SIGTERM
+
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK EAGAIN
+#endif
+#ifndef ELOOP
+#define ELOOP EMLINK
+#endif
+#define SHUT_WR SD_SEND
+
+#define SIGHUP 1
+#define SIGQUIT 3
+#define SIGKILL 9
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGCHLD 17
+
+#define F_GETFD 1
+#define F_SETFD 2
+#define FD_CLOEXEC 0x1
+
+#if !defined O_CLOEXEC && defined O_NOINHERIT
+#define O_CLOEXEC O_NOINHERIT
+#endif
+
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#endif
+#ifndef ECONNABORTED
+#define ECONNABORTED WSAECONNABORTED
+#endif
+#ifndef ENOTSOCK
+#define ENOTSOCK WSAENOTSOCK
+#endif
+
+struct passwd {
+ char *pw_name;
+ char *pw_gecos;
+ char *pw_dir;
+};
+
+typedef void (__cdecl *sig_handler_t)(int);
+struct sigaction {
+ sig_handler_t sa_handler;
+ unsigned sa_flags;
+};
+#define SA_RESTART 0
+
+struct itimerval {
+ struct timeval it_value, it_interval;
+};
+#define ITIMER_REAL 0
+
+struct utsname {
+ char sysname[16];
+ char nodename[1];
+ char release[16];
+ char version[16];
+ char machine[1];
+};
+
+/*
+ * sanitize preprocessor namespace polluted by Windows headers defining
+ * macros which collide with git local versions
+ */
+#undef HELP_COMMAND /* from winuser.h */
+
+/*
+ * trivial stubs
+ */
+
+static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED)
+{ errno = ENOSYS; return -1; }
+static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED)
+{ errno = ENOSYS; return -1; }
+static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED)
+{ errno = ENOSYS; return -1; }
+#ifndef __MINGW64_VERSION_MAJOR
+static inline pid_t fork(void)
+{ errno = ENOSYS; return -1; }
+#endif
+static inline unsigned int alarm(unsigned int seconds UNUSED)
+{ return 0; }
+static inline int fsync(int fd)
+{ return _commit(fd); }
+static inline void sync(void)
+{}
+static inline uid_t getuid(void)
+{ return 1; }
+static inline struct passwd *getpwnam(const char *name UNUSED)
+{ return NULL; }
+static inline int fcntl(int fd UNUSED, int cmd, ...)
+{
+ if (cmd == F_GETFD || cmd == F_SETFD)
+ return 0;
+ errno = EINVAL;
+ return -1;
+}
+
+#define sigemptyset(x) (void)0
+static inline int sigaddset(sigset_t *set UNUSED, int signum UNUSED)
+{ return 0; }
+#define SIG_BLOCK 0
+#define SIG_UNBLOCK 0
+static inline int sigprocmask(int how UNUSED, const sigset_t *set UNUSED, sigset_t *oldset UNUSED)
+{ return 0; }
+static inline pid_t getppid(void)
+{ return 1; }
+static inline pid_t getpgid(pid_t pid)
+{ return pid == 0 ? getpid() : pid; }
+static inline pid_t tcgetpgrp(int fd UNUSED)
+{ return getpid(); }
+
+/*
+ * simple adaptors
+ */
+
+int mingw_mkdir(const char *path, int mode);
+#define mkdir mingw_mkdir
+
+#define WNOHANG 1
+pid_t waitpid(pid_t pid, int *status, int options);
+
+#define kill mingw_kill
+int mingw_kill(pid_t pid, int sig);
+
+#define locate_in_PATH mingw_locate_in_PATH
+char *mingw_locate_in_PATH(const char *cmd);
+
+/*
+ * implementations of missing functions
+ */
+
+int pipe(int filedes[2]);
+unsigned int sleep (unsigned int seconds);
+int mkstemp(char *template);
+int gettimeofday(struct timeval *tv, void *tz);
+#ifndef __MINGW64_VERSION_MAJOR
+struct tm *gmtime_r(const time_t *timep, struct tm *result);
+struct tm *localtime_r(const time_t *timep, struct tm *result);
+#endif
+int getpagesize(void); /* defined in MinGW's libgcc.a */
+struct passwd *getpwuid(uid_t uid);
+int setitimer(int type, struct itimerval *in, struct itimerval *out);
+int sigaction(int sig, struct sigaction *in, struct sigaction *out);
+int link(const char *oldpath, const char *newpath);
+int uname(struct utsname *buf);
+
+/*
+ * replacements of existing functions
+ */
+
+int mingw_unlink(const char *pathname);
+#define unlink mingw_unlink
+
+int mingw_rmdir(const char *path);
+#define rmdir mingw_rmdir
+
+int mingw_open (const char *filename, int oflags, ...);
+#define open mingw_open
+#undef OPEN_RETURNS_EINTR
+
+int mingw_fgetc(FILE *stream);
+#define fgetc mingw_fgetc
+
+FILE *mingw_fopen (const char *filename, const char *otype);
+#define fopen mingw_fopen
+
+FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream);
+#define freopen mingw_freopen
+
+int mingw_fflush(FILE *stream);
+#define fflush mingw_fflush
+
+ssize_t mingw_write(int fd, const void *buf, size_t len);
+#define write mingw_write
+
+int mingw_access(const char *filename, int mode);
+#undef access
+#define access mingw_access
+
+int mingw_chdir(const char *dirname);
+#define chdir mingw_chdir
+
+int mingw_chmod(const char *filename, int mode);
+#define chmod mingw_chmod
+
+char *mingw_mktemp(char *template);
+#define mktemp mingw_mktemp
+
+char *mingw_getcwd(char *pointer, int len);
+#define getcwd mingw_getcwd
+
+#ifdef NO_UNSETENV
+#error "NO_UNSETENV is incompatible with the Windows-specific startup code!"
+#endif
+
+/*
+ * We bind *env() routines (even the mingw_ ones) to private mingw_ versions.
+ * These talk to the CRT using UNICODE/wchar_t, but maintain the original
+ * narrow-char API.
+ *
+ * Note that the MSCRT maintains both ANSI (getenv()) and UNICODE (_wgetenv())
+ * routines and stores both versions of each environment variable in parallel
+ * (and secretly updates both when you set one or the other), but it uses CP_ACP
+ * to do the conversion rather than CP_UTF8.
+ *
+ * Since everything in the git code base is UTF8, we define the mingw_ routines
+ * to access the CRT using the UNICODE routines and manually convert them to
+ * UTF8. This also avoids round-trip problems.
+ *
+ * This also helps with our linkage, since "_wenviron" is publicly exported
+ * from the CRT. But to access "_environ" we would have to statically link
+ * to the CRT (/MT).
+ *
+ * We require NO_SETENV (and let gitsetenv() call our mingw_putenv).
+ */
+#define getenv mingw_getenv
+#define putenv mingw_putenv
+#define unsetenv mingw_putenv
+char *mingw_getenv(const char *name);
+int mingw_putenv(const char *name);
+
+int mingw_gethostname(char *host, int namelen);
+#define gethostname mingw_gethostname
+
+struct hostent *mingw_gethostbyname(const char *host);
+#define gethostbyname mingw_gethostbyname
+
+int mingw_getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hints, struct addrinfo **res);
+#define getaddrinfo mingw_getaddrinfo
+
+int mingw_socket(int domain, int type, int protocol);
+#define socket mingw_socket
+
+int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
+#define connect mingw_connect
+
+int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz);
+#define bind mingw_bind
+
+int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen);
+#define setsockopt mingw_setsockopt
+
+int mingw_shutdown(int sockfd, int how);
+#define shutdown mingw_shutdown
+
+int mingw_listen(int sockfd, int backlog);
+#define listen mingw_listen
+
+int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz);
+#define accept mingw_accept
+
+int mingw_rename(const char*, const char*);
+#define rename mingw_rename
+
+#if defined(USE_WIN32_MMAP) || defined(_MSC_VER)
+int mingw_getpagesize(void);
+#define getpagesize mingw_getpagesize
+#endif
+
+int win32_fsync_no_flush(int fd);
+#define fsync_no_flush win32_fsync_no_flush
+
+#define FSYNC_COMPONENTS_PLATFORM_DEFAULT (FSYNC_COMPONENTS_DEFAULT | FSYNC_COMPONENT_LOOSE_OBJECT)
+#define FSYNC_METHOD_DEFAULT (FSYNC_METHOD_BATCH)
+
+struct rlimit {
+ unsigned int rlim_cur;
+};
+#define RLIMIT_NOFILE 0
+
+static inline int getrlimit(int resource, struct rlimit *rlp)
+{
+ if (resource != RLIMIT_NOFILE) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ rlp->rlim_cur = 2048;
+ return 0;
+}
+
+/*
+ * Use mingw specific stat()/lstat()/fstat() implementations on Windows,
+ * including our own struct stat with 64 bit st_size and nanosecond-precision
+ * file times.
+ */
+#ifndef __MINGW64_VERSION_MAJOR
+#define off_t off64_t
+#define lseek _lseeki64
+#ifndef _MSC_VER
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif
+#endif
+
+struct mingw_stat {
+ _dev_t st_dev;
+ _ino_t st_ino;
+ _mode_t st_mode;
+ short st_nlink;
+ short st_uid;
+ short st_gid;
+ _dev_t st_rdev;
+ off64_t st_size;
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+};
+
+#define st_atime st_atim.tv_sec
+#define st_mtime st_mtim.tv_sec
+#define st_ctime st_ctim.tv_sec
+
+#ifdef stat
+#undef stat
+#endif
+#define stat mingw_stat
+int mingw_lstat(const char *file_name, struct stat *buf);
+int mingw_stat(const char *file_name, struct stat *buf);
+int mingw_fstat(int fd, struct stat *buf);
+#ifdef fstat
+#undef fstat
+#endif
+#define fstat mingw_fstat
+#ifdef lstat
+#undef lstat
+#endif
+#define lstat mingw_lstat
+
+
+int mingw_utime(const char *file_name, const struct utimbuf *times);
+#define utime mingw_utime
+size_t mingw_strftime(char *s, size_t max,
+ const char *format, const struct tm *tm);
+#define strftime mingw_strftime
+
+pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
+ const char *dir,
+ int fhin, int fhout, int fherr);
+int mingw_execvp(const char *cmd, char *const *argv);
+#define execvp mingw_execvp
+int mingw_execv(const char *cmd, char *const *argv);
+#define execv mingw_execv
+
+static inline unsigned int git_ntohl(unsigned int x)
+{ return (unsigned int)ntohl(x); }
+#define ntohl git_ntohl
+
+sig_handler_t mingw_signal(int sig, sig_handler_t handler);
+#define signal mingw_signal
+
+int mingw_raise(int sig);
+#define raise mingw_raise
+
+/*
+ * ANSI emulation wrappers
+ */
+
+int winansi_isatty(int fd);
+#define isatty winansi_isatty
+
+int winansi_dup2(int oldfd, int newfd);
+#define dup2 winansi_dup2
+
+void winansi_init(void);
+HANDLE winansi_get_osfhandle(int fd);
+
+#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
+#define PRIuMAX "I64u"
+#define PRId64 "I64d"
+#else
+#include <inttypes.h>
+#endif
+
+#endif /* COMPAT_MINGW_POSIX_H */
diff --git a/compat/mingw.h b/compat/mingw.h
index ebfb8ba423b..444daedfa52 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -1,185 +1,10 @@
-#ifdef __MINGW64_VERSION_MAJOR
-#include <stdint.h>
-#include <wchar.h>
-typedef _sigset_t sigset_t;
-#endif
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-/* MinGW-w64 reports to have flockfile, but it does not actually have it. */
-#ifdef __MINGW64_VERSION_MAJOR
-#undef _POSIX_THREAD_SAFE_FUNCTIONS
-#endif
+#include "mingw-posix.h"
struct config_context;
int mingw_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);
#define platform_core_config mingw_core_config
-/*
- * things that are not available in header files
- */
-
-typedef int uid_t;
-typedef int socklen_t;
-#ifndef __MINGW64_VERSION_MAJOR
-typedef int pid_t;
-#define hstrerror strerror
-#endif
-
-#define S_IFLNK 0120000 /* Symbolic link */
-#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
-#define S_ISSOCK(x) 0
-
-#ifndef S_IRWXG
-#define S_IRGRP 0
-#define S_IWGRP 0
-#define S_IXGRP 0
-#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
-#endif
-#ifndef S_IRWXO
-#define S_IROTH 0
-#define S_IWOTH 0
-#define S_IXOTH 0
-#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
-#endif
-
-#define S_ISUID 0004000
-#define S_ISGID 0002000
-#define S_ISVTX 0001000
-
-#define WIFEXITED(x) 1
-#define WIFSIGNALED(x) 0
-#define WEXITSTATUS(x) ((x) & 0xff)
-#define WTERMSIG(x) SIGTERM
-
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK EAGAIN
-#endif
-#ifndef ELOOP
-#define ELOOP EMLINK
-#endif
-#define SHUT_WR SD_SEND
-
-#define SIGHUP 1
-#define SIGQUIT 3
-#define SIGKILL 9
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGCHLD 17
-
-#define F_GETFD 1
-#define F_SETFD 2
-#define FD_CLOEXEC 0x1
-
-#if !defined O_CLOEXEC && defined O_NOINHERIT
-#define O_CLOEXEC O_NOINHERIT
-#endif
-
-#ifndef EAFNOSUPPORT
-#define EAFNOSUPPORT WSAEAFNOSUPPORT
-#endif
-#ifndef ECONNABORTED
-#define ECONNABORTED WSAECONNABORTED
-#endif
-#ifndef ENOTSOCK
-#define ENOTSOCK WSAENOTSOCK
-#endif
-
-struct passwd {
- char *pw_name;
- char *pw_gecos;
- char *pw_dir;
-};
-
-typedef void (__cdecl *sig_handler_t)(int);
-struct sigaction {
- sig_handler_t sa_handler;
- unsigned sa_flags;
-};
-#define SA_RESTART 0
-
-struct itimerval {
- struct timeval it_value, it_interval;
-};
-#define ITIMER_REAL 0
-
-struct utsname {
- char sysname[16];
- char nodename[1];
- char release[16];
- char version[16];
- char machine[1];
-};
-
-/*
- * sanitize preprocessor namespace polluted by Windows headers defining
- * macros which collide with git local versions
- */
-#undef HELP_COMMAND /* from winuser.h */
-
-/*
- * trivial stubs
- */
-
-static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED)
-{ errno = ENOSYS; return -1; }
-static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED)
-{ errno = ENOSYS; return -1; }
-static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED)
-{ errno = ENOSYS; return -1; }
-#ifndef __MINGW64_VERSION_MAJOR
-static inline pid_t fork(void)
-{ errno = ENOSYS; return -1; }
-#endif
-static inline unsigned int alarm(unsigned int seconds UNUSED)
-{ return 0; }
-static inline int fsync(int fd)
-{ return _commit(fd); }
-static inline void sync(void)
-{}
-static inline uid_t getuid(void)
-{ return 1; }
-static inline struct passwd *getpwnam(const char *name UNUSED)
-{ return NULL; }
-static inline int fcntl(int fd UNUSED, int cmd, ...)
-{
- if (cmd == F_GETFD || cmd == F_SETFD)
- return 0;
- errno = EINVAL;
- return -1;
-}
-
-#define sigemptyset(x) (void)0
-static inline int sigaddset(sigset_t *set UNUSED, int signum UNUSED)
-{ return 0; }
-#define SIG_BLOCK 0
-#define SIG_UNBLOCK 0
-static inline int sigprocmask(int how UNUSED, const sigset_t *set UNUSED, sigset_t *oldset UNUSED)
-{ return 0; }
-static inline pid_t getppid(void)
-{ return 1; }
-static inline pid_t getpgid(pid_t pid)
-{ return pid == 0 ? getpid() : pid; }
-static inline pid_t tcgetpgrp(int fd UNUSED)
-{ return getpid(); }
-
-/*
- * simple adaptors
- */
-
-int mingw_mkdir(const char *path, int mode);
-#define mkdir mingw_mkdir
-
-#define WNOHANG 1
-pid_t waitpid(pid_t pid, int *status, int options);
-
-#define kill mingw_kill
-int mingw_kill(pid_t pid, int sig);
-
-#define locate_in_PATH mingw_locate_in_PATH
-char *mingw_locate_in_PATH(const char *cmd);
-
#ifndef NO_OPENSSL
#include <openssl/ssl.h>
static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
@@ -201,249 +26,6 @@ static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
#define SSL_set_wfd mingw_SSL_set_wfd
#endif
-/*
- * implementations of missing functions
- */
-
-int pipe(int filedes[2]);
-unsigned int sleep (unsigned int seconds);
-int mkstemp(char *template);
-int gettimeofday(struct timeval *tv, void *tz);
-#ifndef __MINGW64_VERSION_MAJOR
-struct tm *gmtime_r(const time_t *timep, struct tm *result);
-struct tm *localtime_r(const time_t *timep, struct tm *result);
-#endif
-int getpagesize(void); /* defined in MinGW's libgcc.a */
-struct passwd *getpwuid(uid_t uid);
-int setitimer(int type, struct itimerval *in, struct itimerval *out);
-int sigaction(int sig, struct sigaction *in, struct sigaction *out);
-int link(const char *oldpath, const char *newpath);
-int uname(struct utsname *buf);
-
-/*
- * replacements of existing functions
- */
-
-int mingw_unlink(const char *pathname);
-#define unlink mingw_unlink
-
-int mingw_rmdir(const char *path);
-#define rmdir mingw_rmdir
-
-int mingw_open (const char *filename, int oflags, ...);
-#define open mingw_open
-#undef OPEN_RETURNS_EINTR
-
-int mingw_fgetc(FILE *stream);
-#define fgetc mingw_fgetc
-
-FILE *mingw_fopen (const char *filename, const char *otype);
-#define fopen mingw_fopen
-
-FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream);
-#define freopen mingw_freopen
-
-int mingw_fflush(FILE *stream);
-#define fflush mingw_fflush
-
-ssize_t mingw_write(int fd, const void *buf, size_t len);
-#define write mingw_write
-
-int mingw_access(const char *filename, int mode);
-#undef access
-#define access mingw_access
-
-int mingw_chdir(const char *dirname);
-#define chdir mingw_chdir
-
-int mingw_chmod(const char *filename, int mode);
-#define chmod mingw_chmod
-
-char *mingw_mktemp(char *template);
-#define mktemp mingw_mktemp
-
-char *mingw_getcwd(char *pointer, int len);
-#define getcwd mingw_getcwd
-
-#ifdef NO_UNSETENV
-#error "NO_UNSETENV is incompatible with the Windows-specific startup code!"
-#endif
-
-/*
- * We bind *env() routines (even the mingw_ ones) to private mingw_ versions.
- * These talk to the CRT using UNICODE/wchar_t, but maintain the original
- * narrow-char API.
- *
- * Note that the MSCRT maintains both ANSI (getenv()) and UNICODE (_wgetenv())
- * routines and stores both versions of each environment variable in parallel
- * (and secretly updates both when you set one or the other), but it uses CP_ACP
- * to do the conversion rather than CP_UTF8.
- *
- * Since everything in the git code base is UTF8, we define the mingw_ routines
- * to access the CRT using the UNICODE routines and manually convert them to
- * UTF8. This also avoids round-trip problems.
- *
- * This also helps with our linkage, since "_wenviron" is publicly exported
- * from the CRT. But to access "_environ" we would have to statically link
- * to the CRT (/MT).
- *
- * We require NO_SETENV (and let gitsetenv() call our mingw_putenv).
- */
-#define getenv mingw_getenv
-#define putenv mingw_putenv
-#define unsetenv mingw_putenv
-char *mingw_getenv(const char *name);
-int mingw_putenv(const char *name);
-
-int mingw_gethostname(char *host, int namelen);
-#define gethostname mingw_gethostname
-
-struct hostent *mingw_gethostbyname(const char *host);
-#define gethostbyname mingw_gethostbyname
-
-int mingw_getaddrinfo(const char *node, const char *service,
- const struct addrinfo *hints, struct addrinfo **res);
-#define getaddrinfo mingw_getaddrinfo
-
-int mingw_socket(int domain, int type, int protocol);
-#define socket mingw_socket
-
-int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
-#define connect mingw_connect
-
-int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz);
-#define bind mingw_bind
-
-int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen);
-#define setsockopt mingw_setsockopt
-
-int mingw_shutdown(int sockfd, int how);
-#define shutdown mingw_shutdown
-
-int mingw_listen(int sockfd, int backlog);
-#define listen mingw_listen
-
-int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz);
-#define accept mingw_accept
-
-int mingw_rename(const char*, const char*);
-#define rename mingw_rename
-
-#if defined(USE_WIN32_MMAP) || defined(_MSC_VER)
-int mingw_getpagesize(void);
-#define getpagesize mingw_getpagesize
-#endif
-
-int win32_fsync_no_flush(int fd);
-#define fsync_no_flush win32_fsync_no_flush
-
-#define FSYNC_COMPONENTS_PLATFORM_DEFAULT (FSYNC_COMPONENTS_DEFAULT | FSYNC_COMPONENT_LOOSE_OBJECT)
-#define FSYNC_METHOD_DEFAULT (FSYNC_METHOD_BATCH)
-
-struct rlimit {
- unsigned int rlim_cur;
-};
-#define RLIMIT_NOFILE 0
-
-static inline int getrlimit(int resource, struct rlimit *rlp)
-{
- if (resource != RLIMIT_NOFILE) {
- errno = EINVAL;
- return -1;
- }
-
- rlp->rlim_cur = 2048;
- return 0;
-}
-
-/*
- * Use mingw specific stat()/lstat()/fstat() implementations on Windows,
- * including our own struct stat with 64 bit st_size and nanosecond-precision
- * file times.
- */
-#ifndef __MINGW64_VERSION_MAJOR
-#define off_t off64_t
-#define lseek _lseeki64
-#ifndef _MSC_VER
-struct timespec {
- time_t tv_sec;
- long tv_nsec;
-};
-#endif
-#endif
-
-struct mingw_stat {
- _dev_t st_dev;
- _ino_t st_ino;
- _mode_t st_mode;
- short st_nlink;
- short st_uid;
- short st_gid;
- _dev_t st_rdev;
- off64_t st_size;
- struct timespec st_atim;
- struct timespec st_mtim;
- struct timespec st_ctim;
-};
-
-#define st_atime st_atim.tv_sec
-#define st_mtime st_mtim.tv_sec
-#define st_ctime st_ctim.tv_sec
-
-#ifdef stat
-#undef stat
-#endif
-#define stat mingw_stat
-int mingw_lstat(const char *file_name, struct stat *buf);
-int mingw_stat(const char *file_name, struct stat *buf);
-int mingw_fstat(int fd, struct stat *buf);
-#ifdef fstat
-#undef fstat
-#endif
-#define fstat mingw_fstat
-#ifdef lstat
-#undef lstat
-#endif
-#define lstat mingw_lstat
-
-
-int mingw_utime(const char *file_name, const struct utimbuf *times);
-#define utime mingw_utime
-size_t mingw_strftime(char *s, size_t max,
- const char *format, const struct tm *tm);
-#define strftime mingw_strftime
-
-pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
- const char *dir,
- int fhin, int fhout, int fherr);
-int mingw_execvp(const char *cmd, char *const *argv);
-#define execvp mingw_execvp
-int mingw_execv(const char *cmd, char *const *argv);
-#define execv mingw_execv
-
-static inline unsigned int git_ntohl(unsigned int x)
-{ return (unsigned int)ntohl(x); }
-#define ntohl git_ntohl
-
-sig_handler_t mingw_signal(int sig, sig_handler_t handler);
-#define signal mingw_signal
-
-int mingw_raise(int sig);
-#define raise mingw_raise
-
-/*
- * ANSI emulation wrappers
- */
-
-int winansi_isatty(int fd);
-#define isatty winansi_isatty
-
-int winansi_dup2(int oldfd, int newfd);
-#define dup2 winansi_dup2
-
-void winansi_init(void);
-HANDLE winansi_get_osfhandle(int fd);
-
/*
* git specific compatibility
*/
@@ -457,12 +39,6 @@ static inline void convert_slashes(char *path)
#define PATH_SEP ';'
char *mingw_query_user_email(void);
#define query_user_email mingw_query_user_email
-#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
-#define PRIuMAX "I64u"
-#define PRId64 "I64d"
-#else
-#include <inttypes.h>
-#endif
/**
* Verifies that the specified path is owned by the user running the
diff --git a/compat/msvc-posix.h b/compat/msvc-posix.h
new file mode 100644
index 00000000000..c500b8b4aaf
--- /dev/null
+++ b/compat/msvc-posix.h
@@ -0,0 +1,33 @@
+#ifndef COMPAT_MSVC_POSIX_H
+#define COMPAT_MSVC_POSIX_H
+
+#include <direct.h>
+#include <process.h>
+#include <malloc.h>
+#include <io.h>
+
+#pragma warning(disable: 4018) /* signed/unsigned comparison */
+#pragma warning(disable: 4244) /* type conversion, possible loss of data */
+#pragma warning(disable: 4090) /* 'function' : different 'const' qualifiers (ALLOC_GROW etc.)*/
+
+/* porting function */
+#define inline __inline
+#define __inline__ __inline
+#define __attribute__(x)
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+#define ftruncate _chsize
+#define strtoull _strtoui64
+#define strtoll _strtoi64
+
+#undef ERROR
+
+#define ftello _ftelli64
+
+typedef int sigset_t;
+/* open for reading, writing, or both (not in fcntl.h) */
+#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
+
+#include "mingw-posix.h"
+
+#endif /* COMPAT_MSVC_POSIX_H */
diff --git a/compat/msvc.h b/compat/msvc.h
index 1d7a8c61456..2b87c0a7c70 100644
--- a/compat/msvc.h
+++ b/compat/msvc.h
@@ -1,33 +1,7 @@
#ifndef __MSVC__HEAD
#define __MSVC__HEAD
-#include <direct.h>
-#include <process.h>
-#include <malloc.h>
-#include <io.h>
-
-#pragma warning(disable: 4018) /* signed/unsigned comparison */
-#pragma warning(disable: 4244) /* type conversion, possible loss of data */
-#pragma warning(disable: 4090) /* 'function' : different 'const' qualifiers (ALLOC_GROW etc.)*/
-
-/* porting function */
-#define inline __inline
-#define __inline__ __inline
-#define __attribute__(x)
-#define strcasecmp _stricmp
-#define strncasecmp _strnicmp
-#define ftruncate _chsize
-#define strtoull _strtoui64
-#define strtoll _strtoi64
-
-#undef ERROR
-
-#define ftello _ftelli64
-
-typedef int sigset_t;
-/* open for reading, writing, or both (not in fcntl.h) */
-#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
-
-#include "compat/mingw.h"
+#include "msvc-posix.h"
+#include "mingw.h"
#endif
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 16/18] git-compat-util.h: split out POSIX-emulating bits
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (14 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
` (2 subsequent siblings)
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
The "git-compat-util.h" header is a treasure trove of various bits and
pieces used throughout the project. It basically mixes two different
things into one:
- Providing a POSIX-like interface even on platforms that aren't
POSIX-compliant.
- Providing low-level functionality that is specific to Git.
This intermixing is a bit of a problem for the reftable library as we
don't want to recreate the POSIX-like interface there. But neither do we
want to pull in the Git-specific functionality, as it is otherwise quite
easy to start depending on the Git codebase again.
Split out a new header "compat/posix.h" that only contains the bits and
pieces relevant for the emulation of POSIX, which we will start using in
the next commit.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
compat/posix.h | 541 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
git-compat-util.h | 531 +----------------------------------------------------
2 files changed, 543 insertions(+), 529 deletions(-)
diff --git a/compat/posix.h b/compat/posix.h
new file mode 100644
index 00000000000..f4c71f9427d
--- /dev/null
+++ b/compat/posix.h
@@ -0,0 +1,541 @@
+#ifndef COMPAT_POSIX_H
+#define COMPAT_POSIX_H
+
+#define _FILE_OFFSET_BITS 64
+
+/*
+ * Derived from Linux "Features Test Macro" header
+ * Convenience macros to test the versions of gcc (or
+ * a compatible compiler).
+ * Use them like this:
+ * #if GIT_GNUC_PREREQ (2,8)
+ * ... code requiring gcc 2.8 or later ...
+ * #endif
+ *
+ * This macro of course is not part of POSIX, but we need it for the UNUSED
+ * macro which is used by some of our POSIX compatibility wrappers.
+*/
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define GIT_GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+ #define GIT_GNUC_PREREQ(maj, min) 0
+#endif
+
+/*
+ * UNUSED marks a function parameter that is always unused. It also
+ * can be used to annotate a function, a variable, or a type that is
+ * always unused.
+ *
+ * A callback interface may dictate that a function accepts a
+ * parameter at that position, but the implementation of the function
+ * may not need to use the parameter. In such a case, mark the parameter
+ * with UNUSED.
+ *
+ * When a parameter may be used or unused, depending on conditional
+ * compilation, consider using MAYBE_UNUSED instead.
+ */
+#if GIT_GNUC_PREREQ(4, 5)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated ("parameter declared as UNUSED")))
+#elif defined(__GNUC__)
+#define UNUSED __attribute__((unused)) \
+ __attribute__((deprecated))
+#else
+#define UNUSED
+#endif
+
+#ifdef __MINGW64__
+#define _POSIX_C_SOURCE 1
+#elif defined(__sun__)
+ /*
+ * On Solaris, when _XOPEN_EXTENDED is set, its header file
+ * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
+ * setting to say we are XPG5 or XPG6. Also on Solaris,
+ * XPG6 programs must be compiled with a c99 compiler, while
+ * non XPG6 programs must be compiled with a pre-c99 compiler.
+ */
+# if __STDC_VERSION__ - 0 >= 199901L
+# define _XOPEN_SOURCE 600
+# else
+# define _XOPEN_SOURCE 500
+# endif
+#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
+ !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
+ !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
+ !defined(__CYGWIN__)
+#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
+#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
+#endif
+#define _ALL_SOURCE 1
+#define _GNU_SOURCE 1
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+#define _NETBSD_SOURCE 1
+#define _SGI_SOURCE 1
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
+# if !defined(_WIN32_WINNT)
+# define _WIN32_WINNT 0x0600
+# endif
+#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
+#include <winsock2.h>
+#ifndef NO_UNIX_SOCKETS
+#include <afunix.h>
+#endif
+#include <windows.h>
+#define GIT_WINDOWS_NATIVE
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h> /* for strcasecmp() */
+#endif
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#ifdef NEEDS_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#include <syslog.h>
+#if !defined(NO_POLL_H)
+#include <poll.h>
+#elif !defined(NO_SYS_POLL_H)
+#include <sys/poll.h>
+#else
+/* Pull the compat stuff */
+#include <poll.h>
+#endif
+#ifdef HAVE_BSD_SYSCTL
+#include <sys/sysctl.h>
+#endif
+
+#if defined(__MINGW32__)
+#include "mingw-posix.h"
+#elif defined(_MSC_VER)
+#include "msvc-posix.h"
+#else
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/statvfs.h>
+#include <termios.h>
+#ifndef NO_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/un.h>
+#ifndef NO_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+#ifdef HAVE_ARC4RANDOM_LIBBSD
+#include <bsd/stdlib.h>
+#endif
+#ifdef HAVE_GETRANDOM
+#include <sys/random.h>
+#endif
+#ifdef NO_INTPTR_T
+/*
+ * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
+ * on LLP86, IL33LLP64 and P64 it needs to be "long long",
+ * while on IP16 and IP16L32 it is "int" (resp. "short")
+ * Size needs to match (or exceed) 'sizeof(void *)'.
+ * We can't take "long long" here as not everybody has it.
+ */
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+#endif
+#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
+#include <grp.h>
+#define _ALL_SOURCE 1
+#endif
+
+#ifdef MKDIR_WO_TRAILING_SLASH
+#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
+int compat_mkdir_wo_trailing_slash(const char*, mode_t);
+#endif
+
+#ifdef time
+#undef time
+#endif
+static inline time_t git_time(time_t *tloc)
+{
+ struct timeval tv;
+
+ /*
+ * Avoid time(NULL), which can disagree with gettimeofday(2)
+ * and filesystem timestamps.
+ */
+ gettimeofday(&tv, NULL);
+
+ if (tloc)
+ *tloc = tv.tv_sec;
+ return tv.tv_sec;
+}
+#define time git_time
+
+#ifdef NO_STRUCT_ITIMERVAL
+struct itimerval {
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+#endif
+
+#ifdef NO_SETITIMER
+static inline int git_setitimer(int which UNUSED,
+ const struct itimerval *value UNUSED,
+ struct itimerval *newvalue UNUSED) {
+ return 0; /* pretend success */
+}
+#undef setitimer
+#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
+#endif
+
+#ifndef NO_LIBGEN_H
+#include <libgen.h>
+#else
+#define basename gitbasename
+char *gitbasename(char *);
+#define dirname gitdirname
+char *gitdirname(char *);
+#endif
+
+#ifndef NO_ICONV
+#include <iconv.h>
+#endif
+
+/* On most systems <netdb.h> would have given us this, but
+ * not on some systems (e.g. z/OS).
+ */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+/* On most systems <limits.h> would have given us this, but
+ * not on some systems (e.g. GNU/Hurd).
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+typedef uintmax_t timestamp_t;
+#define PRItime PRIuMAX
+#define parse_timestamp strtoumax
+#define TIME_MAX UINTMAX_MAX
+#define TIME_MIN 0
+
+int lstat_cache_aware_rmdir(const char *path);
+#if !defined(__MINGW32__) && !defined(_MSC_VER)
+#define rmdir lstat_cache_aware_rmdir
+#endif
+
+#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
+
+#ifndef PROT_READ
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define MAP_PRIVATE 1
+#endif
+
+#define mmap git_mmap
+#define munmap git_munmap
+void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int git_munmap(void *start, size_t length);
+
+#else /* NO_MMAP || USE_WIN32_MMAP */
+
+#include <sys/mman.h>
+
+#endif /* NO_MMAP || USE_WIN32_MMAP */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#ifdef NEEDS_MODE_TRANSLATION
+#undef S_IFMT
+#undef S_IFREG
+#undef S_IFDIR
+#undef S_IFLNK
+#undef S_IFBLK
+#undef S_IFCHR
+#undef S_IFIFO
+#undef S_IFSOCK
+#define S_IFMT 0170000
+#define S_IFREG 0100000
+#define S_IFDIR 0040000
+#define S_IFLNK 0120000
+#define S_IFBLK 0060000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_IFSOCK 0140000
+#ifdef stat
+#undef stat
+#endif
+#define stat(path, buf) git_stat(path, buf)
+int git_stat(const char *, struct stat *);
+#ifdef fstat
+#undef fstat
+#endif
+#define fstat(fd, buf) git_fstat(fd, buf)
+int git_fstat(int, struct stat *);
+#ifdef lstat
+#undef lstat
+#endif
+#define lstat(path, buf) git_lstat(path, buf)
+int git_lstat(const char *, struct stat *);
+#endif
+
+#ifdef NO_PREAD
+#define pread git_pread
+ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+
+#ifdef NO_SETENV
+#define setenv gitsetenv
+int gitsetenv(const char *, const char *, int);
+#endif
+
+#ifdef NO_MKDTEMP
+#define mkdtemp gitmkdtemp
+char *gitmkdtemp(char *);
+#endif
+
+#ifdef NO_UNSETENV
+#define unsetenv gitunsetenv
+int gitunsetenv(const char *);
+#endif
+
+#ifdef NO_STRCASESTR
+#define strcasestr gitstrcasestr
+char *gitstrcasestr(const char *haystack, const char *needle);
+#endif
+
+#ifdef NO_STRLCPY
+#define strlcpy gitstrlcpy
+size_t gitstrlcpy(char *, const char *, size_t);
+#endif
+
+#ifdef NO_STRTOUMAX
+#define strtoumax gitstrtoumax
+uintmax_t gitstrtoumax(const char *, char **, int);
+#define strtoimax gitstrtoimax
+intmax_t gitstrtoimax(const char *, char **, int);
+#endif
+
+#ifdef NO_HSTRERROR
+#define hstrerror githstrerror
+const char *githstrerror(int herror);
+#endif
+
+#ifdef NO_MEMMEM
+#define memmem gitmemmem
+void *gitmemmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+#endif
+
+#ifdef OVERRIDE_STRDUP
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup gitstrdup
+char *gitstrdup(const char *s);
+#endif
+
+#ifdef NO_GETPAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifdef FREAD_READS_DIRECTORIES
+# if !defined(SUPPRESS_FOPEN_REDEFINITION)
+# ifdef fopen
+# undef fopen
+# endif
+# define fopen(a,b) git_fopen(a,b)
+# endif
+FILE *git_fopen(const char*, const char*);
+#endif
+
+#ifdef SNPRINTF_RETURNS_BOGUS
+#ifdef snprintf
+#undef snprintf
+#endif
+#define snprintf git_snprintf
+int git_snprintf(char *str, size_t maxsize,
+ const char *format, ...);
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#define vsnprintf git_vsnprintf
+int git_vsnprintf(char *str, size_t maxsize,
+ const char *format, va_list ap);
+#endif
+
+#ifdef OPEN_RETURNS_EINTR
+#undef open
+#define open git_open_with_retry
+int git_open_with_retry(const char *path, int flag, ...);
+#endif
+
+#ifdef __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2, 1)
+#define HAVE_STRCHRNUL
+#endif
+#endif
+
+#ifndef HAVE_STRCHRNUL
+#define strchrnul gitstrchrnul
+static inline char *gitstrchrnul(const char *s, int c)
+{
+ while (*s && *s != c)
+ s++;
+ return (char *)s;
+}
+#endif
+
+#ifdef NO_INET_PTON
+int inet_pton(int af, const char *src, void *dst);
+#endif
+
+#ifdef NO_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
+#ifdef NO_PTHREADS
+#define atexit git_atexit
+int git_atexit(void (*handler)(void));
+#endif
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
+#include "../sane-ctype.h"
+
+void git_stable_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
+#ifdef INTERNAL_QSORT
+#define qsort git_stable_qsort
+#endif
+
+#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
+static inline void sane_qsort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *))
+{
+ if (nmemb > 1)
+ qsort(base, nmemb, size, compar);
+}
+
+#define STABLE_QSORT(base, n, compar) \
+ git_stable_qsort((base), (n), sizeof(*(base)), compar)
+
+#ifndef HAVE_ISO_QSORT_S
+int git_qsort_s(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *), void *ctx);
+#define qsort_s git_qsort_s
+#endif
+
+#define QSORT_S(base, n, compar, ctx) do { \
+ if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
+ BUG("qsort_s() failed"); \
+} while (0)
+
+#ifdef NO_NSEC
+#undef USE_NSEC
+#define ST_CTIME_NSEC(st) 0
+#define ST_MTIME_NSEC(st) 0
+#else
+#ifdef USE_ST_TIMESPEC
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
+#else
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
+#endif
+#endif
+
+#ifndef va_copy
+/*
+ * Since an obvious implementation of va_list would be to make it a
+ * pointer into the stack frame, a simple assignment will work on
+ * many systems. But let's try to be more portable.
+ */
+#ifdef __va_copy
+#define va_copy(dst, src) __va_copy(dst, src)
+#else
+#define va_copy(dst, src) ((dst) = (src))
+#endif
+#endif
+
+#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+static inline void git_flockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+static inline void git_funlockfile(FILE *fh UNUSED)
+{
+ ; /* nothing */
+}
+#undef flockfile
+#undef funlockfile
+#undef getc_unlocked
+#define flockfile(fh) git_flockfile(fh)
+#define funlockfile(fh) git_funlockfile(fh)
+#define getc_unlocked(fh) getc(fh)
+#endif
+
+#ifdef FILENO_IS_A_MACRO
+int git_fileno(FILE *stream);
+# ifndef COMPAT_CODE_FILENO
+# undef fileno
+# define fileno(p) git_fileno(p)
+# endif
+#endif
+
+#ifdef NEED_ACCESS_ROOT_HANDLER
+int git_access(const char *path, int mode);
+# ifndef COMPAT_CODE_ACCESS
+# ifdef access
+# undef access
+# endif
+# define access(path, mode) git_access(path, mode)
+# endif
+#endif
+
+#endif /* COMPAT_POSIX_H */
diff --git a/git-compat-util.h b/git-compat-util.h
index e123288e8f1..03e2ba59d3e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -23,26 +23,9 @@
#include <crtdbg.h>
#endif
-struct strbuf;
-
-
-#define _FILE_OFFSET_BITS 64
+#include "compat/posix.h"
-
-/* Derived from Linux "Features Test Macro" header
- * Convenience macros to test the versions of gcc (or
- * a compatible compiler).
- * Use them like this:
- * #if GIT_GNUC_PREREQ (2,8)
- * ... code requiring gcc 2.8 or later ...
- * #endif
-*/
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define GIT_GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-#else
- #define GIT_GNUC_PREREQ(maj, min) 0
-#endif
+struct strbuf;
#if defined(__GNUC__) || defined(__clang__)
# define PRAGMA(pragma) _Pragma(#pragma)
@@ -176,71 +159,6 @@ DISABLE_WARNING(-Wsign-compare)
/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-#ifdef __MINGW64__
-#define _POSIX_C_SOURCE 1
-#elif defined(__sun__)
- /*
- * On Solaris, when _XOPEN_EXTENDED is set, its header file
- * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
- * setting to say we are XPG5 or XPG6. Also on Solaris,
- * XPG6 programs must be compiled with a c99 compiler, while
- * non XPG6 programs must be compiled with a pre-c99 compiler.
- */
-# if __STDC_VERSION__ - 0 >= 199901L
-# define _XOPEN_SOURCE 600
-# else
-# define _XOPEN_SOURCE 500
-# endif
-#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
- !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
- !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \
- !defined(__CYGWIN__)
-#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
-#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
-#endif
-#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
-#define _BSD_SOURCE 1
-#define _DEFAULT_SOURCE 1
-#define _NETBSD_SOURCE 1
-#define _SGI_SOURCE 1
-
-/*
- * UNUSED marks a function parameter that is always unused. It also
- * can be used to annotate a function, a variable, or a type that is
- * always unused.
- *
- * A callback interface may dictate that a function accepts a
- * parameter at that position, but the implementation of the function
- * may not need to use the parameter. In such a case, mark the parameter
- * with UNUSED.
- *
- * When a parameter may be used or unused, depending on conditional
- * compilation, consider using MAYBE_UNUSED instead.
- */
-#if GIT_GNUC_PREREQ(4, 5)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated ("parameter declared as UNUSED")))
-#elif defined(__GNUC__)
-#define UNUSED __attribute__((unused)) \
- __attribute__((deprecated))
-#else
-#define UNUSED
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
-# if !defined(_WIN32_WINNT)
-# define _WIN32_WINNT 0x0600
-# endif
-#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
-#include <winsock2.h>
-#ifndef NO_UNIX_SOCKETS
-#include <afunix.h>
-#endif
-#include <windows.h>
-#define GIT_WINDOWS_NATIVE
-#endif
-
#if defined(NO_UNIX_SOCKETS) || !defined(GIT_WINDOWS_NATIVE)
static inline int _have_unix_sockets(void)
{
@@ -253,45 +171,6 @@ static inline int _have_unix_sockets(void)
#define have_unix_sockets _have_unix_sockets
#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h> /* for strcasecmp() */
-#endif
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#ifdef NEEDS_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <time.h>
-#include <signal.h>
-#include <assert.h>
-#include <regex.h>
-#include <utime.h>
-#include <syslog.h>
-#if !defined(NO_POLL_H)
-#include <poll.h>
-#elif !defined(NO_SYS_POLL_H)
-#include <sys/poll.h>
-#else
-/* Pull the compat stuff */
-#include <poll.h>
-#endif
-#ifdef HAVE_BSD_SYSCTL
-#include <sys/sysctl.h>
-#endif
-
/* Used by compat/win32/path-utils.h, and more */
static inline int is_xplatform_dir_sep(int c)
{
@@ -308,48 +187,6 @@ static inline int is_xplatform_dir_sep(int c)
#elif defined(_MSC_VER)
#include "compat/win32/path-utils.h"
#include "compat/msvc.h"
-#else
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/statvfs.h>
-#include <termios.h>
-#ifndef NO_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <sys/un.h>
-#ifndef NO_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <stdint.h>
-#endif
-#ifdef HAVE_ARC4RANDOM_LIBBSD
-#include <bsd/stdlib.h>
-#endif
-#ifdef HAVE_GETRANDOM
-#include <sys/random.h>
-#endif
-#ifdef NO_INTPTR_T
-/*
- * On I16LP32, ILP32 and LP64 "long" is the safe bet, however
- * on LLP86, IL33LLP64 and P64 it needs to be "long long",
- * while on IP16 and IP16L32 it is "int" (resp. "short")
- * Size needs to match (or exceed) 'sizeof(void *)'.
- * We can't take "long long" here as not everybody has it.
- */
-typedef long intptr_t;
-typedef unsigned long uintptr_t;
-#endif
-#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
-#include <grp.h>
-#define _ALL_SOURCE 1
#endif
/* used on Mac OS X */
@@ -370,60 +207,6 @@ static inline const char *precompose_string_if_needed(const char *in)
#define probe_utf8_pathname_composition()
#endif
-#ifdef MKDIR_WO_TRAILING_SLASH
-#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
-int compat_mkdir_wo_trailing_slash(const char*, mode_t);
-#endif
-
-#ifdef time
-#undef time
-#endif
-static inline time_t git_time(time_t *tloc)
-{
- struct timeval tv;
-
- /*
- * Avoid time(NULL), which can disagree with gettimeofday(2)
- * and filesystem timestamps.
- */
- gettimeofday(&tv, NULL);
-
- if (tloc)
- *tloc = tv.tv_sec;
- return tv.tv_sec;
-}
-#define time git_time
-
-#ifdef NO_STRUCT_ITIMERVAL
-struct itimerval {
- struct timeval it_interval;
- struct timeval it_value;
-};
-#endif
-
-#ifdef NO_SETITIMER
-static inline int git_setitimer(int which UNUSED,
- const struct itimerval *value UNUSED,
- struct itimerval *newvalue UNUSED) {
- return 0; /* pretend success */
-}
-#undef setitimer
-#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue)
-#endif
-
-#ifndef NO_LIBGEN_H
-#include <libgen.h>
-#else
-#define basename gitbasename
-char *gitbasename(char *);
-#define dirname gitdirname
-char *gitdirname(char *);
-#endif
-
-#ifndef NO_ICONV
-#include <iconv.h>
-#endif
-
#ifndef NO_OPENSSL
#ifdef __APPLE__
#undef __AVAILABILITY_MACROS_USES_AVAILABILITY
@@ -441,34 +224,6 @@ char *gitdirname(char *);
# include <sys/sysinfo.h>
#endif
-/* On most systems <netdb.h> would have given us this, but
- * not on some systems (e.g. z/OS).
- */
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
-
-/* On most systems <limits.h> would have given us this, but
- * not on some systems (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-typedef uintmax_t timestamp_t;
-#define PRItime PRIuMAX
-#define parse_timestamp strtoumax
-#define TIME_MAX UINTMAX_MAX
-#define TIME_MIN 0
-
#ifndef PATH_SEP
#define PATH_SEP ':'
#endif
@@ -492,11 +247,6 @@ static inline int noop_core_config(const char *var UNUSED,
#define platform_core_config noop_core_config
#endif
-int lstat_cache_aware_rmdir(const char *path);
-#if !defined(__MINGW32__) && !defined(_MSC_VER)
-#define rmdir lstat_cache_aware_rmdir
-#endif
-
#ifndef has_dos_drive_prefix
static inline int git_has_dos_drive_prefix(const char *path UNUSED)
{
@@ -824,25 +574,6 @@ static inline bool strip_suffix(const char *str, const char *suffix,
memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \
} while (0)
-#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-
-#ifndef PROT_READ
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define MAP_PRIVATE 1
-#endif
-
-#define mmap git_mmap
-#define munmap git_munmap
-void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-int git_munmap(void *start, size_t length);
-
-#else /* NO_MMAP || USE_WIN32_MMAP */
-
-#include <sys/mman.h>
-
-#endif /* NO_MMAP || USE_WIN32_MMAP */
-
#ifdef NO_MMAP
/* This value must be multiple of (pagesize * 2) */
@@ -858,177 +589,15 @@ int git_munmap(void *start, size_t length);
#endif /* NO_MMAP */
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
#define on_disk_bytes(st) ((st).st_size)
#else
#define on_disk_bytes(st) ((st).st_blocks * 512)
#endif
-#ifdef NEEDS_MODE_TRANSLATION
-#undef S_IFMT
-#undef S_IFREG
-#undef S_IFDIR
-#undef S_IFLNK
-#undef S_IFBLK
-#undef S_IFCHR
-#undef S_IFIFO
-#undef S_IFSOCK
-#define S_IFMT 0170000
-#define S_IFREG 0100000
-#define S_IFDIR 0040000
-#define S_IFLNK 0120000
-#define S_IFBLK 0060000
-#define S_IFCHR 0020000
-#define S_IFIFO 0010000
-#define S_IFSOCK 0140000
-#ifdef stat
-#undef stat
-#endif
-#define stat(path, buf) git_stat(path, buf)
-int git_stat(const char *, struct stat *);
-#ifdef fstat
-#undef fstat
-#endif
-#define fstat(fd, buf) git_fstat(fd, buf)
-int git_fstat(int, struct stat *);
-#ifdef lstat
-#undef lstat
-#endif
-#define lstat(path, buf) git_lstat(path, buf)
-int git_lstat(const char *, struct stat *);
-#endif
-
#define DEFAULT_PACKED_GIT_LIMIT \
((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))
-#ifdef NO_PREAD
-#define pread git_pread
-ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
-#endif
-
-#ifdef NO_SETENV
-#define setenv gitsetenv
-int gitsetenv(const char *, const char *, int);
-#endif
-
-#ifdef NO_MKDTEMP
-#define mkdtemp gitmkdtemp
-char *gitmkdtemp(char *);
-#endif
-
-#ifdef NO_UNSETENV
-#define unsetenv gitunsetenv
-int gitunsetenv(const char *);
-#endif
-
-#ifdef NO_STRCASESTR
-#define strcasestr gitstrcasestr
-char *gitstrcasestr(const char *haystack, const char *needle);
-#endif
-
-#ifdef NO_STRLCPY
-#define strlcpy gitstrlcpy
-size_t gitstrlcpy(char *, const char *, size_t);
-#endif
-
-#ifdef NO_STRTOUMAX
-#define strtoumax gitstrtoumax
-uintmax_t gitstrtoumax(const char *, char **, int);
-#define strtoimax gitstrtoimax
-intmax_t gitstrtoimax(const char *, char **, int);
-#endif
-
-#ifdef NO_HSTRERROR
-#define hstrerror githstrerror
-const char *githstrerror(int herror);
-#endif
-
-#ifdef NO_MEMMEM
-#define memmem gitmemmem
-void *gitmemmem(const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen);
-#endif
-
-#ifdef OVERRIDE_STRDUP
-#ifdef strdup
-#undef strdup
-#endif
-#define strdup gitstrdup
-char *gitstrdup(const char *s);
-#endif
-
-#ifdef NO_GETPAGESIZE
-#define getpagesize() sysconf(_SC_PAGESIZE)
-#endif
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
-#endif
-
-#ifdef FREAD_READS_DIRECTORIES
-# if !defined(SUPPRESS_FOPEN_REDEFINITION)
-# ifdef fopen
-# undef fopen
-# endif
-# define fopen(a,b) git_fopen(a,b)
-# endif
-FILE *git_fopen(const char*, const char*);
-#endif
-
-#ifdef SNPRINTF_RETURNS_BOGUS
-#ifdef snprintf
-#undef snprintf
-#endif
-#define snprintf git_snprintf
-int git_snprintf(char *str, size_t maxsize,
- const char *format, ...);
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#define vsnprintf git_vsnprintf
-int git_vsnprintf(char *str, size_t maxsize,
- const char *format, va_list ap);
-#endif
-
-#ifdef OPEN_RETURNS_EINTR
-#undef open
-#define open git_open_with_retry
-int git_open_with_retry(const char *path, int flag, ...);
-#endif
-
-#ifdef __GLIBC_PREREQ
-#if __GLIBC_PREREQ(2, 1)
-#define HAVE_STRCHRNUL
-#endif
-#endif
-
-#ifndef HAVE_STRCHRNUL
-#define strchrnul gitstrchrnul
-static inline char *gitstrchrnul(const char *s, int c)
-{
- while (*s && *s != c)
- s++;
- return (char *)s;
-}
-#endif
-
-#ifdef NO_INET_PTON
-int inet_pton(int af, const char *src, void *dst);
-#endif
-
-#ifdef NO_INET_NTOP
-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-#endif
-
-#ifdef NO_PTHREADS
-#define atexit git_atexit
-int git_atexit(void (*handler)(void));
-#endif
-
static inline size_t st_add(size_t a, size_t b)
{
if (unsigned_add_overflows(a, b))
@@ -1295,12 +864,6 @@ static inline size_t xsize_t(off_t len)
return (size_t) len;
}
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
-#endif
-
-#include "sane-ctype.h"
-
/*
* Like skip_prefix, but compare case-insensitively. Note that the comparison
* is done via tolower(), so it is strictly ASCII (no multi-byte characters or
@@ -1366,34 +929,6 @@ static inline int strtol_i(char const *s, int base, int *result)
return 0;
}
-void git_stable_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *));
-#ifdef INTERNAL_QSORT
-#define qsort git_stable_qsort
-#endif
-
-#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar)
-static inline void sane_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *))
-{
- if (nmemb > 1)
- qsort(base, nmemb, size, compar);
-}
-
-#define STABLE_QSORT(base, n, compar) \
- git_stable_qsort((base), (n), sizeof(*(base)), compar)
-
-#ifndef HAVE_ISO_QSORT_S
-int git_qsort_s(void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *, void *), void *ctx);
-#define qsort_s git_qsort_s
-#endif
-
-#define QSORT_S(base, n, compar, ctx) do { \
- if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \
- BUG("qsort_s() failed"); \
-} while (0)
-
#ifndef REG_STARTEND
#error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd"
#endif
@@ -1418,39 +953,12 @@ int git_regcomp(regex_t *preg, const char *pattern, int cflags);
# define FORCE_DIR_SET_GID 0
#endif
-#ifdef NO_NSEC
-#undef USE_NSEC
-#define ST_CTIME_NSEC(st) 0
-#define ST_MTIME_NSEC(st) 0
-#else
-#ifdef USE_ST_TIMESPEC
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
-#else
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
-#endif
-#endif
-
#ifdef UNRELIABLE_FSTAT
#define fstat_is_reliable() 0
#else
#define fstat_is_reliable() 1
#endif
-#ifndef va_copy
-/*
- * Since an obvious implementation of va_list would be to make it a
- * pointer into the stack frame, a simple assignment will work on
- * many systems. But let's try to be more portable.
- */
-#ifdef __va_copy
-#define va_copy(dst, src) __va_copy(dst, src)
-#else
-#define va_copy(dst, src) ((dst) = (src))
-#endif
-#endif
-
/* usage.c: only to be used for testing BUG() implementation (see test-tool) */
extern int BUG_exit_code;
@@ -1480,41 +988,6 @@ void bug_fl(const char *file, int line, const char *fmt, ...);
# define SHELL_PATH "/bin/sh"
#endif
-#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
-static inline void git_flockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-static inline void git_funlockfile(FILE *fh UNUSED)
-{
- ; /* nothing */
-}
-#undef flockfile
-#undef funlockfile
-#undef getc_unlocked
-#define flockfile(fh) git_flockfile(fh)
-#define funlockfile(fh) git_funlockfile(fh)
-#define getc_unlocked(fh) getc(fh)
-#endif
-
-#ifdef FILENO_IS_A_MACRO
-int git_fileno(FILE *stream);
-# ifndef COMPAT_CODE_FILENO
-# undef fileno
-# define fileno(p) git_fileno(p)
-# endif
-#endif
-
-#ifdef NEED_ACCESS_ROOT_HANDLER
-int git_access(const char *path, int mode);
-# ifndef COMPAT_CODE_ACCESS
-# ifdef access
-# undef access
-# endif
-# define access(path, mode) git_access(path, mode)
-# endif
-#endif
-
/*
* Our code often opens a path to an optional file, to work on its
* contents when we can successfully open it. We can ignore a failure
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h"
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (15 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-02-18 18:55 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Junio C Hamano
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
The reftable library includes "git-compat-util.h" in order to get a
POSIX-like programming environment that papers over various differences
between platforms. The header also brings with it a couple of helpers
specific to the Git codebase though, and over time we have started to
use these helpers in the reftable library, as well.
This makes it very hard to use the reftable library as a standalone
library without the rest of the Git codebase, so other libraries like
e.g. libgit2 cannot easily use it. But now that we have removed all
calls to Git-specific functionality and have split out "compat/posix.h"
as a separate header we can address this.
Stop including "git-compat-util.h" and instead include "compat/posix.h"
to finalize the decoupling of the reftable library from the rest of the
Git codebase. The only bits which remain specific to Git are "system.h"
and "system.c", which projects will have to provide.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
reftable/system.c | 2 ++
reftable/system.h | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/reftable/system.c b/reftable/system.c
index e25ccc0da3c..1ee268b125d 100644
--- a/reftable/system.c
+++ b/reftable/system.c
@@ -1,3 +1,5 @@
+#include "../git-compat-util.h"
+
#include "system.h"
#include "basics.h"
#include "reftable-error.h"
diff --git a/reftable/system.h b/reftable/system.h
index bb6a7e6285b..10055fbff2d 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -11,7 +11,7 @@ license that can be found in the LICENSE file or at
/* This header glues the reftable library to the rest of Git */
-#include "git-compat-util.h"
+#include "compat/posix.h"
#include "compat/zlib-compat.h"
/*
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* [PATCH v6 18/18] Makefile: skip reftable library for Coccinelle
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (16 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
@ 2025-02-18 9:20 ` Patrick Steinhardt
2025-02-18 18:55 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Junio C Hamano
18 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-02-18 9:20 UTC (permalink / raw)
To: git
Cc: Edward Thomson, Justin Tobler, Junio C Hamano, Johannes Sixt,
Johannes Schindelin
The reftable library does not use any of the common helpers that the Git
project has. Consequently, most of the rules that we have in Coccinelle
do not apply to the library at all and may even generate false positives
when a pattern can be converted to use a Git helper function.
Exclude reftable library sources from being checked by Coccinelle to
avoid such false positives.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index cd0806e1e69..83f1df5502b 100644
--- a/Makefile
+++ b/Makefile
@@ -955,7 +955,7 @@ FOUND_SOURCE_FILES := $(filter-out $(GENERATED_H),$(shell $(SOURCES_CMD)))
FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES))
FOUND_H_SOURCES = $(filter %.h,$(FOUND_SOURCE_FILES))
-COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
+COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES) reftable/%,$(FOUND_C_SOURCES))
LIB_H = $(FOUND_H_SOURCES)
--
2.48.1.666.gff9fcf71b7.dirty
^ permalink raw reply related [flat|nested] 146+ messages in thread
* Re: [PATCH v6 00/18] reftable: stop using "git-compat-util.h"
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
` (17 preceding siblings ...)
2025-02-18 9:20 ` [PATCH v6 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
@ 2025-02-18 18:55 ` Junio C Hamano
2025-03-11 23:29 ` Junio C Hamano
18 siblings, 1 reply; 146+ messages in thread
From: Junio C Hamano @ 2025-02-18 18:55 UTC (permalink / raw)
To: Patrick Steinhardt
Cc: git, Edward Thomson, Justin Tobler, Johannes Sixt,
Johannes Schindelin, Toon Claes
Patrick Steinhardt <ps@pks.im> writes:
> Changes in v6:
> - I have rebased the patch series on top of "master" at 03944513488
> (The eleventh batch, 2025-02-14). On the one hand this gets rid of
> the conflict with the zlib-ng changes, which have meanwhile been
> merged to that branch. And on the other hand it pulls in the new CI
> build for MSVC+Meson, which allows me to have better test coverage
> on Windows to better detect breakage there.
> - Stop moving around Win32 files so that we do the minimum viable
> change in this context. Hopefully, this makes it easier for Dscho to
> integrate into Git for Windows. If it doesn't I don't really have
> any other good ideas for how to do it, so the only alternative would
> be to just ignore Windows altogether.
> - Link to v5: https://lore.kernel.org/r/20250207-pks-reftable-drop-git-compat-util-v5-0-ba2adc79110f@pks.im
Thanks. I think the "unlink" thing on Windows I have was queued
depended on the previous iteration of this series so let me make
sure that I'd unentangle it while replacing the topic with this
round.
Will queue. Thanks.
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v6 00/18] reftable: stop using "git-compat-util.h"
2025-02-18 18:55 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Junio C Hamano
@ 2025-03-11 23:29 ` Junio C Hamano
2025-03-12 6:51 ` Patrick Steinhardt
0 siblings, 1 reply; 146+ messages in thread
From: Junio C Hamano @ 2025-03-11 23:29 UTC (permalink / raw)
To: Patrick Steinhardt
Cc: git, Edward Thomson, Justin Tobler, Johannes Sixt,
Johannes Schindelin, Toon Claes
Junio C Hamano <gitster@pobox.com> writes:
> Patrick Steinhardt <ps@pks.im> writes:
>
>> Changes in v6:
>> - I have rebased the patch series on top of "master" at 03944513488
>> (The eleventh batch, 2025-02-14). On the one hand this gets rid of
>> the conflict with the zlib-ng changes, which have meanwhile been
>> merged to that branch. And on the other hand it pulls in the new CI
>> build for MSVC+Meson, which allows me to have better test coverage
>> on Windows to better detect breakage there.
>> - Stop moving around Win32 files so that we do the minimum viable
>> change in this context. Hopefully, this makes it easier for Dscho to
>> integrate into Git for Windows. If it doesn't I don't really have
>> any other good ideas for how to do it, so the only alternative would
>> be to just ignore Windows altogether.
>> - Link to v5: https://lore.kernel.org/r/20250207-pks-reftable-drop-git-compat-util-v5-0-ba2adc79110f@pks.im
>
> Thanks. I think the "unlink" thing on Windows I have was queued
> depended on the previous iteration of this series so let me make
> sure that I'd unentangle it while replacing the topic with this
> round.
>
> Will queue. Thanks.
So, sorry I lost track. I think I saw you ask Dscho about the
Windows specific bits once in a thread on What's cooking report,
but I do not recall the outcome. Is this topic (and the unlink fix
that depends on this series) now OK, or would we see further updates
once 2.49 is tagged?
Thanks.
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v6 00/18] reftable: stop using "git-compat-util.h"
2025-03-11 23:29 ` Junio C Hamano
@ 2025-03-12 6:51 ` Patrick Steinhardt
2025-03-20 15:17 ` Patrick Steinhardt
0 siblings, 1 reply; 146+ messages in thread
From: Patrick Steinhardt @ 2025-03-12 6:51 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Edward Thomson, Justin Tobler, Johannes Sixt,
Johannes Schindelin, Toon Claes
On Tue, Mar 11, 2025 at 04:29:27PM -0700, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
> > Patrick Steinhardt <ps@pks.im> writes:
> >
> >> Changes in v6:
> >> - I have rebased the patch series on top of "master" at 03944513488
> >> (The eleventh batch, 2025-02-14). On the one hand this gets rid of
> >> the conflict with the zlib-ng changes, which have meanwhile been
> >> merged to that branch. And on the other hand it pulls in the new CI
> >> build for MSVC+Meson, which allows me to have better test coverage
> >> on Windows to better detect breakage there.
> >> - Stop moving around Win32 files so that we do the minimum viable
> >> change in this context. Hopefully, this makes it easier for Dscho to
> >> integrate into Git for Windows. If it doesn't I don't really have
> >> any other good ideas for how to do it, so the only alternative would
> >> be to just ignore Windows altogether.
> >> - Link to v5: https://lore.kernel.org/r/20250207-pks-reftable-drop-git-compat-util-v5-0-ba2adc79110f@pks.im
> >
> > Thanks. I think the "unlink" thing on Windows I have was queued
> > depended on the previous iteration of this series so let me make
> > sure that I'd unentangle it while replacing the topic with this
> > round.
> >
> > Will queue. Thanks.
>
> So, sorry I lost track. I think I saw you ask Dscho about the
> Windows specific bits once in a thread on What's cooking report,
> but I do not recall the outcome. Is this topic (and the unlink fix
> that depends on this series) now OK, or would we see further updates
> once 2.49 is tagged?
There was a class of test failures caused by mismatching allocators in
Git for Windows for which I've sent a proposed fix for downstream [1].
I've been talking to Johannes on Monday and he mentioned that he'll
likely end up taking that patch as the pragmatic fix. Which to the best
of my knowledge would mean that this series here is unblocked and can
start to move forward again. Johannes, please correct me in case I'm
misstating anything here.
So based on that I don't plan to reroll and hope that we can move
forward with the series once Git v2.49.0 is out.
Thanks!
Patrick
[1]: <Z8bQsflIqzZd3AMs@pks.im>
^ permalink raw reply [flat|nested] 146+ messages in thread
* Re: [PATCH v6 00/18] reftable: stop using "git-compat-util.h"
2025-03-12 6:51 ` Patrick Steinhardt
@ 2025-03-20 15:17 ` Patrick Steinhardt
0 siblings, 0 replies; 146+ messages in thread
From: Patrick Steinhardt @ 2025-03-20 15:17 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Edward Thomson, Justin Tobler, Johannes Sixt,
Johannes Schindelin, Toon Claes
On Wed, Mar 12, 2025 at 07:51:41AM +0100, Patrick Steinhardt wrote:
> On Tue, Mar 11, 2025 at 04:29:27PM -0700, Junio C Hamano wrote:
> > Junio C Hamano <gitster@pobox.com> writes:
> >
> > > Patrick Steinhardt <ps@pks.im> writes:
> > >
> > >> Changes in v6:
> > >> - I have rebased the patch series on top of "master" at 03944513488
> > >> (The eleventh batch, 2025-02-14). On the one hand this gets rid of
> > >> the conflict with the zlib-ng changes, which have meanwhile been
> > >> merged to that branch. And on the other hand it pulls in the new CI
> > >> build for MSVC+Meson, which allows me to have better test coverage
> > >> on Windows to better detect breakage there.
> > >> - Stop moving around Win32 files so that we do the minimum viable
> > >> change in this context. Hopefully, this makes it easier for Dscho to
> > >> integrate into Git for Windows. If it doesn't I don't really have
> > >> any other good ideas for how to do it, so the only alternative would
> > >> be to just ignore Windows altogether.
> > >> - Link to v5: https://lore.kernel.org/r/20250207-pks-reftable-drop-git-compat-util-v5-0-ba2adc79110f@pks.im
> > >
> > > Thanks. I think the "unlink" thing on Windows I have was queued
> > > depended on the previous iteration of this series so let me make
> > > sure that I'd unentangle it while replacing the topic with this
> > > round.
> > >
> > > Will queue. Thanks.
> >
> > So, sorry I lost track. I think I saw you ask Dscho about the
> > Windows specific bits once in a thread on What's cooking report,
> > but I do not recall the outcome. Is this topic (and the unlink fix
> > that depends on this series) now OK, or would we see further updates
> > once 2.49 is tagged?
>
> There was a class of test failures caused by mismatching allocators in
> Git for Windows for which I've sent a proposed fix for downstream [1].
> I've been talking to Johannes on Monday and he mentioned that he'll
> likely end up taking that patch as the pragmatic fix. Which to the best
> of my knowledge would mean that this series here is unblocked and can
> start to move forward again. Johannes, please correct me in case I'm
> misstating anything here.
>
> So based on that I don't plan to reroll and hope that we can move
> forward with the series once Git v2.49.0 is out.
Quick status update: Johannes mentioned in [1] that he is fine with
moving forward with this topic now. Thanks!
Patrick
[1]: https://github.com/gitgitgadget/git/pull/1874#issuecomment-2740342672
^ permalink raw reply [flat|nested] 146+ messages in thread
end of thread, other threads:[~2025-03-20 15:17 UTC | newest]
Thread overview: 146+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-27 13:04 [PATCH 00/19] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 01/19] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-01-27 16:57 ` Justin Tobler
2025-01-28 8:06 ` Patrick Steinhardt
2025-01-28 17:05 ` Junio C Hamano
2025-01-29 7:29 ` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 02/19] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 03/19] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 04/19] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 05/19] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
2025-01-27 17:36 ` Justin Tobler
2025-01-27 13:04 ` [PATCH 06/19] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
2025-01-27 19:21 ` Justin Tobler
2025-01-27 13:04 ` [PATCH 07/19] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 08/19] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 09/19] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 10/19] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 11/19] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 12/19] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 13/19] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 14/19] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 15/19] compat/mingw: split out POSIX-related bits Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 16/19] compat/msvc: " Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 17/19] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
2025-01-27 19:25 ` Justin Tobler
2025-01-27 13:04 ` [PATCH 18/19] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
2025-01-27 13:04 ` [PATCH 19/19] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-01-27 17:44 ` [PATCH 00/19] reftable: stop using "git-compat-util.h" Junio C Hamano
2025-01-28 8:22 ` Patrick Steinhardt
2025-01-28 17:32 ` Junio C Hamano
2025-01-28 8:28 ` [PATCH v2 00/20] " Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 01/20] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 02/20] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 03/20] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 04/20] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
2025-01-29 15:46 ` Justin Tobler
2025-02-03 8:40 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 05/20] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 06/20] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 07/20] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 08/20] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 09/20] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 10/20] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 11/20] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 12/20] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 13/20] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 14/20] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 15/20] compat: consistently resolve headers via project root Patrick Steinhardt
2025-01-29 7:50 ` Johannes Sixt
2025-01-29 14:23 ` Junio C Hamano
2025-02-03 8:40 ` Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 16/20] compat/mingw: split out POSIX-related bits Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 17/20] compat/msvc: " Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 18/20] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 19/20] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
2025-01-28 8:28 ` [PATCH v2 20/20] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-01-28 22:48 ` [PATCH v2 00/20] reftable: stop using "git-compat-util.h" Junio C Hamano
2025-01-29 7:25 ` Patrick Steinhardt
2025-01-29 13:50 ` Junio C Hamano
2025-02-03 8:03 ` [PATCH v3 00/18] " Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 14/18] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
2025-02-03 8:03 ` [PATCH v3 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-02-06 4:04 ` [PATCH v3 00/18] reftable: stop using "git-compat-util.h" Justin Tobler
2025-02-06 7:52 ` [PATCH v4 " Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 14/18] reftable/basics: stop using `UNUSED` annotation Patrick Steinhardt
2025-02-07 10:03 ` Toon Claes
2025-02-07 11:50 ` Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
2025-02-06 7:52 ` [PATCH v4 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
2025-02-07 11:51 ` [PATCH v5 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 14/18] reftable/basics: introduce `REFTABLE_UNUSED` annotation Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
2025-02-09 13:14 ` Johannes Sixt
2025-02-10 15:50 ` Junio C Hamano
2025-02-13 18:22 ` Johannes Schindelin
2025-02-17 12:47 ` Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
2025-02-07 11:52 ` [PATCH v5 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 01/18] reftable/stack: stop using `read_in_full()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 02/18] reftable/stack: stop using `write_in_full()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 03/18] reftable/blocksource: stop using `xmmap()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 04/18] reftable/record: stop using `COPY_ARRAY()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 05/18] reftable/record: stop using `BUG()` in `reftable_record_init()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 06/18] reftable/record: don't `BUG()` in `reftable_record_cmp()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 07/18] reftable: stop using `BUG()` in trivial cases Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 08/18] reftable/basics: stop using `st_mult()` in array allocators Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 09/18] reftable/basics: provide wrappers for big endian conversion Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 10/18] reftable/reader: stop using `ARRAY_SIZE()` macro Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 11/18] reftable/system: introduce `reftable_rand()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 12/18] reftable/stack: stop using `sleep_millisec()` Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 13/18] reftable/basics: stop using `SWAP()` macro Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 14/18] reftable/basics: introduce `REFTABLE_UNUSED` annotation Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 15/18] compat/mingw: split out POSIX-related bits Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 16/18] git-compat-util.h: split out POSIX-emulating bits Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 17/18] reftable: decouple from Git codebase by pulling in "compat/posix.h" Patrick Steinhardt
2025-02-18 9:20 ` [PATCH v6 18/18] Makefile: skip reftable library for Coccinelle Patrick Steinhardt
2025-02-18 18:55 ` [PATCH v6 00/18] reftable: stop using "git-compat-util.h" Junio C Hamano
2025-03-11 23:29 ` Junio C Hamano
2025-03-12 6:51 ` Patrick Steinhardt
2025-03-20 15:17 ` Patrick Steinhardt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).