[{"id":38001,"web_url":"https://patchwork.libcamera.org/comment/38001/","msgid":"<20260128150407.GB3201622@killaraus>","date":"2026-01-28T15:04:07","subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Wed, Jan 28, 2026 at 03:56:49PM +0100, Barnabás Pőcze wrote:\n> `O_TMPFILE` requires file system support, which may not be available in\n> certain environments, usually containerized ones. So do not use it.\n> \n> In the ipc/unixsocket and log/log_api tests the temporary file is replaced\n> with a memfd using the `libcamera::MemFd` class since these tests are\n> already internal tests.\n> \n> In the unique-fd and shared-fd tests instead of creating a temporary file\n> simply open \"/proc/self/exe\", which should be available and readable in\n> most cases.\n\nThat really feels like a hack (maybe because it's really a hack). Can't\nwe have a TemporaryFile class in libtest instead ? If we centralize the\nimplementation, using memfd without the MemFd class won't be difficult.\n\n> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n> ---\n>  test/ipc/unixsocket.cpp | 34 ++++++++++++++--------------------\n>  test/log/log_api.cpp    | 14 ++++++--------\n>  test/shared-fd.cpp      |  2 +-\n>  test/unique-fd.cpp      |  2 +-\n>  4 files changed, 22 insertions(+), 30 deletions(-)\n> \n> diff --git a/test/ipc/unixsocket.cpp b/test/ipc/unixsocket.cpp\n> index f39bd986b..28864b829 100644\n> --- a/test/ipc/unixsocket.cpp\n> +++ b/test/ipc/unixsocket.cpp\n> @@ -18,6 +18,7 @@\n>  #include <vector>\n>  \n>  #include <libcamera/base/event_dispatcher.h>\n> +#include <libcamera/base/memfd.h>\n>  #include <libcamera/base/thread.h>\n>  #include <libcamera/base/timer.h>\n>  \n> @@ -137,11 +138,11 @@ private:\n>  \t\t}\n>  \n>  \t\tcase CMD_JOIN: {\n> -\t\t\tint outfd = open(\"/tmp\", O_TMPFILE | O_RDWR,\n> -\t\t\t\t\t S_IRUSR | S_IWUSR);\n> -\t\t\tif (outfd < 0) {\n> +\t\t\tauto outfd = MemFd::create(\"test\", 0);\n> +\t\t\tif (!outfd.isValid()) {\n> +\t\t\t\tret = errno;\n>  \t\t\t\tcerr << \"Create out file failed\" << endl;\n> -\t\t\t\tstop(outfd);\n> +\t\t\t\tstop(ret);\n>  \t\t\t\treturn;\n>  \t\t\t}\n>  \n> @@ -152,15 +153,13 @@ private:\n>  \n>  \t\t\t\t\tif (num < 0) {\n>  \t\t\t\t\t\tcerr << \"Read failed\" << endl;\n> -\t\t\t\t\t\tclose(outfd);\n>  \t\t\t\t\t\tstop(-EIO);\n>  \t\t\t\t\t\treturn;\n>  \t\t\t\t\t} else if (!num)\n>  \t\t\t\t\t\tbreak;\n>  \n> -\t\t\t\t\tif (write(outfd, buf, num) < 0) {\n> +\t\t\t\t\tif (write(outfd.get(), buf, num) < 0) {\n>  \t\t\t\t\t\tcerr << \"Write failed\" << endl;\n> -\t\t\t\t\t\tclose(outfd);\n>  \t\t\t\t\t\tstop(-EIO);\n>  \t\t\t\t\t\treturn;\n>  \t\t\t\t\t}\n> @@ -169,9 +168,9 @@ private:\n>  \t\t\t\tclose(fd);\n>  \t\t\t}\n>  \n> -\t\t\tlseek(outfd, 0, 0);\n> +\t\t\tlseek(outfd.get(), 0, SEEK_SET);\n>  \t\t\tresponse.data.push_back(CMD_JOIN);\n> -\t\t\tresponse.fds.push_back(outfd);\n> +\t\t\tresponse.fds.push_back(outfd.get());\n>  \n>  \t\t\tret = ipc_.send(response);\n>  \t\t\tif (ret < 0) {\n> @@ -179,8 +178,6 @@ private:\n>  \t\t\t\tstop(ret);\n>  \t\t\t}\n>  \n> -\t\t\tclose(outfd);\n> -\n>  \t\t\tbreak;\n>  \t\t}\n>  \n> @@ -315,22 +312,21 @@ protected:\n>  \t\t\t\"Foo\",\n>  \t\t\t\"Bar\",\n>  \t\t};\n> -\t\tint fds[2];\n> +\t\tstd::array<UniqueFD, 2> fds;\n>  \n>  \t\tfor (unsigned int i = 0; i < std::size(strings); i++) {\n>  \t\t\tunsigned int len = strlen(strings[i]);\n>  \n> -\t\t\tfds[i] = open(\"/tmp\", O_TMPFILE | O_RDWR,\n> -\t\t\t\t      S_IRUSR | S_IWUSR);\n> -\t\t\tif (fds[i] < 0)\n> +\t\t\tfds[i] = MemFd::create(\"test\", 0);\n> +\t\t\tif (!fds[i].isValid())\n>  \t\t\t\treturn TestFail;\n>  \n> -\t\t\tret = write(fds[i], strings[i], len);\n> +\t\t\tret = write(fds[i].get(), strings[i], len);\n>  \t\t\tif (ret < 0)\n>  \t\t\t\treturn TestFail;\n>  \n> -\t\t\tlseek(fds[i], 0, 0);\n> -\t\t\tmessage.fds.push_back(fds[i]);\n> +\t\t\tlseek(fds[i].get(), 0, SEEK_SET);\n> +\t\t\tmessage.fds.push_back(fds[i].get());\n>  \t\t}\n>  \n>  \t\tmessage.data.push_back(CMD_JOIN);\n> @@ -343,8 +339,6 @@ protected:\n>  \t\t\tunsigned int len = strlen(strings[i]);\n>  \t\t\tstd::vector<char> buf(len);\n>  \n> -\t\t\tclose(fds[i]);\n> -\n>  \t\t\tif (read(response.fds[0], buf.data(), len) <= 0)\n>  \t\t\t\treturn TestFail;\n>  \n> diff --git a/test/log/log_api.cpp b/test/log/log_api.cpp\n> index 8d19cf0ce..0eaf67a71 100644\n> --- a/test/log/log_api.cpp\n> +++ b/test/log/log_api.cpp\n> @@ -17,6 +17,7 @@\n>  #include <unistd.h>\n>  \n>  #include <libcamera/base/log.h>\n> +#include <libcamera/base/memfd.h>\n>  \n>  #include <libcamera/logging.h>\n>  \n> @@ -109,18 +110,17 @@ protected:\n>  \n>  \tint testFile()\n>  \t{\n> -\t\tint fd = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> -\t\tif (fd < 0) {\n> +\t\tauto fd = MemFd::create(\"test\", 0);\n> +\t\tif (!fd.isValid()) {\n>  \t\t\tcerr << \"Failed to open tmp log file\" << endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n>  \t\tchar path[32];\n> -\t\tsnprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd);\n> +\t\tsnprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd.get());\n>  \n>  \t\tif (logSetFile(path) < 0) {\n>  \t\t\tcerr << \"Failed to set log file\" << endl;\n> -\t\t\tclose(fd);\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> @@ -128,13 +128,11 @@ protected:\n>  \n>  \t\tchar buf[1000];\n>  \t\tmemset(buf, 0, sizeof(buf));\n> -\t\tlseek(fd, 0, SEEK_SET);\n> -\t\tif (read(fd, buf, sizeof(buf)) < 0) {\n> +\t\tlseek(fd.get(), 0, SEEK_SET);\n> +\t\tif (read(fd.get(), buf, sizeof(buf)) < 0) {\n>  \t\t\tcerr << \"Failed to read tmp log file\" << endl;\n> -\t\t\tclose(fd);\n>  \t\t\treturn TestFail;\n>  \t\t}\n> -\t\tclose(fd);\n>  \n>  \t\tistringstream iss(buf);\n>  \t\treturn verifyOutput(iss);\n> diff --git a/test/shared-fd.cpp b/test/shared-fd.cpp\n> index 57199dfe7..09634f2c2 100644\n> --- a/test/shared-fd.cpp\n> +++ b/test/shared-fd.cpp\n> @@ -27,7 +27,7 @@ protected:\n>  \t\tdesc1_ = nullptr;\n>  \t\tdesc2_ = nullptr;\n>  \n> -\t\tfd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> +\t\tfd_ = open(\"/proc/self/exe\", O_RDONLY);\n>  \t\tif (fd_ < 0)\n>  \t\t\treturn TestFail;\n>  \n> diff --git a/test/unique-fd.cpp b/test/unique-fd.cpp\n> index e556439ea..7d7ba1447 100644\n> --- a/test/unique-fd.cpp\n> +++ b/test/unique-fd.cpp\n> @@ -189,7 +189,7 @@ protected:\n>  private:\n>  \tint createFd()\n>  \t{\n> -\t\tfd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> +\t\tfd_ = open(\"/proc/self/exe\", O_RDONLY);\n>  \t\tif (fd_ < 0)\n>  \t\t\treturn TestFail;\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CBAA1C3200\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 28 Jan 2026 15:04:11 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id CFA0E61FC9;\n\tWed, 28 Jan 2026 16:04:10 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3D18161FC4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 28 Jan 2026 16:04:09 +0100 (CET)","from killaraus.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 1F00822F;\n\tWed, 28 Jan 2026 16:03:32 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"vscWhRIH\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769612612;\n\tbh=ZRv0EMtGTplpmP2OZHgjOGkYgqPfmPJkNx06lHaFhAQ=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=vscWhRIHCUwTXmmfJtkRD868Ai9JMDKSUHFOqCw/FKbVLz9sD3ED8SxD5fSSVFDsU\n\tTH1eaA9/Ao+oarSq1BQkhBK7ZTublQoDOZMpkMvD+R5JpCQBS4cQdVGvSeNsU3JYMm\n\t/cpyZ2069+m4sqRVel8yFk1/7xAcbA478mQclEKk=","Date":"Wed, 28 Jan 2026 17:04:07 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","Message-ID":"<20260128150407.GB3201622@killaraus>","References":"<20260128145649.890107-1-barnabas.pocze@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20260128145649.890107-1-barnabas.pocze@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38002,"web_url":"https://patchwork.libcamera.org/comment/38002/","msgid":"<2ee709c7-93ae-4740-a394-90238b373611@ideasonboard.com>","date":"2026-01-28T15:13:34","subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 01. 28. 16:04 keltezéssel, Laurent Pinchart írta:\n> On Wed, Jan 28, 2026 at 03:56:49PM +0100, Barnabás Pőcze wrote:\n>> `O_TMPFILE` requires file system support, which may not be available in\n>> certain environments, usually containerized ones. So do not use it.\n>>\n>> In the ipc/unixsocket and log/log_api tests the temporary file is replaced\n>> with a memfd using the `libcamera::MemFd` class since these tests are\n>> already internal tests.\n>>\n>> In the unique-fd and shared-fd tests instead of creating a temporary file\n>> simply open \"/proc/self/exe\", which should be available and readable in\n>> most cases.\n> \n> That really feels like a hack (maybe because it's really a hack). Can't\n> we have a TemporaryFile class in libtest instead ? If we centralize the\n> implementation, using memfd without the MemFd class won't be difficult.\n\nI was also considering using one end of a pipe, one of the standard streams,\nor simply opening \"/tmp\" / \".\" / etc with O_DIRECTORY.\n\nA `TemporaryFile` class is certainly an option, but:\n   * arguably none of the tests here need \"real temporary files\"\n     * in the ipc/unixsocket and log/log_api tests\n       simple pipes could work as far as I can tell\n     * in the unique-fd and shared-fd tests no file is actually needed,\n       only a file descriptor that can be `stat()`-ed\n   * it seems suboptimal to reimplement what's already in the MemFd class\n\nThat's why I did not want to do that as a first attempt.\n\n\n> \n>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n>> ---\n>>   test/ipc/unixsocket.cpp | 34 ++++++++++++++--------------------\n>>   test/log/log_api.cpp    | 14 ++++++--------\n>>   test/shared-fd.cpp      |  2 +-\n>>   test/unique-fd.cpp      |  2 +-\n>>   4 files changed, 22 insertions(+), 30 deletions(-)\n>>\n>> diff --git a/test/ipc/unixsocket.cpp b/test/ipc/unixsocket.cpp\n>> index f39bd986b..28864b829 100644\n>> --- a/test/ipc/unixsocket.cpp\n>> +++ b/test/ipc/unixsocket.cpp\n>> @@ -18,6 +18,7 @@\n>>   #include <vector>\n>>   \n>>   #include <libcamera/base/event_dispatcher.h>\n>> +#include <libcamera/base/memfd.h>\n>>   #include <libcamera/base/thread.h>\n>>   #include <libcamera/base/timer.h>\n>>   \n>> @@ -137,11 +138,11 @@ private:\n>>   \t\t}\n>>   \n>>   \t\tcase CMD_JOIN: {\n>> -\t\t\tint outfd = open(\"/tmp\", O_TMPFILE | O_RDWR,\n>> -\t\t\t\t\t S_IRUSR | S_IWUSR);\n>> -\t\t\tif (outfd < 0) {\n>> +\t\t\tauto outfd = MemFd::create(\"test\", 0);\n>> +\t\t\tif (!outfd.isValid()) {\n>> +\t\t\t\tret = errno;\n>>   \t\t\t\tcerr << \"Create out file failed\" << endl;\n>> -\t\t\t\tstop(outfd);\n>> +\t\t\t\tstop(ret);\n>>   \t\t\t\treturn;\n>>   \t\t\t}\n>>   \n>> @@ -152,15 +153,13 @@ private:\n>>   \n>>   \t\t\t\t\tif (num < 0) {\n>>   \t\t\t\t\t\tcerr << \"Read failed\" << endl;\n>> -\t\t\t\t\t\tclose(outfd);\n>>   \t\t\t\t\t\tstop(-EIO);\n>>   \t\t\t\t\t\treturn;\n>>   \t\t\t\t\t} else if (!num)\n>>   \t\t\t\t\t\tbreak;\n>>   \n>> -\t\t\t\t\tif (write(outfd, buf, num) < 0) {\n>> +\t\t\t\t\tif (write(outfd.get(), buf, num) < 0) {\n>>   \t\t\t\t\t\tcerr << \"Write failed\" << endl;\n>> -\t\t\t\t\t\tclose(outfd);\n>>   \t\t\t\t\t\tstop(-EIO);\n>>   \t\t\t\t\t\treturn;\n>>   \t\t\t\t\t}\n>> @@ -169,9 +168,9 @@ private:\n>>   \t\t\t\tclose(fd);\n>>   \t\t\t}\n>>   \n>> -\t\t\tlseek(outfd, 0, 0);\n>> +\t\t\tlseek(outfd.get(), 0, SEEK_SET);\n>>   \t\t\tresponse.data.push_back(CMD_JOIN);\n>> -\t\t\tresponse.fds.push_back(outfd);\n>> +\t\t\tresponse.fds.push_back(outfd.get());\n>>   \n>>   \t\t\tret = ipc_.send(response);\n>>   \t\t\tif (ret < 0) {\n>> @@ -179,8 +178,6 @@ private:\n>>   \t\t\t\tstop(ret);\n>>   \t\t\t}\n>>   \n>> -\t\t\tclose(outfd);\n>> -\n>>   \t\t\tbreak;\n>>   \t\t}\n>>   \n>> @@ -315,22 +312,21 @@ protected:\n>>   \t\t\t\"Foo\",\n>>   \t\t\t\"Bar\",\n>>   \t\t};\n>> -\t\tint fds[2];\n>> +\t\tstd::array<UniqueFD, 2> fds;\n>>   \n>>   \t\tfor (unsigned int i = 0; i < std::size(strings); i++) {\n>>   \t\t\tunsigned int len = strlen(strings[i]);\n>>   \n>> -\t\t\tfds[i] = open(\"/tmp\", O_TMPFILE | O_RDWR,\n>> -\t\t\t\t      S_IRUSR | S_IWUSR);\n>> -\t\t\tif (fds[i] < 0)\n>> +\t\t\tfds[i] = MemFd::create(\"test\", 0);\n>> +\t\t\tif (!fds[i].isValid())\n>>   \t\t\t\treturn TestFail;\n>>   \n>> -\t\t\tret = write(fds[i], strings[i], len);\n>> +\t\t\tret = write(fds[i].get(), strings[i], len);\n>>   \t\t\tif (ret < 0)\n>>   \t\t\t\treturn TestFail;\n>>   \n>> -\t\t\tlseek(fds[i], 0, 0);\n>> -\t\t\tmessage.fds.push_back(fds[i]);\n>> +\t\t\tlseek(fds[i].get(), 0, SEEK_SET);\n>> +\t\t\tmessage.fds.push_back(fds[i].get());\n>>   \t\t}\n>>   \n>>   \t\tmessage.data.push_back(CMD_JOIN);\n>> @@ -343,8 +339,6 @@ protected:\n>>   \t\t\tunsigned int len = strlen(strings[i]);\n>>   \t\t\tstd::vector<char> buf(len);\n>>   \n>> -\t\t\tclose(fds[i]);\n>> -\n>>   \t\t\tif (read(response.fds[0], buf.data(), len) <= 0)\n>>   \t\t\t\treturn TestFail;\n>>   \n>> diff --git a/test/log/log_api.cpp b/test/log/log_api.cpp\n>> index 8d19cf0ce..0eaf67a71 100644\n>> --- a/test/log/log_api.cpp\n>> +++ b/test/log/log_api.cpp\n>> @@ -17,6 +17,7 @@\n>>   #include <unistd.h>\n>>   \n>>   #include <libcamera/base/log.h>\n>> +#include <libcamera/base/memfd.h>\n>>   \n>>   #include <libcamera/logging.h>\n>>   \n>> @@ -109,18 +110,17 @@ protected:\n>>   \n>>   \tint testFile()\n>>   \t{\n>> -\t\tint fd = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n>> -\t\tif (fd < 0) {\n>> +\t\tauto fd = MemFd::create(\"test\", 0);\n>> +\t\tif (!fd.isValid()) {\n>>   \t\t\tcerr << \"Failed to open tmp log file\" << endl;\n>>   \t\t\treturn TestFail;\n>>   \t\t}\n>>   \n>>   \t\tchar path[32];\n>> -\t\tsnprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd);\n>> +\t\tsnprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd.get());\n>>   \n>>   \t\tif (logSetFile(path) < 0) {\n>>   \t\t\tcerr << \"Failed to set log file\" << endl;\n>> -\t\t\tclose(fd);\n>>   \t\t\treturn TestFail;\n>>   \t\t}\n>>   \n>> @@ -128,13 +128,11 @@ protected:\n>>   \n>>   \t\tchar buf[1000];\n>>   \t\tmemset(buf, 0, sizeof(buf));\n>> -\t\tlseek(fd, 0, SEEK_SET);\n>> -\t\tif (read(fd, buf, sizeof(buf)) < 0) {\n>> +\t\tlseek(fd.get(), 0, SEEK_SET);\n>> +\t\tif (read(fd.get(), buf, sizeof(buf)) < 0) {\n>>   \t\t\tcerr << \"Failed to read tmp log file\" << endl;\n>> -\t\t\tclose(fd);\n>>   \t\t\treturn TestFail;\n>>   \t\t}\n>> -\t\tclose(fd);\n>>   \n>>   \t\tistringstream iss(buf);\n>>   \t\treturn verifyOutput(iss);\n>> diff --git a/test/shared-fd.cpp b/test/shared-fd.cpp\n>> index 57199dfe7..09634f2c2 100644\n>> --- a/test/shared-fd.cpp\n>> +++ b/test/shared-fd.cpp\n>> @@ -27,7 +27,7 @@ protected:\n>>   \t\tdesc1_ = nullptr;\n>>   \t\tdesc2_ = nullptr;\n>>   \n>> -\t\tfd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n>> +\t\tfd_ = open(\"/proc/self/exe\", O_RDONLY);\n>>   \t\tif (fd_ < 0)\n>>   \t\t\treturn TestFail;\n>>   \n>> diff --git a/test/unique-fd.cpp b/test/unique-fd.cpp\n>> index e556439ea..7d7ba1447 100644\n>> --- a/test/unique-fd.cpp\n>> +++ b/test/unique-fd.cpp\n>> @@ -189,7 +189,7 @@ protected:\n>>   private:\n>>   \tint createFd()\n>>   \t{\n>> -\t\tfd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n>> +\t\tfd_ = open(\"/proc/self/exe\", O_RDONLY);\n>>   \t\tif (fd_ < 0)\n>>   \t\t\treturn TestFail;\n>>   \n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 251B0C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 28 Jan 2026 15:13:41 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7892661FD1;\n\tWed, 28 Jan 2026 16:13:40 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6854E61FC4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 28 Jan 2026 16:13:38 +0100 (CET)","from [192.168.33.40] (185.221.142.123.nat.pool.zt.hu\n\t[185.221.142.123])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 2DB9EC6F;\n\tWed, 28 Jan 2026 16:13:01 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"rrIUHfAb\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769613181;\n\tbh=cZCRMHwCVtXBeXiipY+5yZUjyexTeEQcxl8+JzJkLcI=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=rrIUHfAb5fUPOwPNgAPJP6wG05Dl54RWeLMEfMTRyZnRcvOOnwlJQnuCxzHygeZ22\n\t5ci9EDSxkGxajn6ZinaZ6LlRUHlYF95U9t/2J41PLlrgYvQAZ7NZwkLyZwV5Uo2mCq\n\tO3be9bAMy4Dd7Cqpv7V9ZooUq8ve+63nP9wkmkM4=","Message-ID":"<2ee709c7-93ae-4740-a394-90238b373611@ideasonboard.com>","Date":"Wed, 28 Jan 2026 16:13:34 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","References":"<20260128145649.890107-1-barnabas.pocze@ideasonboard.com>\n\t<20260128150407.GB3201622@killaraus>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260128150407.GB3201622@killaraus>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38008,"web_url":"https://patchwork.libcamera.org/comment/38008/","msgid":"<9cd98694-a3e9-4611-9e77-80f04eea6347@ideasonboard.com>","date":"2026-01-28T16:35:01","subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 01. 28. 16:13 keltezéssel, Barnabás Pőcze írta:\n> 2026. 01. 28. 16:04 keltezéssel, Laurent Pinchart írta:\n>> On Wed, Jan 28, 2026 at 03:56:49PM +0100, Barnabás Pőcze wrote:\n>>> `O_TMPFILE` requires file system support, which may not be available in\n>>> certain environments, usually containerized ones. So do not use it.\n>>>\n>>> In the ipc/unixsocket and log/log_api tests the temporary file is replaced\n>>> with a memfd using the `libcamera::MemFd` class since these tests are\n>>> already internal tests.\n>>>\n>>> In the unique-fd and shared-fd tests instead of creating a temporary file\n>>> simply open \"/proc/self/exe\", which should be available and readable in\n>>> most cases.\n>>\n>> That really feels like a hack (maybe because it's really a hack). Can't\n>> we have a TemporaryFile class in libtest instead ? If we centralize the\n>> implementation, using memfd without the MemFd class won't be difficult.\n> \n> I was also considering using one end of a pipe, one of the standard streams,\n> or simply opening \"/tmp\" / \".\" / etc with O_DIRECTORY.\n> \n> A `TemporaryFile` class is certainly an option, but:\n>    * arguably none of the tests here need \"real temporary files\"\n>      * in the ipc/unixsocket and log/log_api tests\n>        simple pipes could work as far as I can tell\n>      * in the unique-fd and shared-fd tests no file is actually needed,\n>        only a file descriptor that can be `stat()`-ed\n>    * it seems suboptimal to reimplement what's already in the MemFd class\n> \n> That's why I did not want to do that as a first attempt.\n> \n\nI see that \"libtest\" can use the internal parts. So I suppose I can add\na `createTemporaryFile()` function that just returns `MemFd::create(\"libcamera-test-temp-file\", 0)`\nif opening \"/proc/self/exe\" and similar are considered too problematic workarounds.\n(It's not clear to me what interface a `TemporaryFile` class would have\n  (unless it's just a single static function to create one).)\n\n\n> \n>>\n>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n>>> ---\n>>>   test/ipc/unixsocket.cpp | 34 ++++++++++++++--------------------\n>>>   test/log/log_api.cpp    | 14 ++++++--------\n>>>   test/shared-fd.cpp      |  2 +-\n>>>   test/unique-fd.cpp      |  2 +-\n>>>   4 files changed, 22 insertions(+), 30 deletions(-)\n>>>\n>>> diff --git a/test/ipc/unixsocket.cpp b/test/ipc/unixsocket.cpp\n>>> index f39bd986b..28864b829 100644\n>>> --- a/test/ipc/unixsocket.cpp\n>>> +++ b/test/ipc/unixsocket.cpp\n>>> @@ -18,6 +18,7 @@\n>>>   #include <vector>\n>>>   #include <libcamera/base/event_dispatcher.h>\n>>> +#include <libcamera/base/memfd.h>\n>>>   #include <libcamera/base/thread.h>\n>>>   #include <libcamera/base/timer.h>\n>>> @@ -137,11 +138,11 @@ private:\n>>>           }\n>>>           case CMD_JOIN: {\n>>> -            int outfd = open(\"/tmp\", O_TMPFILE | O_RDWR,\n>>> -                     S_IRUSR | S_IWUSR);\n>>> -            if (outfd < 0) {\n>>> +            auto outfd = MemFd::create(\"test\", 0);\n>>> +            if (!outfd.isValid()) {\n>>> +                ret = errno;\n>>>                   cerr << \"Create out file failed\" << endl;\n>>> -                stop(outfd);\n>>> +                stop(ret);\n>>>                   return;\n>>>               }\n>>> @@ -152,15 +153,13 @@ private:\n>>>                       if (num < 0) {\n>>>                           cerr << \"Read failed\" << endl;\n>>> -                        close(outfd);\n>>>                           stop(-EIO);\n>>>                           return;\n>>>                       } else if (!num)\n>>>                           break;\n>>> -                    if (write(outfd, buf, num) < 0) {\n>>> +                    if (write(outfd.get(), buf, num) < 0) {\n>>>                           cerr << \"Write failed\" << endl;\n>>> -                        close(outfd);\n>>>                           stop(-EIO);\n>>>                           return;\n>>>                       }\n>>> @@ -169,9 +168,9 @@ private:\n>>>                   close(fd);\n>>>               }\n>>> -            lseek(outfd, 0, 0);\n>>> +            lseek(outfd.get(), 0, SEEK_SET);\n>>>               response.data.push_back(CMD_JOIN);\n>>> -            response.fds.push_back(outfd);\n>>> +            response.fds.push_back(outfd.get());\n>>>               ret = ipc_.send(response);\n>>>               if (ret < 0) {\n>>> @@ -179,8 +178,6 @@ private:\n>>>                   stop(ret);\n>>>               }\n>>> -            close(outfd);\n>>> -\n>>>               break;\n>>>           }\n>>> @@ -315,22 +312,21 @@ protected:\n>>>               \"Foo\",\n>>>               \"Bar\",\n>>>           };\n>>> -        int fds[2];\n>>> +        std::array<UniqueFD, 2> fds;\n>>>           for (unsigned int i = 0; i < std::size(strings); i++) {\n>>>               unsigned int len = strlen(strings[i]);\n>>> -            fds[i] = open(\"/tmp\", O_TMPFILE | O_RDWR,\n>>> -                      S_IRUSR | S_IWUSR);\n>>> -            if (fds[i] < 0)\n>>> +            fds[i] = MemFd::create(\"test\", 0);\n>>> +            if (!fds[i].isValid())\n>>>                   return TestFail;\n>>> -            ret = write(fds[i], strings[i], len);\n>>> +            ret = write(fds[i].get(), strings[i], len);\n>>>               if (ret < 0)\n>>>                   return TestFail;\n>>> -            lseek(fds[i], 0, 0);\n>>> -            message.fds.push_back(fds[i]);\n>>> +            lseek(fds[i].get(), 0, SEEK_SET);\n>>> +            message.fds.push_back(fds[i].get());\n>>>           }\n>>>           message.data.push_back(CMD_JOIN);\n>>> @@ -343,8 +339,6 @@ protected:\n>>>               unsigned int len = strlen(strings[i]);\n>>>               std::vector<char> buf(len);\n>>> -            close(fds[i]);\n>>> -\n>>>               if (read(response.fds[0], buf.data(), len) <= 0)\n>>>                   return TestFail;\n>>> diff --git a/test/log/log_api.cpp b/test/log/log_api.cpp\n>>> index 8d19cf0ce..0eaf67a71 100644\n>>> --- a/test/log/log_api.cpp\n>>> +++ b/test/log/log_api.cpp\n>>> @@ -17,6 +17,7 @@\n>>>   #include <unistd.h>\n>>>   #include <libcamera/base/log.h>\n>>> +#include <libcamera/base/memfd.h>\n>>>   #include <libcamera/logging.h>\n>>> @@ -109,18 +110,17 @@ protected:\n>>>       int testFile()\n>>>       {\n>>> -        int fd = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n>>> -        if (fd < 0) {\n>>> +        auto fd = MemFd::create(\"test\", 0);\n>>> +        if (!fd.isValid()) {\n>>>               cerr << \"Failed to open tmp log file\" << endl;\n>>>               return TestFail;\n>>>           }\n>>>           char path[32];\n>>> -        snprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd);\n>>> +        snprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd.get());\n>>>           if (logSetFile(path) < 0) {\n>>>               cerr << \"Failed to set log file\" << endl;\n>>> -            close(fd);\n>>>               return TestFail;\n>>>           }\n>>> @@ -128,13 +128,11 @@ protected:\n>>>           char buf[1000];\n>>>           memset(buf, 0, sizeof(buf));\n>>> -        lseek(fd, 0, SEEK_SET);\n>>> -        if (read(fd, buf, sizeof(buf)) < 0) {\n>>> +        lseek(fd.get(), 0, SEEK_SET);\n>>> +        if (read(fd.get(), buf, sizeof(buf)) < 0) {\n>>>               cerr << \"Failed to read tmp log file\" << endl;\n>>> -            close(fd);\n>>>               return TestFail;\n>>>           }\n>>> -        close(fd);\n>>>           istringstream iss(buf);\n>>>           return verifyOutput(iss);\n>>> diff --git a/test/shared-fd.cpp b/test/shared-fd.cpp\n>>> index 57199dfe7..09634f2c2 100644\n>>> --- a/test/shared-fd.cpp\n>>> +++ b/test/shared-fd.cpp\n>>> @@ -27,7 +27,7 @@ protected:\n>>>           desc1_ = nullptr;\n>>>           desc2_ = nullptr;\n>>> -        fd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n>>> +        fd_ = open(\"/proc/self/exe\", O_RDONLY);\n>>>           if (fd_ < 0)\n>>>               return TestFail;\n>>> diff --git a/test/unique-fd.cpp b/test/unique-fd.cpp\n>>> index e556439ea..7d7ba1447 100644\n>>> --- a/test/unique-fd.cpp\n>>> +++ b/test/unique-fd.cpp\n>>> @@ -189,7 +189,7 @@ protected:\n>>>   private:\n>>>       int createFd()\n>>>       {\n>>> -        fd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n>>> +        fd_ = open(\"/proc/self/exe\", O_RDONLY);\n>>>           if (fd_ < 0)\n>>>               return TestFail;\n>>\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 7C7A3C3200\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 28 Jan 2026 16:35:07 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 16C0F61FD5;\n\tWed, 28 Jan 2026 17:35:07 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1144D61FC5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 28 Jan 2026 17:35:05 +0100 (CET)","from [192.168.33.40] (185.221.142.123.nat.pool.zt.hu\n\t[185.221.142.123])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 70BBEE70;\n\tWed, 28 Jan 2026 17:34:27 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"dcBsDiIT\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769618068;\n\tbh=H8rTHrRcC1wolJcIvaiHFuooN8YpR2+bTziayBy+kyM=;\n\th=Date:Subject:From:To:Cc:References:In-Reply-To:From;\n\tb=dcBsDiITXvqYxEfReejt6TdOjBCIA+ehtWeWOehFjJB7hYEo6ZWjVzchQQWHBIuni\n\tloh0okk7A6rP04idHijFuC4MzlZ24c7Mh+aBF87/1Wzzo15FFPAHgRxOQxkpZz1jKq\n\t387S+Fd9N/TAYLy/rc/YC6+Y6/tWRHx833oPspIA=","Message-ID":"<9cd98694-a3e9-4611-9e77-80f04eea6347@ideasonboard.com>","Date":"Wed, 28 Jan 2026 17:35:01 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","References":"<20260128145649.890107-1-barnabas.pocze@ideasonboard.com>\n\t<20260128150407.GB3201622@killaraus>\n\t<2ee709c7-93ae-4740-a394-90238b373611@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<2ee709c7-93ae-4740-a394-90238b373611@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38010,"web_url":"https://patchwork.libcamera.org/comment/38010/","msgid":"<20260128163752.GB3225981@killaraus>","date":"2026-01-28T16:37:52","subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Wed, Jan 28, 2026 at 04:13:34PM +0100, Barnabás Pőcze wrote:\n> 2026. 01. 28. 16:04 keltezéssel, Laurent Pinchart írta:\n> > On Wed, Jan 28, 2026 at 03:56:49PM +0100, Barnabás Pőcze wrote:\n> >> `O_TMPFILE` requires file system support, which may not be available in\n> >> certain environments, usually containerized ones. So do not use it.\n> >>\n> >> In the ipc/unixsocket and log/log_api tests the temporary file is replaced\n> >> with a memfd using the `libcamera::MemFd` class since these tests are\n> >> already internal tests.\n> >>\n> >> In the unique-fd and shared-fd tests instead of creating a temporary file\n> >> simply open \"/proc/self/exe\", which should be available and readable in\n> >> most cases.\n> > \n> > That really feels like a hack (maybe because it's really a hack). Can't\n> > we have a TemporaryFile class in libtest instead ? If we centralize the\n> > implementation, using memfd without the MemFd class won't be difficult.\n> \n> I was also considering using one end of a pipe, one of the standard streams,\n> or simply opening \"/tmp\" / \".\" / etc with O_DIRECTORY.\n> \n> A `TemporaryFile` class is certainly an option, but:\n>    * arguably none of the tests here need \"real temporary files\"\n>      * in the ipc/unixsocket and log/log_api tests\n>        simple pipes could work as far as I can tell\n>      * in the unique-fd and shared-fd tests no file is actually needed,\n>        only a file descriptor that can be `stat()`-ed\n>    * it seems suboptimal to reimplement what's already in the MemFd class\n> \n> That's why I did not want to do that as a first attempt.\n\nWhat I like about a TemporaryFile class in libtest is that it would\ncentralize the implementation and abstract the underlying API. I think\nit would make the tests simpler, there would be less to think about in\nthe unit tests code.\n\n> >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n> >> ---\n> >>   test/ipc/unixsocket.cpp | 34 ++++++++++++++--------------------\n> >>   test/log/log_api.cpp    | 14 ++++++--------\n> >>   test/shared-fd.cpp      |  2 +-\n> >>   test/unique-fd.cpp      |  2 +-\n> >>   4 files changed, 22 insertions(+), 30 deletions(-)\n> >>\n> >> diff --git a/test/ipc/unixsocket.cpp b/test/ipc/unixsocket.cpp\n> >> index f39bd986b..28864b829 100644\n> >> --- a/test/ipc/unixsocket.cpp\n> >> +++ b/test/ipc/unixsocket.cpp\n> >> @@ -18,6 +18,7 @@\n> >>   #include <vector>\n> >>   \n> >>   #include <libcamera/base/event_dispatcher.h>\n> >> +#include <libcamera/base/memfd.h>\n> >>   #include <libcamera/base/thread.h>\n> >>   #include <libcamera/base/timer.h>\n> >>   \n> >> @@ -137,11 +138,11 @@ private:\n> >>   \t\t}\n> >>   \n> >>   \t\tcase CMD_JOIN: {\n> >> -\t\t\tint outfd = open(\"/tmp\", O_TMPFILE | O_RDWR,\n> >> -\t\t\t\t\t S_IRUSR | S_IWUSR);\n> >> -\t\t\tif (outfd < 0) {\n> >> +\t\t\tauto outfd = MemFd::create(\"test\", 0);\n> >> +\t\t\tif (!outfd.isValid()) {\n> >> +\t\t\t\tret = errno;\n> >>   \t\t\t\tcerr << \"Create out file failed\" << endl;\n> >> -\t\t\t\tstop(outfd);\n> >> +\t\t\t\tstop(ret);\n> >>   \t\t\t\treturn;\n> >>   \t\t\t}\n> >>   \n> >> @@ -152,15 +153,13 @@ private:\n> >>   \n> >>   \t\t\t\t\tif (num < 0) {\n> >>   \t\t\t\t\t\tcerr << \"Read failed\" << endl;\n> >> -\t\t\t\t\t\tclose(outfd);\n> >>   \t\t\t\t\t\tstop(-EIO);\n> >>   \t\t\t\t\t\treturn;\n> >>   \t\t\t\t\t} else if (!num)\n> >>   \t\t\t\t\t\tbreak;\n> >>   \n> >> -\t\t\t\t\tif (write(outfd, buf, num) < 0) {\n> >> +\t\t\t\t\tif (write(outfd.get(), buf, num) < 0) {\n> >>   \t\t\t\t\t\tcerr << \"Write failed\" << endl;\n> >> -\t\t\t\t\t\tclose(outfd);\n> >>   \t\t\t\t\t\tstop(-EIO);\n> >>   \t\t\t\t\t\treturn;\n> >>   \t\t\t\t\t}\n> >> @@ -169,9 +168,9 @@ private:\n> >>   \t\t\t\tclose(fd);\n> >>   \t\t\t}\n> >>   \n> >> -\t\t\tlseek(outfd, 0, 0);\n> >> +\t\t\tlseek(outfd.get(), 0, SEEK_SET);\n> >>   \t\t\tresponse.data.push_back(CMD_JOIN);\n> >> -\t\t\tresponse.fds.push_back(outfd);\n> >> +\t\t\tresponse.fds.push_back(outfd.get());\n> >>   \n> >>   \t\t\tret = ipc_.send(response);\n> >>   \t\t\tif (ret < 0) {\n> >> @@ -179,8 +178,6 @@ private:\n> >>   \t\t\t\tstop(ret);\n> >>   \t\t\t}\n> >>   \n> >> -\t\t\tclose(outfd);\n> >> -\n> >>   \t\t\tbreak;\n> >>   \t\t}\n> >>   \n> >> @@ -315,22 +312,21 @@ protected:\n> >>   \t\t\t\"Foo\",\n> >>   \t\t\t\"Bar\",\n> >>   \t\t};\n> >> -\t\tint fds[2];\n> >> +\t\tstd::array<UniqueFD, 2> fds;\n> >>   \n> >>   \t\tfor (unsigned int i = 0; i < std::size(strings); i++) {\n> >>   \t\t\tunsigned int len = strlen(strings[i]);\n> >>   \n> >> -\t\t\tfds[i] = open(\"/tmp\", O_TMPFILE | O_RDWR,\n> >> -\t\t\t\t      S_IRUSR | S_IWUSR);\n> >> -\t\t\tif (fds[i] < 0)\n> >> +\t\t\tfds[i] = MemFd::create(\"test\", 0);\n> >> +\t\t\tif (!fds[i].isValid())\n> >>   \t\t\t\treturn TestFail;\n> >>   \n> >> -\t\t\tret = write(fds[i], strings[i], len);\n> >> +\t\t\tret = write(fds[i].get(), strings[i], len);\n> >>   \t\t\tif (ret < 0)\n> >>   \t\t\t\treturn TestFail;\n> >>   \n> >> -\t\t\tlseek(fds[i], 0, 0);\n> >> -\t\t\tmessage.fds.push_back(fds[i]);\n> >> +\t\t\tlseek(fds[i].get(), 0, SEEK_SET);\n> >> +\t\t\tmessage.fds.push_back(fds[i].get());\n> >>   \t\t}\n> >>   \n> >>   \t\tmessage.data.push_back(CMD_JOIN);\n> >> @@ -343,8 +339,6 @@ protected:\n> >>   \t\t\tunsigned int len = strlen(strings[i]);\n> >>   \t\t\tstd::vector<char> buf(len);\n> >>   \n> >> -\t\t\tclose(fds[i]);\n> >> -\n> >>   \t\t\tif (read(response.fds[0], buf.data(), len) <= 0)\n> >>   \t\t\t\treturn TestFail;\n> >>   \n> >> diff --git a/test/log/log_api.cpp b/test/log/log_api.cpp\n> >> index 8d19cf0ce..0eaf67a71 100644\n> >> --- a/test/log/log_api.cpp\n> >> +++ b/test/log/log_api.cpp\n> >> @@ -17,6 +17,7 @@\n> >>   #include <unistd.h>\n> >>   \n> >>   #include <libcamera/base/log.h>\n> >> +#include <libcamera/base/memfd.h>\n> >>   \n> >>   #include <libcamera/logging.h>\n> >>   \n> >> @@ -109,18 +110,17 @@ protected:\n> >>   \n> >>   \tint testFile()\n> >>   \t{\n> >> -\t\tint fd = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> >> -\t\tif (fd < 0) {\n> >> +\t\tauto fd = MemFd::create(\"test\", 0);\n> >> +\t\tif (!fd.isValid()) {\n> >>   \t\t\tcerr << \"Failed to open tmp log file\" << endl;\n> >>   \t\t\treturn TestFail;\n> >>   \t\t}\n> >>   \n> >>   \t\tchar path[32];\n> >> -\t\tsnprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd);\n> >> +\t\tsnprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd.get());\n> >>   \n> >>   \t\tif (logSetFile(path) < 0) {\n> >>   \t\t\tcerr << \"Failed to set log file\" << endl;\n> >> -\t\t\tclose(fd);\n> >>   \t\t\treturn TestFail;\n> >>   \t\t}\n> >>   \n> >> @@ -128,13 +128,11 @@ protected:\n> >>   \n> >>   \t\tchar buf[1000];\n> >>   \t\tmemset(buf, 0, sizeof(buf));\n> >> -\t\tlseek(fd, 0, SEEK_SET);\n> >> -\t\tif (read(fd, buf, sizeof(buf)) < 0) {\n> >> +\t\tlseek(fd.get(), 0, SEEK_SET);\n> >> +\t\tif (read(fd.get(), buf, sizeof(buf)) < 0) {\n> >>   \t\t\tcerr << \"Failed to read tmp log file\" << endl;\n> >> -\t\t\tclose(fd);\n> >>   \t\t\treturn TestFail;\n> >>   \t\t}\n> >> -\t\tclose(fd);\n> >>   \n> >>   \t\tistringstream iss(buf);\n> >>   \t\treturn verifyOutput(iss);\n> >> diff --git a/test/shared-fd.cpp b/test/shared-fd.cpp\n> >> index 57199dfe7..09634f2c2 100644\n> >> --- a/test/shared-fd.cpp\n> >> +++ b/test/shared-fd.cpp\n> >> @@ -27,7 +27,7 @@ protected:\n> >>   \t\tdesc1_ = nullptr;\n> >>   \t\tdesc2_ = nullptr;\n> >>   \n> >> -\t\tfd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> >> +\t\tfd_ = open(\"/proc/self/exe\", O_RDONLY);\n> >>   \t\tif (fd_ < 0)\n> >>   \t\t\treturn TestFail;\n> >>   \n> >> diff --git a/test/unique-fd.cpp b/test/unique-fd.cpp\n> >> index e556439ea..7d7ba1447 100644\n> >> --- a/test/unique-fd.cpp\n> >> +++ b/test/unique-fd.cpp\n> >> @@ -189,7 +189,7 @@ protected:\n> >>   private:\n> >>   \tint createFd()\n> >>   \t{\n> >> -\t\tfd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> >> +\t\tfd_ = open(\"/proc/self/exe\", O_RDONLY);\n> >>   \t\tif (fd_ < 0)\n> >>   \t\t\treturn TestFail;\n> >>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 79174C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 28 Jan 2026 16:37:56 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4382861FD1;\n\tWed, 28 Jan 2026 17:37:56 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 57BB161FC4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 28 Jan 2026 17:37:54 +0100 (CET)","from killaraus.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 2008DE70;\n\tWed, 28 Jan 2026 17:37:17 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"QW15tJoH\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769618237;\n\tbh=yf4fVDAYt39/V/k7vJryWuoLoAXHEEN8lekzNtPtnFs=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=QW15tJoHFRr882mV9Qs4B5bLCxIRrfTCY5cd/ymz6KJAdYrZhev6S2h5/ZOEf1CoL\n\tZNyIZUCBQ+BbxCR7Pqr3lF7Xaii61bof8gCC7xrNtKiF60yU7+J31p2SVJdE2OUh1y\n\tBOnQ3LOnBjqW1ZvnJ2EBTRygA4P9rTP2Rt+MSU+8=","Date":"Wed, 28 Jan 2026 18:37:52 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","Message-ID":"<20260128163752.GB3225981@killaraus>","References":"<20260128145649.890107-1-barnabas.pocze@ideasonboard.com>\n\t<20260128150407.GB3201622@killaraus>\n\t<2ee709c7-93ae-4740-a394-90238b373611@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<2ee709c7-93ae-4740-a394-90238b373611@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38011,"web_url":"https://patchwork.libcamera.org/comment/38011/","msgid":"<20260128164535.GC3225981@killaraus>","date":"2026-01-28T16:45:35","subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Wed, Jan 28, 2026 at 05:35:01PM +0100, Barnabás Pőcze wrote:\n> 2026. 01. 28. 16:13 keltezéssel, Barnabás Pőcze írta:\n> > 2026. 01. 28. 16:04 keltezéssel, Laurent Pinchart írta:\n> >> On Wed, Jan 28, 2026 at 03:56:49PM +0100, Barnabás Pőcze wrote:\n> >>> `O_TMPFILE` requires file system support, which may not be available in\n> >>> certain environments, usually containerized ones. So do not use it.\n> >>>\n> >>> In the ipc/unixsocket and log/log_api tests the temporary file is replaced\n> >>> with a memfd using the `libcamera::MemFd` class since these tests are\n> >>> already internal tests.\n> >>>\n> >>> In the unique-fd and shared-fd tests instead of creating a temporary file\n> >>> simply open \"/proc/self/exe\", which should be available and readable in\n> >>> most cases.\n> >>\n> >> That really feels like a hack (maybe because it's really a hack). Can't\n> >> we have a TemporaryFile class in libtest instead ? If we centralize the\n> >> implementation, using memfd without the MemFd class won't be difficult.\n> > \n> > I was also considering using one end of a pipe, one of the standard streams,\n> > or simply opening \"/tmp\" / \".\" / etc with O_DIRECTORY.\n> > \n> > A `TemporaryFile` class is certainly an option, but:\n> >    * arguably none of the tests here need \"real temporary files\"\n> >      * in the ipc/unixsocket and log/log_api tests\n> >        simple pipes could work as far as I can tell\n> >      * in the unique-fd and shared-fd tests no file is actually needed,\n> >        only a file descriptor that can be `stat()`-ed\n> >    * it seems suboptimal to reimplement what's already in the MemFd class\n> > \n> > That's why I did not want to do that as a first attempt.\n> > \n> \n> I see that \"libtest\" can use the internal parts. So I suppose I can add\n> a `createTemporaryFile()` function that just returns `MemFd::create(\"libcamera-test-temp-file\", 0)`\n> if opening \"/proc/self/exe\" and similar are considered too problematic workarounds.\n> (It's not clear to me what interface a `TemporaryFile` class would have\n>   (unless it's just a single static function to create one).)\n\nYes, a single function sounds good. I'm fine using MemFd there as it\nwill be easy to change that if needed.\n\n> >>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n> >>> ---\n> >>>   test/ipc/unixsocket.cpp | 34 ++++++++++++++--------------------\n> >>>   test/log/log_api.cpp    | 14 ++++++--------\n> >>>   test/shared-fd.cpp      |  2 +-\n> >>>   test/unique-fd.cpp      |  2 +-\n> >>>   4 files changed, 22 insertions(+), 30 deletions(-)\n> >>>\n> >>> diff --git a/test/ipc/unixsocket.cpp b/test/ipc/unixsocket.cpp\n> >>> index f39bd986b..28864b829 100644\n> >>> --- a/test/ipc/unixsocket.cpp\n> >>> +++ b/test/ipc/unixsocket.cpp\n> >>> @@ -18,6 +18,7 @@\n> >>>   #include <vector>\n> >>>   #include <libcamera/base/event_dispatcher.h>\n> >>> +#include <libcamera/base/memfd.h>\n> >>>   #include <libcamera/base/thread.h>\n> >>>   #include <libcamera/base/timer.h>\n> >>> @@ -137,11 +138,11 @@ private:\n> >>>           }\n> >>>           case CMD_JOIN: {\n> >>> -            int outfd = open(\"/tmp\", O_TMPFILE | O_RDWR,\n> >>> -                     S_IRUSR | S_IWUSR);\n> >>> -            if (outfd < 0) {\n> >>> +            auto outfd = MemFd::create(\"test\", 0);\n> >>> +            if (!outfd.isValid()) {\n> >>> +                ret = errno;\n> >>>                   cerr << \"Create out file failed\" << endl;\n> >>> -                stop(outfd);\n> >>> +                stop(ret);\n> >>>                   return;\n> >>>               }\n> >>> @@ -152,15 +153,13 @@ private:\n> >>>                       if (num < 0) {\n> >>>                           cerr << \"Read failed\" << endl;\n> >>> -                        close(outfd);\n> >>>                           stop(-EIO);\n> >>>                           return;\n> >>>                       } else if (!num)\n> >>>                           break;\n> >>> -                    if (write(outfd, buf, num) < 0) {\n> >>> +                    if (write(outfd.get(), buf, num) < 0) {\n> >>>                           cerr << \"Write failed\" << endl;\n> >>> -                        close(outfd);\n> >>>                           stop(-EIO);\n> >>>                           return;\n> >>>                       }\n> >>> @@ -169,9 +168,9 @@ private:\n> >>>                   close(fd);\n> >>>               }\n> >>> -            lseek(outfd, 0, 0);\n> >>> +            lseek(outfd.get(), 0, SEEK_SET);\n> >>>               response.data.push_back(CMD_JOIN);\n> >>> -            response.fds.push_back(outfd);\n> >>> +            response.fds.push_back(outfd.get());\n> >>>               ret = ipc_.send(response);\n> >>>               if (ret < 0) {\n> >>> @@ -179,8 +178,6 @@ private:\n> >>>                   stop(ret);\n> >>>               }\n> >>> -            close(outfd);\n> >>> -\n> >>>               break;\n> >>>           }\n> >>> @@ -315,22 +312,21 @@ protected:\n> >>>               \"Foo\",\n> >>>               \"Bar\",\n> >>>           };\n> >>> -        int fds[2];\n> >>> +        std::array<UniqueFD, 2> fds;\n> >>>           for (unsigned int i = 0; i < std::size(strings); i++) {\n> >>>               unsigned int len = strlen(strings[i]);\n> >>> -            fds[i] = open(\"/tmp\", O_TMPFILE | O_RDWR,\n> >>> -                      S_IRUSR | S_IWUSR);\n> >>> -            if (fds[i] < 0)\n> >>> +            fds[i] = MemFd::create(\"test\", 0);\n> >>> +            if (!fds[i].isValid())\n> >>>                   return TestFail;\n> >>> -            ret = write(fds[i], strings[i], len);\n> >>> +            ret = write(fds[i].get(), strings[i], len);\n> >>>               if (ret < 0)\n> >>>                   return TestFail;\n> >>> -            lseek(fds[i], 0, 0);\n> >>> -            message.fds.push_back(fds[i]);\n> >>> +            lseek(fds[i].get(), 0, SEEK_SET);\n> >>> +            message.fds.push_back(fds[i].get());\n> >>>           }\n> >>>           message.data.push_back(CMD_JOIN);\n> >>> @@ -343,8 +339,6 @@ protected:\n> >>>               unsigned int len = strlen(strings[i]);\n> >>>               std::vector<char> buf(len);\n> >>> -            close(fds[i]);\n> >>> -\n> >>>               if (read(response.fds[0], buf.data(), len) <= 0)\n> >>>                   return TestFail;\n> >>> diff --git a/test/log/log_api.cpp b/test/log/log_api.cpp\n> >>> index 8d19cf0ce..0eaf67a71 100644\n> >>> --- a/test/log/log_api.cpp\n> >>> +++ b/test/log/log_api.cpp\n> >>> @@ -17,6 +17,7 @@\n> >>>   #include <unistd.h>\n> >>>   #include <libcamera/base/log.h>\n> >>> +#include <libcamera/base/memfd.h>\n> >>>   #include <libcamera/logging.h>\n> >>> @@ -109,18 +110,17 @@ protected:\n> >>>       int testFile()\n> >>>       {\n> >>> -        int fd = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> >>> -        if (fd < 0) {\n> >>> +        auto fd = MemFd::create(\"test\", 0);\n> >>> +        if (!fd.isValid()) {\n> >>>               cerr << \"Failed to open tmp log file\" << endl;\n> >>>               return TestFail;\n> >>>           }\n> >>>           char path[32];\n> >>> -        snprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd);\n> >>> +        snprintf(path, sizeof(path), \"/proc/self/fd/%u\", fd.get());\n> >>>           if (logSetFile(path) < 0) {\n> >>>               cerr << \"Failed to set log file\" << endl;\n> >>> -            close(fd);\n> >>>               return TestFail;\n> >>>           }\n> >>> @@ -128,13 +128,11 @@ protected:\n> >>>           char buf[1000];\n> >>>           memset(buf, 0, sizeof(buf));\n> >>> -        lseek(fd, 0, SEEK_SET);\n> >>> -        if (read(fd, buf, sizeof(buf)) < 0) {\n> >>> +        lseek(fd.get(), 0, SEEK_SET);\n> >>> +        if (read(fd.get(), buf, sizeof(buf)) < 0) {\n> >>>               cerr << \"Failed to read tmp log file\" << endl;\n> >>> -            close(fd);\n> >>>               return TestFail;\n> >>>           }\n> >>> -        close(fd);\n> >>>           istringstream iss(buf);\n> >>>           return verifyOutput(iss);\n> >>> diff --git a/test/shared-fd.cpp b/test/shared-fd.cpp\n> >>> index 57199dfe7..09634f2c2 100644\n> >>> --- a/test/shared-fd.cpp\n> >>> +++ b/test/shared-fd.cpp\n> >>> @@ -27,7 +27,7 @@ protected:\n> >>>           desc1_ = nullptr;\n> >>>           desc2_ = nullptr;\n> >>> -        fd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> >>> +        fd_ = open(\"/proc/self/exe\", O_RDONLY);\n> >>>           if (fd_ < 0)\n> >>>               return TestFail;\n> >>> diff --git a/test/unique-fd.cpp b/test/unique-fd.cpp\n> >>> index e556439ea..7d7ba1447 100644\n> >>> --- a/test/unique-fd.cpp\n> >>> +++ b/test/unique-fd.cpp\n> >>> @@ -189,7 +189,7 @@ protected:\n> >>>   private:\n> >>>       int createFd()\n> >>>       {\n> >>> -        fd_ = open(\"/tmp\", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);\n> >>> +        fd_ = open(\"/proc/self/exe\", O_RDONLY);\n> >>>           if (fd_ < 0)\n> >>>               return TestFail;","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 5C857C3200\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 28 Jan 2026 16:45:39 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9C08B61FC9;\n\tWed, 28 Jan 2026 17:45:38 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9FB9261FC4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 28 Jan 2026 17:45:36 +0100 (CET)","from killaraus.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 5B74BE70;\n\tWed, 28 Jan 2026 17:44:59 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"shZDJplI\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769618699;\n\tbh=OCse2pxHnRWnYGtEjHgfJKFdm2eNl/42w4yvs40F2Q4=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=shZDJplIikNnJzv8MRgX7wO666iuyOyzKrFJAh9lxtusw/kDC65Rxnlt2oBUQ0a4y\n\tjFBIdVPCDyLXrn1aJ/ZdY1AhaV2/aj7Jv8epbC2LIvCYpGZ9m99VcFGsTlMFVRj1WG\n\tr3ofZbsJz8HvXjFPV/6jOw/qrxn+2g8xny4xM5pE=","Date":"Wed, 28 Jan 2026 18:45:35 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v1] test: Remove uses of `O_TMPFILE`","Message-ID":"<20260128164535.GC3225981@killaraus>","References":"<20260128145649.890107-1-barnabas.pocze@ideasonboard.com>\n\t<20260128150407.GB3201622@killaraus>\n\t<2ee709c7-93ae-4740-a394-90238b373611@ideasonboard.com>\n\t<9cd98694-a3e9-4611-9e77-80f04eea6347@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<9cd98694-a3e9-4611-9e77-80f04eea6347@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]