浏览代码

refactor: Compile user programs uniformly (#1239)

* refactor: Compile user programs uniformly

Signed-off-by: Godones <chenlinfeng25@outlook.com>

* add a rust app example

Signed-off-by: Godones <chenlinfeng25@outlook.com>

* Restore riscv_init directory from origin/master

Signed-off-by: longjin <longjin@DragonOS.org>

---------

Signed-off-by: Godones <chenlinfeng25@outlook.com>
Signed-off-by: longjin <longjin@DragonOS.org>
Co-authored-by: longjin <longjin@DragonOS.org>
linfeng 1 周之前
父节点
当前提交
9d8f287d1c
共有 100 个文件被更改,包括 4988 次插入1172 次删除
  1. 1 0
      user/apps/c_unitest/.gitignore
  2. 35 0
      user/apps/c_unitest/Makefile
  3. 179 0
      user/apps/c_unitest/dmesg.c
  4. 213 0
      user/apps/c_unitest/http_server.c
  5. 202 0
      user/apps/c_unitest/test_bind.c
  6. 43 0
      user/apps/c_unitest/test_cred.c
  7. 30 0
      user/apps/c_unitest/test_dup3.c
  8. 0 0
      user/apps/c_unitest/test_epoll.c
  9. 50 0
      user/apps/c_unitest/test_eventfd.c
  10. 3 3
      user/apps/c_unitest/test_fifo_write.c
  11. 57 0
      user/apps/c_unitest/test_filemap.c
  12. 2 3
      user/apps/c_unitest/test_fork_wait.c
  13. 0 0
      user/apps/c_unitest/test_fstat.c
  14. 41 0
      user/apps/c_unitest/test_fstatfs.c
  15. 22 0
      user/apps/c_unitest/test_gettimeofday.c
  16. 534 0
      user/apps/c_unitest/test_kvm.c
  17. 70 0
      user/apps/c_unitest/test_mkfifo.c
  18. 64 0
      user/apps/c_unitest/test_newfstatat.c
  19. 83 0
      user/apps/c_unitest/test_overlayfs.c
  20. 0 0
      user/apps/c_unitest/test_poll.c
  21. 0 0
      user/apps/c_unitest/test_ppoll.c
  22. 83 0
      user/apps/c_unitest/test_processgroup.c
  23. 47 0
      user/apps/c_unitest/test_pty.c
  24. 115 0
      user/apps/c_unitest/test_ramfs.c
  25. 0 0
      user/apps/c_unitest/test_select.c
  26. 77 0
      user/apps/c_unitest/test_session.c
  27. 149 0
      user/apps/c_unitest/test_shm_info.c
  28. 38 0
      user/apps/c_unitest/test_shm_receiver.c
  29. 43 0
      user/apps/c_unitest/test_shm_sender.c
  30. 25 0
      user/apps/c_unitest/test_sigint.c
  31. 19 24
      user/apps/c_unitest/test_signal.c
  32. 0 0
      user/apps/c_unitest/test_signal_restart.c
  33. 128 0
      user/apps/c_unitest/test_sigprocmask.c
  34. 0 0
      user/apps/c_unitest/test_stack.c
  35. 36 0
      user/apps/c_unitest/test_statfs.c
  36. 1 1
      user/apps/c_unitest/test_uart.c
  37. 11 0
      user/apps/c_unitest/test_utimensat.c
  38. 0 1
      user/apps/dmesg/.gitignore
  39. 0 20
      user/apps/dmesg/Makefile
  40. 0 88
      user/apps/dmesg/dmesg.c
  41. 0 27
      user/apps/dmesg/dmesg.h
  42. 0 117
      user/apps/dmesg/main.c
  43. 0 1
      user/apps/http_server/.gitignore
  44. 0 20
      user/apps/http_server/Makefile
  45. 0 240
      user/apps/http_server/main.c
  46. 2 0
      user/apps/r_unitest/.cargo/config.toml
  47. 1 0
      user/apps/r_unitest/.gitignore
  48. 2413 0
      user/apps/r_unitest/Cargo.lock
  49. 15 0
      user/apps/r_unitest/Cargo.toml
  50. 5 2
      user/apps/r_unitest/Makefile
  51. 57 0
      user/apps/r_unitest/src/bin/README.md
  52. 0 0
      user/apps/r_unitest/src/bin/test_alarm.rs
  53. 0 0
      user/apps/r_unitest/src/bin/test_backlog.rs
  54. 2 2
      user/apps/r_unitest/src/bin/test_blockcache.rs
  55. 3 6
      user/apps/r_unitest/src/bin/test_chown.rs
  56. 0 0
      user/apps/r_unitest/src/bin/test_lo.rs
  57. 1 1
      user/apps/r_unitest/src/bin/test_mount.rs
  58. 0 0
      user/apps/r_unitest/src/bin/test_mount_ext4.rs
  59. 0 0
      user/apps/r_unitest/src/bin/test_mount_fat.rs
  60. 0 0
      user/apps/r_unitest/src/bin/test_namespace.rs
  61. 0 0
      user/apps/r_unitest/src/bin/test_robustfutex.rs
  62. 87 0
      user/apps/r_unitest/src/bin/test_socket.rs
  63. 0 0
      user/apps/r_unitest/src/bin/test_statx.rs
  64. 0 0
      user/apps/r_unitest/src/bin/test_symlink.rs
  65. 1 0
      user/apps/r_unitest/src/lib.rs
  66. 0 2
      user/apps/test-backlog/.cargo/config.toml
  67. 0 3
      user/apps/test-backlog/.gitignore
  68. 0 12
      user/apps/test-backlog/Cargo.toml
  69. 0 57
      user/apps/test-backlog/Makefile
  70. 0 9
      user/apps/test-backlog/README.md
  71. 0 2
      user/apps/test-blockcache/.cargo/config.toml
  72. 0 3
      user/apps/test-blockcache/.gitignore
  73. 0 10
      user/apps/test-blockcache/Cargo.toml
  74. 0 41
      user/apps/test-blockcache/Makefile
  75. 0 8
      user/apps/test-blockcache/README.md
  76. 0 4
      user/apps/test-chown/.gitignore
  77. 0 13
      user/apps/test-chown/Cargo.toml
  78. 0 56
      user/apps/test-chown/Makefile
  79. 0 8
      user/apps/test-chown/README.md
  80. 0 2
      user/apps/test-for-robustfutex/.cargo/config.toml
  81. 0 3
      user/apps/test-for-robustfutex/.gitignore
  82. 0 12
      user/apps/test-for-robustfutex/Cargo.toml
  83. 0 5
      user/apps/test-for-robustfutex/README.md
  84. 0 1
      user/apps/test-fork-wait/.gitignore
  85. 0 20
      user/apps/test-fork-wait/Makefile
  86. 0 3
      user/apps/test-mount-ext4/.gitignore
  87. 0 12
      user/apps/test-mount-ext4/Cargo.toml
  88. 0 56
      user/apps/test-mount-ext4/Makefile
  89. 0 3
      user/apps/test-mount-fat/.gitignore
  90. 0 12
      user/apps/test-mount-fat/Cargo.toml
  91. 0 56
      user/apps/test-mount-fat/Makefile
  92. 0 3
      user/apps/test-mount/.gitignore
  93. 0 12
      user/apps/test-mount/Cargo.toml
  94. 0 56
      user/apps/test-mount/Makefile
  95. 0 3
      user/apps/test-mount/README.md
  96. 0 1
      user/apps/test-processgroup/.gitignore
  97. 0 20
      user/apps/test-processgroup/Makefile
  98. 0 87
      user/apps/test-processgroup/main.c
  99. 0 1
      user/apps/test-session/.gitignore
  100. 0 20
      user/apps/test-session/Makefile

+ 1 - 0
user/apps/test_bind/.gitignore → user/apps/c_unitest/.gitignore

@@ -1 +1,2 @@
 test_bind
+test_cred

+ 35 - 0
user/apps/c_unitest/Makefile

@@ -0,0 +1,35 @@
+ifeq ($(ARCH), x86_64)
+	CROSS_COMPILE=x86_64-linux-musl-
+else ifeq ($(ARCH), riscv64)
+	CROSS_COMPILE=riscv64-linux-musl-
+endif
+
+CC=$(CROSS_COMPILE)gcc
+CFLAGS := -Wall -O2 -static
+
+SRCS := $(wildcard *.c)
+BINS := $(SRCS:.c=)
+
+
+
+$(C_TARGETS): %.o: %.c
+	$(CC) -c $< -o $@
+
+all: $(BINS)
+# 	@echo "src: $(SRCS)"
+	@echo "bins: $(BINS)"
+
+%: %.c
+	$(CC) $(CFLAGS)  $< -o $@
+
+
+install: all
+	@echo "Installing binaries to $(DADK_CURRENT_BUILD_DIR)/"
+	mv $(BINS) $(DADK_CURRENT_BUILD_DIR)/
+
+
+clean:
+	rm -f $(BINS)
+
+
+.PHONY: all install clean

+ 179 - 0
user/apps/c_unitest/dmesg.c

@@ -0,0 +1,179 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/klog.h>
+#include <unistd.h>
+/**
+ * @brief 识别dmesg程序的第一个选项参数
+ *
+ * @param arg dmesg命令第一个选项参数
+ * @return int 有效时返回对应选项码,无效时返回 -1
+ */
+int getoption(char *arg) {
+  if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
+    return 0;
+  else if (!strcmp(arg, "-c") || !strcmp(arg, "--read-clear"))
+    return 4;
+  else if (!strcmp(arg, "-C") || !strcmp(arg, "--clear"))
+    return 5;
+  else if (!strcmp(arg, "-l") || !strcmp(arg, "--level"))
+    return 8;
+
+  return -1;
+}
+
+/**
+ * @brief 识别dmesg程序的第二个选项参数
+ *
+ * @param arg dmesg命令第一个选项参数
+ * @return int 有效时返回设置的日志级别,无效时返回 -1
+ */
+int getlevel(char *arg) {
+  if (!strcmp(arg, "EMERG") || !strcmp(arg, "emerg"))
+    return 0;
+  else if (!strcmp(arg, "ALERT") || !strcmp(arg, "alert"))
+    return 1;
+  else if (!strcmp(arg, "CRIT") || !strcmp(arg, "crit"))
+    return 2;
+  else if (!strcmp(arg, "ERR") || !strcmp(arg, "err"))
+    return 3;
+  else if (!strcmp(arg, "WARN") || !strcmp(arg, "warn"))
+    return 4;
+  else if (!strcmp(arg, "NOTICE") || !strcmp(arg, "notice"))
+    return 5;
+  else if (!strcmp(arg, "INFO") || !strcmp(arg, "info"))
+    return 6;
+  else if (!strcmp(arg, "DEBUG") || !strcmp(arg, "debug"))
+    return 7;
+  else {
+    printf("dmesg: unknown level '%s'\n", arg);
+  }
+  return -2;
+}
+
+/**
+ * @brief 打印dmesg手册
+ */
+void print_help_msg() {
+  const char *help_msg =
+      "Usage:\n"
+      " dmesg [options]\n\n"
+      "Display or control the kernel ring buffer.\n\n"
+      "Options:\n"
+      " -C, --clear                 clear the kernel ring buffer\n"
+      " -c, --read-clear            read and clear all messages\n"
+      " -l, --level <list>          restrict output to defined levels\n"
+      " -h, --help                  display this help\n\n"
+      "Supported log levels (priorities):\n"
+      "   emerg - system is unusable\n"
+      "   alert - action must be taken immediately\n"
+      "    crit - critical conditions\n"
+      "     err - error conditions\n"
+      "    warn - warning conditions\n"
+      "  notice - normal but significant condition\n"
+      "    info - informational\n"
+      "   debug - debug-level messages\n";
+  printf("%s\n", help_msg);
+}
+
+/**
+ * @brief 打印dmesg错误使用的信息
+ */
+void print_bad_usage_msg() {
+  const char *bad_usage_msg =
+      "dmesg: bad usage\nTry 'dmesg --help' for more information.";
+  printf("%s\n", bad_usage_msg);
+}
+int main(int argc, char **argv) {
+  unsigned int len = 1;
+  char *buf = NULL;
+  int opt;
+  unsigned int color = 65280;
+
+  // 获取内核缓冲区大小
+  len = klogctl(10, buf, len);
+
+  if (len < 16 * 1024)
+    len = 16 * 1024;
+  if (len > 16 * 1024 * 1024)
+    len = 16 * 1024 * 1024;
+
+  buf = malloc(len);
+  if (buf == NULL) {
+    perror("");
+    return -1;
+  }
+
+  if (argc == 1) {
+    // 无选项参数,默认打印所有日志消息
+    len = klogctl(2, buf, len);
+  } else {
+    // 获取第一个选项参数
+    opt = getoption(argv[1]);
+
+    // 无效参数
+    if (opt == -1) {
+      print_bad_usage_msg();
+      return -1;
+    }
+    // 打印帮助手册
+    else if (opt == 0) {
+      print_help_msg();
+      return 0;
+    }
+    // 4 -> 读取内核缓冲区后,清空缓冲区
+    // 5 -> 清空内核缓冲区
+    else if (opt == 4 || opt == 5) {
+      len = klogctl(opt, buf, len);
+    }
+    // 读取特定日志级别的消息
+    else if (opt == 8) {
+      // 无指定日志级别参数,打印错误使用信息
+      if (argc < 3) {
+        print_bad_usage_msg();
+        return -1;
+      }
+
+      int level = -1;
+
+      // 获取日志级别
+      // 这里加1的原因是:如果klogctl的第三个参数是0,不会发生系统调用
+      level = getlevel(argv[2]) + 1;
+
+      if (level == -1)
+        return -1;
+
+      klogctl(8, buf, level);
+      len = klogctl(2, buf, len);
+    }
+  }
+
+  // 当前打印内容
+  // 0: 日志级别
+  // 1: 时间戳
+  // 2: 代码行号
+  // 3: 日志消息
+  unsigned int content = 0;
+  for (int i = 0; i < len; i++) {
+    char c[2];
+    c[0] = buf[i];
+    c[1] = '\0';
+    syscall(100000, &c[0], color, 0);
+    if (content == 0 && buf[i] == '>') {
+      content++;
+    } else if (content == 1 && buf[i] == ']') {
+      color = 16744448;
+      content++;
+    } else if (content == 2 && buf[i] == ')') {
+      color = 16777215;
+      content++;
+    } else if (content == 3 && buf[i] == '\n') {
+      color = 65280;
+      content = 0;
+    }
+  }
+
+  free(buf);
+
+  return 0;
+}

+ 213 - 0
user/apps/c_unitest/http_server.c

@@ -0,0 +1,213 @@
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define PORT 12580
+#define MAX_REQUEST_SIZE 1500
+#define MAX_RESPONSE_SIZE 1500
+// 网页根目录
+#define WEB_ROOT "/var/www/html/"
+#define EXIT_CODE 1
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#define DEFAULT_PAGE "/index.html"
+
+int security_check(char *path) {
+  // 检查路径是否包含 ..
+  if (strstr(path, "..")) {
+    return 0;
+  }
+  return 1;
+}
+
+ssize_t send_response(int sockfd, char *response) {
+  return write(sockfd, response, strlen(response));
+}
+
+void send_header(int sockfd, int content_length, char *path) {
+  char buffer[MAX_RESPONSE_SIZE];
+  // 获取文件类型
+  char *content_type;
+  if (strstr(path, ".html")) {
+    content_type = "text/html";
+  } else if (strstr(path, ".css")) {
+    content_type = "text/css";
+  } else if (strstr(path, ".js")) {
+    content_type = "application/javascript";
+  } else if (strstr(path, ".png")) {
+    content_type = "image/png";
+  } else if (strstr(path, ".jpg")) {
+    content_type = "image/jpeg";
+  } else if (strstr(path, ".gif")) {
+    content_type = "image/gif";
+  } else {
+    content_type = "text/plain;charset=utf-8";
+  }
+  sprintf(buffer, "HTTP/1.1 200 OK\nContent-Type: %s\nContent-Length: %d\n\n",
+          content_type, content_length);
+  send_response(sockfd, buffer);
+}
+
+void send_file(int sockfd, char *path) {
+  printf("send_file: path: %s\n", path);
+
+  int fd = open(path, 0);
+  if (fd == -1) {
+    send_response(sockfd,
+                  "HTTP/1.1 404 Not Found\nContent-Type: "
+                  "text/html\n\n<html><body><h1>404 Not Found</h1><p>DragonOS "
+                  "Http Server</p></body></html>");
+    return;
+  }
+
+  int content_length = lseek(fd, 0, SEEK_END);
+  int remaining = content_length;
+  printf("send_file: content_length: %d\n", content_length);
+  lseek(fd, 0, SEEK_SET);
+  send_header(sockfd, content_length, path);
+
+  char buffer[1048576];
+  int readSize;
+  while (remaining) {
+    // 由于磁盘IO耗时较长,所以每次读取1MB,然后再分批发送
+    int to_read = min(1048576, remaining);
+    readSize = read(fd, &buffer, to_read);
+
+    remaining -= readSize;
+    void *p = buffer;
+    while (readSize > 0) {
+      int wsize = write(sockfd, p, min(readSize, MAX_RESPONSE_SIZE));
+      if (wsize <= 0) {
+        printf("send_file failed: wsize: %d\n", wsize);
+        close(fd);
+        return;
+      }
+      p += wsize;
+      readSize -= wsize;
+    }
+  }
+
+  close(fd);
+}
+
+void handle_request(int sockfd, char *request) {
+  char *method, *url, *http_version;
+  char path[MAX_REQUEST_SIZE];
+
+  method = strtok(request, " ");
+  url = strtok(NULL, " ");
+  http_version = strtok(NULL, "\r\n");
+
+  printf("handle_request: method: %s, url: %s, http_version: %s\n", method, url,
+         http_version);
+  // 检查空指针等异常情况
+  if (method == NULL || url == NULL || http_version == NULL) {
+    send_response(sockfd,
+                  "HTTP/1.1 400 Bad Request\nContent-Type: "
+                  "text/html\n\n<html><body><h1>400 Bad "
+                  "Request</h1><p>DragonOS Http Server</p></body></html>");
+    return;
+  }
+  // 检查url是否为空
+  if (strlen(url) == 0) {
+    send_response(sockfd,
+                  "HTTP/1.1 400 Bad Request\nContent-Type: "
+                  "text/html\n\n<html><body><h1>400 Bad "
+                  "Request</h1><p>DragonOS Http Server</p></body></html>");
+    return;
+  }
+  int default_page = 0;
+  if (url[strlen(url) - 1] == '/') {
+    default_page = 1;
+  }
+
+  if (strcmp(method, "GET") == 0) {
+    if (default_page) {
+      sprintf(path, "%s%s%s", WEB_ROOT, url, DEFAULT_PAGE);
+    } else {
+      sprintf(path, "%s%s", WEB_ROOT, url);
+    }
+    if (!security_check(path)) {
+      send_response(sockfd,
+                    "HTTP/1.1 403 Forbidden\nContent-Type: "
+                    "text/html\n\n<html><body><h1>403 "
+                    "Forbidden</h1><p>DragonOS Http Server</p></body></html>");
+      return;
+    }
+    send_file(sockfd, path);
+  } else {
+    send_response(sockfd,
+                  "HTTP/1.1 501 Not Implemented\nContent-Type: "
+                  "text/html\n\n<html><body><h1>501 Not "
+                  "Implemented</h1><p>DragonOS Http Server</p></body></html>");
+  }
+}
+
+int main(int argc, char const *argv[]) {
+  int server_fd, new_socket, valread;
+  struct sockaddr_in address;
+  int addrlen = sizeof(address);
+  char buffer[MAX_REQUEST_SIZE] = {0};
+  int opt = 1;
+
+  // 创建socket
+  if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("socket failed");
+    exit(EXIT_CODE);
+  }
+
+  // 设置socket选项,允许地址重用
+  // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt,
+  // sizeof(opt)))
+  // {
+  //     perror("setsockopt failed");
+  //     exit(EXIT_CODE);
+  // }
+
+  // 设置地址和端口
+  address.sin_family = AF_INET;
+  address.sin_addr.s_addr = INADDR_ANY;
+  address.sin_port = htons(PORT);
+
+  // 把socket绑定到地址和端口上
+  if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("bind failed");
+    exit(EXIT_CODE);
+  }
+
+  // 监听socket
+  if (listen(server_fd, 3) < 0) {
+    perror("listen failed");
+    exit(EXIT_CODE);
+  }
+
+  while (1) {
+    printf("Waiting for a client...\n");
+
+    // 等待并接受客户端连接
+    if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
+                             (socklen_t *)&addrlen)) < 0) {
+      perror("accept failed");
+      exit(EXIT_CODE);
+    }
+
+    // 接收客户端消息
+    valread = read(new_socket, buffer, MAX_REQUEST_SIZE);
+    printf("%s\n", buffer);
+
+    // 处理请求
+    handle_request(new_socket, buffer);
+
+    // 关闭客户端连接
+    close(new_socket);
+  }
+  // 关闭tcp socket
+  close(server_fd);
+
+  return 0;
+}

