1+ #include < sys/socket.h>
2+ #include < sys/un.h>
3+ #include < unistd.h>
4+ #include < cinttypes>
5+ #include < malloc.h>
6+ #include < dirent.h>
7+ #include " riru.h"
8+ #include " rirud.h"
9+ #include " logging.h"
10+ #include " socket.h"
11+ #include " misc.h"
12+
13+ #define SOCKET_ADDRESS " rirud"
14+
15+ static const uint32_t ACTION_READ_FILE = 4 ;
16+ static const uint32_t ACTION_READ_DIR = 5 ;
17+
18+ bool rirud::ReadFile (const char *path, char *&bytes, size_t &bytes_size) {
19+ if (riru_api_version < 10 ) return false ;
20+
21+ struct sockaddr_un addr{};
22+ uint32_t path_size = strlen (path);
23+ int32_t reply;
24+ int32_t file_size;
25+ int fd;
26+ socklen_t socklen;
27+ uint32_t buffer_size = 1024 * 8 ;
28+ bool res = false ;
29+
30+ bytes = nullptr ;
31+ bytes_size = 0 ;
32+
33+ if ((fd = socket (PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0 )) < 0 ) {
34+ PLOGE (" socket" );
35+ goto clean;
36+ }
37+
38+ socklen = setup_sockaddr (&addr, SOCKET_ADDRESS);
39+
40+ if (connect (fd, (struct sockaddr *) &addr, socklen) == -1 ) {
41+ PLOGE (" connect %s" , SOCKET_ADDRESS);
42+ goto clean;
43+ }
44+
45+ if (write_full (fd, &ACTION_READ_FILE, sizeof (uint32_t )) != 0
46+ || write_full (fd, &path_size, sizeof (uint32_t )) != 0
47+ || write_full (fd, path, path_size) != 0 ) {
48+ PLOGE (" write %s" , SOCKET_ADDRESS);
49+ goto clean;
50+ }
51+
52+ if (read_full (fd, &reply, sizeof (int32_t )) != 0 ) {
53+ PLOGE (" read %s" , SOCKET_ADDRESS);
54+ goto clean;
55+ }
56+
57+ if (reply != 0 ) {
58+ LOGE (" open %s failed with %d from remote: %s" , path, reply, strerror (reply));
59+ errno = reply;
60+ goto clean;
61+ }
62+
63+ if (read_full (fd, &file_size, sizeof (uint32_t )) != 0 ) {
64+ PLOGE (" read %s" , SOCKET_ADDRESS);
65+ goto clean;
66+ }
67+
68+ LOGD (" %s size %d" , path, file_size);
69+
70+ if (file_size > 0 ) {
71+ bytes = (char *) malloc (file_size);
72+ while (file_size > 0 ) {
73+ LOGD (" attempt to read %d bytes" , (int ) buffer_size);
74+ auto read_size = TEMP_FAILURE_RETRY (read (fd, bytes + bytes_size, buffer_size));
75+ if (read_size == -1 ) {
76+ PLOGE (" read" );
77+ goto clean;
78+ }
79+
80+ file_size -= read_size;
81+ bytes_size += read_size;
82+ LOGD (" read %d bytes (total %d)" , (int ) read_size, (int ) bytes_size);
83+ }
84+ res = true ;
85+ } else if (file_size == 0 ) {
86+ while (true ) {
87+ if (bytes == nullptr ) {
88+ bytes = (char *) malloc (buffer_size);
89+ } else {
90+ bytes = (char *) realloc (bytes, bytes_size + buffer_size);
91+ }
92+
93+ LOGD (" attempt to read %d bytes" , (int ) buffer_size);
94+ auto read_size = TEMP_FAILURE_RETRY (read (fd, bytes + bytes_size, buffer_size));
95+ if (read_size == -1 ) {
96+ PLOGE (" read" );
97+ goto clean;
98+ }
99+ if (read_size == 0 ) {
100+ res = true ;
101+ goto clean;
102+ }
103+
104+ bytes_size += read_size;
105+ LOGD (" read %d bytes (total %d)" , (int ) read_size, (int ) bytes_size);
106+ }
107+ }
108+
109+
110+ clean:
111+ if (fd != -1 ) close (fd);
112+ return res;
113+ }
114+
115+ bool rirud::ForeachDir (const char *path, void (*callback)(struct dirent *, bool *continue_read)) {
116+ if (riru_api_version < 10 ) return false ;
117+
118+ struct sockaddr_un addr{};
119+ uint32_t path_size = strlen (path);
120+ int32_t reply;
121+ int fd;
122+ socklen_t socklen;
123+ bool res = false ;
124+ bool continue_read = true ;
125+
126+ dirent dirent{};
127+
128+ if ((fd = socket (PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0 )) < 0 ) {
129+ PLOGE (" socket" );
130+ goto clean;
131+ }
132+
133+ socklen = setup_sockaddr (&addr, SOCKET_ADDRESS);
134+
135+ if (connect (fd, (struct sockaddr *) &addr, socklen) == -1 ) {
136+ PLOGE (" connect %s" , SOCKET_ADDRESS);
137+ goto clean;
138+ }
139+
140+ if (write_full (fd, &ACTION_READ_DIR, sizeof (uint32_t )) != 0
141+ || write_full (fd, &path_size, sizeof (uint32_t )) != 0
142+ || write_full (fd, path, path_size) != 0 ) {
143+ PLOGE (" write %s" , SOCKET_ADDRESS);
144+ goto clean;
145+ }
146+
147+ if (read_full (fd, &reply, sizeof (int32_t )) != 0 ) {
148+ PLOGE (" read %s" , SOCKET_ADDRESS);
149+ goto clean;
150+ }
151+
152+ if (reply != 0 ) {
153+ LOGE (" opendir %s failed with %d from remote: %s" , path, reply, strerror (reply));
154+ errno = reply;
155+ goto clean;
156+ }
157+
158+ while (true ) {
159+ if (write_full (fd, &continue_read, sizeof (uint8_t )) != 0 ) {
160+ PLOGE (" write %s" , SOCKET_ADDRESS);
161+ goto clean;
162+ }
163+
164+ if (read_full (fd, &reply, sizeof (int32_t )) != 0 ) {
165+ PLOGE (" read %s" , SOCKET_ADDRESS);
166+ goto clean;
167+ }
168+
169+ if (reply == -1 ) {
170+ goto clean;
171+ }
172+
173+ if (reply != 0 ) {
174+ LOGE (" opendir %s failed with %d from remote: %s" , path, reply, strerror (reply));
175+ continue ;
176+ }
177+
178+ if (read_full (fd, &dirent.d_type , sizeof (unsigned char )) != 0
179+ || read_full (fd, dirent.d_name , 256 ) != 0 ) {
180+ PLOGE (" read %s" , SOCKET_ADDRESS);
181+ goto clean;
182+ }
183+
184+ callback (&dirent, &continue_read);
185+ }
186+
187+ clean:
188+ if (fd != -1 ) close (fd);
189+ return res;
190+ }
0 commit comments