This is an automated email from the ASF dual-hosted git repository.

xyji pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 64b61c7c6 Add opendal_metadata_last_modified and 
opendal_operator_create_dir (#3515)
64b61c7c6 is described below

commit 64b61c7c657932596e9e23dc0a31d699e37faba5
Author: Enwei Jiao <[email protected]>
AuthorDate: Wed Nov 8 06:07:43 2023 +0800

    Add opendal_metadata_last_modified and opendal_operator_create_dir (#3515)
    
    * Add opendal_metadata_last_modified and opendal_operator_create_dir for C 
binding
    
    * Fix comments
    
    * Make clippy happy
---
 bindings/c/include/opendal.h | 53 ++++++++++++++++++++++++++++++++++++++++++++
 bindings/c/src/metadata.rs   | 20 +++++++++++++++++
 bindings/c/src/operator.rs   | 50 +++++++++++++++++++++++++++++++++++++++++
 bindings/c/tests/bdd.cpp     | 15 +++++++++++++
 4 files changed, 138 insertions(+)

diff --git a/bindings/c/include/opendal.h b/bindings/c/include/opendal.h
index 55586cd83..5d9962518 100644
--- a/bindings/c/include/opendal.h
+++ b/bindings/c/include/opendal.h
@@ -772,6 +772,21 @@ bool opendal_metadata_is_file(const struct 
opendal_metadata *self);
  */
 bool opendal_metadata_is_dir(const struct opendal_metadata *self);
 
+/**
+ * \brief Return the last_modified of the metadata, in milliseconds
+ *
+ * # Example
+ * ```C
+ * // ... previously you wrote "Hello, World!" to path "/testpath"
+ * opendal_result_stat s = opendal_operator_stat(ptr, "/testpath");
+ * assert(s.error == NULL);
+ *
+ * opendal_metadata *meta = s.meta;
+ * assert(opendal_metadata_last_modified_ms(meta) != -1);
+ * ```
+ */
+int64_t opendal_metadata_last_modified_ms(const struct opendal_metadata *self);
+
 /**
  * \brief Free the heap-allocated operator pointed by opendal_operator.
  *
@@ -1149,6 +1164,44 @@ struct opendal_result_stat opendal_operator_stat(const 
struct opendal_operator *
 struct opendal_result_list opendal_operator_list(const struct opendal_operator 
*op,
                                                  const char *path);
 
+/**
+ * \brief Blockingly create the directory in `path`.
+ *
+ * Create the directory in `path` blockingly by `op_ptr`.
+ * Error is NULL if successful, otherwise it contains the error code and error 
message.
+ *
+ * @param ptr The opendal_operator created previously
+ * @param path The designated directory you want to create
+ * @see opendal_operator
+ * @see opendal_error
+ * @return NULL if succeeds, otherwise it contains the error code and error 
message.
+ *
+ * # Example
+ *
+ * Following is an example
+ * ```C
+ * //...prepare your opendal_operator, named ptr for example
+ *
+ * // create your directory
+ * opendal_error *error = opendal_operator_create_dir(ptr, "/testdir/");
+ *
+ * // Assert that this succeeds
+ * assert(error == NULL);
+ * ```
+ *
+ * # Safety
+ *
+ * It is **safe** under the cases below
+ * * The memory pointed to by `path` must contain a valid nul terminator at 
the end of
+ *   the string.
+ *
+ * # Panic
+ *
+ * * If the `path` points to NULL, this function panics, i.e. exits with 
information
+ */
+struct opendal_error *opendal_operator_create_dir(const struct 
opendal_operator *op,
+                                                  const char *path);
+
 /**
  * \brief Get information of underlying accessor.
  *
diff --git a/bindings/c/src/metadata.rs b/bindings/c/src/metadata.rs
index a28d72d7b..1e532e3de 100644
--- a/bindings/c/src/metadata.rs
+++ b/bindings/c/src/metadata.rs
@@ -111,4 +111,24 @@ impl opendal_metadata {
         // The use-after-free is undefined behavior
         unsafe { (*self.inner).is_dir() }
     }
+
+    /// \brief Return the last_modified of the metadata, in milliseconds
+    ///
+    /// # Example
+    /// ```C
+    /// // ... previously you wrote "Hello, World!" to path "/testpath"
+    /// opendal_result_stat s = opendal_operator_stat(ptr, "/testpath");
+    /// assert(s.error == NULL);
+    ///
+    /// opendal_metadata *meta = s.meta;
+    /// assert(opendal_metadata_last_modified_ms(meta) != -1);
+    /// ```
+    #[no_mangle]
+    pub extern "C" fn opendal_metadata_last_modified_ms(&self) -> i64 {
+        let mtime = unsafe { (*self.inner).last_modified() };
+        match mtime {
+            None => -1,
+            Some(time) => time.timestamp_millis(),
+        }
+    }
 }
diff --git a/bindings/c/src/operator.rs b/bindings/c/src/operator.rs
index 4f6406236..2fc102229 100644
--- a/bindings/c/src/operator.rs
+++ b/bindings/c/src/operator.rs
@@ -628,3 +628,53 @@ pub unsafe extern "C" fn opendal_operator_list(
         },
     }
 }
+
+/// \brief Blockingly create the directory in `path`.
+///
+/// Create the directory in `path` blockingly by `op_ptr`.
+/// Error is NULL if successful, otherwise it contains the error code and 
error message.
+///
+/// @param ptr The opendal_operator created previously
+/// @param path The designated directory you want to create
+/// @see opendal_operator
+/// @see opendal_error
+/// @return NULL if succeeds, otherwise it contains the error code and error 
message.
+///
+/// # Example
+///
+/// Following is an example
+/// ```C
+/// //...prepare your opendal_operator, named ptr for example
+///
+/// // create your directory
+/// opendal_error *error = opendal_operator_create_dir(ptr, "/testdir/");
+///
+/// // Assert that this succeeds
+/// assert(error == NULL);
+/// ```
+///
+/// # Safety
+///
+/// It is **safe** under the cases below
+/// * The memory pointed to by `path` must contain a valid nul terminator at 
the end of
+///   the string.
+///
+/// # Panic
+///
+/// * If the `path` points to NULL, this function panics, i.e. exits with 
information
+#[no_mangle]
+pub unsafe extern "C" fn opendal_operator_create_dir(
+    op: *const opendal_operator,
+    path: *const c_char,
+) -> *mut opendal_error {
+    if path.is_null() {
+        panic!("The path given is pointing at NULL");
+    }
+
+    let op = (*op).as_ref();
+    let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
+    match op.create_dir(path) {
+        Ok(_) => std::ptr::null_mut(),
+        Err(e) => opendal_error::new(e),
+    }
+}
diff --git a/bindings/c/tests/bdd.cpp b/bindings/c/tests/bdd.cpp
index fd33a0125..ee307cc19 100644
--- a/bindings/c/tests/bdd.cpp
+++ b/bindings/c/tests/bdd.cpp
@@ -77,8 +77,12 @@ TEST_F(OpendalBddTest, FeatureTest)
 
     // The blocking file "test" content length must be 13
     EXPECT_EQ(opendal_metadata_content_length(meta), 13);
+
+    // the blocking file "test" last modified time must not be -1
+    EXPECT_FALSE(opendal_metadata_last_modified_ms(meta) != -1);
     opendal_metadata_free(meta);
 
+
     // The blocking file "test" must have content "Hello, World!"
     struct opendal_result_read r = opendal_operator_read(this->p, 
this->path.c_str());
     EXPECT_EQ(r.error, nullptr);
@@ -111,6 +115,17 @@ TEST_F(OpendalBddTest, FeatureTest)
     EXPECT_EQ(error, nullptr);
 
     opendal_bytes_free(r.data);
+
+    // The directory "tmpdir/" should exist and should be a directory
+    error = opendal_operator_create_dir(this->p, "tmpdir/");
+    EXPECT_EQ(error, nullptr);
+    auto stat = opendal_operator_stat(this->p, "tmpdir/");
+    EXPECT_EQ(stat.error, nullptr);
+    EXPECT_TRUE(opendal_metadata_is_dir(stat.meta));
+    EXPECT_FALSE(opendal_metadata_is_file(stat.meta));
+    opendal_metadata_free(stat.meta);
+    error = opendal_operator_delete(this->p, "tmpdir/");
+    EXPECT_EQ(error, nullptr);
 }
 
 int main(int argc, char** argv)

Reply via email to