+ 202 - 0
user/apps/c_unitest/test_bind.c

@@ -0,0 +1,202 @@
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define PORT 12580
+#define MAX_REQUEST_SIZE 1500
+#define MAX_RESPONSE_SIZE 1500
+#define EXIT_CODE 1
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+struct sockaddr_in address;
+int addrlen = sizeof(address);
+char buffer[MAX_REQUEST_SIZE] = {0};
+int opt = 1;
+
+void test_tcp_bind() {
+  int tcp_sk_fd1, tcp_sk_fd2, tcp_sk_fd3;
+
+  // create tcp sockets
+  if ((tcp_sk_fd1 = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("tcp socket (1) failed");
+    exit(EXIT_CODE);
+  }
+  if ((tcp_sk_fd2 = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("tcp socket (2) failed");
+    exit(EXIT_CODE);
+  }
+  if ((tcp_sk_fd3 = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("tcp socket (3) failed");
+    exit(EXIT_CODE);
+  }
+
+  // TEST tcp bind diff ports
+  if (bind(tcp_sk_fd1, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("tcp bind (1) failed");
+    exit(EXIT_CODE);
+  }
+  address.sin_port = htons(PORT + 1);
+  if (bind(tcp_sk_fd2, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("tcp bind (2) failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 4 PASSED===\n");
+
+  // TEST tcp bind same ports
+  address.sin_port = htons(PORT);
+  if (bind(tcp_sk_fd3, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("tcp bind (3) failed");
+    // exit(EXIT_CODE);
+  }
+  printf("===TEST 5 PASSED===\n");
+
+  if (close(tcp_sk_fd1) < 0) {
+    perror("tcp close (1) failed");
+    exit(EXIT_CODE);
+  }
+  if (close(tcp_sk_fd2) < 0) {
+    perror("tcp close (2) failed");
+    exit(EXIT_CODE);
+  }
+  if (close(tcp_sk_fd3) < 0) {
+    perror("tcp close (3) failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 6 PASSED===\n");
+}
+
+void test_udp_bind() {
+  int udp_sk_fd1, udp_sk_fd2, udp_sk_fd3;
+
+  // create tcp sockets
+  if ((udp_sk_fd1 = socket(AF_INET, SOCK_DGRAM, 0)) == 0) {
+    perror("udp socket (1) failed");
+    exit(EXIT_CODE);
+  }
+  if ((udp_sk_fd2 = socket(AF_INET, SOCK_DGRAM, 0)) == 0) {
+    perror("udp socket (2) failed");
+    exit(EXIT_CODE);
+  }
+  if ((udp_sk_fd3 = socket(AF_INET, SOCK_DGRAM, 0)) == 0) {
+    perror("udp socket (3) failed");
+    exit(EXIT_CODE);
+  }
+
+  // TEST udp bind diff ports
+  if (bind(udp_sk_fd1, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("udp bind (1) failed");
+    exit(EXIT_CODE);
+  }
+  address.sin_port = htons(PORT + 1);
+  if (bind(udp_sk_fd2, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("udp bind (2) failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 7 PASSED===\n");
+
+  // TEST udp bind same ports
+  address.sin_port = htons(PORT);
+  if (bind(udp_sk_fd3, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("udp bind (3) failed");
+    // exit(EXIT_CODE);
+  }
+  printf("===TEST 8 PASSED===\n");
+
+  if (close(udp_sk_fd1) < 0) {
+    perror("udp close (1) failed");
+    exit(EXIT_CODE);
+  }
+  if (close(udp_sk_fd2) < 0) {
+    perror("udp close (2) failed");
+    exit(EXIT_CODE);
+  }
+  if (close(udp_sk_fd3) < 0) {
+    perror("udp close (3) failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 9 PASSED===\n");
+}
+
+void test_all_ports() {
+  int count = 0;
+
+  while (1) {
+    int tcp_fd;
+    if ((tcp_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+      perror("socket failed");
+      exit(EXIT_CODE);
+    }
+
+    address.sin_port = htons(0);
+    if (bind(tcp_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+      perror("bind failed");
+      // exit(EXIT_CODE);
+      break;
+    }
+
+    count++;
+  }
+  printf("===TEST 10===\n");
+  printf("count: %d\n", count);
+}
+
+int main(int argc, char const *argv[]) {
+  int server_fd;
+  int udp_sk_fd;
+
+  // 创建socket
+  if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("tcp socket failed");
+    exit(EXIT_CODE);
+  }
+
+  if ((udp_sk_fd = socket(AF_INET, SOCK_DGRAM, 0)) == 0) {
+    perror("udp socket failed");
+    exit(EXIT_CODE);
+  }
+
+  // 设置地址和端口
+  address.sin_family = AF_INET;
+  address.sin_addr.s_addr = INADDR_ANY;
+  address.sin_port = htons(PORT);
+
+  // TEST socket's bind
+  if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("tcp bind failed");
+    exit(EXIT_CODE);
+  }
+  address.sin_port = htons(PORT);
+  if (bind(udp_sk_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("udp bind failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 1 PASSED===\n");
+
+  // TEST socket's listen
+  if (listen(server_fd, 3) < 0) {
+    perror("listen failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 2 PASSED===\n");
+
+  // TEST socket's close
+  if (close(server_fd) < 0) {
+    perror("tcp close failed");
+    exit(EXIT_CODE);
+  }
+  if (close(udp_sk_fd) < 0) {
+    perror("udp close failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 3 PASSED===\n");
+
+  test_tcp_bind();
+  test_udp_bind();
+  test_all_ports();
+
+  return 0;
+}

+ 43 - 0
user/apps/c_unitest/test_cred.c

@@ -0,0 +1,43 @@
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main() {
+  printf("Current uid: %d, euid: %d, gid: %d, egid: %d\n\n", getuid(),
+         geteuid(), getgid(), getegid());
+
+  // 测试uid
+  printf("Set uid 1000\n");
+  setuid(1000);
+  int uid = getuid();
+  assert(uid == 1000);
+  printf("Current uid:%d\n\n", uid);
+
+  // 测试gid
+  printf("Set gid 1000\n");
+  setgid(1000);
+  int gid = getgid();
+  assert(gid == 1000);
+  printf("Current gid:%d\n\n", gid);
+
+  // 测试euid
+  printf("Setg euid 1000\n");
+  seteuid(1000);
+  int euid = geteuid();
+  assert(euid == 1000);
+  printf("Current euid:%d\n\n", euid);
+
+  // 测试egid
+  printf("Set egid 1000\n");
+  setegid(1000);
+  int egid = getegid();
+  assert(egid == 1000);
+  printf("Current egid:%d\n\n", egid);
+
+  // 测试uid在非root用户下无法修改
+  printf("Try to setuid for non_root.\n");
+  assert(setuid(0) < 0); // 非root用户无法修改uid
+  printf("Current uid: %d, euid: %d, gid: %d, egid: %d\n", getuid(), geteuid(),
+         getgid(), getegid());
+}

+ 30 - 0
user/apps/c_unitest/test_dup3.c

@@ -0,0 +1,30 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main() {
+  int fd = open("/history_commands.txt", O_RDONLY);
+  if (fd < 0) {
+    perror("Failed to open file");
+    return 1;
+  }
+
+  int new_fd = 777;
+  int rt = dup3(fd, new_fd, O_CLOEXEC);
+  if (rt < 0) {
+    perror("Failed to duplicate file descriptor with flags");
+  }
+
+  char buffer[100];
+  int bytes_read = read(new_fd, buffer, sizeof(buffer));
+  if (bytes_read < 0) {
+    perror("Failed to read data");
+    return 1;
+  }
+
+  printf("Data:\n %.*s\n", bytes_read, buffer);
+
+  close(fd);
+  close(new_fd);
+  return 0;
+}

+ 0 - 0
user/apps/test_epoll/main.c → user/apps/c_unitest/test_epoll.c


+ 50 - 0
user/apps/c_unitest/test_eventfd.c

@@ -0,0 +1,50 @@
+#include <err.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/eventfd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[]) {
+  int efd;
+  uint64_t u;
+  ssize_t s;
+
+  if (argc < 2) {
+    fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
+    exit(EXIT_FAILURE);
+  }
+
+  efd = eventfd(0, 0);
+  if (efd == -1)
+    err(EXIT_FAILURE, "eventfd");
+
+  switch (fork()) {
+  case 0:
+    for (size_t j = 1; j < argc; j++) {
+      printf("Child writing %s to efd\n", argv[j]);
+      u = strtoull(argv[j], NULL, 0);
+      /* strtoull() allows various bases */
+      s = write(efd, &u, sizeof(uint64_t));
+      if (s != sizeof(uint64_t))
+        err(EXIT_FAILURE, "write");
+    }
+    printf("Child completed write loop\n");
+
+    exit(EXIT_SUCCESS);
+
+  default:
+    sleep(2);
+
+    printf("Parent about to read\n");
+    s = read(efd, &u, sizeof(uint64_t));
+    if (s != sizeof(uint64_t))
+      err(EXIT_FAILURE, "read");
+    printf("Parent read %" PRIu64 " (%#" PRIx64 ") from efd\n", u, u);
+    exit(EXIT_SUCCESS);
+
+  case -1:
+    err(EXIT_FAILURE, "fork");
+  }
+}

+ 3 - 3
user/apps/test_fifo_write/main.c → user/apps/c_unitest/test_fifo_write.c

@@ -159,13 +159,13 @@ void run_tests(int nonblocking) {
            nonblocking);
     switch (i) {
     case 0:
-    //   test_case1(nonblocking);
+      //   test_case1(nonblocking);
       break;
     case 1:
       test_case2(nonblocking);
       break;
     case 2:
-    //   test_case3(nonblocking);
+      //   test_case3(nonblocking);
       break;
     }
   }
@@ -202,7 +202,7 @@ int main() {
   // 设置 SIGPIPE 信号处理
   signal(SIGPIPE, sigpipe_handler);
 
-//   test_blocking();
+  //   test_blocking();
   test_non_blocking();
 
   printf("\nAll tests completed.\n");

+ 57 - 0
user/apps/c_unitest/test_filemap.c

@@ -0,0 +1,57 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main() {
+  // 打开文件
+  int fd = open("example.txt", O_RDWR | O_CREAT | O_TRUNC, 0777);
+
+  if (fd == -1) {
+    perror("open");
+    exit(EXIT_FAILURE);
+  }
+
+  write(fd, "HelloWorld!", 11);
+  char buf[12];
+  buf[11] = '\0';
+  close(fd);
+
+  fd = open("example.txt", O_RDWR);
+  read(fd, buf, 11);
+  printf("File content: %s\n", buf);
+
+  // 将文件映射到内存
+  void *map = mmap(NULL, 11, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (map == MAP_FAILED) {
+    perror("mmap");
+    close(fd);
+    exit(EXIT_FAILURE);
+  }
+  printf("mmap address: %p\n", map);
+
+  // 关闭文件描述符
+  // close(fd);
+
+  // 访问和修改文件内容
+  char *fileContent = (char *)map;
+  printf("change 'H' to 'G'\n");
+  fileContent[0] = 'G'; // 修改第一个字符为 'G'
+  printf("mmap content: %s\n", fileContent);
+
+  // 解除映射
+  printf("unmap\n");
+  if (munmap(map, 11) == -1) {
+    perror("munmap");
+    exit(EXIT_FAILURE);
+  }
+
+  fd = open("example.txt", O_RDWR);
+  read(fd, buf, 11);
+  printf("File content: %s\n", buf);
+
+  return 0;
+}

+ 2 - 3
user/apps/test-fork-wait/main.c → user/apps/c_unitest/test_fork_wait.c

@@ -10,17 +10,16 @@
 #include <time.h>
 #include <unistd.h>
 
-
 // 子线程或子进程模拟事件发生
 void trigger_event(unsigned int delay_sec) {
   printf("[child] triggere event after %u seconds...\n", delay_sec);
   sleep(delay_sec);
- 
+
   printf("[child] Event triggered.\n");
 }
 
 int main() {
- 
+
   pid_t pid = fork();
   if (pid < 0) {
     perror("fork");

+ 0 - 0
user/apps/test_fstat/main.c → user/apps/c_unitest/test_fstat.c


+ 41 - 0
user/apps/c_unitest/test_fstatfs.c

@@ -0,0 +1,41 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/statfs.h>
+
+int main(int argc, char **argv) {
+  int fd = open("/bin/about.elf", O_RDONLY);
+  if (fd == -1)
+    return 0;
+  printf("fd = %d\n", fd);
+  struct statfs diskInfo;
+
+  fstatfs(fd, &diskInfo);
+  unsigned long long blocksize1 = diskInfo.f_bsize; //每个block里包含的字节数
+  unsigned long long totalsize =
+      blocksize1 * diskInfo.f_blocks; //总的字节数,f_blocks为block的数目
+  printf("Total_size=%llu B =%llu KB =%llu MB = %llu GB\n", totalsize,
+         totalsize >> 10, totalsize >> 20, totalsize >> 30);
+
+  /* 2.获取一下剩余空间和可用空间的大小 */
+  unsigned long long freeDisk = diskInfo.f_bfree * blocksize1; //剩余空间的大小
+  unsigned long long availableDisk =
+      diskInfo.f_bavail * blocksize1; //可用空间大小
+  printf("Disk_free=%llu MB =%llu GB Disk_available=%llu MB = %llu GB\n",
+         freeDisk >> 20, freeDisk >> 30, availableDisk >> 20,
+         availableDisk >> 30);
+
+  printf("====================\n");
+  printf("diskInfo address: %p\n", diskInfo);
+  printf("f_type= %lu\n", diskInfo.f_type);
+  printf("f_bsize = %lu\n", diskInfo.f_bsize);
+  printf("f_blocks = %d\n", diskInfo.f_blocks);
+  printf("f_bfree = %lu\n", diskInfo.f_bfree);
+  printf("b_avail = %d\n", diskInfo.f_bavail);
+  printf("f_files = %d\n", diskInfo.f_files);
+  printf("f_ffree = %lu\n", diskInfo.f_ffree);
+  printf("f_fsid = %ld\n", diskInfo.f_fsid);
+  printf("f_namelen = %ld\n", diskInfo.f_namelen);
+  printf("f_frsize = %ld\n", diskInfo.f_frsize);
+  printf("f_flags = %ld\n", diskInfo.f_flags);
+  return 0;
+}

+ 22 - 0
user/apps/c_unitest/test_gettimeofday.c

@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+int main() {
+  struct timeval *tv = malloc(sizeof(struct timeval));
+  struct timezone *tz = malloc(sizeof(struct timezone));
+  for (int i = 0; i < 15; i++) {
+    gettimeofday(tv, NULL);
+    printf("%ld.%06ld\n", tv->tv_sec, tv->tv_usec);
+    for (int i = 0; i < 10; i++) {
+      usleep(500000);
+    }
+  }
+  gettimeofday(tv, NULL);
+  printf("tv = %ld.%06ld\n", tv->tv_sec, tv->tv_usec);
+  // printf("tz_minuteswest = %d,tz_dsttime = %d", (*tz).tz_minuteswest,
+  // (*tz).tz_dsttime);
+  return 0;
+}

+ 534 - 0
user/apps/c_unitest/test_kvm.c

@@ -0,0 +1,534 @@
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+//#include <linux/kvm.h>
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#ifdef __GNUC__
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
+#else
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+// from linux/kvm.h
+#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */
+#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
+#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */
+
+#define KVM_RUN _IO(KVMIO, 0x80)
+#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs)
+#define KVM_SET_REGS _IOW(KVMIO, 0x82, struct kvm_regs)
+#define KVM_GET_SREGS _IOR(KVMIO, 0x83, struct kvm_sregs)
+#define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs)
+
+#define KVMIO 0xAE
+#define KVM_SET_USER_MEMORY_REGION                                             \
+  _IOW(KVMIO, 0x46, struct kvm_userspace_memory_region)
+/* Architectural interrupt line count. */
+#define KVM_NR_INTERRUPTS 256
+struct kvm_hyperv_exit {
+#define KVM_EXIT_HYPERV_SYNIC 1
+#define KVM_EXIT_HYPERV_HCALL 2
+#define KVM_EXIT_HYPERV_SYNDBG 3
+  __u32 type;
+  __u32 pad1;
+  union {
+    struct {
+      __u32 msr;
+      __u32 pad2;
+      __u64 control;
+      __u64 evt_page;
+      __u64 msg_page;
+    } synic;
+    struct {
+      __u64 input;
+      __u64 result;
+      __u64 params[2];
+    } hcall;
+    struct {
+      __u32 msr;
+      __u32 pad2;
+      __u64 control;
+      __u64 status;
+      __u64 send_page;
+      __u64 recv_page;
+      __u64 pending_page;
+    } syndbg;
+  } u;
+};
+struct kvm_debug_exit_arch {
+  __u32 exception;
+  __u32 pad;
+  __u64 pc;
+  __u64 dr6;
+  __u64 dr7;
+};
+/* for KVM_SET_USER_MEMORY_REGION */
+struct kvm_userspace_memory_region {
+  __u32 slot;
+  __u32 flags;
+  __u64 guest_phys_addr;
+  __u64 memory_size;    /* bytes */
+  __u64 userspace_addr; /* start of the userspace allocated memory */
+};
+struct kvm_xen_exit {
+#define KVM_EXIT_XEN_HCALL 1
+  __u32 type;
+  union {
+    struct {
+      __u32 longmode;
+      __u32 cpl;
+      __u64 input;
+      __u64 result;
+      __u64 params[6];
+    } hcall;
+  } u;
+};
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+  /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+  __u64 rax, rbx, rcx, rdx;
+  __u64 rsi, rdi, rsp, rbp;
+  __u64 r8, r9, r10, r11;
+  __u64 r12, r13, r14, r15;
+  __u64 rip, rflags;
+};
+struct my_kvm_segment {
+  __u64 base;
+  __u32 limit;
+  __u16 selector;
+  __u8 type;
+  __u8 present, dpl, db, s, l, g, avl;
+  __u8 unusable;
+  __u8 padding;
+};
+struct kvm_dtable {
+  __u64 base;
+  __u16 limit;
+  __u16 padding[3];
+};
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+  /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
+  struct my_kvm_segment cs, ds, es, fs, gs, ss;
+  struct my_kvm_segment tr, ldt;
+  struct kvm_dtable gdt, idt;
+  __u64 cr0, cr2, cr3, cr4, cr8;
+  __u64 efer;
+  __u64 apic_base;
+  __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
+};
+
+/* for KVM_GET/SET_VCPU_EVENTS */
+struct kvm_vcpu_events {
+  struct {
+    __u8 injected;
+    __u8 nr;
+    __u8 has_error_code;
+    __u8 pending;
+    __u32 error_code;
+  } exception;
+  struct {
+    __u8 injected;
+    __u8 nr;
+    __u8 soft;
+    __u8 shadow;
+  } interrupt;
+  struct {
+    __u8 injected;
+    __u8 pending;
+    __u8 masked;
+    __u8 pad;
+  } nmi;
+  __u32 sipi_vector;
+  __u32 flags;
+  struct {
+    __u8 smm;
+    __u8 pending;
+    __u8 smm_inside_nmi;
+    __u8 latched_init;
+  } smi;
+  __u8 reserved[27];
+  __u8 exception_has_payload;
+  __u64 exception_payload;
+};
+/* kvm_sync_regs struct included by kvm_run struct */
+struct kvm_sync_regs {
+  /* Members of this structure are potentially malicious.
+   * Care must be taken by code reading, esp. interpreting,
+   * data fields from them inside KVM to prevent TOCTOU and
+   * double-fetch types of vulnerabilities.
+   */
+  struct kvm_regs regs;
+  struct kvm_sregs sregs;
+  struct kvm_vcpu_events events;
+};
+
+/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
+struct kvm_run {
+  /* in */
+  __u8 request_interrupt_window;
+  __u8 immediate_exit;
+  __u8 padding1[6];
+
+  /* out */
+  __u32 exit_reason;
+  __u8 ready_for_interrupt_injection;
+  __u8 if_flag;
+  __u16 flags;
+
+  /* in (pre_kvm_run), out (post_kvm_run) */
+  __u64 cr8;
+  __u64 apic_base;
+
+#ifdef __KVM_S390
+  /* the processor status word for s390 */
+  __u64 psw_mask; /* psw upper half */
+  __u64 psw_addr; /* psw lower half */
+#endif
+  union {
+    /* KVM_EXIT_UNKNOWN */
+    struct {
+      __u64 hardware_exit_reason;
+    } hw;
+    /* KVM_EXIT_FAIL_ENTRY */
+    struct {
+      __u64 hardware_entry_failure_reason;
+      __u32 cpu;
+    } fail_entry;
+    /* KVM_EXIT_EXCEPTION */
+    struct {
+      __u32 exception;
+      __u32 error_code;
+    } ex;
+    /* KVM_EXIT_IO */
+    struct {
+#define KVM_EXIT_IO_IN 0
+#define KVM_EXIT_IO_OUT 1
+      __u8 direction;
+      __u8 size; /* bytes */
+      __u16 port;
+      __u32 count;
+      __u64 data_offset; /* relative to kvm_run start */
+    } io;
+    /* KVM_EXIT_DEBUG */
+    struct {
+      struct kvm_debug_exit_arch arch;
+    } debug;
+    /* KVM_EXIT_MMIO */
+    struct {
+      __u64 phys_addr;
+      __u8 data[8];
+      __u32 len;
+      __u8 is_write;
+    } mmio;
+    /* KVM_EXIT_HYPERCALL */
+    struct {
+      __u64 nr;
+      __u64 args[6];
+      __u64 ret;
+      __u32 longmode;
+      __u32 pad;
+    } hypercall;
+    /* KVM_EXIT_TPR_ACCESS */
+    struct {
+      __u64 rip;
+      __u32 is_write;
+      __u32 pad;
+    } tpr_access;
+    /* KVM_EXIT_S390_SIEIC */
+    struct {
+      __u8 icptcode;
+      __u16 ipa;
+      __u32 ipb;
+    } s390_sieic;
+    /* KVM_EXIT_S390_RESET */
+#define KVM_S390_RESET_POR 1
+#define KVM_S390_RESET_CLEAR 2
+#define KVM_S390_RESET_SUBSYSTEM 4
+#define KVM_S390_RESET_CPU_INIT 8
+#define KVM_S390_RESET_IPL 16
+    __u64 s390_reset_flags;
+    /* KVM_EXIT_S390_UCONTROL */
+    struct {
+      __u64 trans_exc_code;
+      __u32 pgm_code;
+    } s390_ucontrol;
+    /* KVM_EXIT_DCR (deprecated) */
+    struct {
+      __u32 dcrn;
+      __u32 data;
+      __u8 is_write;
+    } dcr;
+    /* KVM_EXIT_INTERNAL_ERROR */
+    struct {
+      __u32 suberror;
+      /* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
+      __u32 ndata;
+      __u64 data[16];
+    } internal;
+    /*
+     * KVM_INTERNAL_ERROR_EMULATION
+     *
+     * "struct emulation_failure" is an overlay of "struct internal"
+     * that is used for the KVM_INTERNAL_ERROR_EMULATION sub-type of
+     * KVM_EXIT_INTERNAL_ERROR.  Note, unlike other internal error
+     * sub-types, this struct is ABI!  It also needs to be backwards
+     * compatible with "struct internal".  Take special care that
+     * "ndata" is correct, that new fields are enumerated in "flags",
+     * and that each flag enumerates fields that are 64-bit aligned
+     * and sized (so that ndata+internal.data[] is valid/accurate).
+     */
+    struct {
+      __u32 suberror;
+      __u32 ndata;
+      __u64 flags;
+      __u8 insn_size;
+      __u8 insn_bytes[15];
+    } emulation_failure;
+    /* KVM_EXIT_OSI */
+    struct {
+      __u64 gprs[32];
+    } osi;
+    /* KVM_EXIT_PAPR_HCALL */
+    struct {
+      __u64 nr;
+      __u64 ret;
+      __u64 args[9];
+    } papr_hcall;
+    /* KVM_EXIT_S390_TSCH */
+    struct {
+      __u16 subchannel_id;
+      __u16 subchannel_nr;
+      __u32 io_int_parm;
+      __u32 io_int_word;
+      __u32 ipb;
+      __u8 dequeued;
+    } s390_tsch;
+    /* KVM_EXIT_EPR */
+    struct {
+      __u32 epr;
+    } epr;
+    /* KVM_EXIT_SYSTEM_EVENT */
+    struct {
+#define KVM_SYSTEM_EVENT_SHUTDOWN 1
+#define KVM_SYSTEM_EVENT_RESET 2
+#define KVM_SYSTEM_EVENT_CRASH 3
+      __u32 type;
+      __u64 flags;
+    } system_event;
+    /* KVM_EXIT_S390_STSI */
+    struct {
+      __u64 addr;
+      __u8 ar;
+      __u8 reserved;
+      __u8 fc;
+      __u8 sel1;
+      __u16 sel2;
+    } s390_stsi;
+    /* KVM_EXIT_IOAPIC_EOI */
+    struct {
+      __u8 vector;
+    } eoi;
+    /* KVM_EXIT_HYPERV */
+    struct kvm_hyperv_exit hyperv;
+    /* KVM_EXIT_ARM_NISV */
+    struct {
+      __u64 esr_iss;
+      __u64 fault_ipa;
+    } arm_nisv;
+    /* KVM_EXIT_X86_RDMSR / KVM_EXIT_X86_WRMSR */
+    struct {
+      __u8 error; /* user -> kernel */
+      __u8 pad[7];
+#define KVM_MSR_EXIT_REASON_INVAL (1 << 0)
+#define KVM_MSR_EXIT_REASON_UNKNOWN (1 << 1)
+#define KVM_MSR_EXIT_REASON_FILTER (1 << 2)
+      __u32 reason; /* kernel -> user */
+      __u32 index;  /* kernel -> user */
+      __u64 data;   /* kernel <-> user */
+    } msr;
+    /* KVM_EXIT_XEN */
+    struct kvm_xen_exit xen;
+    /* Fix the size of the union. */
+    char padding[256];
+  };
+
+/* 2048 is the size of the char array used to bound/pad the size
+ * of the union that holds sync regs.
+ */
+#define SYNC_REGS_SIZE_BYTES 2048
+  /*
+   * shared registers between kvm and userspace.
+   * kvm_valid_regs specifies the register classes set by the host
+   * kvm_dirty_regs specified the register classes dirtied by userspace
+   * struct kvm_sync_regs is architecture specific, as well as the
+   * bits for kvm_valid_regs and kvm_dirty_regs
+   */
+  __u64 kvm_valid_regs;
+  __u64 kvm_dirty_regs;
+  union {
+    struct kvm_sync_regs regs;
+    char padding[SYNC_REGS_SIZE_BYTES];
+  } s;
+};
+
+int kvm(uint8_t code[], size_t code_len) {
+  // step 1, open /dev/kvm
+  int kvmfd = open("/dev/kvm", O_RDWR | O_CLOEXEC);
+  if (kvmfd == -1) {
+    printf("failed to open /dev/kvm\n");
+    return 0;
+  }
+
+  // step 2, create VM
+  int vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
+  printf("vmfd %d\n", vmfd);
+  // step 3, set up user memory region
+  size_t mem_size = 0x100000; // size of user memory you want to assign
+  void *mem = mmap(0, mem_size, PROT_READ | PROT_WRITE,
+                   MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+
+  printf("map mem %p\n", mem);
+  int user_entry = 0x0;
+  memcpy((void *)((size_t)mem + user_entry), code, code_len);
+  struct kvm_userspace_memory_region region = {.slot = 0,
+                                               .flags = 0,
+                                               .guest_phys_addr = 0,
+                                               .memory_size = mem_size,
+                                               .userspace_addr = (size_t)mem};
+  ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &region);
+  /* end of step 3 */
+
+  // step 4, create vCPU
+  int vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
+  printf("create vcpu,fd: %p\n", vcpufd);
+  // step 5, set up memory for vCPU
+  size_t vcpu_mmap_size = ioctl(kvmfd, KVM_GET_VCPU_MMAP_SIZE, NULL);
+  struct kvm_run *run = (struct kvm_run *)mmap(
+      0, vcpu_mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0);
+
+  // step 6, set up vCPU's registers
+  /* standard registers include general-purpose registers and flags */
+  struct kvm_regs regs;
+  ioctl(vcpufd, KVM_GET_REGS, &regs);
+  regs.rip = user_entry;
+  regs.rsp = 0x200000;                // stack address
+  regs.rflags = 0x2;                  // in x86 the 0x2 bit should always be set
+  ioctl(vcpufd, KVM_SET_REGS, &regs); // set registers
+
+  /* special registers include segment registers */
+  struct kvm_sregs sregs;
+  ioctl(vcpufd, KVM_GET_SREGS, &sregs);
+  sregs.cs.base = sregs.cs.selector =
+      0; // let base of code segment equal to zero
+  ioctl(vcpufd, KVM_SET_SREGS, &sregs);
+  ioctl(vcpufd, KVM_GET_SREGS, &sregs);
+// step 7, execute vm and handle exit reason
+#define KVM_EXIT_UNKNOWN 0
+#define KVM_EXIT_EXCEPTION 1
+#define KVM_EXIT_IO 2
+#define KVM_EXIT_HYPERCALL 3
+#define KVM_EXIT_DEBUG 4
+#define KVM_EXIT_HLT 5
+#define KVM_EXIT_MMIO 6
+#define KVM_EXIT_IRQ_WINDOW_OPEN 7
+#define KVM_EXIT_SHUTDOWN 8
+#define KVM_EXIT_FAIL_ENTRY 9
+#define KVM_EXIT_INTR 10
+#define KVM_EXIT_SET_TPR 11
+#define KVM_EXIT_TPR_ACCESS 12
+#define KVM_EXIT_S390_SIEIC 13
+#define KVM_EXIT_S390_RESET 14
+#define KVM_EXIT_DCR 15 /* deprecated */
+#define KVM_EXIT_NMI 16
+#define KVM_EXIT_INTERNAL_ERROR 17
+#define KVM_EXIT_OSI 18
+#define KVM_EXIT_PAPR_HCALL 19
+#define KVM_EXIT_S390_UCONTROL 20
+#define KVM_EXIT_WATCHDOG 21
+#define KVM_EXIT_S390_TSCH 22
+#define KVM_EXIT_EPR 23
+#define KVM_EXIT_SYSTEM_EVENT 24
+#define KVM_EXIT_S390_STSI 25
+#define KVM_EXIT_IOAPIC_EOI 26
+#define KVM_EXIT_HYPERV 27
+#define KVM_EXIT_ARM_NISV 28
+#define KVM_EXIT_X86_RDMSR 29
+#define KVM_EXIT_X86_WRMSR 30
+#define KVM_EXIT_DIRTY_RING_FULL 31
+#define KVM_EXIT_AP_RESET_HOLD 32
+#define KVM_EXIT_X86_BUS_LOCK 33
+#define KVM_EXIT_XEN 34
+  while (1) {
+    ioctl(vcpufd, KVM_RUN, NULL);
+    ioctl(vcpufd, KVM_GET_SREGS, &sregs);
+    printf("Guest CR3: 0x%llx\n", sregs.cr3);
+    switch (run->exit_reason) {
+    case KVM_EXIT_HLT:
+      fputs("KVM_EXIT_HLT \n", stderr);
+      return 0;
+    case KVM_EXIT_IO:
+      /* TODO: check port and direction here */
+      putchar(*(((char *)run) + run->io.data_offset));
+      printf("KVM_EXIT_IO: run->io.port = %lx \n", run->io.port);
+      break;
+    case KVM_EXIT_FAIL_ENTRY:
+      printf("KVM_EXIT_FAIL_ENTRY: hardware_entry_failure_reason = 0x%lx",
+             run->fail_entry.hardware_entry_failure_reason);
+      return 0;
+    case KVM_EXIT_INTERNAL_ERROR:
+      printf("KVM_EXIT_INTERNAL_ERROR: suberror = 0x%x",
+             run->internal.suberror);
+      return 0;
+    case KVM_EXIT_SHUTDOWN:
+      printf("KVM_EXIT_SHUTDOWN");
+      return 0;
+    default:
+      printf("Unhandled reason: %d", run->exit_reason);
+      return 0;
+    }
+  }
+}
+
+/*汇编指令解释
+0xB0 0x61 (mov al, 0x61)
+解释:将立即数 0x61(ASCII 字符 'a')加载到 AL 寄存器中。
+
+0xBA 0x17 0x02 (mov dx, 0x0217)
+Linux: ilen = 3 外中断和EPT_VIOLATION
+解释:将立即数 0x0217 加载到 DX 寄存器中。
+
+0xEE (out dx, al)
+解释:将 AL 寄存器的值输出到 DX 寄存器指定的端口。
+
+0xB0 0x0A (mov al, 0x0A)
+解释:将立即数 0x0A(换行符)加载到 AL 寄存器中。
+
+0xEE (out dx, al)
+解释:将 AL 寄存器的值输出到 DX 寄存器指定的端口。
+
+0xF4 (hlt)
+解释:执行 hlt 指令,使处理器进入休眠状态,直到下一个外部中断到来。*/
+
+int main() {
+  // uint8_t code[] = "\xB0\x61\xBA\x17\x02\xEE\xB0\n\xEE\xF4";
+  // uint8_t code[] = "\xB0\x61\xBA\x17\x02\xEE\xF4";
+  uint8_t code[] = "\xB0\x61\xF4";
+  kvm(code, sizeof(code));
+  return 0;
+}

+ 70 - 0
user/apps/c_unitest/test_mkfifo.c

@@ -0,0 +1,70 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define BUFFER_SIZE 256
+#define PIPE_NAME "/bin/fifo"
+
+int main() {
+  pid_t pid;
+  int pipe_fd;
+  char buffer[BUFFER_SIZE];
+  int bytes_read;
+  int status;
+
+  // 创建命名管道
+  mkfifo(PIPE_NAME, 0666);
+
+  // 创建子进程
+  pid = fork();
+
+  if (pid < 0) {
+    fprintf(stderr, "Fork failed\n");
+    return 1;
+  } else if (pid == 0) {
+    // 子进程
+
+    // 打开管道以供读取
+    pipe_fd = open(PIPE_NAME, O_RDONLY);
+
+    // 从管道中读取数据
+    bytes_read = read(pipe_fd, buffer, BUFFER_SIZE);
+    if (bytes_read > 0) {
+      printf("Child process received message: %s\n", buffer);
+    }
+
+    // 关闭管道文件描述符
+    close(pipe_fd);
+
+    // 删除命名管道
+    unlink(PIPE_NAME);
+
+    exit(0);
+  } else {
+    // 父进程
+
+    // 打开管道以供写入
+    pipe_fd = open(PIPE_NAME, O_WRONLY);
+
+    // 向管道写入数据
+    const char *message = "Hello from parent process";
+    write(pipe_fd, message, strlen(message) + 1);
+
+    // 关闭管道文件描述符
+    close(pipe_fd);
+
+    // 等待子进程结束
+    waitpid(pid, &status, 0);
+
+    if (WIFEXITED(status)) {
+      printf("Child process exited with status: %d\n", WEXITSTATUS(status));
+    }
+  }
+
+  return 0;
+}

+ 64 - 0
user/apps/c_unitest/test_newfstatat.c

@@ -0,0 +1,64 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#define TEST_DIR "test_dir"
+#define TEST_FILE "test_file"
+
+void create_test_files() {
+  mkdir(TEST_DIR, 0755);
+  int fd = open(TEST_FILE, O_CREAT | O_RDWR, 0644);
+  if (fd >= 0)
+    close(fd);
+}
+
+void cleanup_test_files() {
+  unlink(TEST_FILE);
+  rmdir(TEST_DIR);
+}
+
+void run_test(const char *name, int (*test_func)(), int expected) {
+  printf("Testing %s... ", name);
+  int result = test_func();
+  if (result == expected) {
+    printf("[PASS]\n");
+  } else {
+    printf("[FAILED] (expected %d, got %d)\n", expected, result);
+  }
+}
+
+int test_normal_file() {
+  struct stat st;
+  return syscall(__NR_newfstatat, AT_FDCWD, TEST_FILE, &st, 0);
+}
+
+int test_directory() {
+  struct stat st;
+  return syscall(__NR_newfstatat, AT_FDCWD, TEST_DIR, &st, 0);
+}
+
+int test_invalid_fd() {
+  struct stat st;
+  return syscall(__NR_newfstatat, -1, TEST_FILE, &st, 0);
+}
+
+int test_nonexistent_path() {
+  struct stat st;
+  return syscall(__NR_newfstatat, AT_FDCWD, "nonexistent_file", &st, 0);
+}
+
+int main() {
+  create_test_files();
+
+  run_test("normal file stat", test_normal_file, 0);
+  run_test("directory stat", test_directory, 0);
+  run_test("invalid file descriptor", test_invalid_fd, -1);
+  run_test("nonexistent path", test_nonexistent_path, -1);
+
+  cleanup_test_files();
+  return 0;
+}

+ 83 - 0
user/apps/c_unitest/test_overlayfs.c

@@ -0,0 +1,83 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+// #define LOWERDIR "/tmp/overlayfs/lower"
+// #define UPPERDIR "/tmp/overlayfs/upper"
+// #define WORKDIR "/tmp/overlayfs/work"
+// #define MERGEDDIR "/tmp/overlayfs/merged"
+
+// void create_directories()
+// {
+//     mkdir(LOWERDIR, 0755);
+//     mkdir(UPPERDIR, 0755);
+//     mkdir(WORKDIR, 0755);
+//     mkdir(MERGEDDIR, 0755);
+// }
+#define TMPDIR "/tmp"
+#define OVERLAYFSDIR "/tmp/overlayfs"
+#define LOWERDIR "/tmp/overlayfs/lower"
+#define UPPERDIR "/tmp/overlayfs/upper"
+#define WORKDIR "/tmp/overlayfs/work"
+#define MERGEDDIR "/tmp/overlayfs/merged"
+
+void create_directories() {
+  mkdir(TMPDIR, 0755);
+  mkdir(OVERLAYFSDIR, 0755);
+  mkdir(LOWERDIR, 0755);
+  mkdir(UPPERDIR, 0755);
+  mkdir(WORKDIR, 0755);
+  mkdir(MERGEDDIR, 0755);
+  printf("step1 : success\n");
+}
+
+void create_lower_file() {
+  char filepath[256];
+  snprintf(filepath, sizeof(filepath), "%s/lowerfile.txt", LOWERDIR);
+
+  int fd = open(filepath, O_CREAT | O_WRONLY, 0644);
+  if (fd < 0) {
+    perror("Failed to create file in lowerdir");
+    exit(EXIT_FAILURE);
+  }
+  write(fd, "This is a lower layer file.\n", 28);
+  close(fd);
+  printf("step2 : success\n");
+}
+
+void mount_overlayfs() {
+  char options[1024];
+  snprintf(options, sizeof(options), "lowerdir=%s,upperdir=%s,workdir=%s",
+           LOWERDIR, UPPERDIR, WORKDIR);
+
+  if (mount("overlay", MERGEDDIR, "overlay", 0, options) != 0) {
+    perror("Mount failed");
+    exit(EXIT_FAILURE);
+  }
+  printf("OverlayFS mounted successfully.\n");
+  printf("step3 : success\n");
+}
+
+void create_directory_in_merged() {
+  char dirpath[256];
+  snprintf(dirpath, sizeof(dirpath), "%s/newdir", UPPERDIR);
+
+  if (mkdir(dirpath, 0755) != 0) {
+    perror("Failed to create directory in merged dir");
+    exit(EXIT_FAILURE);
+  }
+  printf("Directory created in merged: %s\n", dirpath);
+  printf("step4 : success\n");
+}
+
+int main() {
+  create_directories();
+  mount_overlayfs();
+  create_directory_in_merged();
+  return 0;
+}

+ 0 - 0
user/apps/test_poll/main.c → user/apps/c_unitest/test_poll.c


+ 0 - 0
user/apps/test_poll/ppoll.c → user/apps/c_unitest/test_ppoll.c


+ 83 - 0
user/apps/c_unitest/test_processgroup.c

@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define TEST_ASSERT(left, right, success_msg, fail_msg)                        \
+  do {                                                                         \
+    if ((left) == (right)) {                                                   \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n", fail_msg,           \
+             (unsigned long)(right), (unsigned long)(left));                   \
+    }                                                                          \
+  } while (0)
+
+// 打印进程信息
+void print_ids(const char *name) {
+  printf("[%s] PID=%d, PPID=%d, PGID=%d, SID=%d\n", name, getpid(), getppid(),
+         getpgid(0), // 获取当前进程的 PGID
+         getsid(0)); // 获取当前进程的 SID
+}
+
+int main() {
+  printf("===== 测试进程组 =====\n");
+  print_ids("Parent");
+
+  // 创建第一个子进程
+  pid_t child1 = fork();
+  if (child1 == 0) {
+    // 子进程1:设置自己的进程组
+    printf("\n[Child1] 子进程启动...\n");
+    print_ids("Child1 (before setpgid)");
+
+    if (setpgid(0, 0) == -1) { // 将自己的 PGID 设置为自己的 PID
+      perror("setpgid failed");
+      exit(EXIT_FAILURE);
+    }
+
+    print_ids("Child1 (after setpgid)");
+
+    // Assert: PGID 应该等于 PID
+    // assert(getpgid(0) == getpid());
+    TEST_ASSERT(getpgid(0), getpid(),
+                "Successfully set child1 as processgroup leader",
+                "Child1 PGID check failed");
+
+    sleep(2); // 保持运行,便于观察
+    exit(EXIT_SUCCESS);
+  }
+
+  // 创建第二个子进程
+  pid_t child2 = fork();
+  if (child2 == 0) {
+    // 子进程2:加入第一个子进程的进程组
+    printf("\n[Child2] 子进程启动...\n");
+    print_ids("Child2 (before setpgid)");
+
+    if (setpgid(0, child1) == -1) { // 将自己的 PGID 设置为 child1 的 PID
+      perror("setpgid failed");
+      exit(EXIT_FAILURE);
+    }
+
+    print_ids("Child2 (after setpgid)");
+
+    // Assert: PGID 应该等于 child1 的 PID
+    // assert(getpgid(0) == child1);
+    TEST_ASSERT(getpgid(0), child1, "Child2 PGID is equal to Child1",
+                "Child2 PGID check failed");
+
+    sleep(2); // 保持运行,便于观察
+    exit(EXIT_SUCCESS);
+  }
+
+  // 父进程:等待子进程结束
+  waitpid(child1, NULL, 0);
+  waitpid(child2, NULL, 0);
+
+  printf("\n[Parent] 所有子进程结束后...\n");
+  print_ids("Parent");
+
+  return 0;
+}

+ 47 - 0
user/apps/c_unitest/test_pty.c

@@ -0,0 +1,47 @@
+#include <fcntl.h>
+#include <pty.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+int main() {
+  int ptm, pts;
+  char name[256];
+  struct termios term;
+
+  if (openpty(&ptm, &pts, name, NULL, NULL) == -1) {
+    perror("openpty");
+    exit(EXIT_FAILURE);
+  }
+
+  printf("slave name: %s fd: %d\n", name, pts);
+
+  tcgetattr(pts, &term);
+  term.c_lflag &= ~(ICANON | ECHO);
+  term.c_cc[VMIN] = 1;
+  term.c_cc[VTIME] = 0;
+  tcsetattr(pts, TCSANOW, &term);
+
+  printf("before print to pty slave\n");
+  dprintf(pts, "Hello world!\n");
+
+  char buf[256];
+  ssize_t n = read(ptm, buf, sizeof(buf));
+  if (n > 0) {
+    printf("read %ld bytes from slave: %.*s", n, (int)n, buf);
+  }
+
+  dprintf(ptm, "hello world from master\n");
+
+  char nbuf[256];
+  ssize_t nn = read(pts, nbuf, sizeof(nbuf));
+  if (nn > 0) {
+    printf("read %ld bytes from master: %.*s", nn, (int)nn, nbuf);
+  }
+
+  close(ptm);
+  close(pts);
+
+  return 0;
+}

+ 115 - 0
user/apps/c_unitest/test_ramfs.c

@@ -0,0 +1,115 @@
+// #include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MAX_PATH_LENGTH 100
+#define MAX_DIR_DEPTH 4
+
+int main(int argc, char const *argv[]) {
+
+  if (mkdir("/SOME", 0777) == -1) {
+    perror("Failed to create directory under /some");
+    return 1;
+  }
+
+  // Create a directory under /SOME/RAMFS
+  if (mkdir("/SOME/RAMFS", 0777) == -1) {
+    perror("Failed to create directory under /SOME/RAMFS");
+    return 1;
+  }
+
+  // Mount the first ramfs at /SOME/RAMFS
+  if (mount("", "/SOME/RAMFS", "ramfs", 0, NULL) == -1) {
+    perror("Failed to mount ramfs at /SOME/RAMFS");
+    return 1;
+  }
+
+  if (mkdir("/SOME/RAMFS/some", 0777) == -1) {
+    perror("Failed to create directory under /SOME/RAMFS/some");
+    return 1;
+  }
+
+  puts("Success mkdir /SOME/RAMFS/some");
+
+  // Create a directory under /SOME/RAMFS/some/another
+  if (mkdir("/SOME/RAMFS/some/another", 0777) == -1) {
+    perror("Failed to create directory under /SOME/RAMFS/some/another");
+    return 1;
+  }
+
+  puts("Success mkdir /SOME/RAMFS/some/another");
+
+  if (mount("", "/SOME/RAMFS/some/another", "ramfs", 0, NULL) == -1) {
+    perror("Failed to mount ramfs at /SOME/RAMFS/some/another");
+    return 1;
+  }
+
+  puts("Success mount on /SOME/RAMFS/some/another");
+
+  if (mkdir("/SOME/RAMFS/some/another/just_another", 0777) == -1) {
+    perror("Failed to create directory under /SOME/RAMFS/some/another");
+    return 1;
+  }
+
+  puts("Success mkdir /SOME/RAMFS/some/another/just_another");
+
+  if (mount("", "/SOME/RAMFS/some/another/just_another", "ramfs", 0, NULL) ==
+      -1) {
+    perror("Failed to mount ramfs at /SOME/RAMFS/some/another");
+    return 1;
+  }
+
+  puts("Success mount on /SOME/RAMFS/some/another/just_another");
+
+  // Write files under /SOME/RAMFS and /SOME/RAMFS/some/another
+  FILE *file1 = fopen("/SOME/RAMFS/file1.txt", "w");
+  if (file1 == NULL) {
+    perror("Failed to open /SOME/RAMFS/file1.txt");
+    return 1;
+  }
+  fprintf(file1, "This is file1.txt\n");
+  fclose(file1);
+
+  FILE *file2 = fopen("/SOME/RAMFS/some/another/file2.txt", "w");
+  if (file2 == NULL) {
+    perror("Failed to open /SOME/RAMFS/some/another/file2.txt");
+    return 1;
+  }
+  fprintf(file2, "This is file2.txt\n");
+  fclose(file2);
+
+  FILE *file3 = fopen("/SOME/RAMFS/some/another/just_another/file3.txt", "w+");
+  if (file3 == NULL) {
+    perror("Failed to open /SOME/RAMFS/some/another/just_another/file3.txt");
+    return 1;
+  }
+  fprintf(file3, "Multi mount behave well.\n");
+  // print file3.txt
+  char buffer[100];
+  fseek(file3, 0, SEEK_SET);
+  fread(buffer, 1, 100, file3);
+  printf("file3.txt content: %s\n", buffer);
+  fclose(file3);
+
+  // test umount with flags ( use umount2 )
+  if (umount("/SOME/RAMFS/some/another/just_another") == -1) {
+    perror("Failed to umount ramfs at /SOME/RAMFS/some/another/just_another");
+    return 1;
+  }
+
+  puts("Successful umount /SOME/RAMFS/some/another/just_another");
+
+  // delete just_another
+  if (rmdir("/SOME/RAMFS/some/another/just_another") == -1) {
+    perror("Failed to delete /SOME/RAMFS/some/another/just_another");
+    return 1;
+  }
+
+  return 0;
+}

+ 0 - 0
user/apps/test_select/main.c → user/apps/c_unitest/test_select.c


+ 77 - 0
user/apps/c_unitest/test_session.c

@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define TEST_ASSERT(left, right, success_msg, fail_msg)                        \
+  do {                                                                         \
+    if ((left) == (right)) {                                                   \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n", fail_msg,           \
+             (unsigned long)(right), (unsigned long)(left));                   \
+    }                                                                          \
+  } while (0)
+
+#define TEST_CONDITION(condition, success_msg, fail_msg)                       \
+  do {                                                                         \
+    if (condition) {                                                           \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s\n", fail_msg);                                         \
+    }                                                                          \
+  } while (0)
+
+// 打印进程信息
+void print_ids(const char *name) {
+  printf("[%s] PID=%d, PPID=%d, PGID=%d, SID=%d\n", name, getpid(), getppid(),
+         getpgid(0), // 获取当前进程的 PGID
+         getsid(0)); // 获取当前进程的 SID
+}
+
+int main() {
+  printf("===== 测试 getsid =====\n");
+  print_ids("Parent");
+
+  pid_t child = fork();
+  if (child == 0) {
+    // 子进程
+    printf("\n[Child] 子进程启动...\n");
+    print_ids("Child (before setsid)");
+
+    // 创建新会话
+    pid_t newsid = setsid();
+    if (newsid == -1) {
+      perror("setsid failed");
+      exit(EXIT_FAILURE);
+    }
+
+    printf("[Child] 创建新会话成功,新 SID = %d\n", newsid);
+    print_ids("Child (after setsid)");
+
+    TEST_ASSERT(newsid, getpid(), "New sid equal to child pid",
+                "failed to set new sid");
+    TEST_ASSERT(getsid(0), getpid(), "Child sid equal to child pid",
+                "failed to set new sid");
+    TEST_ASSERT(getpgid(0), getpid(), "Child pgid equal to child pid",
+                "failed to set new sid");
+
+    exit(EXIT_SUCCESS);
+  } else if (child > 0) {
+    // 父进程
+    waitpid(child, NULL, 0); // 等待子进程结束
+    printf("\n[Parent] 子进程结束后...\n");
+    print_ids("Parent");
+
+    TEST_CONDITION(getsid(0) != child, "Parent sid unchanged",
+                   "Parent sid changed");
+    TEST_CONDITION(getpgid(0) != child, "Parent pgid unchanged",
+                   "Parent pgid changed");
+  } else {
+    perror("fork failed");
+    exit(EXIT_FAILURE);
+  }
+
+  return 0;
+}

+ 149 - 0
user/apps/c_unitest/test_shm_info.c

@@ -0,0 +1,149 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+void print_shmidds(struct shmid_ds *shminfo) {
+  struct ipc_perm shm_perm = shminfo->shm_perm;
+
+  printf("ipc_perm:\n");
+  printf("ipc_perm_key: %d\n", shm_perm.__key);
+  printf("uid: %d\n", shm_perm.uid);
+  printf("gid: %d\n", shm_perm.gid);
+  printf("cuid: %d\n", shm_perm.cuid);
+  printf("cgid: %d\n", shm_perm.cgid);
+  printf("mode: %d\n", shm_perm.mode);
+  printf("seq: %d\n", shm_perm.__seq);
+  printf("\n");
+
+  printf("shmid_ds:\n");
+  printf("shm_atime: %lu\n", shminfo->shm_atime);
+  printf("shm_dtime: %lu\n", shminfo->shm_dtime);
+  printf("shm_ctime: %lu\n", shminfo->shm_ctime);
+  printf("shm_segsz: %lu\n", shminfo->shm_segsz);
+  printf("shm_cpid: %d\n", shminfo->shm_cpid);
+  printf("shm_lpid: %d\n", shminfo->shm_lpid);
+  printf("shm_nattch: %lu\n", shminfo->shm_nattch);
+  printf("\n");
+}
+
+const int SHM_SIZE = 9999;
+
+int main() {
+  int shmid;
+  char *shmaddr;
+  key_t key = 6666;
+
+  // 测试shmget
+  shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT);
+  if (shmid < 0) {
+    perror("shmget failed");
+    exit(EXIT_FAILURE);
+  }
+
+  // 测试shmat
+  shmaddr = shmat(shmid, 0, 0);
+
+  // IPC_STAT:
+  printf("\n");
+  printf("IPC_STAT:\n");
+  struct shmid_ds shminfo2;
+  if (shmctl(shmid, IPC_STAT, &shminfo2) == -1) {
+    // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+  print_shmidds(&shminfo2);
+
+  // 测试shmctl
+  // IPC_INFO
+  printf("IPC_INFO:\n");
+  struct shminfo shmmetainfo;
+  if (shmctl(shmid, IPC_INFO, &shmmetainfo) == -1) { // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+  printf("shmmax: %lu\n", shmmetainfo.shmmax);
+  printf("shmmin: %lu\n", shmmetainfo.shmmin);
+  printf("shmmni: %lu\n", shmmetainfo.shmmni);
+  printf("shmseg: %lu\n", shmmetainfo.shmseg);
+  printf("shmall: %lu\n", shmmetainfo.shmall);
+
+  // SHM_INFO
+  printf("\n");
+  printf("SHM_INFO:\n");
+  struct shm_info shm_info;
+  if (shmctl(shmid, SHM_INFO, &shm_info) == -1) { // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+  printf("__used_ids: %lu\n", shm_info.__used_ids);
+  printf("shm_tot: %lu\n", shm_info.shm_tot);
+  printf("shm_rss: %lu\n", shm_info.shm_rss);
+  printf("shm_swp: %lu\n", shm_info.shm_swp);
+  printf("__swap_attempts: %lu\n", shm_info.__swap_attempts);
+  printf("__swap_successes: %lu\n", shm_info.__swap_successes);
+
+  // SHM_STAT
+  printf("\n");
+  printf("SHM_STAT:\n");
+  struct shmid_ds shminfo0;
+  if (shmctl(shmid, SHM_STAT, &shminfo0) == -1) { // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+  print_shmidds(&shminfo0);
+
+  // SHM_STAT_ANY
+  printf("SHM_STAT_ANY:\n");
+  struct shmid_ds shminfo1;
+  if (shmctl(shmid, SHM_STAT_ANY, &shminfo1) == -1) { // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+  print_shmidds(&shminfo1);
+
+  // IPC_SET
+  printf("\n");
+  printf("IPC_SET:\n");
+  struct shmid_ds shminfo;
+  shminfo.shm_atime = 1;
+  shminfo.shm_dtime = 2;
+  shminfo.shm_ctime = 3;
+  shminfo.shm_segsz = 4;
+  shminfo.shm_cpid = 5;
+  shminfo.shm_lpid = 6;
+  shminfo.shm_nattch = 7;
+  if (shmctl(shmid, IPC_SET, &shminfo) == -1) { // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+
+  // IPC_RMID
+  printf("\n");
+  printf("IPC_RMID:\n");
+  if (shmctl(shmid, IPC_RMID, NULL) == -1) { // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+
+  // SHM_LOCK
+  printf("\n");
+  printf("SHM_LOCK:\n");
+  if (shmctl(shmid, SHM_LOCK, NULL) == -1) { // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+
+  // SHM_UNLOCK
+  printf("\n");
+  printf("SHM_UNLOCK:\n");
+  if (shmctl(shmid, SHM_UNLOCK, NULL) == -1) { // 获取共享内存段信息
+    perror("shmctl");
+    exit(EXIT_FAILURE);
+  }
+}

+ 38 - 0
user/apps/c_unitest/test_shm_receiver.c

@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define SHM_SIZE 9999
+
+int main() {
+  int shmid;
+  char *shmaddr;
+  key_t key = 6666;
+
+  // 测试shmget
+  shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT);
+  if (shmid < 0) {
+    perror("shmget failed");
+    exit(EXIT_FAILURE);
+  }
+
+  // 测试shmat
+  shmaddr = shmat(shmid, 0, 0);
+
+  char read_buf[20];
+  memcpy(read_buf, shmaddr, 14);
+
+  printf("Receiver receive: %s\n", read_buf);
+
+  memset(shmaddr, 0, SHM_SIZE);
+  memcpy(shmaddr, "Reveiver Hello!", 16);
+
+  shmdt(shmaddr);
+
+  return 0;
+}

+ 43 - 0
user/apps/c_unitest/test_shm_sender.c

@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define SHM_SIZE 9999
+
+int main() {
+  int shmid;
+  char *shmaddr;
+  key_t key = 6666;
+
+  // 测试shmget
+  shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT);
+  if (shmid < 0) {
+    perror("shmget failed");
+    exit(EXIT_FAILURE);
+  }
+
+  // 测试shmat
+  shmaddr = shmat(shmid, 0, 0);
+
+  memset(shmaddr, 0, SHM_SIZE);
+  memcpy(shmaddr, "Sender Hello!", 14);
+
+  int pid = fork();
+  if (pid == 0) {
+    execl("/bin/test_shm_receiver", NULL, NULL);
+  }
+
+  waitpid(pid, NULL, 0);
+
+  char read_buf[20];
+  memcpy(read_buf, shmaddr, 16);
+  printf("Sender receive: %s\n", read_buf);
+
+  shmdt(shmaddr);
+  shmctl(shmid, IPC_RMID, NULL);
+}

+ 25 - 0
user/apps/c_unitest/test_sigint.c

@@ -0,0 +1,25 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+// 信号处理函数
+void handle_signal(int signal) {
+  if (signal == SIGINT) {
+    printf("Caught SIGINT (Ctrl+C). Exiting gracefully...\n");
+    exit(0); // 终止程序
+  }
+}
+
+int main() {
+  // 注册信号处理函数
+  signal(SIGINT, handle_signal);
+
+  // 模拟一个长时间运行的进程
+  while (1) {
+    printf("Running... Press Ctrl+C to stop.\n");
+    sleep(5);
+  }
+
+  return 0;
+}

+ 19 - 24
user/apps/test_signal/main.c → user/apps/c_unitest/test_signal.c

@@ -24,33 +24,28 @@
 
 bool handle_ok = false;
 int count = 0;
-void handler(int sig)
-{
-    printf("handle %d\n", sig);
-    handle_ok = true;
-    count++;
+void handler(int sig) {
+  printf("handle %d\n", sig);
+  handle_ok = true;
+  count++;
 }
 
-int main()
-{
-    signal(SIGKILL, &handler);
-    printf("registered.\n");
+int main() {
+  signal(SIGKILL, &handler);
+  printf("registered.\n");
 
-    while (1)
-    {
-        // handler(SIGKILL);
-        printf("Test signal running\n");
-        raise(SIGKILL);
-        if (handle_ok)
-        {
-            printf("Handle OK!\n");
-            handle_ok = false;
-        }
-        if (count > 0)
-        {
-            signal(SIGKILL, SIG_DFL);
-        }
+  while (1) {
+    // handler(SIGKILL);
+    printf("Test signal running\n");
+    raise(SIGKILL);
+    if (handle_ok) {
+      printf("Handle OK!\n");
+      handle_ok = false;
     }
+    if (count > 0) {
+      signal(SIGKILL, SIG_DFL);
+    }
+  }
 
-    return 0;
+  return 0;
 }

+ 0 - 0
user/apps/test_signal_restart/main.c → user/apps/c_unitest/test_signal_restart.c


+ 128 - 0
user/apps/c_unitest/test_sigprocmask.c

@@ -0,0 +1,128 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define TEST_ASSERT(left, right, success_msg, fail_msg)                        \
+  do {                                                                         \
+    if ((left) == (right)) {                                                   \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n", fail_msg,           \
+             (unsigned long)(right), (unsigned long)(left));                   \
+    }                                                                          \
+  } while (0)
+
+static int signal_received = 0;
+
+void signal_handler(int signo) {
+  if (signo == SIGINT) {
+    printf("\nReceived SIGINT (Ctrl+C)\n");
+    signal_received = 1;
+  }
+}
+
+void print_signal_mask(const char *msg, const sigset_t *mask) {
+  printf("%s: ", msg);
+  for (int signo = 1; signo < NSIG; ++signo) {
+    if (sigismember(mask, signo)) {
+      printf("%d ", signo);
+    }
+  }
+  printf("\n");
+}
+
+// 获取当前屏蔽字的函数
+unsigned long get_signal_mask() {
+  sigset_t sigset;
+  if (sigprocmask(SIG_BLOCK, NULL, &sigset) == -1) {
+    perror("sigprocmask");
+    return -1; // 返回错误标记
+  }
+
+  // 将信号集编码为位掩码
+  unsigned long mask = 0;
+  for (int i = 1; i < NSIG; i++) {
+    if (sigismember(&sigset, i)) {
+      mask |= 1UL << (i - 1);
+    }
+  }
+  return mask;
+}
+
+int main() {
+  sigset_t new_mask, old_mask;
+  sigemptyset(&old_mask);
+
+  // 注册 SIGINT 的信号处理函数
+  if (signal(SIGINT, signal_handler) == SIG_ERR) {
+    perror("signal");
+    exit(EXIT_FAILURE);
+  }
+  printf("Signal handler for SIGINT is registered.\n");
+  signal_received = 0;
+  kill(getpid(), SIGINT);
+  sleep(5);
+
+  TEST_ASSERT(signal_received, 1, "SIGINT was received",
+              "SIGINT was not received");
+  signal_received = 0;
+
+  // 初始化新的信号集,并将 SIGINT 添加到其中
+  sigemptyset(&new_mask);
+  sigaddset(&new_mask, SIGINT);
+
+  // 打印 new_mask 的值
+  print_signal_mask("new_mask", &new_mask);
+
+  // 屏蔽 SIGINT
+  if (sigprocmask(SIG_BLOCK, &new_mask, &old_mask) < 0) {
+    perror("sigprocmask - SIG_BLOCK");
+    exit(EXIT_FAILURE);
+  }
+
+  // 打印 old_mask 的值
+  print_signal_mask("old_mask", &old_mask);
+
+  // 检查 SIGINT 是否被屏蔽
+  unsigned long actual_mask = get_signal_mask();
+  unsigned long expected_mask = (1UL << (SIGINT - 1));
+  TEST_ASSERT(actual_mask, expected_mask, "Signal mask is as expected",
+              "Signal mask mismatch");
+
+  printf("SIGINT is now blocked.\n");
+  signal_received = 0;
+  // 向当前进程发送 SIGINT
+  kill(getpid(), SIGINT);
+
+  // 等待 5 秒,以便测试 SIGINT 是否被屏蔽
+  sleep(5);
+  TEST_ASSERT(signal_received, 0, "SIGINT was blocked",
+              "SIGINT was not blocked");
+  signal_received = 0;
+  // 恢复原来的信号屏蔽字
+  if (sigprocmask(SIG_SETMASK, &old_mask, &old_mask) < 0) {
+    perror("sigprocmask - SIG_SETMASK");
+    exit(EXIT_FAILURE);
+  }
+  print_signal_mask("old_mask returned", &old_mask);
+
+  // 检查 SIGINT 是否被解除屏蔽
+  actual_mask = get_signal_mask();
+  expected_mask = 0;
+  TEST_ASSERT(actual_mask, expected_mask, "Signal mask is as expected",
+              "Signal mask mismatch");
+
+  printf("SIGINT is now unblocked.\n");
+
+  signal_received = 0;
+  kill(getpid(), SIGINT);
+
+  // 等待 5 秒,以便测试 SIGINT 是否解除屏蔽
+  sleep(5);
+  TEST_ASSERT(signal_received, 1, "SIGINT was received",
+              "SIGINT was not received");
+
+  printf("Exiting program.\n");
+  return 0;
+}

+ 0 - 0
user/apps/test_stack/main.c → user/apps/c_unitest/test_stack.c


+ 36 - 0
user/apps/c_unitest/test_statfs.c

@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <sys/statfs.h>
+
+int main(int argc, char **argv) {
+  struct statfs diskInfo;
+
+  statfs("/bin/about.elf", &diskInfo);
+  unsigned long long blocksize1 = diskInfo.f_bsize; //每个block里包含的字节数
+  unsigned long long totalsize =
+      blocksize1 * diskInfo.f_blocks; //总的字节数,f_blocks为block的数目
+  printf("Total_size=%llu B =%llu KB =%llu MB = %llu GB\n", totalsize,
+         totalsize >> 10, totalsize >> 20, totalsize >> 30);
+
+  /* 2.获取一下剩余空间和可用空间的大小 */
+  unsigned long long freeDisk = diskInfo.f_bfree * blocksize1; //剩余空间的大小
+  unsigned long long availableDisk =
+      diskInfo.f_bavail * blocksize1; //可用空间大小
+  printf("Disk_free=%llu MB =%llu GB Disk_available=%llu MB = %llu GB\n",
+         freeDisk >> 20, freeDisk >> 30, availableDisk >> 20,
+         availableDisk >> 30);
+
+  printf("====================\n");
+  printf("diskInfo address: %p\n", diskInfo);
+  printf("f_type= %lu\n", diskInfo.f_type);
+  printf("f_bsize = %lu\n", diskInfo.f_bsize);
+  printf("f_blocks = %d\n", diskInfo.f_blocks);
+  printf("f_bfree = %lu\n", diskInfo.f_bfree);
+  printf("b_avail = %d\n", diskInfo.f_bavail);
+  printf("f_files = %d\n", diskInfo.f_files);
+  printf("f_ffree = %lu\n", diskInfo.f_ffree);
+  printf("f_fsid = %ld\n", diskInfo.f_fsid);
+  printf("f_namelen = %ld\n", diskInfo.f_namelen);
+  printf("f_frsize = %ld\n", diskInfo.f_frsize);
+  printf("f_flags = %ld\n", diskInfo.f_flags);
+  return 0;
+}

+ 1 - 1
user/apps/test_uart/main.c → user/apps/c_unitest/test_uart.c

@@ -13,7 +13,7 @@ int main() {
     n = read(fd, buf, 1);
     close(fd);
     fd = open("/dev/char/uart:1088", O_WRONLY | O_NONBLOCK);
-    if (n != 0) {               // 添加字符串结束符
+    if (n != 0) {                    // 添加字符串结束符
       printf("Received: %s\n", buf); // 打印接收到的数据
       if (buf[0] == 'g') {
         break;

+ 11 - 0
user/apps/c_unitest/test_utimensat.c

@@ -0,0 +1,11 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main() {
+  int res = utimensat(AT_FDCWD, "/bin/about.elf", NULL, 0);
+  printf("utimensat res = %d\n", res);
+}

+ 0 - 1
user/apps/dmesg/.gitignore

@@ -1 +0,0 @@
-dmesg

+ 0 - 20
user/apps/dmesg/Makefile

@@ -1,20 +0,0 @@
-ifeq ($(ARCH), x86_64)
-	CROSS_COMPILE=x86_64-linux-musl-
-else ifeq ($(ARCH), riscv64)
-	CROSS_COMPILE=riscv64-linux-musl-
-endif
-
-CC=$(CROSS_COMPILE)gcc
-
-
-all: main.c dmesg.c
-	$(CC) -static -o dmesg main.c dmesg.c
-
-.PHONY: install clean
-install: all
-	mv dmesg $(DADK_CURRENT_BUILD_DIR)/dmesg
-
-clean:
-	rm dmesg *.o
-
-fmt:

+ 0 - 88
user/apps/dmesg/dmesg.c

@@ -1,88 +0,0 @@
-#include "dmesg.h"
-#include <stdio.h>
-#include <string.h>
-
-/**
- * @brief 识别dmesg程序的第一个选项参数
- *
- * @param arg dmesg命令第一个选项参数
- * @return int 有效时返回对应选项码,无效时返回 -1
- */
-int getoption(char *arg)
-{
-    if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
-        return 0;
-    else if (!strcmp(arg, "-c") || !strcmp(arg, "--read-clear"))
-        return 4;
-    else if (!strcmp(arg, "-C") || !strcmp(arg, "--clear"))
-        return 5;
-    else if (!strcmp(arg, "-l") || !strcmp(arg, "--level"))
-        return 8;
-
-    return -1;
-}
-
-/**
- * @brief 识别dmesg程序的第二个选项参数
- *
- * @param arg dmesg命令第一个选项参数
- * @return int 有效时返回设置的日志级别,无效时返回 -1
- */
-int getlevel(char *arg)
-{
-    if (!strcmp(arg, "EMERG") || !strcmp(arg, "emerg"))
-        return 0;
-    else if (!strcmp(arg, "ALERT") || !strcmp(arg, "alert"))
-        return 1;
-    else if (!strcmp(arg, "CRIT") || !strcmp(arg, "crit"))
-        return 2;
-    else if (!strcmp(arg, "ERR") || !strcmp(arg, "err"))
-        return 3;
-    else if (!strcmp(arg, "WARN") || !strcmp(arg, "warn"))
-        return 4;
-    else if (!strcmp(arg, "NOTICE") || !strcmp(arg, "notice"))
-        return 5;
-    else if (!strcmp(arg, "INFO") || !strcmp(arg, "info"))
-        return 6;
-    else if (!strcmp(arg, "DEBUG") || !strcmp(arg, "debug"))
-        return 7;
-    else
-    {
-        printf("dmesg: unknown level '%s'\n", arg);
-    }
-    return -2;
-}
-
-/**
- * @brief 打印dmesg手册
- */
-void print_help_msg()
-{
-    const char *help_msg = "Usage:\n"
-                           " dmesg [options]\n\n"
-                           "Display or control the kernel ring buffer.\n\n"
-                           "Options:\n"
-                           " -C, --clear                 clear the kernel ring buffer\n"
-                           " -c, --read-clear            read and clear all messages\n"
-                           " -l, --level <list>          restrict output to defined levels\n"
-                           " -h, --help                  display this help\n\n"
-                           "Supported log levels (priorities):\n"
-                           "   emerg - system is unusable\n"
-                           "   alert - action must be taken immediately\n"
-                           "    crit - critical conditions\n"
-                           "     err - error conditions\n"
-                           "    warn - warning conditions\n"
-                           "  notice - normal but significant condition\n"
-                           "    info - informational\n"
-                           "   debug - debug-level messages\n";
-    printf("%s\n", help_msg);
-}
-
-/**
- * @brief 打印dmesg错误使用的信息
- */
-void print_bad_usage_msg()
-{
-    const char *bad_usage_msg = "dmesg: bad usage\nTry 'dmesg --help' for more information.";
-    printf("%s\n", bad_usage_msg);
-}

+ 0 - 27
user/apps/dmesg/dmesg.h

@@ -1,27 +0,0 @@
-#pragma once
-
-/**
- * @brief 识别dmesg程序的第一个选项参数
- *
- * @param arg dmesg命令第一个选项参数
- * @return int 有效时返回对应选项码,无效时返回 -1
- */
-int getoption(char *arg);
-
-/**
- * @brief 识别dmesg程序的第二个选项参数
- *
- * @param arg dmesg命令第一个选项参数
- * @return int 有效时返回设置的日志级别,无效时返回 -1
- */
-int getlevel(char *arg);
-
-/**
- * @brief 打印dmesg手册
- */
-void print_help_msg();
-
-/**
- * @brief 打印dmesg错误使用的信息
- */
-void print_bad_usage_msg();

+ 0 - 117
user/apps/dmesg/main.c

@@ -1,117 +0,0 @@
-#include "dmesg.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/klog.h>
-#include <unistd.h>
-
-int main(int argc, char **argv)
-{
-    unsigned int len = 1;
-    char *buf = NULL;
-    int opt;
-    unsigned int color = 65280;
-
-    // 获取内核缓冲区大小
-    len = klogctl(10, buf, len);
-
-    if (len < 16 * 1024)
-        len = 16 * 1024;
-    if (len > 16 * 1024 * 1024)
-        len = 16 * 1024 * 1024;
-
-    buf = malloc(len);
-    if (buf == NULL)
-    {
-        perror("");
-        return -1;
-    }
-
-    if (argc == 1)
-    {
-        // 无选项参数,默认打印所有日志消息
-        len = klogctl(2, buf, len);
-    }
-    else
-    {
-        // 获取第一个选项参数
-        opt = getoption(argv[1]);
-
-        // 无效参数
-        if (opt == -1)
-        {
-            print_bad_usage_msg();
-            return -1;
-        }
-        // 打印帮助手册
-        else if (opt == 0)
-        {
-            print_help_msg();
-            return 0;
-        }
-        // 4 -> 读取内核缓冲区后,清空缓冲区
-        // 5 -> 清空内核缓冲区
-        else if (opt == 4 || opt == 5)
-        {
-            len = klogctl(opt, buf, len);
-        }
-        // 读取特定日志级别的消息
-        else if (opt == 8)
-        {
-            // 无指定日志级别参数,打印错误使用信息
-            if (argc < 3)
-            {
-                print_bad_usage_msg();
-                return -1;
-            }
-
-            int level = -1;
-
-            // 获取日志级别
-            // 这里加1的原因是:如果klogctl的第三个参数是0,不会发生系统调用
-            level = getlevel(argv[2]) + 1;
-
-            if (level == -1)
-                return -1;
-
-            klogctl(8, buf, level);
-            len = klogctl(2, buf, len);
-        }
-    }
-
-    // 当前打印内容
-    // 0: 日志级别
-    // 1: 时间戳
-    // 2: 代码行号
-    // 3: 日志消息
-    unsigned int content = 0;
-    for (int i = 0; i < len; i++)
-    {
-        char c[2];
-        c[0] = buf[i];
-        c[1] = '\0';
-        syscall(100000, &c[0], color, 0);
-        if (content == 0 && buf[i] == '>')
-        {
-            content++;
-        }
-        else if (content == 1 && buf[i] == ']')
-        {
-            color = 16744448;
-            content++;
-        }
-        else if (content == 2 && buf[i] == ')')
-        {
-            color = 16777215;
-            content++;
-        }
-        else if (content == 3 && buf[i] == '\n')
-        {
-            color = 65280;
-            content = 0;
-        }
-    }
-
-    free(buf);
-
-    return 0;
-}

+ 0 - 1
user/apps/http_server/.gitignore

@@ -1 +0,0 @@
-http_server

+ 0 - 20
user/apps/http_server/Makefile

@@ -1,20 +0,0 @@
-ifeq ($(ARCH), x86_64)
-	CROSS_COMPILE=x86_64-linux-musl-
-else ifeq ($(ARCH), riscv64)
-	CROSS_COMPILE=riscv64-linux-musl-
-endif
-
-CC=$(CROSS_COMPILE)gcc
-
-.PHONY: all
-all: main.c
-	$(CC) -static -o http_server main.c
-
-.PHONY: install clean
-install: all
-	mv http_server $(DADK_CURRENT_BUILD_DIR)/http_server
-
-clean:
-	rm http_server *.o
-
-fmt:

+ 0 - 240
user/apps/http_server/main.c

@@ -1,240 +0,0 @@
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#define PORT 12580
-#define MAX_REQUEST_SIZE 1500
-#define MAX_RESPONSE_SIZE 1500
-// 网页根目录
-#define WEB_ROOT "/var/www/html/"
-#define EXIT_CODE 1
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-#define DEFAULT_PAGE "/index.html"
-
-int security_check(char *path)
-{
-    // 检查路径是否包含 ..
-    if (strstr(path, ".."))
-    {
-        return 0;
-    }
-    return 1;
-}
-
-ssize_t send_response(int sockfd, char *response)
-{
-    return write(sockfd, response, strlen(response));
-}
-
-void send_header(int sockfd, int content_length, char *path)
-{
-    char buffer[MAX_RESPONSE_SIZE];
-    // 获取文件类型
-    char *content_type;
-    if (strstr(path, ".html"))
-    {
-        content_type = "text/html";
-    }
-    else if (strstr(path, ".css"))
-    {
-        content_type = "text/css";
-    }
-    else if (strstr(path, ".js"))
-    {
-        content_type = "application/javascript";
-    }
-    else if (strstr(path, ".png"))
-    {
-        content_type = "image/png";
-    }
-    else if (strstr(path, ".jpg"))
-    {
-        content_type = "image/jpeg";
-    }
-    else if (strstr(path, ".gif"))
-    {
-        content_type = "image/gif";
-    }
-    else
-    {
-        content_type = "text/plain;charset=utf-8";
-    }
-    sprintf(buffer, "HTTP/1.1 200 OK\nContent-Type: %s\nContent-Length: %d\n\n", content_type, content_length);
-    send_response(sockfd, buffer);
-}
-
-void send_file(int sockfd, char *path)
-{
-    printf("send_file: path: %s\n", path);
-
-    int fd = open(path, 0);
-    if (fd == -1)
-    {
-        send_response(
-            sockfd,
-            "HTTP/1.1 404 Not Found\nContent-Type: text/html\n\n<html><body><h1>404 Not Found</h1><p>DragonOS Http Server</p></body></html>");
-        return;
-    }
-
-    int content_length = lseek(fd, 0, SEEK_END);
-    int remaining = content_length;
-    printf("send_file: content_length: %d\n", content_length);
-    lseek(fd, 0, SEEK_SET);
-    send_header(sockfd, content_length, path);
-
-    char buffer[1048576];
-    int readSize;
-    while (remaining)
-    {
-        // 由于磁盘IO耗时较长,所以每次读取1MB,然后再分批发送
-        int to_read = min(1048576, remaining);
-        readSize = read(fd, &buffer, to_read);
-
-        remaining -= readSize;
-        void *p = buffer;
-        while (readSize > 0)
-        {
-            int wsize = write(sockfd, p, min(readSize, MAX_RESPONSE_SIZE));
-            if (wsize <= 0)
-            {
-                printf("send_file failed: wsize: %d\n", wsize);
-                close(fd);
-                return;
-            }
-            p += wsize;
-            readSize -= wsize;
-        }
-    }
-
-    close(fd);
-}
-
-void handle_request(int sockfd, char *request)
-{
-    char *method, *url, *http_version;
-    char path[MAX_REQUEST_SIZE];
-
-    method = strtok(request, " ");
-    url = strtok(NULL, " ");
-    http_version = strtok(NULL, "\r\n");
-    
-    printf("handle_request: method: %s, url: %s, http_version: %s\n", method, url, http_version);
-    // 检查空指针等异常情况
-    if (method == NULL || url == NULL || http_version == NULL)
-    {
-        send_response(sockfd, "HTTP/1.1 400 Bad Request\nContent-Type: text/html\n\n<html><body><h1>400 Bad "
-                              "Request</h1><p>DragonOS Http Server</p></body></html>");
-        return;
-    }
-    // 检查url是否为空
-    if (strlen(url) == 0)
-    {
-        send_response(sockfd, "HTTP/1.1 400 Bad Request\nContent-Type: text/html\n\n<html><body><h1>400 Bad "
-                              "Request</h1><p>DragonOS Http Server</p></body></html>");
-        return;
-    }
-    int default_page = 0;
-    if (url[strlen(url) - 1] == '/')
-    {
-        default_page = 1;
-    }
-
-    if (strcmp(method, "GET") == 0)
-    {
-        if (default_page)
-        {
-            sprintf(path, "%s%s%s", WEB_ROOT, url, DEFAULT_PAGE);
-        }
-        else
-        {
-            sprintf(path, "%s%s", WEB_ROOT, url);
-        }
-        if (!security_check(path))
-        {
-            send_response(
-                sockfd,
-                "HTTP/1.1 403 Forbidden\nContent-Type: text/html\n\n<html><body><h1>403 Forbidden</h1><p>DragonOS Http Server</p></body></html>");
-            return;
-        }
-        send_file(sockfd, path);
-    }
-    else
-    {
-        send_response(sockfd, "HTTP/1.1 501 Not Implemented\nContent-Type: text/html\n\n<html><body><h1>501 Not "
-                              "Implemented</h1><p>DragonOS Http Server</p></body></html>");
-    }
-}
-
-int main(int argc, char const *argv[])
-{
-    int server_fd, new_socket, valread;
-    struct sockaddr_in address;
-    int addrlen = sizeof(address);
-    char buffer[MAX_REQUEST_SIZE] = {0};
-    int opt = 1;
-
-    // 创建socket
-    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
-    {
-        perror("socket failed");
-        exit(EXIT_CODE);
-    }
-
-    // 设置socket选项,允许地址重用
-    // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
-    // {
-    //     perror("setsockopt failed");
-    //     exit(EXIT_CODE);
-    // }
-
-    // 设置地址和端口
-    address.sin_family = AF_INET;
-    address.sin_addr.s_addr = INADDR_ANY;
-    address.sin_port = htons(PORT);
-
-    // 把socket绑定到地址和端口上
-    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
-    {
-        perror("bind failed");
-        exit(EXIT_CODE);
-    }
-
-    // 监听socket
-    if (listen(server_fd, 3) < 0)
-    {
-        perror("listen failed");
-        exit(EXIT_CODE);
-    }
-
-    while (1)
-    {
-        printf("Waiting for a client...\n");
-
-        // 等待并接受客户端连接
-        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
-        {
-            perror("accept failed");
-            exit(EXIT_CODE);
-        }
-
-        // 接收客户端消息
-        valread = read(new_socket, buffer, MAX_REQUEST_SIZE);
-        printf("%s\n", buffer);
-
-        // 处理请求
-        handle_request(new_socket, buffer);
-
-        // 关闭客户端连接
-        close(new_socket);
-    }
-    // 关闭tcp socket
-    close(server_fd);
-
-    return 0;
-}

+ 2 - 0
user/apps/r_unitest/.cargo/config.toml

@@ -0,0 +1,2 @@
+[target.riscv64gc-unknown-linux-musl]
+linker = "riscv64-linux-gnu-gcc"

+ 1 - 0
user/apps/r_unitest/.gitignore

@@ -0,0 +1 @@
+target/*

+ 2413 - 0
user/apps/r_unitest/Cargo.lock

@@ -0,0 +1,2413 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "actix-codec"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570"
+dependencies = [
+ "bitflags 1.3.2",
+ "bytes 0.5.6",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project 0.4.30",
+ "tokio 0.2.25",
+ "tokio-util",
+]
+
+[[package]]
+name = "actix-connect"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "177837a10863f15ba8d3ae3ec12fac1099099529ed20083a27fdfe247381d0dc"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "derive_more",
+ "either",
+ "futures-util",
+ "http",
+ "log",
+ "trust-dns-proto",
+ "trust-dns-resolver",
+]
+
+[[package]]
+name = "actix-http"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2be6b66b62a794a8e6d366ac9415bb7d475ffd1e9f4671f38c1d8a8a5df950b3"
+dependencies = [
+ "actix-codec",
+ "actix-connect",
+ "actix-rt",
+ "actix-service",
+ "actix-threadpool",
+ "actix-utils",
+ "base64 0.13.1",
+ "bitflags 1.3.2",
+ "bytes 0.5.6",
+ "cookie",
+ "copyless",
+ "derive_more",
+ "either",
+ "encoding_rs",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "fxhash",
+ "h2",
+ "http",
+ "httparse",
+ "indexmap",
+ "itoa 0.4.8",
+ "language-tags",
+ "lazy_static",
+ "log",
+ "mime",
+ "percent-encoding",
+ "pin-project 1.1.10",
+ "rand",
+ "regex",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sha-1",
+ "slab",
+ "time",
+]
+
+[[package]]
+name = "actix-macros"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "actix-router"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ad299af73649e1fc893e333ccf86f377751eb95ff875d095131574c6f43452c"
+dependencies = [
+ "bytestring",
+ "http",
+ "log",
+ "regex",
+ "serde",
+]
+
+[[package]]
+name = "actix-rt"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227"
+dependencies = [
+ "actix-macros",
+ "actix-threadpool",
+ "copyless",
+ "futures-channel",
+ "futures-util",
+ "smallvec",
+ "tokio 0.2.25",
+]
+
+[[package]]
+name = "actix-server"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45407e6e672ca24784baa667c5d32ef109ccdd8d5e0b5ebb9ef8a67f4dfb708e"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "futures-channel",
+ "futures-util",
+ "log",
+ "mio 0.6.23",
+ "mio-uds",
+ "num_cpus",
+ "slab",
+ "socket2 0.3.19",
+]
+
+[[package]]
+name = "actix-service"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb"
+dependencies = [
+ "futures-util",
+ "pin-project 0.4.30",
+]
+
+[[package]]
+name = "actix-testing"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c"
+dependencies = [
+ "actix-macros",
+ "actix-rt",
+ "actix-server",
+ "actix-service",
+ "log",
+ "socket2 0.3.19",
+]
+
+[[package]]
+name = "actix-threadpool"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30"
+dependencies = [
+ "derive_more",
+ "futures-channel",
+ "lazy_static",
+ "log",
+ "num_cpus",
+ "parking_lot",
+ "threadpool",
+]
+
+[[package]]
+name = "actix-tls"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24789b7d7361cf5503a504ebe1c10806896f61e96eca9a7350e23001aca715fb"
+dependencies = [
+ "actix-codec",
+ "actix-service",
+ "actix-utils",
+ "futures-util",
+]
+
+[[package]]
+name = "actix-utils"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e9022dec56632d1d7979e59af14f0597a28a830a9c1c7fec8b2327eb9f16b5a"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "bitflags 1.3.2",
+ "bytes 0.5.6",
+ "either",
+ "futures-channel",
+ "futures-sink",
+ "futures-util",
+ "log",
+ "pin-project 0.4.30",
+ "slab",
+]
+
+[[package]]
+name = "actix-web"
+version = "3.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6534a126df581caf443ba2751cab42092c89b3f1d06a9d829b1e17edfe3e277"
+dependencies = [
+ "actix-codec",
+ "actix-http",
+ "actix-macros",
+ "actix-router",
+ "actix-rt",
+ "actix-server",
+ "actix-service",
+ "actix-testing",
+ "actix-threadpool",
+ "actix-tls",
+ "actix-utils",
+ "actix-web-codegen",
+ "awc",
+ "bytes 0.5.6",
+ "derive_more",
+ "encoding_rs",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "fxhash",
+ "log",
+ "mime",
+ "pin-project 1.1.10",
+ "regex",
+ "rustls",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "socket2 0.3.19",
+ "time",
+ "tinyvec",
+ "url",
+]
+
+[[package]]
+name = "actix-web-codegen"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "addr2line"
+version = "0.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler2"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.88"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "awc"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b381e490e7b0cfc37ebc54079b0413d8093ef43d14a4e4747083f7fa47a9e691"
+dependencies = [
+ "actix-codec",
+ "actix-http",
+ "actix-rt",
+ "actix-service",
+ "base64 0.13.1",
+ "bytes 0.5.6",
+ "cfg-if 1.0.1",
+ "derive_more",
+ "futures-core",
+ "log",
+ "mime",
+ "percent-encoding",
+ "rand",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
+dependencies = [
+ "addr2line",
+ "cfg-if 1.0.1",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "base-x"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
+
+[[package]]
+name = "base64"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "bytes"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+
+[[package]]
+name = "bytes"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+
+[[package]]
+name = "bytestring"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f"
+dependencies = [
+ "bytes 1.10.1",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
+
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
+[[package]]
+name = "const_fn"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f8a2ca5ac02d09563609681103aada9e1777d54fc57a5acd7a41404f9c93b6e"
+
+[[package]]
+name = "convert_case"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+
+[[package]]
+name = "cookie"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951"
+dependencies = [
+ "percent-encoding",
+ "time",
+ "version_check",
+]
+
+[[package]]
+name = "copyless"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "rustc_version 0.4.1",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "discard"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
+
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "encoding_rs"
+version = "0.8.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
+dependencies = [
+ "cfg-if 1.0.1",
+]
+
+[[package]]
+name = "enum-as-inner"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
+dependencies = [
+ "libc",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+dependencies = [
+ "bitflags 1.3.2",
+ "fuchsia-zircon-sys",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+
+[[package]]
+name = "futures"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
+
+[[package]]
+name = "futures-io"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
+
+[[package]]
+name = "futures-task"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+
+[[package]]
+name = "futures-util"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite 0.2.16",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if 1.0.1",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "gimli"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+
+[[package]]
+name = "h2"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535"
+dependencies = [
+ "bytes 0.5.6",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio 0.2.25",
+ "tokio-util",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "hermit-abi"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
+
+[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes 1.10.1",
+ "fnv",
+ "itoa 1.0.15",
+]
+
+[[package]]
+name = "httparse"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+
+[[package]]
+name = "icu_collections"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
+dependencies = [
+ "displaydoc",
+ "potential_utf",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locale_core"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
+
+[[package]]
+name = "icu_properties"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locale_core",
+ "icu_properties_data",
+ "icu_provider",
+ "potential_utf",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
+
+[[package]]
+name = "icu_provider"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
+dependencies = [
+ "displaydoc",
+ "icu_locale_core",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "idna"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "idna"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
+dependencies = [
+ "cfg-if 1.0.1",
+]
+
+[[package]]
+name = "io-uring"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
+dependencies = [
+ "bitflags 2.9.1",
+ "cfg-if 1.0.1",
+ "libc",
+]
+
+[[package]]
+name = "iovec"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "ipconfig"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
+dependencies = [
+ "socket2 0.3.19",
+ "widestring",
+ "winapi 0.3.9",
+ "winreg",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
+
+[[package]]
+name = "itoa"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
+[[package]]
+name = "js-sys"
+version = "0.3.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "language-tags"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.174"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
+name = "litemap"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
+
+[[package]]
+name = "lock_api"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+
+[[package]]
+name = "lru-cache"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
+
+[[package]]
+name = "memchr"
+version = "2.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "mio"
+version = "0.6.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
+dependencies = [
+ "cfg-if 0.1.10",
+ "fuchsia-zircon",
+ "fuchsia-zircon-sys",
+ "iovec",
+ "kernel32-sys",
+ "libc",
+ "log",
+ "miow",
+ "net2",
+ "slab",
+ "winapi 0.2.8",
+]
+
+[[package]]
+name = "mio"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
+dependencies = [
+ "libc",
+ "wasi 0.11.1+wasi-snapshot-preview1",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "mio-uds"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
+dependencies = [
+ "iovec",
+ "libc",
+ "mio 0.6.23",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
+dependencies = [
+ "kernel32-sys",
+ "net2",
+ "winapi 0.2.8",
+ "ws2_32-sys",
+]
+
+[[package]]
+name = "net2"
+version = "0.2.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac"
+dependencies = [
+ "cfg-if 0.1.10",
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "nix"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
+dependencies = [
+ "bitflags 2.9.1",
+ "cfg-if 1.0.1",
+ "cfg_aliases",
+ "libc",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.36.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "opaque-debug"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
+dependencies = [
+ "cfg-if 1.0.1",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pin-project"
+version = "0.4.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ef0f924a5ee7ea9cbcea77529dba45f8a9ba9f622419fe3386ca581a3ae9d5a"
+dependencies = [
+ "pin-project-internal 0.4.30",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
+dependencies = [
+ "pin-project-internal 1.1.10",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "0.4.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "potential_utf"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
+dependencies = [
+ "zerovec",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.20+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r_unitest"
+version = "0.1.0"
+dependencies = [
+ "actix-web",
+ "errno",
+ "libc",
+ "nix",
+ "sc",
+ "syscalls",
+ "tokio 1.46.1",
+]
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom",
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "resolv-conf"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3"
+
+[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver 0.9.0",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver 1.0.26",
+]
+
+[[package]]
+name = "rustls"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81"
+dependencies = [
+ "base64 0.12.3",
+ "log",
+ "ring",
+ "sct",
+ "webpki",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
+
+[[package]]
+name = "ryu"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+
+[[package]]
+name = "sc"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "010e18bd3bfd1d45a7e666b236c78720df0d9a7698ebaa9c1c559961eb60a38b"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "sct"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "serde"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.141"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
+dependencies = [
+ "itoa 1.0.15",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_repr"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa 1.0.15",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha-1"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
+dependencies = [
+ "block-buffer",
+ "cfg-if 1.0.1",
+ "cpufeatures",
+ "digest",
+ "opaque-debug",
+]
+
+[[package]]
+name = "sha1"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
+dependencies = [
+ "sha1_smol",
+]
+
+[[package]]
+name = "sha1_smol"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "socket2"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
+dependencies = [
+ "cfg-if 1.0.1",
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "socket2"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "standback"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "stdweb"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
+dependencies = [
+ "discard",
+ "rustc_version 0.2.3",
+ "stdweb-derive",
+ "stdweb-internal-macros",
+ "stdweb-internal-runtime",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "stdweb-derive"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_derive",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "stdweb-internal-macros"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
+dependencies = [
+ "base-x",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "sha1",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "stdweb-internal-runtime"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "syscalls"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43d0e35dc7d73976a53c7e6d7d177ef804a0c0ee774ec77bcc520c2216fd7cbe"
+dependencies = [
+ "serde",
+ "serde_repr",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "threadpool"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
+dependencies = [
+ "num_cpus",
+]
+
+[[package]]
+name = "time"
+version = "0.2.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
+dependencies = [
+ "const_fn",
+ "libc",
+ "standback",
+ "stdweb",
+ "time-macros",
+ "version_check",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "time-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
+dependencies = [
+ "proc-macro-hack",
+ "time-macros-impl",
+]
+
+[[package]]
+name = "time-macros-impl"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "standback",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "tinystr"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "0.2.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092"
+dependencies = [
+ "bytes 0.5.6",
+ "futures-core",
+ "iovec",
+ "lazy_static",
+ "libc",
+ "memchr",
+ "mio 0.6.23",
+ "mio-uds",
+ "pin-project-lite 0.1.12",
+ "signal-hook-registry",
+ "slab",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "tokio"
+version = "1.46.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
+dependencies = [
+ "backtrace",
+ "io-uring",
+ "libc",
+ "mio 1.0.4",
+ "pin-project-lite 0.2.16",
+ "signal-hook-registry",
+ "slab",
+ "socket2 0.5.10",
+ "tokio-macros",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
+dependencies = [
+ "bytes 0.5.6",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite 0.1.12",
+ "tokio 0.2.25",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
+dependencies = [
+ "log",
+ "pin-project-lite 0.2.16",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project 1.1.10",
+ "tracing",
+]
+
+[[package]]
+name = "trust-dns-proto"
+version = "0.19.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cad71a0c0d68ab9941d2fb6e82f8fb2e86d9945b94e1661dd0aaea2b88215a9"
+dependencies = [
+ "async-trait",
+ "cfg-if 1.0.1",
+ "enum-as-inner",
+ "futures",
+ "idna 0.2.3",
+ "lazy_static",
+ "log",
+ "rand",
+ "smallvec",
+ "thiserror",
+ "tokio 0.2.25",
+ "url",
+]
+
+[[package]]
+name = "trust-dns-resolver"
+version = "0.19.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "710f593b371175db53a26d0b38ed2978fafb9e9e8d3868b1acd753ea18df0ceb"
+dependencies = [
+ "cfg-if 0.1.10",
+ "futures",
+ "ipconfig",
+ "lazy_static",
+ "log",
+ "lru-cache",
+ "resolv-conf",
+ "smallvec",
+ "thiserror",
+ "tokio 0.2.25",
+ "trust-dns-proto",
+]
+
+[[package]]
+name = "typenum"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
+name = "url"
+version = "2.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
+dependencies = [
+ "form_urlencoded",
+ "idna 1.0.3",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
+dependencies = [
+ "cfg-if 1.0.1",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki"
+version = "0.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "widestring"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets 0.53.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm 0.52.6",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
+dependencies = [
+ "windows_aarch64_gnullvm 0.53.0",
+ "windows_aarch64_msvc 0.53.0",
+ "windows_i686_gnu 0.53.0",
+ "windows_i686_gnullvm 0.53.0",
+ "windows_i686_msvc 0.53.0",
+ "windows_x86_64_gnu 0.53.0",
+ "windows_x86_64_gnullvm 0.53.0",
+ "windows_x86_64_msvc 0.53.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+
+[[package]]
+name = "winreg"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "writeable"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
+
+[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "yoke"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+ "synstructure",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+ "synstructure",
+]
+
+[[package]]
+name = "zerotrie"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]

+ 15 - 0
user/apps/r_unitest/Cargo.toml

@@ -0,0 +1,15 @@
+[package]
+name = "r_unitest"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+libc = "0.2.0"
+nix = { version = "0.29.0", features = ["sched", "process"] }
+errno = "0.3.9"
+syscalls = '0.6.18'
+sc = "0.2.7"
+actix-web = { version = "3.0.0", default-features = false, features = [
+    "rust-tls",
+] }
+

+ 5 - 2
user/apps/test-for-robustfutex/Makefile → user/apps/r_unitest/Makefile

@@ -11,8 +11,9 @@ endif
 
 ifeq ($(ARCH), x86_64)
 	export RUST_TARGET=x86_64-unknown-linux-musl
+	export CC=x86_64-linux-musl-gcc
 else ifeq ($(ARCH), riscv64)
-	export RUST_TARGET=riscv64gc-unknown-linux-gnu
+	export RUST_TARGET=riscv64gc-unknown-linux-musl
 else 
 # 默认为x86_86,用于本地编译
 	export RUST_TARGET=x86_64-unknown-linux-musl
@@ -43,7 +44,7 @@ run-release:
 	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
 
 build-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build -Zbuild-std --target $(RUST_TARGET) --release
 
 clean-release:
 	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
@@ -54,3 +55,5 @@ test-release:
 .PHONY: install
 install:
 	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force
+	mv $(INSTALL_DIR)/bin/* $(INSTALL_DIR)/
+	rm $(INSTALL_DIR)/bin -d

+ 57 - 0
user/apps/r_unitest/src/bin/README.md

@@ -0,0 +1,57 @@
+# 部分测试描述
+
+## test-lo 
+
+lo网卡功能测试程序
+
+### 测试过程:
+
+通过创建一个UDP套接字,然后发送一条消息到本地回环地址127.0.0.1(lo网卡),再接收并验证这条消息,以此来测试lo网卡的功能。期望发送的消息和接收到的消息是完全一样的。通过日志输出查看测试是否成功。
+
+## test_alarm
+
+### 测试流程
+
+首先测试能否正常启用sysalarm系统调用,然后测试在上一个alarm未结束时调用alarm能否取消上一个,返回剩余时间,启动下一个alarm
+
+
+## test_backlog
+
+用于测试tcp的backlog功能的测试程序
+本程序绑定到0.0.0.0:12580端口,并在外部手动多线程请求这个端口来测试backlog功能
+
+### 使用方法
+
+1. 打开系统的/bin目录
+2. 输入指令exec test-backlog即可开始测试
+3. 可以在外部使用apifox进行多次请求,当请求数目超过backlog时会有几个请求失败
+
+
+## test_blockcache
+
+用于测试BlockCache的测试程序
+本程序生成一个文件,并开始对这个文件进行单纯的读操作(共读10000次)
+
+### 使用方法
+
+1. 打开系统的/bin目录
+2. 输入指令exec test-blockcache即可开始测试
+
+## test_chown
+
+一个简单的用于测试chown系列系统调用的程序
+
+由于symlink系统调用还未实现,目前只测试chown和fchown
+
+测试前需要手动添加nogroup用户组和nobody用户(程序里加不了)
+
+```groupadd -g 65534 nogroup
+useradd -d /nonexistent -g 65534 -u 65534 -s /usr/local/bin/false nobody
+```
+## test_robustfutex
+
+测试robust lock机制
+
+此代码主要是用于测试:
+1、robust lock机制中的两个系统调用是否能正常使用
+2、当持有锁的线程异常终止时,等待该锁的其他线程能够被通知到,以避免死锁或数据不一样

+ 0 - 0
user/apps/test_alarm/src/main.rs → user/apps/r_unitest/src/bin/test_alarm.rs


+ 0 - 0
user/apps/test-backlog/src/main.rs → user/apps/r_unitest/src/bin/test_backlog.rs


+ 2 - 2
user/apps/test-blockcache/src/main.rs → user/apps/r_unitest/src/bin/test_blockcache.rs

@@ -1,5 +1,5 @@
 use std::fs::File;
-use std::io::{BufReader, Read, Seek, SeekFrom, Write};
+use std::io::{Read, Seek, SeekFrom, Write};
 
 fn main() -> std::io::Result<()> {
     let file_size_bytes: u64 = 512;
@@ -13,7 +13,7 @@ fn main() -> std::io::Result<()> {
     loop {
         count += 1;
         file.seek(SeekFrom::Start(0))?;
-        let bytes_read = file.read_exact(&mut buffer)?;
+        file.read_exact(&mut buffer)?;
         if count > 10000 {
             break;
         }

+ 3 - 6
user/apps/test-chown/src/main.rs → user/apps/r_unitest/src/bin/test_chown.rs

@@ -6,12 +6,9 @@ use libc::{
 use nix::errno::Errno;
 use std::{
     ffi::CString,
-    fs::{self, metadata, File},
-    io::{self, Error, Write},
-    os::unix::{
-        fs::{MetadataExt, PermissionsExt},
-        io::AsRawFd,
-    },
+    fs::{self, File},
+    io::{Error, Write},
+    os::unix::{fs::MetadataExt, io::AsRawFd},
     path::Path,
 };
 

+ 0 - 0
user/apps/test_lo/src/main.rs → user/apps/r_unitest/src/bin/test_lo.rs


+ 1 - 1
user/apps/test-mount/src/main.rs → user/apps/r_unitest/src/bin/test_mount.rs

@@ -17,7 +17,7 @@ fn main() {
     let fstype = b"ramfs\0".as_ptr() as *const c_char;
     let flags = MS_BIND;
     let data = std::ptr::null() as *const c_void;
-    let result = unsafe { mount(source, target, fstype, flags, data) };
+    let _result = unsafe { mount(source, target, fstype, flags, data) };
     let path = Path::new("mnt/tmp/tmp");
     let dir = fs::create_dir_all(path);
     if dir.is_err() {

+ 0 - 0
user/apps/test-mount-ext4/src/main.rs → user/apps/r_unitest/src/bin/test_mount_ext4.rs


+ 0 - 0
user/apps/test-mount-fat/src/main.rs → user/apps/r_unitest/src/bin/test_mount_fat.rs


+ 0 - 0
user/apps/test_namespace/src/main.rs → user/apps/r_unitest/src/bin/test_namespace.rs


+ 0 - 0
user/apps/test-for-robustfutex/src/main.rs → user/apps/r_unitest/src/bin/test_robustfutex.rs


+ 87 - 0
user/apps/r_unitest/src/bin/test_socket.rs

@@ -0,0 +1,87 @@
+use test_unix_stream::test_unix_stream;
+use test_unix_stream_pair::test_unix_stream_pair;
+
+fn main() -> std::io::Result<()> {
+    if let Err(e) = test_unix_stream() {
+        println!("[ fault ] test_unix_stream, err: {}", e);
+    } else {
+        println!("[success] test_unix_stream");
+    }
+
+    if let Err(e) = test_unix_stream_pair() {
+        println!("[ fault ] test_unix_stream_pair, err: {}", e);
+    } else {
+        println!("[success] test_unix_stream_pair");
+    }
+
+    Ok(())
+}
+
+mod test_unix_stream_pair {
+    use std::io::{Error, Read, Write};
+    use std::os::unix::net::UnixStream;
+    use std::str;
+
+    const MSG: &str = "Hello, unix stream socketpair!";
+
+    pub fn test_unix_stream_pair() -> std::io::Result<()> {
+        let (mut sock0, mut sock1) = UnixStream::pair()?;
+
+        sock1.write_all(MSG.as_bytes())?;
+
+        let mut buffer = [0; 1024];
+        let nbytes = sock0.read(&mut buffer).expect("read error");
+        let received_msg = str::from_utf8(&buffer[..nbytes]).unwrap();
+
+        if received_msg == MSG {
+            Ok(())
+        } else {
+            Err(Error::from_raw_os_error(-1))
+        }
+    }
+}
+
+mod test_unix_stream {
+    use std::io::{Error, Read, Write};
+    use std::os::unix::net::{UnixListener, UnixStream};
+    use std::thread;
+    use std::{fs, str};
+
+    const SOCKET_PATH: &str = "/test.socket";
+    const MSG: &str = "Hello, unix stream socket!";
+
+    fn client() -> std::io::Result<()> {
+        // 连接到服务器
+        let mut stream = UnixStream::connect(SOCKET_PATH)?;
+        // 发送消息到服务器
+        stream.write_all(MSG.as_bytes())?;
+        Ok(())
+    }
+
+    pub fn test_unix_stream() -> std::io::Result<()> {
+        println!("unix stream socket path: {}", SOCKET_PATH);
+        // 删除可能已存在的socket文件
+        fs::remove_file(&SOCKET_PATH).ok();
+        // 创建Unix域监听socket
+        let listener = UnixListener::bind(SOCKET_PATH)?;
+
+        let client_thread = thread::spawn(move || client());
+
+        // 监听并接受连接
+        let (mut stream, _) = listener.accept().expect("listen error");
+
+        let mut buffer = [0; 1024];
+        let nbytes = stream.read(&mut buffer).expect("read error");
+        let received_msg = str::from_utf8(&buffer[..nbytes]).unwrap();
+
+        client_thread.join().ok();
+
+        fs::remove_file(&SOCKET_PATH).ok();
+
+        if received_msg == MSG {
+            Ok(())
+        } else {
+            Err(Error::from_raw_os_error(-1))
+        }
+    }
+}

+ 0 - 0
user/apps/test_statx/src/main.rs → user/apps/r_unitest/src/bin/test_statx.rs


+ 0 - 0
user/apps/test-symlink/src/main.rs → user/apps/r_unitest/src/bin/test_symlink.rs


+ 1 - 0
user/apps/r_unitest/src/lib.rs

@@ -0,0 +1 @@
+

+ 0 - 2
user/apps/test-backlog/.cargo/config.toml

@@ -1,2 +0,0 @@
-[build]
-target = "x86_64-unknown-linux-musl"

+ 0 - 3
user/apps/test-backlog/.gitignore

@@ -1,3 +0,0 @@
-/target
-Cargo.lock
-/install/

+ 0 - 12
user/apps/test-backlog/Cargo.toml

@@ -1,12 +0,0 @@
-[package]
-name = "test-backlog"
-version = "0.1.0"
-edition = "2021"
-description = "test the tcp backlog"
-authors = [ "saga" ]
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-actix-web={ version = "3.0.0",default-features = false,features=["rust-tls"] }
-

+ 0 - 57
user/apps/test-backlog/Makefile

@@ -1,57 +0,0 @@
-TOOLCHAIN="+nightly-2024-11-05-x86_64-unknown-linux-gnu"
-RUSTFLAGS+=""
-
-ifdef DADK_CURRENT_BUILD_DIR
-# 如果是在dadk中编译,那么安装到dadk的安装目录中
-	INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
-else
-# 如果是在本地编译,那么安装到当前目录下的install目录中
-	INSTALL_DIR = ./install
-endif
-
-ifeq ($(ARCH), x86_64)
-	export RUST_TARGET=x86_64-unknown-linux-musl
-	export CC=x86_64-linux-musl-gcc
-else ifeq ($(ARCH), riscv64)
-	export RUST_TARGET=riscv64gc-unknown-linux-gnu
-else 
-# 默认为x86_86,用于本地编译
-	export RUST_TARGET=x86_64-unknown-linux-musl
-endif
-
-run:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --features"rust-tls"
-
-build:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --features"rust-tls"
-
-clean:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)
-
-test:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)
-
-doc:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)
-
-fmt:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
-
-fmt-check:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
-
-run-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
-
-build-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
-
-clean-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
-
-test-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release
-
-.PHONY: install
-install:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

+ 0 - 9
user/apps/test-backlog/README.md

@@ -1,9 +0,0 @@
-## 程序说明
-用于测试tcp的backlog功能的测试程序
-本程序绑定到0.0.0.0:12580端口,并在外部手动多线程请求这个端口来测试backlog功能
-
-## 使用方法
-
-1. 打开系统的/bin目录
-2. 输入指令exec test-backlog即可开始测试
-3. 可以在外部使用apifox进行多次请求,当请求数目超过backlog时会有几个请求失败

+ 0 - 2
user/apps/test-blockcache/.cargo/config.toml

@@ -1,2 +0,0 @@
-[build]
-target = "x86_64-unknown-linux-musl"

+ 0 - 3
user/apps/test-blockcache/.gitignore

@@ -1,3 +0,0 @@
-/target
-Cargo.lock
-/install/

+ 0 - 10
user/apps/test-blockcache/Cargo.toml

@@ -1,10 +0,0 @@
-[package]
-name = "test-blockcache"
-version = "0.1.0"
-edition = "2021"
-description = "用于测试blockcac小程序"
-authors = [ "ZZJJWarth <2678328250@qq.com>" ]
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]

+ 0 - 41
user/apps/test-blockcache/Makefile

@@ -1,41 +0,0 @@
-# The toolchain we use.
-# You can get it by running DragonOS' `tools/bootstrap.sh`
-TOOLCHAIN="+nightly-2024-11-05-x86_64-unknown-linux-gnu"
-RUSTFLAGS+="-C target-feature=+crt-static -C link-arg=-no-pie"
-
-# 如果是在dadk中编译,那么安装到dadk的安装目录中
-INSTALL_DIR?=$(DADK_CURRENT_BUILD_DIR)
-# 如果是在本地编译,那么安装到当前目录下的install目录中
-INSTALL_DIR?=./install
-
-
-run:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run
-
-build:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build
-
-clean:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean
-
-test:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test
-
-doc:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc
-
-run-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --release
-
-build-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --release
-
-clean-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --release
-
-test-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --release
-
-.PHONY: install
-install: 
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --path . --no-track --root $(INSTALL_DIR) --force

+ 0 - 8
user/apps/test-blockcache/README.md

@@ -1,8 +0,0 @@
-## 程序说明
-用于测试BlockCache的测试程序
-本程序生成一个文件,并开始对这个文件进行单纯的读操作(共读10000次)
-
-## 使用方法
-
-1. 打开系统的/bin目录
-2. 输入指令exec test-blockcache即可开始测试

+ 0 - 4
user/apps/test-chown/.gitignore

@@ -1,4 +0,0 @@
-/target
-Cargo.lock
-testfile.txt
-/install/

+ 0 - 13
user/apps/test-chown/Cargo.toml

@@ -1,13 +0,0 @@
-[package]
-name = "test-chown"
-version = "0.1.0"
-edition = "2021"
-description = "测试chown系列系统调用"
-authors = [ "sparkzky <sparkhhhhhhhhhh@outlook.com>" ]
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-libc = "0.2"
-errno = "0.3.9"
-nix = "0.23"

+ 0 - 56
user/apps/test-chown/Makefile

@@ -1,56 +0,0 @@
-TOOLCHAIN=
-RUSTFLAGS=
-
-ifdef DADK_CURRENT_BUILD_DIR
-# 如果是在dadk中编译,那么安装到dadk的安装目录中
-	INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
-else
-# 如果是在本地编译,那么安装到当前目录下的install目录中
-	INSTALL_DIR = ./install
-endif
-
-ifeq ($(ARCH), x86_64)
-	export RUST_TARGET=x86_64-unknown-linux-musl
-else ifeq ($(ARCH), riscv64)
-	export RUST_TARGET=riscv64gc-unknown-linux-gnu
-else 
-# 默认为x86_86,用于本地编译
-	export RUST_TARGET=x86_64-unknown-linux-musl
-endif
-
-run:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET)
-
-build:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)
-
-clean:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)
-
-test:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)
-
-doc:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)
-
-fmt:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
-
-fmt-check:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
-
-run-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
-
-build-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
-
-clean-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
-
-test-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release
-
-.PHONY: install
-install:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

+ 0 - 8
user/apps/test-chown/README.md

@@ -1,8 +0,0 @@
-# 一个简单的用于测试chown系列系统调用的程序
-
-### 由于symlink系统调用还未实现,目前只测试chown和fchown
-
-### 测试前需要手动添加nogroup用户组和nobody用户(程序里加不了)
-```groupadd -g 65534 nogroup
-useradd -d /nonexistent -g 65534 -u 65534 -s /usr/local/bin/false nobody
-```

+ 0 - 2
user/apps/test-for-robustfutex/.cargo/config.toml

@@ -1,2 +0,0 @@
-[build]
-target = "x86_64-unknown-linux-musl"

+ 0 - 3
user/apps/test-for-robustfutex/.gitignore

@@ -1,3 +0,0 @@
-/target
-Cargo.lock
-/install/

+ 0 - 12
user/apps/test-for-robustfutex/Cargo.toml

@@ -1,12 +0,0 @@
-[package]
-name = "test-for-robustfutex"
-version = "0.1.0"
-edition = "2021"
-description = "some tests for robust futex"
-authors = [ "hmt <1037827920@qq.com>" ]
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-syscalls = '0.6.18'
-libc = '0.2.153'

+ 0 - 5
user/apps/test-for-robustfutex/README.md

@@ -1,5 +0,0 @@
-# 测试robust lock机制
-
-此代码主要是用于测试:
-1、robust lock机制中的两个系统调用是否能正常使用
-2、当持有锁的线程异常终止时,等待该锁的其他线程能够被通知到,以避免死锁或数据不一样

+ 0 - 1
user/apps/test-fork-wait/.gitignore

@@ -1 +0,0 @@
-test-fork-wait

+ 0 - 20
user/apps/test-fork-wait/Makefile

@@ -1,20 +0,0 @@
-ifeq ($(ARCH), x86_64)
-	CROSS_COMPILE=x86_64-linux-musl-
-else ifeq ($(ARCH), riscv64)
-	CROSS_COMPILE=riscv64-linux-musl-
-endif
-
-CC=$(CROSS_COMPILE)gcc
-BINFILE=test-fork-wait
-
-all: main.c
-	$(CC) -static -o $(BINFILE) main.c
-
-.PHONY: install clean
-install: all
-	mv $(BINFILE) $(DADK_CURRENT_BUILD_DIR)/
-
-clean:
-	rm $(BINFILE) *.o
-
-fmt:

+ 0 - 3
user/apps/test-mount-ext4/.gitignore

@@ -1,3 +0,0 @@
-/target
-Cargo.lock
-/install/

+ 0 - 12
user/apps/test-mount-ext4/Cargo.toml

@@ -1,12 +0,0 @@
-[package]
-name = "test-mount-ext4"
-version = "0.1.0"
-edition = "2021"
-description = "测试是否可以通过mount系统调用来挂载ext4类型的硬盘"
-authors = ["sparkzky <sparkhhhhhhhhhh@outlook.com>"]
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-errno = "0.3.9"
-libc = "0.2"

+ 0 - 56
user/apps/test-mount-ext4/Makefile

@@ -1,56 +0,0 @@
-TOOLCHAIN=
-RUSTFLAGS=
-
-ifdef DADK_CURRENT_BUILD_DIR
-# 如果是在dadk中编译,那么安装到dadk的安装目录中
-	INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
-else
-# 如果是在本地编译,那么安装到当前目录下的install目录中
-	INSTALL_DIR = ./install
-endif
-
-ifeq ($(ARCH), x86_64)
-	export RUST_TARGET=x86_64-unknown-linux-musl
-else ifeq ($(ARCH), riscv64)
-	export RUST_TARGET=riscv64gc-unknown-linux-gnu
-else 
-# 默认为x86_86,用于本地编译
-	export RUST_TARGET=x86_64-unknown-linux-musl
-endif
-
-run:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET)
-
-build:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)
-
-clean:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)
-
-test:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)
-
-doc:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)
-
-fmt:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
-
-fmt-check:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
-
-run-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
-
-build-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
-
-clean-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
-
-test-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release
-
-.PHONY: install
-install:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

+ 0 - 3
user/apps/test-mount-fat/.gitignore

@@ -1,3 +0,0 @@
-/target
-Cargo.lock
-/install/

+ 0 - 12
user/apps/test-mount-fat/Cargo.toml

@@ -1,12 +0,0 @@
-[package]
-name = "test-mount-fat"
-version = "0.1.0"
-edition = "2021"
-description = "测试fat的挂载"
-authors = ["sparkzky <sparkhhhhhhhhhh@outlook.com>"]
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-errno = "0.3.9"
-libc = "0.2"

+ 0 - 56
user/apps/test-mount-fat/Makefile

@@ -1,56 +0,0 @@
-TOOLCHAIN=
-RUSTFLAGS=
-
-ifdef DADK_CURRENT_BUILD_DIR
-# 如果是在dadk中编译,那么安装到dadk的安装目录中
-	INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
-else
-# 如果是在本地编译,那么安装到当前目录下的install目录中
-	INSTALL_DIR = ./install
-endif
-
-ifeq ($(ARCH), x86_64)
-	export RUST_TARGET=x86_64-unknown-linux-musl
-else ifeq ($(ARCH), riscv64)
-	export RUST_TARGET=riscv64gc-unknown-linux-gnu
-else 
-# 默认为x86_86,用于本地编译
-	export RUST_TARGET=x86_64-unknown-linux-musl
-endif
-
-run:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET)
-
-build:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)
-
-clean:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)
-
-test:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)
-
-doc:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)
-
-fmt:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
-
-fmt-check:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
-
-run-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
-
-build-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
-
-clean-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
-
-test-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release
-
-.PHONY: install
-install:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

+ 0 - 3
user/apps/test-mount/.gitignore

@@ -1,3 +0,0 @@
-/target
-Cargo.lock
-/install/

+ 0 - 12
user/apps/test-mount/Cargo.toml

@@ -1,12 +0,0 @@
-[package]
-name = "test-mount"
-version = "0.1.0"
-edition = "2021"
-description = "test the new mount syscall"
-authors = [ "xiaolin2004 <1553367438@qq.com>" ]
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-errno = "0.3.9"
-libc="0.2"

+ 0 - 56
user/apps/test-mount/Makefile

@@ -1,56 +0,0 @@
-TOOLCHAIN="+nightly-2024-11-05-x86_64-unknown-linux-gnu"
-RUSTFLAGS+=""
-
-ifdef DADK_CURRENT_BUILD_DIR
-# 如果是在dadk中编译,那么安装到dadk的安装目录中
-	INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
-else
-# 如果是在本地编译,那么安装到当前目录下的install目录中
-	INSTALL_DIR = ./install
-endif
-
-ifeq ($(ARCH), x86_64)
-	export RUST_TARGET=x86_64-unknown-linux-musl
-else ifeq ($(ARCH), riscv64)
-	export RUST_TARGET=riscv64gc-unknown-linux-gnu
-else 
-# 默认为x86_86,用于本地编译
-	export RUST_TARGET=x86_64-unknown-linux-musl
-endif
-
-run:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET)
-
-build:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)
-
-clean:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)
-
-test:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)
-
-doc:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)
-
-fmt:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
-
-fmt-check:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
-
-run-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
-
-build-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
-
-clean-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
-
-test-release:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release
-
-.PHONY: install
-install:
-	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

+ 0 - 3
user/apps/test-mount/README.md

@@ -1,3 +0,0 @@
-# test-mount
-
-用于测试mount系统调用的用户程序

+ 0 - 1
user/apps/test-processgroup/.gitignore

@@ -1 +0,0 @@
-test-processgroup

+ 0 - 20
user/apps/test-processgroup/Makefile

@@ -1,20 +0,0 @@
-ifeq ($(ARCH), x86_64)
-	CROSS_COMPILE=x86_64-linux-musl-
-else ifeq ($(ARCH), riscv64)
-	CROSS_COMPILE=riscv64-linux-musl-
-endif
-
-CC=$(CROSS_COMPILE)gcc
-
-
-all: main.c 
-	$(CC) -static -o test-processgroup main.c
-
-.PHONY: install clean
-install: all
-	mv test-processgroup $(DADK_CURRENT_BUILD_DIR)/test-processgroup
-
-clean:
-	rm test-processgroup *.o
-
-fmt:

+ 0 - 87
user/apps/test-processgroup/main.c

@@ -1,87 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#define TEST_ASSERT(left, right, success_msg, fail_msg)                        \
-    do {                                                                       \
-        if ((left) == (right)) {                                               \
-            printf("[PASS] %s\n", success_msg);                                \
-        } else {                                                               \
-            printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n",               \
-                   fail_msg,                                                   \
-                   (unsigned long)(right),                                     \
-                   (unsigned long)(left));                                     \
-        }                                                                      \
-    } while (0)
-
-
-
-// 打印进程信息
-void print_ids(const char *name) {
-    printf("[%s] PID=%d, PPID=%d, PGID=%d, SID=%d\n",
-           name,
-           getpid(),
-           getppid(),
-           getpgid(0),  // 获取当前进程的 PGID
-           getsid(0));  // 获取当前进程的 SID
-}
-
-int main() {
-    printf("===== 测试进程组 =====\n");
-    print_ids("Parent");
-
-    // 创建第一个子进程
-    pid_t child1 = fork();
-    if (child1 == 0) {
-        // 子进程1:设置自己的进程组
-        printf("\n[Child1] 子进程启动...\n");
-        print_ids("Child1 (before setpgid)");
-
-        if (setpgid(0, 0) == -1) {  // 将自己的 PGID 设置为自己的 PID
-            perror("setpgid failed");
-            exit(EXIT_FAILURE);
-        }
-
-        print_ids("Child1 (after setpgid)");
-
-        // Assert: PGID 应该等于 PID
-        // assert(getpgid(0) == getpid());
-        TEST_ASSERT(getpgid(0), getpid(), "Successfully set child1 as processgroup leader", "Child1 PGID check failed");
-
-        sleep(2);  // 保持运行,便于观察
-        exit(EXIT_SUCCESS);
-    }
-
-    // 创建第二个子进程
-    pid_t child2 = fork();
-    if (child2 == 0) {
-        // 子进程2:加入第一个子进程的进程组
-        printf("\n[Child2] 子进程启动...\n");
-        print_ids("Child2 (before setpgid)");
-
-        if (setpgid(0, child1) == -1) {  // 将自己的 PGID 设置为 child1 的 PID
-            perror("setpgid failed");
-            exit(EXIT_FAILURE);
-        }
-
-        print_ids("Child2 (after setpgid)");
-
-        // Assert: PGID 应该等于 child1 的 PID
-        // assert(getpgid(0) == child1);
-        TEST_ASSERT(getpgid(0),child1,"Child2 PGID is equal to Child1","Child2 PGID check failed");
-
-        sleep(2);  // 保持运行,便于观察
-        exit(EXIT_SUCCESS);
-    }
-
-    // 父进程:等待子进程结束
-    waitpid(child1, NULL, 0);
-    waitpid(child2, NULL, 0);
-
-    printf("\n[Parent] 所有子进程结束后...\n");
-    print_ids("Parent");
-
-    return 0;
-}

+ 0 - 1
user/apps/test-session/.gitignore

@@ -1 +0,0 @@
-test-session

+ 0 - 20
user/apps/test-session/Makefile

@@ -1,20 +0,0 @@
-ifeq ($(ARCH), x86_64)
-	CROSS_COMPILE=x86_64-linux-musl-
-else ifeq ($(ARCH), riscv64)
-	CROSS_COMPILE=riscv64-linux-musl-
-endif
-
-CC=$(CROSS_COMPILE)gcc
-
-
-all: main.c 
-	$(CC) -static -o test-session main.c
-
-.PHONY: install clean
-install: all
-	mv test-session $(DADK_CURRENT_BUILD_DIR)/test-session
-
-clean:
-	rm test-session *.o
-
-fmt:

部分文件因为文件数量过多而无法显示