Changeset 4e6a610 in mainline
- Timestamp:
- 2018-06-25T09:54:28Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bfe90b6
- Parents:
- fb0ec570
- git-author:
- Jiri Svoboda <jiri@…> (2018-06-24 17:51:54)
- git-committer:
- Jiri Svoboda <jiri@…> (2018-06-25 09:54:28)
- Location:
- uspace
- Files:
-
- 5 added
- 1 deleted
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/Makefile.common
rfb0ec570 r4e6a610 165 165 ifneq ($(TEST_SOURCES),) 166 166 TEST_OUTPUTS = $(TEST_BINARY) $(TEST_BINARY).disasm 167 TEST_CFLAGS = -I$(LIB_PREFIX)/pcut/include -D__helenos__ 167 TEST_CFLAGS = -I$(LIB_PREFIX)/pcut/include -D__helenos__ $(EXTRA_TEST_CFLAGS) 168 168 TEST_BINARY_LIBS = $(LIB_PREFIX)/pcut/libpcut.a 169 169 EXTRA_CLEAN += $(TEST_OUTPUTS) $(TEST_BINARY).map -
uspace/lib/c/Makefile
rfb0ec570 r4e6a610 41 41 EXTRA_OUTPUT = $(LINKER_SCRIPTS) 42 42 EXTRA_CLEAN = $(LINKER_SCRIPTS) 43 EXTRA_TEST_CFLAGS = -Wno-deprecated-declarations 43 44 LIBRARY = libc 44 45 SOVERSION = 0.0 … … 151 152 generic/adt/prodcons.c \ 152 153 generic/time.c \ 154 generic/tmpfile.c \ 153 155 generic/stdio.c \ 154 156 generic/stdlib.c \ -
uspace/lib/c/generic/stdio.c
rfb0ec570 r4e6a610 34 34 35 35 #include <errno.h> 36 #include <stdbool.h> 36 37 #include <stdio.h> 38 #include <str.h> 37 39 #include <str_error.h> 40 #include <tmpfile.h> 38 41 #include <vfs/vfs.h> 42 43 /** Static buffer for tmpnam function */ 44 static char tmpnam_buf[L_tmpnam]; 39 45 40 46 /** Get stream position. … … 82 88 rc = vfs_rename_path(old_path, new_path); 83 89 if (rc != EOK) { 90 /* 91 * Note that ISO C leaves the value of errno undefined, 92 * whereas according to UN*X standards, it is set. 93 */ 84 94 errno = rc; 85 95 return -1; … … 96 106 rc = vfs_unlink_path(path); 97 107 if (rc != EOK) { 108 /* 109 * Note that ISO C leaves the value of errno undefined, 110 * whereas according to UN*X standards, it is set. 111 */ 98 112 errno = rc; 99 113 return -1; … … 101 115 102 116 return 0; 117 } 118 119 /** Create a temporary file. 120 * 121 * @return Open stream descriptor or @c NULL on error. In that case 122 * errno is set (UN*X). Note that ISO C leaves the value of errno 123 * undefined. 124 */ 125 FILE *tmpfile(void) 126 { 127 int file; 128 FILE *stream; 129 130 file = __tmpfile(); 131 if (file < 0) { 132 printf("file is < 0\n"); 133 errno = EEXIST; 134 return NULL; 135 } 136 137 stream = fdopen(file, "w+"); 138 if (stream == NULL) { 139 printf("stream = NULL\n"); 140 vfs_put(file); 141 errno = EACCES; 142 return NULL; 143 } 144 145 printf("returning stream\n"); 146 return stream; 147 } 148 149 /** Create name for a temporary file. 150 * 151 * @param s Pointer to array of at least L_tmpnam bytes or @c NULL. 152 * @return The pointer @a s or pointer to internal static buffer on success, 153 * @c NULL on error. 154 */ 155 char *tmpnam(char *s) 156 { 157 char *p; 158 159 p = (s != NULL) ? s : tmpnam_buf; 160 return __tmpnam(p); 103 161 } 104 162 … … 115 173 } 116 174 175 117 176 /** @} 118 177 */ -
uspace/lib/c/include/stdio.h
rfb0ec570 r4e6a610 40 40 #include <stdarg.h> 41 41 #include <io/verify.h> 42 #include <_bits/NULL.h> 42 43 #include <_bits/size_t.h> 43 44 #include <_bits/wchar_t.h> 44 45 #include <_bits/wint_t.h> 45 46 #define EOF (-1)47 48 #ifndef SEEK_SET49 #define SEEK_SET 050 #endif51 52 #ifndef SEEK_CUR53 #define SEEK_CUR 154 #endif55 56 #ifndef SEEK_END57 #define SEEK_END 258 #endif59 60 /** Default size for stream I/O buffers */61 #define BUFSIZ 409662 63 /** Max number of files that is guaranteed to be able to open at the same time */64 #define FOPEN_MAX VFS_MAX_OPEN_FILES65 66 /** Recommended size of fixed-size array for holding file names. */67 #define FILENAME_MAX 409668 46 69 47 /** Forward declaration */ … … 75 53 off64_t pos; 76 54 } fpos_t; 55 56 #ifndef _HELENOS_SOURCE 57 #define _IONBF 0 58 #define _IOLBF 1 59 #define _IOFBF 2 60 #endif 61 62 /** Default size for stream I/O buffers */ 63 #define BUFSIZ 4096 64 65 #define EOF (-1) 66 67 /** Max number of files that is guaranteed to be able to open at the same time */ 68 #define FOPEN_MAX VFS_MAX_OPEN_FILES 69 70 /** Recommended size of fixed-size array for holding file names. */ 71 #define FILENAME_MAX 4096 72 73 /** Length of "/tmp/tmp.XXXXXX" + 1 */ 74 #define L_tmpnam 16 75 76 #ifndef SEEK_SET 77 #define SEEK_SET 0 78 #endif 79 80 #ifndef SEEK_CUR 81 #define SEEK_CUR 1 82 #endif 83 84 #ifndef SEEK_END 85 #define SEEK_END 2 86 #endif 87 88 /** Minimum number of unique temporary file names */ 89 #define TMP_MAX 1000000 77 90 78 91 extern FILE *stdin; … … 157 170 158 171 /* Misc file functions */ 172 extern int remove(const char *); 159 173 extern int rename(const char *, const char *); 160 extern int remove(const char *); 161 162 #ifndef _HELENOS_SOURCE 163 #define _IONBF 0 164 #define _IOLBF 1 165 #define _IOFBF 2 166 167 #endif 174 175 extern FILE *tmpfile(void); 176 extern char *tmpnam(char *s) __attribute__((deprecated)); 168 177 169 178 #ifdef _HELENOS_SOURCE -
uspace/lib/c/test/main.c
rfb0ec570 r4e6a610 38 38 PCUT_IMPORT(scanf); 39 39 PCUT_IMPORT(sprintf); 40 PCUT_IMPORT(stdio); 40 41 PCUT_IMPORT(stdlib); 41 42 PCUT_IMPORT(str); -
uspace/lib/c/test/stdio.c
rfb0ec570 r4e6a610 38 38 #include <pcut/pcut.h> 39 39 #include <stdio.h> 40 #include <str.h> 41 #include <tmpfile.h> 42 #include <vfs/vfs.h> 40 43 41 44 PCUT_INIT; 42 45 43 46 PCUT_TEST_SUITE(stdio); 47 48 /** remove function */ 49 PCUT_TEST(remove) 50 { 51 char buf[L_tmpnam]; 52 char *p; 53 FILE *f; 54 int rc; 55 56 /* Generate unique file name */ 57 p = tmpnam(buf); 58 PCUT_ASSERT_NOT_NULL(p); 59 60 /* Removing it should fail */ 61 rc = remove(buf); 62 PCUT_ASSERT_TRUE(rc != 0); 63 64 f = fopen(buf, "w"); 65 PCUT_ASSERT_NOT_NULL(f); 66 fclose(f); 67 68 /* Remove for the first time */ 69 rc = remove(buf); 70 PCUT_ASSERT_INT_EQUALS(0, rc); 71 72 /* Should fail the second time */ 73 rc = remove(buf); 74 PCUT_ASSERT_TRUE(rc != 0); 75 } 76 77 /** rename function */ 78 PCUT_TEST(rename) 79 { 80 char buf1[L_tmpnam]; 81 char buf2[L_tmpnam]; 82 char *p; 83 FILE *f; 84 int rc; 85 86 /* Generate first unique file name */ 87 p = tmpnam(buf1); 88 PCUT_ASSERT_NOT_NULL(p); 89 90 /* Generate second unique file name */ 91 p = tmpnam(buf2); 92 PCUT_ASSERT_NOT_NULL(p); 93 94 f = fopen(buf1, "w"); 95 PCUT_ASSERT_NOT_NULL(f); 96 fclose(f); 97 98 /* Rename to the second name */ 99 rc = rename(buf1, buf2); 100 PCUT_ASSERT_INT_EQUALS(0, rc); 101 102 /* First name should no longer exist */ 103 rc = remove(buf1); 104 PCUT_ASSERT_TRUE(rc != 0); 105 106 /* Second can be removed */ 107 rc = remove(buf2); 108 PCUT_ASSERT_INT_EQUALS(0, rc); 109 } 110 111 /** tmpfile function */ 112 PCUT_TEST(tmpfile) 113 { 114 FILE *f; 115 char c; 116 size_t n; 117 118 f = tmpfile(); 119 PCUT_ASSERT_NOT_NULL(f); 120 121 c = 'x'; 122 n = fwrite(&c, sizeof(c), 1, f); 123 PCUT_ASSERT_INT_EQUALS(1, n); 124 125 rewind(f); 126 c = '\0'; 127 n = fread(&c, sizeof(c), 1, f); 128 PCUT_ASSERT_INT_EQUALS(1, n); 129 PCUT_ASSERT_INT_EQUALS('x', c); 130 131 fclose(f); 132 } 133 134 /** tmpnam function with buffer argument */ 135 PCUT_TEST(tmpnam_buf) 136 { 137 char buf[L_tmpnam]; 138 char *p; 139 FILE *f; 140 141 p = tmpnam(buf); 142 PCUT_ASSERT_NOT_NULL(p); 143 144 f = fopen(p, "w+"); 145 PCUT_ASSERT_NOT_NULL(f); 146 (void) remove(p); 147 fclose(f); 148 } 149 150 /** tmpnam function called twice */ 151 PCUT_TEST(tmpnam_twice) 152 { 153 char buf1[L_tmpnam]; 154 char buf2[L_tmpnam]; 155 char *p; 156 157 p = tmpnam(buf1); 158 PCUT_ASSERT_NOT_NULL(p); 159 160 p = tmpnam(buf2); 161 PCUT_ASSERT_NOT_NULL(p); 162 163 /* We must get two distinct names */ 164 PCUT_ASSERT_TRUE(str_cmp(buf1, buf2) != 0); 165 } 166 167 /** tmpnam function with NULL argument */ 168 PCUT_TEST(tmpnam_null) 169 { 170 char *p; 171 FILE *f; 172 173 p = tmpnam(NULL); 174 PCUT_ASSERT_NOT_NULL(p); 175 176 f = fopen(p, "w+"); 177 PCUT_ASSERT_NOT_NULL(f); 178 (void) remove(p); 179 fclose(f); 180 } 44 181 45 182 /** fgetpos and fsetpos functions */ … … 50 187 FILE *f; 51 188 52 // XXX Use tmpfile() when it is available 53 f = fopen("/tmp/fgpsp.tmp", "w+"); 54 PCUT_ASSERT_NOT_NULL(f); 55 rc = remove("/tmp/fgpsp.tmp"); 56 PCUT_ASSERT_INT_EQUALS(0, rc); 189 f = tmpfile(); 190 PCUT_ASSERT_NOT_NULL(f); 57 191 58 192 rc = fputs("abc", f); -
uspace/lib/posix/Makefile
rfb0ec570 r4e6a610 82 82 TEST_SOURCES = \ 83 83 test/main.c \ 84 test/scanf.c 84 test/stdio.c \ 85 test/stdlib.c \ 86 test/unistd.c 87 88 EXTRA_TEST_CFLAGS = -Wno-deprecated-declarations 85 89 86 90 EXPORT_CPPFLAGS = \ -
uspace/lib/posix/include/posix/stdio.h
rfb0ec570 r4e6a610 48 48 extern int fileno(FILE *); 49 49 50 #define P_tmpdir "/tmp" 51 50 52 /* Identifying the Terminal */ 51 53 #undef L_ctermid … … 77 79 78 80 /* Temporary Files */ 79 #undef L_tmpnam80 #define L_tmpnam PATH_MAX81 extern char *tmpnam(char *s);82 81 extern char *tempnam(const char *dir, const char *pfx); 83 extern FILE *tmpfile(void);84 82 85 83 #endif /* POSIX_STDIO_H_ */ -
uspace/lib/posix/include/posix/stdlib.h
rfb0ec570 r4e6a610 58 58 59 59 /* Legacy Declarations */ 60 extern char *mktemp(char *tmpl) ;60 extern char *mktemp(char *tmpl) __attribute__((deprecated)); 61 61 extern int bsd_getloadavg(double loadavg[], int nelem); 62 62 -
uspace/lib/posix/src/stdio.c
rfb0ec570 r4e6a610 2 2 * Copyright (c) 2011 Jiri Zarevucky 3 3 * Copyright (c) 2011 Petr Koupy 4 * Copyright (c) 2018 Jiri Svoboda 4 5 * All rights reserved. 5 6 * … … 38 39 39 40 #include <assert.h> 40 41 41 #include <errno.h> 42 42 #include <stdbool.h> 43 #include <tmpfile.h> 44 45 #include "posix/fcntl.h" 43 46 #include "posix/stdlib.h" 44 47 #include "posix/string.h" 48 #include "posix/sys/stat.h" 45 49 #include "posix/sys/types.h" 46 50 #include "posix/unistd.h" … … 353 357 } 354 358 355 /** 356 * Get a unique temporary file name (obsolete). 357 * 358 * @param s Buffer for the file name. Must be at least L_tmpnam bytes long. 359 * @return The value of s on success, NULL on failure. 360 */ 361 char *tmpnam(char *s) 362 { 363 assert(L_tmpnam >= strlen("/tmp/tnXXXXXX")); 364 365 static char buffer[L_tmpnam + 1]; 366 if (s == NULL) { 367 s = buffer; 368 } 369 370 strcpy(s, "/tmp/tnXXXXXX"); 371 mktemp(s); 372 373 if (*s == '\0') { 374 /* Errno set by mktemp(). */ 375 return NULL; 376 } 377 378 return s; 379 } 380 381 /** 382 * Get an unique temporary file name with additional constraints (obsolete). 359 /** Determine if directory is an 'appropriate' temporary directory. 360 * 361 * @param dir Directory path 362 * @return @c true iff directory is appropriate. 363 */ 364 static bool is_appropriate_tmpdir(const char *dir) 365 { 366 struct stat sbuf; 367 368 /* Must not be NULL */ 369 if (dir == NULL) 370 return false; 371 372 /* Must not be empty */ 373 if (dir[0] == '\0') 374 return false; 375 376 if (stat(dir, &sbuf) != 0) 377 return false; 378 379 /* Must be a directory */ 380 if ((sbuf.st_mode & S_IFMT) != S_IFDIR) 381 return false; 382 383 /* Must be writable */ 384 if (access(dir, W_OK) != 0) 385 return false; 386 387 return true; 388 } 389 390 /** Construct unique file name. 391 * 392 * Never use this function. 383 393 * 384 394 * @param dir Path to directory, where the file should be created. … … 388 398 char *tempnam(const char *dir, const char *pfx) 389 399 { 390 /* Sequence number of the filename. */ 391 static int seq = 0; 392 393 size_t dir_len = strlen(dir); 394 if (dir[dir_len - 1] == '/') { 395 dir_len--; 396 } 397 398 size_t pfx_len = strlen(pfx); 399 if (pfx_len > 5) { 400 pfx_len = 5; 401 } 402 403 char *result = malloc(dir_len + /* slash*/ 1 + 404 pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1); 405 406 if (result == NULL) { 407 errno = ENOMEM; 400 const char *dpref; 401 char *d; 402 char *buf; 403 int rc; 404 405 d = getenv("TMPDIR"); 406 if (is_appropriate_tmpdir(d)) 407 dpref = d; 408 else if (is_appropriate_tmpdir(dir)) 409 dpref = dir; 410 else if (is_appropriate_tmpdir(P_tmpdir)) 411 dpref = P_tmpdir; 412 else 413 dpref = "/"; 414 415 if (dpref[strlen(dpref) - 1] != '/') 416 rc = asprintf(&buf, "%s/%sXXXXXX", dpref, pfx); 417 else 418 rc = asprintf(&buf, "%s%sXXXXXX", dpref, pfx); 419 420 if (rc < 0) 421 return NULL; 422 423 rc = __tmpfile_templ(buf, false); 424 if (rc != 0) { 425 free(buf); 408 426 return NULL; 409 427 } 410 428 411 char *res_ptr = result; 412 strncpy(res_ptr, dir, dir_len); 413 res_ptr += dir_len; 414 strncpy(res_ptr, pfx, pfx_len); 415 res_ptr += pfx_len; 416 417 for (; seq < 1000; ++seq) { 418 snprintf(res_ptr, 8, "%03d.tmp", seq); 419 420 int orig_errno = errno; 421 errno = EOK; 422 /* Check if the file exists. */ 423 if (access(result, F_OK) == -1) { 424 if (errno == ENOENT) { 425 errno = orig_errno; 426 break; 427 } else { 428 /* errno set by access() */ 429 return NULL; 430 } 431 } 432 } 433 434 if (seq == 1000) { 435 free(result); 436 errno = EINVAL; 437 return NULL; 438 } 439 440 return result; 441 } 442 443 /** 444 * Create and open an unique temporary file. 445 * The file is automatically removed when the stream is closed. 446 * 447 * @param dir Path to directory, where the file should be created. 448 * @param pfx Optional prefix up to 5 characters long. 449 * @return Newly allocated unique path for temporary file. NULL on failure. 450 */ 451 FILE *tmpfile(void) 452 { 453 char filename[] = "/tmp/tfXXXXXX"; 454 int fd = mkstemp(filename); 455 if (fd == -1) { 456 /* errno set by mkstemp(). */ 457 return NULL; 458 } 459 460 /* Unlink the created file, so that it's removed on close(). */ 461 unlink(filename); 462 return fdopen(fd, "w+"); 429 return buf; 463 430 } 464 431 -
uspace/lib/posix/src/stdlib.c
rfb0ec570 r4e6a610 38 38 39 39 #include <errno.h> 40 #include <tmpfile.h> 40 41 41 42 #include "posix/fcntl.h" … … 163 164 int mkstemp(char *tmpl) 164 165 { 165 int fd = -1; 166 167 char *tptr = tmpl + strlen(tmpl) - 6; 168 169 while (fd < 0) { 170 if (*mktemp(tmpl) == '\0') { 171 /* Errno set by mktemp(). */ 172 return -1; 173 } 174 175 fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); 176 177 if (fd == -1) { 178 /* Restore template to it's original state. */ 179 snprintf(tptr, 7, "XXXXXX"); 180 } 181 } 182 183 return fd; 166 int tmpl_len; 167 int file; 168 169 tmpl_len = strlen(tmpl); 170 if (tmpl_len < 6) { 171 errno = EINVAL; 172 return -1; 173 } 174 175 char *tptr = tmpl + tmpl_len - 6; 176 if (strcmp(tptr, "XXXXXX") != 0) { 177 errno = EINVAL; 178 return -1; 179 } 180 181 file = __tmpfile_templ(tmpl, true); 182 if (file < 0) { 183 errno = EIO; // XXX could be more specific 184 return -1; 185 } 186 187 return file; 184 188 } 185 189 … … 194 198 char *mktemp(char *tmpl) 195 199 { 196 int tmpl_len = strlen(tmpl); 200 int tmpl_len; 201 int rc; 202 203 tmpl_len = strlen(tmpl); 197 204 if (tmpl_len < 6) { 198 205 errno = EINVAL; … … 208 215 } 209 216 210 static int seq = 0; 211 212 for (; seq < 1000000; ++seq) { 213 snprintf(tptr, 7, "%06d", seq); 214 215 int orig_errno = errno; 216 errno = 0; 217 /* Check if the file exists. */ 218 if (access(tmpl, F_OK) == -1) { 219 if (errno == ENOENT) { 220 errno = orig_errno; 221 break; 222 } else { 223 /* errno set by access() */ 224 *tmpl = '\0'; 225 return tmpl; 226 } 227 } 228 } 229 230 if (seq == 10000000) { 231 errno = EEXIST; 217 rc = __tmpfile_templ(tmpl, false); 218 if (rc != 0) { 219 errno = EIO; // XXX could be more specific 232 220 *tmpl = '\0'; 233 221 return tmpl; -
uspace/lib/posix/src/unistd.c
rfb0ec570 r4e6a610 39 39 #include <errno.h> 40 40 41 #include "posix/dirent.h" 41 42 #include "posix/string.h" 43 #include "posix/sys/types.h" 42 44 #include "posix/fcntl.h" 43 45 … … 368 370 */ 369 371 int fd = open(path, O_RDONLY); 370 if (fd < 0) 371 return -1; 372 close(fd); 373 return 0; 372 if (fd >= 0) { 373 close(fd); 374 return 0; 375 } 376 DIR *dir = opendir(path); 377 if (dir != NULL) { 378 closedir(dir); 379 return 0; 380 } 381 return -1; 374 382 } else { 375 383 /* Invalid amode argument. */ -
uspace/lib/posix/test/main.c
rfb0ec570 r4e6a610 1 1 /* 2 * Copyright (c) 201 4 Vojtech Horky2 * Copyright (c) 2018 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 31 31 PCUT_INIT; 32 32 33 PCUT_IMPORT(scanf); 33 PCUT_IMPORT(stdio); 34 PCUT_IMPORT(stdlib); 35 PCUT_IMPORT(unistd); 34 36 35 37 PCUT_MAIN();
Note:
See TracChangeset
for help on using the changeset viewer.