adb_utils.cpp revision 74e0fe73c02531e2aa3c4b9f72527bb7a1731158
15830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes/* 25830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * Copyright (C) 2015 The Android Open Source Project 35830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * 45830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 55830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * you may not use this file except in compliance with the License. 65830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * You may obtain a copy of the License at 75830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * 85830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 95830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * 105830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * Unless required by applicable law or agreed to in writing, software 115830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 125830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * See the License for the specific language governing permissions and 145830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes * limitations under the License. 155830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes */ 165830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes 17aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui#define TRACE_TAG ADB 18e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes 195830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes#include "adb_utils.h" 205830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes 2122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low#include <libgen.h> 22a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes#include <stdlib.h> 235830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes#include <sys/stat.h> 245830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes#include <sys/types.h> 255830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes#include <unistd.h> 265830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes 27e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes#include <algorithm> 28e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes 294f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/logging.h> 304f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h> 314f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/strings.h> 32e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes 337d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao#include "adb.h" 34e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes#include "adb_trace.h" 3553daee6a2b415caa0ff3e425c7fa613c834bca61Elliott Hughes#include "sysdeps.h" 3653daee6a2b415caa0ff3e425c7fa613c834bca61Elliott Hughes 37787f3442cc7d7b1f07189d77413893e2c2c81447Josh GaoADB_MUTEX_DEFINE(basename_lock); 3822191c30a63da7ca951281fffcb1fd59ae40dd54Spencer LowADB_MUTEX_DEFINE(dirname_lock); 3922191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 407d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao#if defined(_WIN32) 417d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gaoconstexpr char kNullFileName[] = "NUL"; 427d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao#else 437d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gaoconstexpr char kNullFileName[] = "/dev/null"; 447d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao#endif 457d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao 467d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gaovoid close_stdin() { 477d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao int fd = unix_open(kNullFileName, O_RDONLY); 487d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao if (fd == -1) { 497d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao fatal_errno("failed to open %s", kNullFileName); 507d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao } 517d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao 527d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) { 537d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao fatal_errno("failed to redirect stdin to %s", kNullFileName); 547d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao } 557d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao unix_close(fd); 567d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao} 577d586073609723cb2f6ed37de0ad1a7996e621aeJosh Gao 58a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughesbool getcwd(std::string* s) { 59a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes char* cwd = getcwd(nullptr, 0); 60a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes if (cwd != nullptr) *s = cwd; 61a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes free(cwd); 62a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes return (cwd != nullptr); 63a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes} 64a7090b94c181f3efe5b53d2c8367b78d99074dfeElliott Hughes 655830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughesbool directory_exists(const std::string& path) { 665830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes struct stat sb; 675830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes return lstat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode); 685830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes} 695830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes 705830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughesstd::string escape_arg(const std::string& s) { 715498adefb00cd979137361b98fcbf8d51f72ebebElliott Hughes std::string result = s; 725830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes 7384b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes // Escape any ' in the string (before we single-quote the whole thing). 7484b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes // The correct way to do this for the shell is to replace ' with '\'' --- that is, 7584b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes // close the existing single-quoted string, escape a single single-quote, and start 7684b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes // a new single-quoted string. Like the C preprocessor, the shell will concatenate 7784b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes // these pieces into one string. 7884b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes for (size_t i = 0; i < s.size(); ++i) { 7984b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes if (s[i] == '\'') { 8084b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes result.insert(i, "'\\'"); 8184b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes i += 2; 8284b0bf22644b35d6b3d3f7dc96311a484c3519b3Elliott Hughes } 835830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes } 845498adefb00cd979137361b98fcbf8d51f72ebebElliott Hughes 855498adefb00cd979137361b98fcbf8d51f72ebebElliott Hughes // Prefix and suffix the whole string with '. 865498adefb00cd979137361b98fcbf8d51f72ebebElliott Hughes result.insert(result.begin(), '\''); 875498adefb00cd979137361b98fcbf8d51f72ebebElliott Hughes result.push_back('\''); 885830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes return result; 895830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes} 90e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes 915c74270f95107952a893584d02b33f9a79f6b3c4Elliott Hughesstd::string adb_basename(const std::string& path) { 92787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // Copy path because basename may modify the string passed in. 93787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao std::string result(path); 94787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao 95787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // Use lock because basename() may write to a process global and return a 96787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // pointer to that. Note that this locking strategy only works if all other 97787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // callers to dirname in the process also grab this same lock. 98787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao adb_mutex_lock(&basename_lock); 99787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao 100787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // Note that if std::string uses copy-on-write strings, &str[0] will cause 101787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // the copy to be made, so there is no chance of us accidentally writing to 102787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // the storage for 'path'. 103787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao char* name = basename(&result[0]); 104787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao 105787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // In case dirname returned a pointer to a process global, copy that string 106787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao // before leaving the lock. 107787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao result.assign(name); 108787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao 109787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao adb_mutex_unlock(&basename_lock); 110787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao 111787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao return result; 1125c74270f95107952a893584d02b33f9a79f6b3c4Elliott Hughes} 1135c74270f95107952a893584d02b33f9a79f6b3c4Elliott Hughes 11422191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Lowstd::string adb_dirname(const std::string& path) { 11522191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // Copy path because dirname may modify the string passed in. 116787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao std::string result(path); 11722191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 11822191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // Use lock because dirname() may write to a process global and return a 11922191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // pointer to that. Note that this locking strategy only works if all other 12022191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // callers to dirname in the process also grab this same lock. 12122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low adb_mutex_lock(&dirname_lock); 12222191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 12322191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // Note that if std::string uses copy-on-write strings, &str[0] will cause 12422191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // the copy to be made, so there is no chance of us accidentally writing to 12522191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // the storage for 'path'. 126787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao char* parent = dirname(&result[0]); 12722191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 12822191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // In case dirname returned a pointer to a process global, copy that string 12922191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // before leaving the lock. 130787f3442cc7d7b1f07189d77413893e2c2c81447Josh Gao result.assign(parent); 13122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 13222191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low adb_mutex_unlock(&dirname_lock); 13322191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 13422191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low return result; 13514216148210fef447aaed46d5f764844a605d3aeAlex Vallée} 13614216148210fef447aaed46d5f764844a605d3aeAlex Vallée 137a1071c6924654de89e077f50f47271bc3e08c569Spencer Low// Given a relative or absolute filepath, create the directory hierarchy 13822191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low// as needed. Returns true if the hierarchy is/was setup. 1395c74270f95107952a893584d02b33f9a79f6b3c4Elliott Hughesbool mkdirs(const std::string& path) { 14022191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // TODO: all the callers do unlink && mkdirs && adb_creat --- 14122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // that's probably the operation we should expose. 14222191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 14322191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // Implementation Notes: 14422191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // 14522191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // Pros: 14622191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // - Uses dirname, so does not need to deal with OS_PATH_SEPARATOR. 14722191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // - On Windows, uses mingw dirname which accepts '/' and '\\', drive letters 14822191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // (C:\foo), UNC paths (\\server\share\dir\dir\file), and Unicode (when 14922191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // combined with our adb_mkdir() which takes UTF-8). 15022191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // - Is optimistic wrt thinking that a deep directory hierarchy will exist. 15122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // So it does as few stat()s as possible before doing mkdir()s. 15222191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // Cons: 15322191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // - Recursive, so it uses stack space relative to number of directory 15422191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // components. 15522191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 15674e0fe73c02531e2aa3c4b9f72527bb7a1731158Josh Gao // If path points to a symlink to a directory, that's fine. 15774e0fe73c02531e2aa3c4b9f72527bb7a1731158Josh Gao struct stat sb; 15874e0fe73c02531e2aa3c4b9f72527bb7a1731158Josh Gao if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) { 15922191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low return true; 16022191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low } 16122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 162a1071c6924654de89e077f50f47271bc3e08c569Spencer Low const std::string parent(adb_dirname(path)); 163a1071c6924654de89e077f50f47271bc3e08c569Spencer Low 16422191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // If dirname returned the same path as what we passed in, don't go recursive. 16522191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // This can happen on Windows when walking up the directory hierarchy and not 16622191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // finding anything that already exists (unlike POSIX that will eventually 16722191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low // find . or /). 16822191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low if (parent == path) { 16922191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low errno = ENOENT; 17022191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low return false; 17122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low } 17222191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 17345b6fc878ab5ba0f76b6bb1947fe04ac6667c2f5Josh Gao // Recursively make parent directories of 'path'. 17422191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low if (!mkdirs(parent)) { 17522191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low return false; 17622191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low } 17722191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 17845b6fc878ab5ba0f76b6bb1947fe04ac6667c2f5Josh Gao // Now that the parent directory hierarchy of 'path' has been ensured, 179a1071c6924654de89e077f50f47271bc3e08c569Spencer Low // create path itself. 18045b6fc878ab5ba0f76b6bb1947fe04ac6667c2f5Josh Gao if (adb_mkdir(path, 0775) == -1) { 18122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low const int saved_errno = errno; 182a1071c6924654de89e077f50f47271bc3e08c569Spencer Low // If someone else created the directory, that is ok. 183a1071c6924654de89e077f50f47271bc3e08c569Spencer Low if (directory_exists(path)) { 18422191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low return true; 18522191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low } 186a1071c6924654de89e077f50f47271bc3e08c569Spencer Low // There might be a pre-existing file at 'path', or there might have been some other error. 18722191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low errno = saved_errno; 18822191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low return false; 18922191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low } 19022191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low 19122191c30a63da7ca951281fffcb1fd59ae40dd54Spencer Low return true; 1925c74270f95107952a893584d02b33f9a79f6b3c4Elliott Hughes} 1935c74270f95107952a893584d02b33f9a79f6b3c4Elliott Hughes 194aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cuistd::string dump_hex(const void* data, size_t byte_count) { 195e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes byte_count = std::min(byte_count, size_t(16)); 196e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes 197e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes const uint8_t* p = reinterpret_cast<const uint8_t*>(data); 198e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes 199e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes std::string line; 200e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes for (size_t i = 0; i < byte_count; ++i) { 201e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes android::base::StringAppendF(&line, "%02x", p[i]); 202e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes } 203e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes line.push_back(' '); 204e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes 205e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes for (size_t i = 0; i < byte_count; ++i) { 206363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low int ch = p[i]; 207363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low line.push_back(isprint(ch) ? ch : '.'); 208e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes } 209e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes 210aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui return line; 211e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes} 2123d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes 213aa2454919098ee14cd232669f1e7dbb33ed07ccfElliott Hughesstd::string perror_str(const char* msg) { 214aa2454919098ee14cd232669f1e7dbb33ed07ccfElliott Hughes return android::base::StringPrintf("%s: %s", msg, strerror(errno)); 215aa2454919098ee14cd232669f1e7dbb33ed07ccfElliott Hughes} 2166dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui 2176dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui#if !defined(_WIN32) 218addab3d84dccd01cae9ca7b8a4b274b935f18fd4Josh Gao// Windows version provided in sysdeps_win32.cpp 2196dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cuibool set_file_block_mode(int fd, bool block) { 2206dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui int flags = fcntl(fd, F_GETFL, 0); 2216dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui if (flags == -1) { 2226dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui PLOG(ERROR) << "failed to fcntl(F_GETFL) for fd " << fd; 2236dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui return false; 2246dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui } 2256dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui flags = block ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); 2266dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui if (fcntl(fd, F_SETFL, flags) != 0) { 2276dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui PLOG(ERROR) << "failed to fcntl(F_SETFL) for fd " << fd << ", flags " << flags; 2286dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui return false; 2296dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui } 2306dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui return true; 2316dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui} 2326dfef255b8fa77e3b5c0a69b7f276ea8e25e22cdYabin Cui#endif 233