[libc-commits] [libc] 827575a - [libc] Add implementation of POSIX lseek function.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Tue Mar 15 09:25:07 PDT 2022


Author: Siva Chandra Reddy
Date: 2022-03-15T16:24:48Z
New Revision: 827575a7f8539a3a779059e0bd672e915dec3fa0

URL: https://github.com/llvm/llvm-project/commit/827575a7f8539a3a779059e0bd672e915dec3fa0
DIFF: https://github.com/llvm/llvm-project/commit/827575a7f8539a3a779059e0bd672e915dec3fa0.diff

LOG: [libc] Add implementation of POSIX lseek function.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D121676

Added: 
    libc/include/llvm-libc-macros/file-seek-macros.h
    libc/src/unistd/linux/lseek.cpp
    libc/src/unistd/lseek.h
    libc/test/src/unistd/lseek_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/api.td
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/CMakeLists.txt
    libc/include/llvm-libc-macros/CMakeLists.txt
    libc/include/stdio.h.def
    libc/include/unistd.h.def
    libc/spec/posix.td
    libc/src/unistd/CMakeLists.txt
    libc/src/unistd/linux/CMakeLists.txt
    libc/test/src/unistd/CMakeLists.txt
    libc/test/src/unistd/testdata/CMakeLists.txt

Removed: 
    libc/include/llvm-libc-macros/stdio-macros.h


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 5bdbced557224..cd2b52f18a906 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -95,6 +95,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     # unistd.h entrypoints
     libc.src.unistd.close
     libc.src.unistd.fsync
+    libc.src.unistd.lseek
     libc.src.unistd.read
     libc.src.unistd.rmdir
     libc.src.unistd.unlink

