source: mainline/uspace/lib/posix/src/unistd.c@ 144fafd

Last change on this file since 144fafd was bc999081, checked in by Jiri Svoboda <jiri@…>, 8 weeks ago

Add dummy execlp() implementation to libposix.

  • Property mode set to 100644
File size: 11.5 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * Copyright (c) 2011 Jiri Zarevucky
4 * Copyright (c) 2011 Petr Koupy
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * - The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/** @addtogroup libposix
32 * @{
33 */
34/** @file Miscellaneous standard definitions.
35 */
36
37#define _LARGEFILE64_SOURCE
38#undef _FILE_OFFSET_BITS
39
40#include "internal/common.h"
41#include <unistd.h>
42
43#include <errno.h>
44
45#include <dirent.h>
46#include <string.h>
47#include <sys/types.h>
48#include <fcntl.h>
49
50#include <fibril.h>
51#include <task.h>
52#include <stats.h>
53#include <stdlib.h>
54#include <vfs/vfs.h>
55
56#include <libarch/config.h>
57
58// FIXME: replace with a hash table
59aoff64_t posix_pos[VFS_MAX_OPEN_FILES];
60
61/* Array of environment variable strings (NAME=VALUE). */
62char **environ = NULL;
63
64/**
65 * Sleep for the specified number of seconds.
66 *
67 * Note that POSIX allows this call to be interrupted and then the return
68 * value represents remaining seconds for the sleep. HelenOS does not offer
69 * such functionality and thus always the whole sleep is taken.
70 *
71 * @param seconds Number of seconds to sleep.
72 * @return Always 0 on HelenOS.
73 */
74unsigned int sleep(unsigned int seconds)
75{
76 fibril_sleep(seconds);
77 return 0;
78}
79
80/**
81 * Get current user name.
82 *
83 * @return User name (static) string or NULL if not found.
84 */
85char *getlogin(void)
86{
87 /* There is currently no support for user accounts in HelenOS. */
88 return (char *) "user";
89}
90
91/**
92 * Get current user name.
93 *
94 * @param name Pointer to a user supplied buffer.
95 * @param namesize Length of the buffer.
96 * @return Zero on success, error code otherwise.
97 */
98int getlogin_r(char *name, size_t namesize)
99{
100 /* There is currently no support for user accounts in HelenOS. */
101 if (namesize >= 5) {
102 strcpy(name, (char *) "user");
103 return 0;
104 } else {
105 errno = ERANGE;
106 return -1;
107 }
108}
109
110/**
111 * Test whether open file descriptor is associated with a terminal.
112 *
113 * @param fd Open file descriptor to test.
114 * @return Boolean result of the test.
115 */
116int isatty(int fd)
117{
118 // TODO
119 /*
120 * Always returns false, because there is no easy way to find
121 * out under HelenOS.
122 */
123 return 0;
124}
125
126/**
127 * Get the pathname of the current working directory.
128 *
129 * @param buf Buffer into which the pathname shall be put.
130 * @param size Size of the buffer.
131 * @return Buffer pointer on success, NULL on failure.
132 */
133char *getcwd(char *buf, size_t size)
134{
135 if (failed(vfs_cwd_get(buf, size)))
136 return NULL;
137 return buf;
138}
139
140/**
141 * Change the current working directory.
142 *
143 * @param path New working directory.
144 */
145int chdir(const char *path)
146{
147 if (failed(vfs_cwd_set(path)))
148 return -1;
149 return 0;
150}
151
152/**
153 * Determine the page size of the current run of the process.
154 *
155 * @return Page size of the process.
156 */
157int getpagesize(void)
158{
159 return PAGE_SIZE;
160}
161
162/**
163 * Get the process ID of the calling process.
164 *
165 * @return Process ID.
166 */
167pid_t getpid(void)
168{
169 return task_get_id();
170}
171
172/**
173 * Get the real user ID of the calling process.
174 *
175 * @return User ID.
176 */
177uid_t getuid(void)
178{
179 /* There is currently no support for user accounts in HelenOS. */
180 return 0;
181}
182
183/**
184 * Get the real group ID of the calling process.
185 *
186 * @return Group ID.
187 */
188gid_t getgid(void)
189{
190 /* There is currently no support for user accounts in HelenOS. */
191 return 0;
192}
193
194/**
195 * Close a file.
196 *
197 * @param fildes File descriptor of the opened file.
198 * @return 0 on success, -1 on error.
199 */
200int close(int fildes)
201{
202 posix_pos[fildes] = 0;
203 if (failed(vfs_put(fildes)))
204 return -1;
205 else
206 return 0;
207}
208
209/**
210 * Read from a file.
211 *
212 * @param fildes File descriptor of the opened file.
213 * @param buf Buffer to which the read bytes shall be stored.
214 * @param nbyte Upper limit on the number of read bytes.
215 * @return Number of read bytes on success, -1 otherwise.
216 */
217ssize_t read(int fildes, void *buf, size_t nbyte)
218{
219 size_t nread;
220 if (failed(vfs_read(fildes, &posix_pos[fildes], buf, nbyte, &nread)))
221 return -1;
222 return (ssize_t) nread;
223}
224
225/**
226 * Write to a file.
227 *
228 * @param fildes File descriptor of the opened file.
229 * @param buf Buffer to write.
230 * @param nbyte Size of the buffer.
231 * @return Number of written bytes on success, -1 otherwise.
232 */
233ssize_t write(int fildes, const void *buf, size_t nbyte)
234{
235 size_t nwr;
236 if (failed(vfs_write(fildes, &posix_pos[fildes], buf, nbyte, &nwr)))
237 return -1;
238 return nwr;
239}
240
241static off64_t _lseek(int fildes, off64_t offset, off64_t max_pos, int whence)
242{
243 vfs_stat_t st;
244 off64_t new_pos;
245
246 switch (whence) {
247 case SEEK_SET:
248 new_pos = offset;
249 break;
250 case SEEK_CUR:
251 if (__builtin_add_overflow(posix_pos[fildes], offset, &new_pos)) {
252 errno = EOVERFLOW;
253 return -1;
254 }
255 break;
256 case SEEK_END:
257 if (failed(vfs_stat(fildes, &st)))
258 return -1;
259
260 if (__builtin_add_overflow(st.size, offset, &new_pos)) {
261 errno = EOVERFLOW;
262 return -1;
263 }
264 break;
265 default:
266 errno = EINVAL;
267 return -1;
268 }
269
270 if (new_pos < 0) {
271 errno = EINVAL;
272 return -1;
273 }
274
275 if (new_pos > max_pos) {
276 /* The resulting file offset is too large for the interface. */
277 errno = EOVERFLOW;
278 return -1;
279 }
280
281 posix_pos[fildes] = new_pos;
282 return new_pos;
283}
284
285static off64_t _lseek64(int fildes, off64_t offset, int whence)
286{
287 return _lseek(fildes, offset, INT64_MAX, whence);
288}
289
290off64_t lseek64(int fildes, off64_t offset, int whence)
291{
292 return _lseek64(fildes, offset, whence);
293}
294
295/**
296 * Reposition read/write file offset
297 *
298 * @param fildes File descriptor of the opened file.
299 * @param offset New offset in the file.
300 * @param whence The position from which the offset argument is specified.
301 * @return Upon successful completion, returns the resulting offset
302 * as measured in bytes from the beginning of the file, -1 otherwise.
303 */
304off_t lseek(int fildes, off_t offset, int whence)
305{
306#if LONG_MAX == INT_MAX
307 return _lseek(fildes, offset, LONG_MAX, whence);
308#else
309 return _lseek64(fildes, offset, whence);
310#endif
311}
312
313/**
314 * Requests outstanding data to be written to the underlying storage device.
315 *
316 * @param fildes File descriptor of the opened file.
317 * @return Zero on success, -1 otherwise.
318 */
319int fsync(int fildes)
320{
321 if (failed(vfs_sync(fildes)))
322 return -1;
323 else
324 return 0;
325}
326
327/**
328 * Truncate a file to a specified length.
329 *
330 * @param fildes File descriptor of the opened file.
331 * @param length New length of the file.
332 * @return Zero on success, -1 otherwise.
333 */
334int ftruncate(int fildes, off_t length)
335{
336 return ftruncate64(fildes, length);
337}
338
339int ftruncate64(int fildes, off64_t length)
340{
341 if (failed(vfs_resize(fildes, (aoff64_t) length)))
342 return -1;
343 else
344 return 0;
345}
346
347/**
348 * Remove a directory.
349 *
350 * @param path Directory pathname.
351 * @return Zero on success, -1 otherwise.
352 */
353int rmdir(const char *path)
354{
355 if (failed(vfs_unlink_path(path)))
356 return -1;
357 else
358 return 0;
359}
360
361/**
362 * Remove a link to a file.
363 *
364 * @param path File pathname.
365 * @return Zero on success, -1 otherwise.
366 */
367int unlink(const char *path)
368{
369 if (failed(vfs_unlink_path(path)))
370 return -1;
371 else
372 return 0;
373}
374
375/**
376 * Duplicate an open file descriptor.
377 *
378 * @param fildes File descriptor to be duplicated.
379 * @return On success, new file descriptor for the same file, otherwise -1.
380 */
381int dup(int fildes)
382{
383 return fcntl(fildes, F_DUPFD, 0);
384}
385
386/**
387 * Duplicate an open file descriptor.
388 *
389 * @param fildes File descriptor to be duplicated.
390 * @param fildes2 File descriptor to be paired with the same file description
391 * as is paired fildes.
392 * @return fildes2 on success, -1 otherwise.
393 */
394int dup2(int fildes, int fildes2)
395{
396 int file;
397 if (failed(vfs_clone(fildes, fildes2, false, &file))) {
398 return -1;
399 }
400 return file;
401}
402
403/**
404 * Determine accessibility of a file.
405 *
406 * @param path File to check accessibility for.
407 * @param amode Either check for existence or intended access mode.
408 * @return Zero on success, -1 otherwise.
409 */
410int access(const char *path, int amode)
411{
412 if (amode == F_OK || (amode & (X_OK | W_OK | R_OK))) {
413 /*
414 * HelenOS doesn't support permissions, permission checks
415 * are equal to existence check.
416 *
417 * Check file existence by attempting to open it.
418 */
419 int fd = open(path, O_RDONLY);
420 if (fd >= 0) {
421 close(fd);
422 return 0;
423 }
424 DIR *dir = opendir(path);
425 if (dir != NULL) {
426 closedir(dir);
427 return 0;
428 }
429 return -1;
430 } else {
431 /* Invalid amode argument. */
432 errno = EINVAL;
433 return -1;
434 }
435}
436
437/**
438 * Get configurable system variables.
439 *
440 * @param name Variable name.
441 * @return Variable value.
442 */
443long sysconf(int name)
444{
445 long clk_tck = 0;
446 size_t cpu_count = 0;
447 stats_cpu_t *cpu_stats = stats_get_cpus(&cpu_count);
448 if (cpu_stats && cpu_count > 0) {
449 clk_tck = ((long) cpu_stats[0].frequency_mhz) * 1000000L;
450 }
451 if (cpu_stats) {
452 free(cpu_stats);
453 cpu_stats = 0;
454 }
455
456 long phys_pages = 0;
457 long avphys_pages = 0;
458 stats_physmem_t *mem_stats = stats_get_physmem();
459 if (mem_stats) {
460 phys_pages = (long) (mem_stats->total / getpagesize());
461 avphys_pages = (long) (mem_stats->free / getpagesize());
462 free(mem_stats);
463 mem_stats = 0;
464 }
465
466 switch (name) {
467 case _SC_PHYS_PAGES:
468 return phys_pages;
469 case _SC_AVPHYS_PAGES:
470 return avphys_pages;
471 case _SC_PAGESIZE:
472 return getpagesize();
473 case _SC_CLK_TCK:
474 return clk_tck;
475 default:
476 errno = EINVAL;
477 return -1;
478 }
479}
480
481/**
482 *
483 * @param path
484 * @param name
485 * @return
486 */
487long pathconf(const char *path, int name)
488{
489 // TODO: low priority, just a compile-time dependency of binutils
490 not_implemented();
491 return -1;
492}
493
494/**
495 *
496 * @return
497 */
498pid_t fork(void)
499{
500 // TODO: low priority, just a compile-time dependency of binutils
501 not_implemented();
502 return -1;
503}
504
505/**
506 *
507 * @param path
508 * @param argv
509 * @return
510 */
511int execv(const char *path, char *const argv[])
512{
513 // TODO: low priority, just a compile-time dependency of binutils
514 not_implemented();
515 return -1;
516}
517
518/**
519 *
520 * @param file
521 * @param argv
522 * @return
523 */
524int execvp(const char *file, char *const argv[])
525{
526 // TODO: low priority, just a compile-time dependency of binutils
527 not_implemented();
528 return -1;
529}
530
531/**
532 *
533 * @param file
534 * @param argv
535 * @return
536 */
537int execlp(const char *file, const char *arg, ...)
538{
539 // TODO: low priority, just a compile-time dependency of dosbox
540 not_implemented();
541 return -1;
542}
543
544/**
545 *
546 * @param fildes
547 * @return
548 */
549int pipe(int fildes[2])
550{
551 // TODO: low priority, just a compile-time dependency of binutils
552 not_implemented();
553 return -1;
554}
555
556unsigned int alarm(unsigned int seconds)
557{
558 not_implemented();
559 return 0;
560}
561
562/** @}
563 */
Note: See TracBrowser for help on using the repository browser.