12b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes/*
22b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * Copyright (C) 2014 The Android Open Source Project
32b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes *
42b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * you may not use this file except in compliance with the License.
62b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * You may obtain a copy of the License at
72b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes *
82b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes *
102b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * Unless required by applicable law or agreed to in writing, software
112b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * See the License for the specific language governing permissions and
142b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes * limitations under the License.
152b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes */
162b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
172b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <stdio_ext.h>
182b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
192b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <gtest/gtest.h>
202b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
212b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <errno.h>
222b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <fcntl.h>
232b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <limits.h>
242b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <math.h>
252b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <stdio.h>
262b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <sys/types.h>
272b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <sys/stat.h>
282b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <unistd.h>
292b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <wchar.h>
302b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include <locale.h>
312b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
322b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes#include "TemporaryFile.h"
3376144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui#include "utils.h"
342b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
352b021e10664c3938249eb18b48eeac253cbb3e20Elliott HughesTEST(stdio_ext, __fbufsize) {
362b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  FILE* fp = fopen("/proc/version", "r");
372b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
38df8f1a42d1cde97bcd46f5a29a67a44330c5c4f2Elliott Hughes  // Initially, there's no buffer in case the first thing you do is disable buffering.
39df8f1a42d1cde97bcd46f5a29a67a44330c5c4f2Elliott Hughes  ASSERT_EQ(0U, __fbufsize(fp));
40df8f1a42d1cde97bcd46f5a29a67a44330c5c4f2Elliott Hughes
41df8f1a42d1cde97bcd46f5a29a67a44330c5c4f2Elliott Hughes  // A read forces a buffer to be created.
422b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  char buf[128];
43df8f1a42d1cde97bcd46f5a29a67a44330c5c4f2Elliott Hughes  fgets(buf, sizeof(buf), fp);
44df8f1a42d1cde97bcd46f5a29a67a44330c5c4f2Elliott Hughes  ASSERT_EQ(1024U, __fbufsize(fp));
452b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
462b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(0, setvbuf(fp, buf, _IOFBF, 1));
472b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(1U, __fbufsize(fp));
482b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
492b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(0, setvbuf(fp, buf, _IOFBF, 8));
502b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(8U, __fbufsize(fp));
512b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
522b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
532b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes}
542b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
552b021e10664c3938249eb18b48eeac253cbb3e20Elliott HughesTEST(stdio_ext, __flbf) {
562b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  FILE* fp = fopen("/proc/version", "r");
572b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
582b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_FALSE(__flbf(fp));
592b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
602b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  char buf[128];
612b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(0, setvbuf(fp, buf, _IOLBF, sizeof(buf)));
622b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
632b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_TRUE(__flbf(fp));
642b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
652b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
662b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes}
672b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
682b021e10664c3938249eb18b48eeac253cbb3e20Elliott HughesTEST(stdio_ext, __fpending) {
692b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  FILE* fp = fopen("/dev/null", "w");
702b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(0U, __fpending(fp));
712b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ('x', fputc('x', fp));
722b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(1U, __fpending(fp));
732b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ('y', fputc('y', fp));
742b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(2U, __fpending(fp));
752b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fflush(fp);
762b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(0U, __fpending(fp));
772b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
782b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes}
792b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
802b021e10664c3938249eb18b48eeac253cbb3e20Elliott HughesTEST(stdio_ext, __fpurge) {
812b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  FILE* fp = tmpfile();
822b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
832b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ('a', fputc('a', fp));
842b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(1U, __fpending(fp));
852b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  __fpurge(fp);
862b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(0U, __fpending(fp));
872b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
882b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ('b', fputc('b', fp));
892b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ('\n', fputc('\n', fp));
902b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(2U, __fpending(fp));
912b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
922b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  rewind(fp);
932b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
942b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  char buf[16];
952b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  char* s = fgets(buf, sizeof(buf), fp);
962b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_TRUE(s != NULL);
972b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_STREQ("b\n", s);
982b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
992b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
1002b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes}
1012b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1022b021e10664c3938249eb18b48eeac253cbb3e20Elliott HughesTEST(stdio_ext, _flushlbf) {
1032b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  FILE* fp = fopen("/dev/null", "w");
1042b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1052b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  char buf[128];
1062b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(0, setvbuf(fp, buf, _IOLBF, sizeof(buf)));
1072b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1082b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ('a', fputc('a', fp));
1092b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(1U, __fpending(fp));
1102b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1112b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  _flushlbf();
1122b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1132b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(0U, __fpending(fp));
1142b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1152b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
1162b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes}
1172b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1182b021e10664c3938249eb18b48eeac253cbb3e20Elliott HughesTEST(stdio_ext, __freadable__fwritable) {
1192b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  FILE* fp = fopen("/dev/null", "r");
1202b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_TRUE(__freadable(fp));
1212b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_FALSE(__fwritable(fp));
1222b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
1232b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1242b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fp = fopen("/dev/null", "w");
1252b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_FALSE(__freadable(fp));
1262b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_TRUE(__fwritable(fp));
1272b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
1282b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1292b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fp = fopen("/dev/null", "w+");
1302b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_TRUE(__freadable(fp));
1312b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_TRUE(__fwritable(fp));
1322b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
1332b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes}
1342b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes
1352b021e10664c3938249eb18b48eeac253cbb3e20Elliott HughesTEST(stdio_ext, __fsetlocking) {
1362b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  FILE* fp = fopen("/proc/version", "r");
1378c4994bbc1a9a01e34ea92c91eb5b2d1a27bd074Elliott Hughes  ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
1388c4994bbc1a9a01e34ea92c91eb5b2d1a27bd074Elliott Hughes  ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_BYCALLER));
1398c4994bbc1a9a01e34ea92c91eb5b2d1a27bd074Elliott Hughes  ASSERT_EQ(FSETLOCKING_BYCALLER, __fsetlocking(fp, FSETLOCKING_QUERY));
1408c4994bbc1a9a01e34ea92c91eb5b2d1a27bd074Elliott Hughes  ASSERT_EQ(FSETLOCKING_BYCALLER, __fsetlocking(fp, FSETLOCKING_INTERNAL));
1412b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
1422b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes  fclose(fp);
1432b021e10664c3938249eb18b48eeac253cbb3e20Elliott Hughes}
14476144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui
14576144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cuistatic void LockingByCallerHelper(std::atomic<pid_t>* pid) {
14676144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  *pid = gettid();
14776144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  flockfile(stdout);
14876144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  funlockfile(stdout);
14976144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui}
15076144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui
15176144aaa6397fe9e16893882cf59c5c9c0684a66Yabin CuiTEST(stdio_ext, __fsetlocking_BYCALLER) {
15276144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  // Check if users can use flockfile/funlockfile to protect stdio operations.
15376144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  int old_state = __fsetlocking(stdout, FSETLOCKING_BYCALLER);
15476144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  flockfile(stdout);
15576144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  pthread_t thread;
15676144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  std::atomic<pid_t> pid(0);
15776144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  ASSERT_EQ(0, pthread_create(&thread, nullptr,
15876144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui                              reinterpret_cast<void* (*)(void*)>(LockingByCallerHelper), &pid));
15976144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  WaitUntilThreadSleep(pid);
16076144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  funlockfile(stdout);
16176144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui
16276144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  ASSERT_EQ(0, pthread_join(thread, nullptr));
16376144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui  __fsetlocking(stdout, old_state);
16476144aaa6397fe9e16893882cf59c5c9c0684a66Yabin Cui}
165