diff --git a/.github/workflows/release_experimental.yml b/.github/workflows/release_experimental.yml index 4c81d76..5d220e9 100644 --- a/.github/workflows/release_experimental.yml +++ b/.github/workflows/release_experimental.yml @@ -1,9 +1,10 @@ -name: release latest with all library versions +name: release experimental with all library versions on: - pull_request: + push: branches: [ "dev/staging" ] + jobs: build: strategy: diff --git a/CMakeLists.txt b/CMakeLists.txt index f18cb68..0e043f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,11 @@ if(NEWLIB) ) add_dependencies(dlibc newlib) + # Additional headers / code needed to get libc to linux compatibility + set(LIBC_EXTENSION "c_extension") + add_subdirectory(libc_extension) + add_dependencies(${LIBC_EXTENSION} dlibc) + set(LLVM_C_FLAGS "-D_GNU_SOURCE=1") string(APPEND LLVM_C_FLAGS " -D_POSIX_TIMERS") string(APPEND LLVM_C_FLAGS " -D_POSIX_THREADS") @@ -208,7 +213,6 @@ if(NEWLIB) -DLLVM_INCLUDE_TESTS=OFF -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON -DCOMPILER_RT_BUILD_BUILTINS=ON - -DCOMPILER_RT_BAREMETAL_BUILD=ON -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_BUILD_LIBFUZZER=OFF -DCOMPILER_RT_BUILD_MEMPROF=OFF @@ -228,7 +232,7 @@ if(NEWLIB) -DLIBCXX_ENABLE_RANDOM_DEVICE=OFF -DLIBCXX_HAS_PTHREAD_API=ON ) - add_dependencies(llvmproject newlib) + add_dependencies(llvmproject newlib ${LIBC_EXTENSION}) # Create folder at configuration time to avoid issues with includes file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include/c++/v1) diff --git a/file_system/file_system.c b/file_system/file_system.c index 484ba8c..8a11607 100644 --- a/file_system/file_system.c +++ b/file_system/file_system.c @@ -51,8 +51,7 @@ D_File *create_directory(Path *name, uint32_t mode) { new_file->type = DIRECTORY; new_file->child = NULL; new_file->hard_links = 0; - // directory where user has full permissions - new_file->mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; + new_file->mode = mode | S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; return new_file; } @@ -61,6 +60,13 @@ int link_file_to_folder(D_File *folder, D_File *file) { // TODO set proper error number return -1; }; + + // Check if file already exists in this directory to prevent duplicates + D_File *existing = find_file_in_dir(folder, (Path){.path = file->name, .length = namelen(file->name, FS_NAME_LENGTH)}); + if (existing != NULL) { + return -1; + } + // set file parent to folder file->parent = folder; // increase the number of hard links to the file @@ -70,18 +76,24 @@ int link_file_to_folder(D_File *folder, D_File *file) { file->next = NULL; } else { D_File *current = folder->child; - if (namecmp(file->name, FS_NAME_LENGTH, current->name, FS_NAME_LENGTH) < - 0) { + int cmp_first = namecmp(file->name, FS_NAME_LENGTH, current->name, FS_NAME_LENGTH); + if (cmp_first < 0) { file->next = current; folder->child = file; + } else if (cmp_first == 0) { + file->hard_links -= 1; + return -1; } else { + // Find correct position to insert while (current->next != NULL) { - if (namecmp(file->name, FS_NAME_LENGTH, current->next->name, - FS_NAME_LENGTH) < 0) { + int cmp_next = namecmp(file->name, FS_NAME_LENGTH, current->next->name, FS_NAME_LENGTH); + if (cmp_next < 0) { break; - } else { - current = current->next; + } else if (cmp_next == 0) { + file->hard_links -= 1; + return -1; } + current = current->next; } file->next = current->next; current->next = file; @@ -163,11 +175,12 @@ D_File *create_directories(D_File *directory, Path path, char prevent_up) { directory = candidate_dir; continue; } - D_File *new_dir = dandelion_alloc(sizeof(D_File), _Alignof(D_File)); - new_dir->type = DIRECTORY; - memcpy(new_dir->name, current_path.path, current_path.length); - new_dir->name[current_path.length] = '\0'; - new_dir->child = NULL; + uint32_t dir_mode = S_IRUSR | S_IWUSR | S_IXUSR; + D_File *new_dir = create_directory(¤t_path, dir_mode); + if (new_dir == NULL) { + return NULL; + } + int error = link_file_to_folder(directory, new_dir); if (error < 0) { dandelion_free(new_dir); @@ -416,9 +429,12 @@ int fs_initialize(int *argc, char ***argv, char ***environ) { fs_root->parent = NULL; fs_root->child = NULL; fs_root->hard_links = 1; + // Set proper root directory mode + //fs_root->mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; // create stdio folder and stdout/stderr file - D_File *stdio_folder = dandelion_alloc(sizeof(D_File), _Alignof(D_File)); + Path stdio_path = path_from_string("stdio"); + D_File *stdio_folder = create_directory(&stdio_path, S_IRUSR | S_IWUSR | S_IXUSR); if (stdio_folder == NULL) { dandelion_exit(ENOMEM); return -1; diff --git a/libc_extension/CMakeLists.txt b/libc_extension/CMakeLists.txt new file mode 100644 index 0000000..cd5701d --- /dev/null +++ b/libc_extension/CMakeLists.txt @@ -0,0 +1,40 @@ +add_library(${LIBC_EXTENSION} STATIC) + +target_sources(${LIBC_EXTENSION} + PRIVATE + dirent.c + netdb.c + socket.c + uio.c + PUBLIC FILE_SET public_headers TYPE HEADERS + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include/ + FILES + include/netdb.h + include/sys/cpuset.h + include/sys/dirent.h + include/sys/mman.h + include/sys/sched.h + include/sys/socket.h + include/sys/statvfs.h + include/sys/uio.h +) + +if(CMAKE_BUILD_TYPE MATCHES "Debug") + target_compile_definitions(${LIBC_EXTENSION} PRIVATE DEBUG) + target_compile_options(${LIBC_EXTENSION} PRIVATE -g) +endif() + +target_link_libraries(${LIBC_EXTENSION} PRIVATE dlibc) + +include(GNUInstallDirs) +install(TARGETS ${LIBC_EXTENSION} + ARCHIVE FILE_SET public_headers + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ +) + +# always install after building, so the headers are available for libcxx +add_custom_command( + TARGET ${LIBC_EXTENSION} + POST_BUILD + COMMAND ${CMAKE_COMMAND} --install ${CMAKE_CURRENT_BINARY_DIR} +) \ No newline at end of file diff --git a/newlib_shim/dirent.c b/libc_extension/dirent.c similarity index 97% rename from newlib_shim/dirent.c rename to libc_extension/dirent.c index f795cdf..c23212e 100644 --- a/newlib_shim/dirent.c +++ b/libc_extension/dirent.c @@ -51,3 +51,6 @@ long int telldir(DIR *dir) { extern void dandelion_seekdir(DIR *dir, long int index); void seekdir(DIR *dir, long int index) { return dandelion_seekdir(dir, index); } +int dirfd(DIR *dirp) { + return -1; +} diff --git a/libc_extension/include/netdb.h b/libc_extension/include/netdb.h new file mode 100644 index 0000000..7e6c133 --- /dev/null +++ b/libc_extension/include/netdb.h @@ -0,0 +1,75 @@ +#ifndef _NETDB_H +#define _NETDB_H 1 + +#include +#include + +/* Description of data base entry for a single host. */ +struct hostent +{ + char *h_name; /* Official name of host. */ + char **h_aliases; /* Alias list. */ + int h_addrtype; /* Host address type. */ + int h_length; /* Length of address. */ + char **h_addr_list; /* List of addresses from name server. */ +}; + +/* Description of data base entry for a single network. NOTE: here a + poor assumption is made. The network number is expected to fit + into an unsigned long int variable. */ +struct netent +{ + char *n_name; /* Official name of network. */ + char **n_aliases; /* Alias list. */ + int n_addrtype; /* Net address type. */ + uint32_t n_net; /* Network number. */ +}; + +/* Description of data base entry for a single service. */ +struct protoent +{ + char *p_name; /* Official protocol name. */ + char **p_aliases; /* Alias list. */ + int p_proto; /* Protocol number. */ +}; + +/* Description of data base entry for a single service. */ +struct servent +{ + char *s_name; /* Official service name. */ + char **s_aliases; /* Alias list. */ + int s_port; /* Port number. */ + char *s_proto; /* Protocol to use. */ +}; + +# define IPPORT_RESERVED 1024 + +extern int h_errno; + +# define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */ +# define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */ +# define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */ +# define NO_DATA 4 /* Valid name, no data record of requested type. */ + +extern void endhostent (void); +extern void endnetent (void); +extern void endprotoent (void); +extern void endservent (void); +extern struct hostent *gethostbyaddr (const void *__addr, __socklen_t __len, int __type); +extern struct hostent *gethostbyname (const char *__name); +extern struct hostent *gethostent (void); +extern struct netent *getnetbyaddr (uint32_t __net, int __type); +extern struct netent *getnetbyname (const char *__name); +extern struct netent *getnetent (void); +extern struct protoent *getprotobyname (const char *__name); +extern struct protoent *getprotobynumber (int __proto); +extern struct protoent *getprotoent (void); +extern struct servent *getservbyname (const char *__name, const char *__proto); +extern struct servent *getservbyport (int __port, const char *__proto); +extern struct servent *getservent (void); +extern void sethostent (int __stay_open); +extern void setnetent (int __stay_open); +extern void setprotoent (int __stay_open); +extern void setservent (int __stay_open); + +#endif // _NETDB_H \ No newline at end of file diff --git a/newlib_shim/cpuset.h b/libc_extension/include/sys/cpuset.h similarity index 100% rename from newlib_shim/cpuset.h rename to libc_extension/include/sys/cpuset.h diff --git a/newlib_shim/dirent.h b/libc_extension/include/sys/dirent.h similarity index 100% rename from newlib_shim/dirent.h rename to libc_extension/include/sys/dirent.h diff --git a/libc_extension/include/sys/mman.h b/libc_extension/include/sys/mman.h new file mode 100644 index 0000000..535e7eb --- /dev/null +++ b/libc_extension/include/sys/mman.h @@ -0,0 +1,64 @@ +/* sys/mman.h + +Copyright 1996, 1997, 1998, 2000, 2001 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _SYS_MMAN_H_ +#define _SYS_MMAN_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +#define MAP_FILE 0 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_TYPE 0xF +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS + /* Non-standard flag */ +#if 0 /* Not yet implemented */ +#define MAP_NORESERVE 0x4000 /* Don't reserve swap space for this mapping. +Page protection must be set explicitely +to access page. */ +#endif +#define MAP_AUTOGROW 0x8000 /* Grow underlying object to mapping size. +File must be opened for writing. */ + +#define MAP_FAILED ((void *)-1) + + /* + * Flags for msync. + */ +#define MS_ASYNC 1 +#define MS_SYNC 2 +#define MS_INVALIDATE 4 + +#ifndef __INSIDE_CYGWIN__ + extern void *mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd, off_t __off); +#endif + extern int munmap (void *__addr, size_t __len); + extern int mprotect (void *__addr, size_t __len, int __prot); + extern int msync (void *__addr, size_t __len, int __flags); + extern int mlock (const void *__addr, size_t __len); + extern int munlock (const void *__addr, size_t __len); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ + +#endif /* _SYS_MMAN_H_ */ \ No newline at end of file diff --git a/newlib_shim/sched.h b/libc_extension/include/sys/sched.h similarity index 100% rename from newlib_shim/sched.h rename to libc_extension/include/sys/sched.h diff --git a/libc_extension/include/sys/socket.h b/libc_extension/include/sys/socket.h new file mode 100644 index 0000000..b0eb27a --- /dev/null +++ b/libc_extension/include/sys/socket.h @@ -0,0 +1,269 @@ +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H 1 + +#include + +/* Type for length arguments in socket calls. */ +typedef unsigned int socklen_t; + +/* POSIX.1g specifies this type name for the `sa_family' member. */ +typedef unsigned short int sa_family_t; + +/* Structure describing a generic socket address. */ +struct sockaddr +{ + sa_family_t sa_family; /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ +}; + +/* Structure large enough to hold any socket address (with the historical + exception of AF_UNIX). */ +struct sockaddr_storage +{ + sa_family_t ss_family; /* Address family, etc. */ + char __ss_padding[(128 - (sizeof (unsigned short int)) - sizeof (unsigned long int))]; + unsigned long int __ss_align; /* Force desired alignment. */ +}; + +/* Structure describing messages sent by + `sendmsg' and received by `recvmsg'. */ +struct msghdr +{ + void *msg_name; /* Address to send to/receive from. */ + socklen_t msg_namelen; /* Length of address data. */ + + struct iovec *msg_iov; /* Vector of data to send/receive into. */ + size_t msg_iovlen; /* Number of elements in the vector. */ + + void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ + size_t msg_controllen; /* Ancillary data buffer length. + !! The type should be socklen_t but the + definition of the kernel is incompatible + with this. */ + + int msg_flags; /* Flags on received message. */ +}; + +/* Structure used for storage of ancillary data object information. */ +struct cmsghdr +{ + size_t cmsg_len; /* Length of data in cmsg_data plus length + of cmsghdr structure. + !! The type should be socklen_t but the + definition of the kernel is incompatible + with this. */ + int cmsg_level; /* Originating protocol. */ + int cmsg_type; /* Protocol specific type. */ +}; + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_STREAM = 1, /* Sequenced, reliable, connection-based + byte streams. */ +#define SOCK_STREAM SOCK_STREAM + SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams + of fixed maximum length. */ +#define SOCK_DGRAM SOCK_DGRAM + SOCK_RAW = 3, /* Raw protocol interface. */ +#define SOCK_RAW SOCK_RAW + SOCK_RDM = 4, /* Reliably-delivered messages. */ +#define SOCK_RDM SOCK_RDM + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ +#define SOCK_SEQPACKET SOCK_SEQPACKET + SOCK_DCCP = 6, /* Datagram Congestion Control Protocol. */ +#define SOCK_DCCP SOCK_DCCP + SOCK_PACKET = 10, /* Linux specific way of getting packets + at the dev level. For writing rarp and + other similar things on the user level. */ +#define SOCK_PACKET SOCK_PACKET + + /* Flags to be ORed into the type parameter of socket and socketpair and + used for the flags parameter of paccept. */ + + SOCK_CLOEXEC = 02000000, /* Atomically set close-on-exec flag for the + new descriptor(s). */ +#define SOCK_CLOEXEC SOCK_CLOEXEC + SOCK_NONBLOCK = 00004000 /* Atomically mark descriptor(s) as + non-blocking. */ +#define SOCK_NONBLOCK SOCK_NONBLOCK +}; + +/* Protocol families. */ +#define PF_UNSPEC 0 /* Unspecified. */ +#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ +#define PF_UNIX PF_LOCAL /* POSIX name for PF_LOCAL. */ +#define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ +#define PF_INET 2 /* IP protocol family. */ +#define PF_AX25 3 /* Amateur Radio AX.25. */ +#define PF_IPX 4 /* Novell Internet Protocol. */ +#define PF_APPLETALK 5 /* Appletalk DDP. */ +#define PF_NETROM 6 /* Amateur radio NetROM. */ +#define PF_BRIDGE 7 /* Multiprotocol bridge. */ +#define PF_ATMPVC 8 /* ATM PVCs. */ +#define PF_X25 9 /* Reserved for X.25 project. */ +#define PF_INET6 10 /* IP version 6. */ +#define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ +#define PF_DECnet 12 /* Reserved for DECnet project. */ +#define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ +#define PF_SECURITY 14 /* Security callback pseudo AF. */ +#define PF_KEY 15 /* PF_KEY key management API. */ +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ +#define PF_PACKET 17 /* Packet family. */ +#define PF_ASH 18 /* Ash. */ +#define PF_ECONET 19 /* Acorn Econet. */ +#define PF_ATMSVC 20 /* ATM SVCs. */ +#define PF_RDS 21 /* RDS sockets. */ +#define PF_SNA 22 /* Linux SNA Project */ +#define PF_IRDA 23 /* IRDA sockets. */ +#define PF_PPPOX 24 /* PPPoX sockets. */ +#define PF_WANPIPE 25 /* Wanpipe API sockets. */ +#define PF_LLC 26 /* Linux LLC. */ +#define PF_IB 27 /* Native InfiniBand address. */ +#define PF_MPLS 28 /* MPLS. */ +#define PF_CAN 29 /* Controller Area Network. */ +#define PF_TIPC 30 /* TIPC sockets. */ +#define PF_BLUETOOTH 31 /* Bluetooth sockets. */ +#define PF_IUCV 32 /* IUCV sockets. */ +#define PF_RXRPC 33 /* RxRPC sockets. */ +#define PF_ISDN 34 /* mISDN sockets. */ +#define PF_PHONET 35 /* Phonet sockets. */ +#define PF_IEEE802154 36 /* IEEE 802.15.4 sockets. */ +#define PF_CAIF 37 /* CAIF sockets. */ +#define PF_ALG 38 /* Algorithm sockets. */ +#define PF_NFC 39 /* NFC sockets. */ +#define PF_VSOCK 40 /* vSockets. */ +#define PF_KCM 41 /* Kernel Connection Multiplexor. */ +#define PF_QIPCRTR 42 /* Qualcomm IPC Router. */ +#define PF_SMC 43 /* SMC sockets. */ +#define PF_XDP 44 /* XDP sockets. */ +#define PF_MCTP 45 /* Management component transport protocol. */ +#define PF_MAX 46 /* For now.. */ + +/* Address families. */ +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX PF_UNIX +#define AF_FILE PF_FILE +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_RDS PF_RDS +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_LLC PF_LLC +#define AF_IB PF_IB +#define AF_MPLS PF_MPLS +#define AF_CAN PF_CAN +#define AF_TIPC PF_TIPC +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_IUCV PF_IUCV +#define AF_RXRPC PF_RXRPC +#define AF_ISDN PF_ISDN +#define AF_PHONET PF_PHONET +#define AF_IEEE802154 PF_IEEE802154 +#define AF_CAIF PF_CAIF +#define AF_ALG PF_ALG +#define AF_NFC PF_NFC +#define AF_VSOCK PF_VSOCK +#define AF_KCM PF_KCM +#define AF_QIPCRTR PF_QIPCRTR +#define AF_SMC PF_SMC +#define AF_XDP PF_XDP +#define AF_MCTP PF_MCTP +#define AF_MAX PF_MAX + +/* Bits in the FLAGS argument to `send', `recv', et al. */ +enum + { + MSG_OOB = 0x01, /* Process out-of-band data. */ +#define MSG_OOB MSG_OOB + MSG_PEEK = 0x02, /* Peek at incoming messages. */ +#define MSG_PEEK MSG_PEEK + MSG_DONTROUTE = 0x04, /* Don't use local routing. */ +#define MSG_DONTROUTE MSG_DONTROUTE + MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ +#define MSG_CTRUNC MSG_CTRUNC + MSG_PROXY = 0x10, /* Supply or ask second address. */ +#define MSG_PROXY MSG_PROXY + MSG_TRUNC = 0x20, +#define MSG_TRUNC MSG_TRUNC + MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ +#define MSG_DONTWAIT MSG_DONTWAIT + MSG_EOR = 0x80, /* End of record. */ +#define MSG_EOR MSG_EOR + MSG_WAITALL = 0x100, /* Wait for a full request. */ +#define MSG_WAITALL MSG_WAITALL + MSG_FIN = 0x200, +#define MSG_FIN MSG_FIN + MSG_SYN = 0x400, +#define MSG_SYN MSG_SYN + MSG_CONFIRM = 0x800, /* Confirm path validity. */ +#define MSG_CONFIRM MSG_CONFIRM + MSG_RST = 0x1000, +#define MSG_RST MSG_RST + MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ +#define MSG_ERRQUEUE MSG_ERRQUEUE + MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ +#define MSG_NOSIGNAL MSG_NOSIGNAL + MSG_MORE = 0x8000, /* Sender will send more. */ +#define MSG_MORE MSG_MORE + MSG_WAITFORONE = 0x10000, /* Wait for at least one packet to return.*/ +#define MSG_WAITFORONE MSG_WAITFORONE + MSG_BATCH = 0x40000, /* sendmmsg: more messages coming. */ +#define MSG_BATCH MSG_BATCH + MSG_ZEROCOPY = 0x4000000, /* Use user data in kernel path. */ +#define MSG_ZEROCOPY MSG_ZEROCOPY + MSG_FASTOPEN = 0x20000000, /* Send data in TCP SYN. */ +#define MSG_FASTOPEN MSG_FASTOPEN + + MSG_CMSG_CLOEXEC = 0x40000000 /* Set close_on_exit for file + descriptor received through + SCM_RIGHTS. */ +#define MSG_CMSG_CLOEXEC MSG_CMSG_CLOEXEC + }; + +extern int accept (int __fd, struct sockaddr *__addr, socklen_t *__addr_len); +extern int bind (int __fd, const struct sockaddr *__addr, socklen_t __len); +extern int connect (int __fd, const struct sockaddr *__addr, socklen_t __len); +extern int getpeername (int __fd, struct sockaddr __addr, socklen_t *__len); +extern int getsockname (int __fd, struct sockaddr __addr, socklen_t *__len); +extern int getsockopt (int __fd, int __level, int __optname, void *__optval, socklen_t *__optlen); +extern int listen (int __fd, int __n); +extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); +extern ssize_t recvfrom (int __fd, void *__buf, size_t __n, int __flags, struct sockaddr __addr, + socklen_t *__addr_len); +extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags); +extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); +extern ssize_t sendmsg (int __fd, const struct msghdr *__message, int __flags); +extern ssize_t sendto (int __fd, const void *__buf, size_t __n, int __flags, + const struct sockaddr *__addr, socklen_t __addr_len); +extern int setsockopt (int __fd, int __level, int __optname, const void *__optval, + socklen_t __optlen); +extern int shutdown (int __fd, int __how); +extern int socket (int __domain, int __type, int __protocol); +extern int sockatmark (int __fd); +extern int socketpair (int __domain, int __type, int __protocol, int __fds[2]); + +#endif // _SYS_SOCKET_H \ No newline at end of file diff --git a/newlib_shim/statvfs.h b/libc_extension/include/sys/statvfs.h similarity index 84% rename from newlib_shim/statvfs.h rename to libc_extension/include/sys/statvfs.h index 8ce27de..9677900 100644 --- a/newlib_shim/statvfs.h +++ b/libc_extension/include/sys/statvfs.h @@ -6,6 +6,7 @@ extern "C" { #endif #include +#include #define ST_RDONLY 1 #define ST_NOSUID 2 @@ -27,8 +28,14 @@ struct statvfs { unsigned long f_namemax; // Maximum filename length. }; -int statvfs(const char *path, struct statvfs *buf); -int fstatvfs(int fd, struct statvfs *buf); +int statvfs(const char *path, struct statvfs *buf) { + errno = ENOSYS; + return -1; +} +int fstatvfs(int fd, struct statvfs *buf) { + errno = ENOSYS; + return -1; +} #ifdef __cplusplus } diff --git a/libc_extension/include/sys/uio.h b/libc_extension/include/sys/uio.h new file mode 100644 index 0000000..4ddeced --- /dev/null +++ b/libc_extension/include/sys/uio.h @@ -0,0 +1,33 @@ +#ifndef _SYS_UIO_H +#define _SYS_UIO_H 1 + +#include + +/* Structure for scatter/gather I/O. */ +struct iovec +{ + void *iov_base; /* Pointer to data. */ + size_t iov_len; /* Length of data. */ +}; + +/* Read data from file descriptor FD, and put the result in the + buffers described by IOVEC, which is a vector of COUNT 'struct iovec's. + The buffers are filled in the order specified. + Operates just like 'read' (see ) except that data are + put in IOVEC instead of a contiguous buffer. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t readv (int __fd, const struct iovec *__iovec, int __count); + +/* Write data pointed by the buffers described by IOVEC, which + is a vector of COUNT 'struct iovec's, to file descriptor FD. + The data is written in the order specified. + Operates just like 'write' (see ) except that the data + are taken from IOVEC instead of a contiguous buffer. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t writev (int __fd, const struct iovec *__iovec, int __count); + +#endif // _SYS_UIO_H diff --git a/libc_extension/netdb.c b/libc_extension/netdb.c new file mode 100644 index 0000000..e697b0e --- /dev/null +++ b/libc_extension/netdb.c @@ -0,0 +1,66 @@ +#include + +void endhostent (void) {} + +void endnetent (void) {} + +void endprotoent (void) {} + +void endservent (void) {} + +struct hostent *gethostbyaddr (const void *__addr, __socklen_t __len, int __type) { + return 0; +} + +struct hostent *gethostbyname (const char *__name) { + return 0; +} + +struct hostent *gethostent (void) { + return 0; +} + +struct netent *getnetbyaddr (uint32_t __net, int __type) { + return 0; +} + +struct netent *getnetbyname (const char *__name) { + return 0; +} + +struct netent *getnetent (void) { + return 0; +} + +struct protoent *getprotobyname (const char *__name) { + return 0; +} + +struct protoent *getprotobynumber (int __proto) { + return 0; +} + +struct protoent *getprotoent (void) { + return 0; +} + +struct servent *getservbyname (const char *__name, const char *__proto) { + return 0; +} + +struct servent *getservbyport (int __port, const char *__proto) { + return 0; +} + +struct servent *getservent (void) { + return 0; +} + +void sethostent (int __stay_open) {} + +void setnetent (int __stay_open) {} + +void setprotoent (int __stay_open) {} + +void setservent (int __stay_open) {} + diff --git a/libc_extension/socket.c b/libc_extension/socket.c new file mode 100644 index 0000000..7d24a11 --- /dev/null +++ b/libc_extension/socket.c @@ -0,0 +1,73 @@ +#include + +int accept (int __fd, struct sockaddr *__addr, socklen_t *__addr_len) { + return -1; +} + +int bind (int __fd, const struct sockaddr *__addr, socklen_t __len) { + return -1; +} + +int connect (int __fd, const struct sockaddr *__addr, socklen_t __len) { + return -1; +} + +int getpeername (int __fd, struct sockaddr __addr, socklen_t *__len) { + return -1; +} + +int getsockname (int __fd, struct sockaddr __addr, socklen_t *__len) { + return -1; +} + +int getsockopt (int __fd, int __level, int __optname, void *__optval, socklen_t *__optlen) { + return -1; +} + +int listen (int __fd, int __n) { + return -1; +} + +ssize_t recv (int __fd, void *__buf, size_t __n, int __flags) { + return -1; +} + +ssize_t recvfrom (int __fd, void *__buf, size_t __n, int __flags, struct sockaddr __addr, socklen_t *__addr_len) { + return -1; +} + +ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags) { + return -1; +} + +ssize_t send (int __fd, const void *__buf, size_t __n, int __flags) { + return -1; +} + +ssize_t sendmsg (int __fd, const struct msghdr *__message, int __flags) { + return -1; +} + +ssize_t sendto (int __fd, const void *__buf, size_t __n, int __flags, const struct sockaddr *__addr, socklen_t __addr_len) { + return -1; +} + +int setsockopt (int __fd, int __level, int __optname, const void *__optval, socklen_t __optlen) { + return -1; +} + +int shutdown (int __fd, int __how) { + return -1; +} + +int socket (int __domain, int __type, int __protocol) { + return -1; +} + +int sockatmark (int __fd) { + return -1; +} + +int socketpair (int __domain, int __type, int __protocol, int __fds[2]) { + return -1; +} diff --git a/libc_extension/uio.c b/libc_extension/uio.c new file mode 100644 index 0000000..590faa1 --- /dev/null +++ b/libc_extension/uio.c @@ -0,0 +1,9 @@ +#include + +ssize_t readv (int __fd, const struct iovec *__iovec, int __count) { + return -1; +} + +ssize_t writev (int __fd, const struct iovec *__iovec, int __count) { + return -1; +} diff --git a/newlib_shim/Makefile.inc b/newlib_shim/Makefile.inc index b8fed40..acbd0d0 100644 --- a/newlib_shim/Makefile.inc +++ b/newlib_shim/Makefile.inc @@ -1,5 +1,4 @@ libc_a_SOURCES += \ - %D%/dirent.c \ %D%/pthread.c \ %D%/shim.c \ %D%/time.c \ diff --git a/newlib_shim/newlib-cygwin-3.5.3.patch b/newlib_shim/newlib-cygwin-3.5.3.patch index eebcbf6..90449af 100644 --- a/newlib_shim/newlib-cygwin-3.5.3.patch +++ b/newlib_shim/newlib-cygwin-3.5.3.patch @@ -159,3 +159,33 @@ index c99ad395d..109112630 100644 #endif /* defined(__rtems__) */ #endif /* __GNU_VISIBLE */ +diff --git a/newlib/libc/include/limits.h a/newlib/libc/include/limits.h +index 893f108..f07076d 100644 +--- a/newlib/libc/include/limits.h ++++ b/newlib/libc/include/limits.h +@@ -145,3 +145,7 @@ + #ifndef PATH_MAX + #define PATH_MAX 4096 + #endif ++ ++#ifndef SSIZE_MAX ++#define SSIZE_MAX LONG_MAX ++#endif ++ +diff --git a/newlib/libc/include/sys/time.h b/newlib/libc/include/sys/time.h +index 5a3dec7ab..980f3378d 100644 +--- a/newlib/libc/include/sys/time.h ++++ b/newlib/libc/include/sys/time.h +@@ -440,6 +440,9 @@ int futimesat (int, const char *, const struct timeval [2]); + int _gettimeofday (struct timeval *__p, void *__tz); + #endif + ++time_t time(time_t *tloc); ++int utime(const char *filename, const struct utimbuf *times); ++ + __END_DECLS + + #endif /* !_KERNEL */ +-- +2.50.1 + diff --git a/newlib_shim/patch_script b/newlib_shim/patch_script index 31f1a81..9f92f72 100755 --- a/newlib_shim/patch_script +++ b/newlib_shim/patch_script @@ -19,19 +19,10 @@ then fi cp $THIS_DIR/Makefile.inc $1/newlib/libc/sys/dandelion/Makefile.inc cp $THIS_DIR/shim.c $1/newlib/libc/sys/dandelion/shim.c -cp $THIS_DIR/dirent.c $1/newlib/libc/sys/dandelion/dirent.c cp $THIS_DIR/pthread.c $1/newlib/libc/sys/dandelion/pthread.c cp $THIS_DIR/time.c $1/newlib/libc/sys/dandelion/time.c cp $THIS_DIR/unistd.c $1/newlib/libc/sys/dandelion/unistd.c cp $THIS_DIR/../include/dandelion/crt.h $1/newlib/libc/sys/dandelion/crt.h -if ! test -d $1/newlib/libc/sys/dandelion/sys -then - mkdir $1/newlib/libc/sys/dandelion/sys -fi -cp $THIS_DIR/dirent.h $1/newlib/libc/sys/dandelion/sys/dirent.h -cp $THIS_DIR/statvfs.h $1/newlib/libc/sys/dandelion/sys/statvfs.h -cp $THIS_DIR/sched.h $1/newlib/libc/sys/dandelion/sys/sched.h -cp $THIS_DIR/cpuset.h $1/newlib/libc/sys/dandelion/sys/cpuset.h cd $1 autoreconf cd newlib diff --git a/newlib_shim/pthread.c b/newlib_shim/pthread.c index d9f5783..c76bb6f 100644 --- a/newlib_shim/pthread.c +++ b/newlib_shim/pthread.c @@ -86,20 +86,48 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) { return EINVAL; } int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr) { - return EAGAIN; + (void)attr; + *cond = _PTHREAD_COND_INITIALIZER; + return 0; +} + +int pthread_cond_destroy(pthread_cond_t *cond) { + pthread_cond_t current = *cond; + if ((current & DESTROYED) == 0) + return EINVAL; + *cond &= ~DESTROYED; + return 0; } -int pthread_cond_destroy(pthread_cond_t *cond) { return EINVAL; } + int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex) { - return ENOTRECOVERABLE; + if ((*cond & DESTROYED) == 0 || (*mutex & DESTROYED) == 0) + return EINVAL; + if ((*mutex & LOCKED) != 0) + return EPERM; + + int r = pthread_mutex_unlock(mutex); + if (r != 0) return r; + return pthread_mutex_lock(mutex); } + int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstim) { - return ENOTRECOVERABLE; + (void)abstim; + return pthread_cond_wait(cond, mutex); +} + +int pthread_cond_signal(pthread_cond_t *cond) { + return 0; } -int pthread_cond_signal(pthread_cond_t *cond) { return EINVAL; } -int pthread_cond_broadcast(pthread_cond_t *cond) { return EINVAL; } + +int pthread_cond_broadcast(pthread_cond_t *cond) { + if ((*cond & DESTROYED) == 0) + return EINVAL; + return 0; +} + int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { if (once_control->init_executed == 0) { @@ -196,4 +224,23 @@ int pthread_key_delete(pthread_key_t key) { int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) { return ENOMEM; +} + +int pthread_attr_init(pthread_attr_t *attr) { + return EINVAL; +} +int pthread_attr_destroy(pthread_attr_t *attr) { + return EINVAL; +} + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { + return EINVAL; +} +int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, + size_t *restrict stacksize) { + return EINVAL; +} + +void pthread_exit(void *retval) { + return; } \ No newline at end of file diff --git a/newlib_shim/shim.c b/newlib_shim/shim.c index d2374ab..50deac3 100644 --- a/newlib_shim/shim.c +++ b/newlib_shim/shim.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -187,16 +186,6 @@ int lstat(const char *file, struct stat *buf) { return stat(file, buf); } mode_t umask(mode_t mask) { return 0777; } -int statvfs(const char *file, struct statvfs *st) { - errno = ENOSYS; - return -1; -} - -int fstatvfs(int fd, struct statvfs *buf) { - errno = ENOSYS; - return -1; -} - int posix_memalign(void **memptr, size_t alignment, size_t size) { void *new_allocation = memalign(alignment, size); if (new_allocation == NULL) { diff --git a/newlib_shim/time.c b/newlib_shim/time.c index a278e54..c7ab289 100644 --- a/newlib_shim/time.c +++ b/newlib_shim/time.c @@ -6,6 +6,7 @@ #define _POSIX_MONOTONIC_CLOCK #include #include +#include #undef errno extern int errno; @@ -68,3 +69,13 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { // always pretend to sleep for that amount return 0; } + +time_t time(time_t *t) { + errno = EINVAL; + return -1; +} + +int utime(const char *filename, const struct utimbuf *buf) { + errno = EINVAL; + return -1; +} \ No newline at end of file diff --git a/newlib_shim/unistd.c b/newlib_shim/unistd.c index 2d2eae6..50e69f3 100644 --- a/newlib_shim/unistd.c +++ b/newlib_shim/unistd.c @@ -1,8 +1,9 @@ #include #include +#include // Implement functions from unistd that are not already defined in other parts -// of newlibs libc or in something we supply +// of newlibs libc Or in something we supply // unsigned alarm (unsigned __secs); int chdir(const char *__path) { @@ -68,8 +69,7 @@ int execv(const char *__path, char *const __argv[]) { // already given in newlib // int execve (const char *__path, char * const __argv[], char * const // __envp[]); - -// int execvp (const char *__file, char * const __argv[]); +// int execvp (const char *__file, char * const __argv[]); // int execvpe (const char *__file, char * const __argv[], char * const // __envp[]); @@ -86,11 +86,15 @@ int execv(const char *__path, char *const __argv[]) { // int fexecve (int __fd, char * const __argv[], char * const __envp[]); // long fpathconf (int __fd, int __name); +// int execvpe (const char *__file, char * const __argv[], char * const +// __envp[]); + int fsync(int __fd) { return 0; } int fdatasync(int __fd) { return 0; } - // char * get_current_dir_name (void); -char *getcwd(char *__buf, size_t __size) { return "/"; } +char * getcwd (char *__buf, size_t __size) { + return (__buf && __size > 1) ? strcpy(__buf, "/") : 0; +} // int getdomainname (char *__name, size_t __len); // gid_t getegid (void); // uid_t geteuid (void); @@ -102,7 +106,9 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // int getlogin_r (char *name, size_t namesize) ; // #endif // char * getpass (const char *__prompt); -// int getpagesize (void); +int getpagesize (void) { + return 4096; // assuming a page size of 4096 bytes +} // pid_t getpgid (pid_t); // pid_t getpgrp (void); // pid_t getpid (void); // already implementedc @@ -113,21 +119,28 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // char * getwd (char *__buf); // int lchown (const char *__path, uid_t __owner, gid_t __group); // #if __ATFILE_VISIBLE -// int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char -// *__path2, int __flags); +// int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char *__path2, int __flags); +// #endif + +// #if __MISC_VISIBLE || __XSI_VISIBLE +// int nice (int __nice_value); +// #endif -// #endif #if __MISC_VISIBLE || __XSI_VISIBLE -// int nice(int __nice_value); -// #endif // #if __MISC_VISIBLE || __XSI_VISIBLE >= 4 -// int lockf(int __fd, int __cmd, off_t __len); -// #endif -// long pathconf (const char *__path, int __name); -// int pause (void); -// #if __POSIX_VISIBLE >= 199506 -// int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); -// #endif -// int pipe (int __fildes[2]) { +// int lockf (int __fd, int __cmd, off_t __len); +// #endif + +// long pathconf (const char *__path, int __name); + +int pause (void) { + return 0; +} + +// #if __POSIX_VISIBLE >= 199506 int +// pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); +// #endif int + +// pipe (int __fildes[2]) { // pipe2(__fileds[2], 0); // } // int pipe2 (int __fildes[2], int flags); diff --git a/sdk_install/CMakeTemplate.txt b/sdk_install/CMakeTemplate.txt index 3ddcc8a..614890b 100644 --- a/sdk_install/CMakeTemplate.txt +++ b/sdk_install/CMakeTemplate.txt @@ -50,6 +50,7 @@ target_link_libraries(dlibc INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/lib/libc.a" "${CMAKE_CURRENT_SOURCE_DIR}/lib/libg.a" "${CMAKE_CURRENT_SOURCE_DIR}/lib/libm.a" + "${CMAKE_CURRENT_SOURCE_DIR}/lib/libc_extension.a" "${CMAKE_CURRENT_SOURCE_DIR}/lib/libdandelion_file_system.a" ) target_link_options(dlibc INTERFACE diff --git a/sdk_install/clang-template.cmake b/sdk_install/clang-template.cmake index c389790..0e2a504 100644 --- a/sdk_install/clang-template.cmake +++ b/sdk_install/clang-template.cmake @@ -23,6 +23,7 @@ -lm -lc -lg +-lc_extension -ldandelion_file_system -ldandelion_runtime -ldandelion_system diff --git a/sdk_install/script-template.sh b/sdk_install/script-template.sh index 6557545..4723191 100644 --- a/sdk_install/script-template.sh +++ b/sdk_install/script-template.sh @@ -18,7 +18,7 @@ while getopts "c:d" opt; do DEFAULT_CLANG=true ;; ?) - echo "Unkown argument to scipt" + echo "Unknown argument to script" ;; esac done @@ -26,8 +26,17 @@ done SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) cd $SCRIPT_DIR +# Detect BSD vs GNU sed +if sed --version >/dev/null 2>&1; then + # GNU sed + SED_INPLACE() { sed -i "$@"; } +else + # BSD sed (macOS) + SED_INPLACE() { sed -i '' "$@"; } +fi + COMPILER_INCLUDES=$($CLANG_NAME -print-file-name=include) -sed -i "s|COMPILER_INCLUDES|$COMPILER_INCLUDES|g" @DANDELION_TARGET@-clang.cfg +SED_INPLACE "s|COMPILER_INCLUDES|$COMPILER_INCLUDES|g" @DANDELION_TARGET@-clang.cfg CLANG_PATH="$(which $CLANG_NAME)" CLANG_DIR="$(dirname $CLANG_PATH)" @@ -40,10 +49,10 @@ fi if [ $DEFAULT_CLANG = true ] && ! [[ -f $CLANG_DIR/clang ]]; then cp "$CLANG_PATH" "$CLANG_DIR/clang" ln -s "$CLANG_DIR/clang" "$CLANG_DIR/clang++" - sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang.cfg >> "$CLANG_DIR/clang.cfg" + sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang.cfg >> "$CLANG_DIR/clang.cfg" # enable stdinc, as we assume it has been cleared when we install our clang as system clang - sed -i "s|-nostdinc||g" "$CLANG_DIR/clang.cfg" - sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang++.cfg >> "$CLANG_DIR/clang++.cfg" + SED_INPLACE "s|-nostdinc||g" "$CLANG_DIR/clang.cfg" + sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang++.cfg >> "$CLANG_DIR/clang++.cfg" # need to change the config to use the clang.cfg in the same folder, so remove prefix - sed -i "s|@DANDELION_TARGET@-||g" "$CLANG_DIR/clang++.cfg" + SED_INPLACE "s|@DANDELION_TARGET@-||g" "$CLANG_DIR/clang++.cfg" fi \ No newline at end of file diff --git a/system/platform/debug/debug.c b/system/platform/debug/debug.c index 143b347..efd5420 100644 --- a/system/platform/debug/debug.c +++ b/system/platform/debug/debug.c @@ -186,6 +186,9 @@ void __dandelion_platform_init(void) { sysdata.input_bufs = heap_ptr; for (size_t input_set = 0; input_set < input_set_index; input_set++) { + // Set the starting offset for this set + input_sets[input_set].offset = total_buffers; + write_all(1, "\t", 1); write_all(1, input_sets[input_set].ident, input_sets[input_set].ident_len); write_all(1, "\n", 1); @@ -250,8 +253,6 @@ void __dandelion_platform_init(void) { } if (set_dirent_read < 0) print_and_exit("getdents failed\n", -dirent_read); - - input_sets[input_set].offset = total_buffers; } // set up sentinel set @@ -328,16 +329,21 @@ void __dandelion_platform_exit(void) { char exit_message[] = "Exiting with code "; size_t message_len = my_strlen(exit_message); write_all(1, exit_message, message_len); - char exit_code_string[11] = " \n"; + char exit_code_string[12] = " 0000000000\n"; // convert int to string int exit_code = sysdata.exit_code; + // remove sign + if (exit_code < 0) { + exit_code_string[0] = '-'; + exit_code *= -1; + } for (size_t index = 0; index < 10; index++) { - exit_code_string[9 - index] = '0' + (exit_code % 10); + exit_code_string[10 - index] = '0' + (exit_code % 10); exit_code = exit_code / 10; if (exit_code == 0) break; } - write_all(1, exit_code_string, 11); + write_all(1, exit_code_string, 12); __syscall(SYS_exit_group, sysdata.exit_code); __builtin_unreachable(); } diff --git a/test_programs/libcpp/CMakeLists.txt b/test_programs/libcpp/CMakeLists.txt index 9080e3a..8922f48 100644 --- a/test_programs/libcpp/CMakeLists.txt +++ b/test_programs/libcpp/CMakeLists.txt @@ -14,5 +14,9 @@ target_link_libraries(${TEST} PRIVATE # prepare files to run the function in debug mode file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/input_sets) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/input_sets/in_a) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input_1.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/input_sets/in_a) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/input_sets/in_b) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input_2.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/input_sets/in_b) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/output_sets) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/output_sets/stdio) \ No newline at end of file diff --git a/test_programs/libcpp/input_1.txt b/test_programs/libcpp/input_1.txt new file mode 100644 index 0000000..01db5dd --- /dev/null +++ b/test_programs/libcpp/input_1.txt @@ -0,0 +1 @@ +first input file \ No newline at end of file diff --git a/test_programs/libcpp/input_2.txt b/test_programs/libcpp/input_2.txt new file mode 100644 index 0000000..e98c3f9 --- /dev/null +++ b/test_programs/libcpp/input_2.txt @@ -0,0 +1 @@ +second input file \ No newline at end of file diff --git a/test_programs/libcpp/test.cpp b/test_programs/libcpp/test.cpp index 4511115..dac8884 100644 --- a/test_programs/libcpp/test.cpp +++ b/test_programs/libcpp/test.cpp @@ -1,15 +1,34 @@ #include #include +#include using namespace std; int main(){ - // cout << "Hello World" << endl; std::fstream fs; fs.open("/stdio/stdout", std::fstream::out); - fs << " test print " << endl; + fs << "test print " << endl; fs.close(); + std::fstream in1; + string in_file_1 = "/in_a/input_1.txt"; + in1.open(in_file_1, std::fstream::in); + if (!in1) { + cerr << "Failed to open " << in_file_1 << endl; + return -1; + } + cout << in1.rdbuf() << endl; + in1.close(); + std::fstream in2; + string in_file_2 = "/in_b/input_2.txt"; + in2.open(in_file_2, std::fstream::in); + if (!in2) { + cerr << "Failed to open " << in_file_2 << endl; + return -1; + } + cerr << in2.rdbuf() << endl; + in2.close(); + cout << "stdout print" << endl; cerr << "stderr print" << endl; return 0;