diff  --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index fc208978b14a4..b351ea6d5e291 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -238,7 +238,7 @@ def ThreadsAPI : PublicAPI<"threads.h"> {
 }
 
 def UniStdAPI : PublicAPI<"unistd.h"> {
-  let Types = ["size_t", "ssize_t"];
+  let Types = ["off_t", "size_t", "ssize_t"];
 }
 
 def SysStatAPI : PublicAPI<"sys/stat.h"> {

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index e08c8fd42c21a..fc64dbf68b452 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -99,6 +99,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     # unistd.h entrypoints
     libc.src.unistd.close
     libc.src.unistd.fsync
+    libc.src.unistd.lseek
     libc.src.unistd.read
     libc.src.unistd.rmdir
     libc.src.unistd.unlink

diff  --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 9370b5a37705e..30e188878eacc 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -124,7 +124,7 @@ add_gen_header(
   GEN_HDR stdio.h
   DEPENDS
     .llvm_libc_common_h
-    .llvm-libc-macros.stdio_macros
+    .llvm-libc-macros.file_seek_macros
     .llvm-libc-types.FILE
     .llvm-libc-types.size_t
 )
@@ -150,6 +150,7 @@ add_gen_header(
   GEN_HDR unistd.h
   DEPENDS
     .llvm_libc_common_h
+    .llvm-libc-macros.file_seek_macros
     .llvm-libc-types.size_t
     .llvm-libc-types.ssize_t
 )

diff  --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 9ef039e499bfe..f583a915e6995 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -9,7 +9,7 @@ add_header(
 )
 
 add_header(
-  stdio_macros
+  file_seek_macros
   HDR
-    stdio-macros.h
+    file-seek-macros.h
 )

diff  --git a/libc/include/llvm-libc-macros/stdio-macros.h b/libc/include/llvm-libc-macros/file-seek-macros.h
similarity index 61%
rename from libc/include/llvm-libc-macros/stdio-macros.h
rename to libc/include/llvm-libc-macros/file-seek-macros.h
index af75193c1ecfb..04f397982f460 100644
--- a/libc/include/llvm-libc-macros/stdio-macros.h
+++ b/libc/include/llvm-libc-macros/file-seek-macros.h
@@ -1,4 +1,4 @@
-//===-- Definition of macros from stdio.h ---------------------------------===//
+//===-- Definition of macros to be used with file seek functions ----------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,11 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef __LLVM_LIBC_MACROS_STDIO_MACROS_H
-#define __LLVM_LIBC_MACROS_STDIO_MACROS_H
+#ifndef __LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H
+#define __LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H
 
 #define SEEK_SET 0
 #define SEEK_CUR 1
 #define SEEK_END 2
 
-#endif // __LLVM_LIBC_MACROS_STDIO_MACROS_H
+#endif // __LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H

diff  --git a/libc/include/stdio.h.def b/libc/include/stdio.h.def
index d3b4cfaed7a95..a643e22664913 100644
--- a/libc/include/stdio.h.def
+++ b/libc/include/stdio.h.def
@@ -10,7 +10,7 @@
 #define LLVM_LIBC_STDIO_H
 
 #include <__llvm-libc-common.h>
-#include <llvm-libc-macros/stdio-macros.h>
+#include <llvm-libc-macros/file-seek-macros.h>
 
 %%public_api()
 

diff  --git a/libc/include/unistd.h.def b/libc/include/unistd.h.def
index 42bab396b2d67..d7a2de93a03d0 100644
--- a/libc/include/unistd.h.def
+++ b/libc/include/unistd.h.def
@@ -10,6 +10,7 @@
 #define LLVM_LIBC_UNISTD_H
 
 #include <__llvm-libc-common.h>
+#include <llvm-libc-macros/file-seek-macros.h>
 
 %%public_api()
 

diff  --git a/libc/spec/posix.td b/libc/spec/posix.td
index d6e3d8564f79e..b9641d8c362da 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -222,6 +222,7 @@ def POSIX : StandardSpec<"POSIX"> {
     "unistd.h",
     [], // Macros
     [
+      OffTType,
       SSizeTType,
       SizeTType,
     ],
@@ -237,6 +238,11 @@ def POSIX : StandardSpec<"POSIX"> {
           RetValSpec<IntType>,
           [ArgSpec<IntType>]
         >,
+        FunctionSpec<
+          "lseek",
+          RetValSpec<OffTType>,
+          [ArgSpec<IntType>, ArgSpec<OffTType>, ArgSpec<IntType>]
+        >,
         FunctionSpec<
           "read",
           RetValSpec<SSizeTType>,

diff  --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index 70210ebd5b790..d67b0b33d179a 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -16,6 +16,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.fsync
 )
 
+add_entrypoint_object(
+  lseek
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.lseek
+)
+
 add_entrypoint_object(
   read
   ALIAS

diff  --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index f990a820b8b98..29a2cd629a4bd 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -24,6 +24,19 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  lseek
+  SRCS
+    lseek.cpp
+  HDRS
+    ../lseek.h
+  DEPENDS
+    libc.include.unistd
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   read
   SRCS

diff  --git a/libc/src/unistd/linux/lseek.cpp b/libc/src/unistd/linux/lseek.cpp
new file mode 100644
index 0000000000000..559673f3f4370
--- /dev/null
+++ b/libc/src/unistd/linux/lseek.cpp
@@ -0,0 +1,39 @@
+//===-- Linux implementation of lseek -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/lseek.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/syscall.h> // For syscall numbers.
+#include <unistd.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(off_t, lseek, (int fd, off_t offset, int whence)) {
+  off_t result;
+#ifdef SYS_lseek
+  long ret = __llvm_libc::syscall(SYS_lseek, fd, offset, whence);
+  result = ret;
+#elif defined(SYS__llseek)
+  long ret = __llvm_libc::syscall(SYS__lseek, fd, offset >> 32, offset, &result,
+                                  whence);
+#else
+#error "lseek and _llseek syscalls not available."
+#endif
+
+  if (ret < 0) {
+    errno = -ret;
+    return -1;
+  }
+  return result;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/unistd/lseek.h b/libc/src/unistd/lseek.h
new file mode 100644
index 0000000000000..28252e4d49171
--- /dev/null
+++ b/libc/src/unistd/lseek.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for lseek -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_LSEEK_H
+#define LLVM_LIBC_SRC_UNISTD_LSEEK_H
+
+#include <unistd.h>
+
+namespace __llvm_libc {
+
+off_t lseek(int fd, off_t offset, int whence);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_UNISTD_LSEEK_H

diff  --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index abaec098af346..a60318a98fc9b 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -19,6 +19,22 @@ add_libc_unittest(
     libc.test.errno_setter_matcher
 )
 
+add_libc_unittest(
+  lseek_test
+  SUITE
+    libc_unistd_unittests
+  SRCS
+    lseek_test.cpp
+  DEPENDS
+    libc.include.errno
+    libc.include.unistd
+    libc.src.fcntl.open
+    libc.src.unistd.close
+    libc.src.unistd.lseek
+    libc.src.unistd.read
+    libc.test.errno_setter_matcher
+)
+
 add_libc_unittest(
   rmdir_test
   SUITE

diff  --git a/libc/test/src/unistd/lseek_test.cpp b/libc/test/src/unistd/lseek_test.cpp
new file mode 100644
index 0000000000000..1285c2d065375
--- /dev/null
+++ b/libc/test/src/unistd/lseek_test.cpp
@@ -0,0 +1,61 @@
+//===-- Unittests for lseek -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/fcntl/open.h"
+#include "src/unistd/close.h"
+#include "src/unistd/lseek.h"
+#include "src/unistd/read.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include "utils/testutils/FDReader.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+TEST(LlvmLibcUniStd, LseekTest) {
+  using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+  constexpr const char *TEST_FILE = "testdata/lseek.test";
+  int fd = __llvm_libc::open(TEST_FILE, O_RDONLY);
+  ASSERT_EQ(errno, 0);
+  ASSERT_GT(fd, 0);
+  constexpr const char LSEEK_TEST[] = "lseek test";
+  constexpr int LSEEK_TEST_SIZE = sizeof(LSEEK_TEST) - 1;
+
+  char read_buf[20];
+  ASSERT_THAT(__llvm_libc::read(fd, read_buf, LSEEK_TEST_SIZE),
+              Succeeds(LSEEK_TEST_SIZE));
+  read_buf[LSEEK_TEST_SIZE] = '\0';
+  EXPECT_STREQ(read_buf, LSEEK_TEST);
+
+  // Seek to the beginning of the file and re-read.
+  ASSERT_THAT(__llvm_libc::lseek(fd, 0, SEEK_SET), Succeeds(0));
+  ASSERT_THAT(__llvm_libc::read(fd, read_buf, LSEEK_TEST_SIZE),
+              Succeeds(LSEEK_TEST_SIZE));
+  read_buf[LSEEK_TEST_SIZE] = '\0';
+  EXPECT_STREQ(read_buf, LSEEK_TEST);
+
+  // Seek to the beginning of the file from the end and re-read.
+  ASSERT_THAT(__llvm_libc::lseek(fd, -LSEEK_TEST_SIZE, SEEK_END), Succeeds(0));
+  ASSERT_THAT(__llvm_libc::read(fd, read_buf, LSEEK_TEST_SIZE),
+              Succeeds(LSEEK_TEST_SIZE));
+  read_buf[LSEEK_TEST_SIZE] = '\0';
+  EXPECT_STREQ(read_buf, LSEEK_TEST);
+
+  ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0));
+}
+
+TEST(LlvmLibcUniStd, LseekFailsTest) {
+  using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+  using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+  constexpr const char *TEST_FILE = "testdata/lseek.test";
+  int fd = __llvm_libc::open(TEST_FILE, O_RDONLY);
+  ASSERT_EQ(errno, 0);
+  ASSERT_GT(fd, 0);
+  EXPECT_THAT(__llvm_libc::lseek(fd, -1, SEEK_CUR), Fails(EINVAL));
+  ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0));
+}

diff  --git a/libc/test/src/unistd/testdata/CMakeLists.txt b/libc/test/src/unistd/testdata/CMakeLists.txt
index 25d6247c1d975..f302be251143c 100644
--- a/libc/test/src/unistd/testdata/CMakeLists.txt
+++ b/libc/test/src/unistd/testdata/CMakeLists.txt
@@ -1,2 +1,4 @@
 # This directory will be used to create test files and delete them
 # from tests.
+
+file(GENERATE OUTPUT lseek.test CONTENT "lseek test")


        


More information about the libc-commits mailing list