Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
android /platform /bionic /refs/heads/main /. /libc /bionic /dirent.cpp
blob: 8921ca0dc28e15d65264f8909f06983c0c1224d4 [file] [log] [blame]
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include<dirent.h>
Elliott Hughes701bec22013-02-25 13:14:31 -0800[diff] [blame]30
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]31#include<errno.h>
32#include<fcntl.h>
Elliott Hughes05fc1d72015-01-28 18:02:33 -0800[diff] [blame]33#include<malloc.h>
34#include<string.h>
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]35#include<sys/stat.h>
36#include<sys/types.h>
37#include<unistd.h>
38
Josh Gaof6e5b582018-06-01 15:30:54 -0700[diff] [blame]39#include<android/fdsan.h>
40
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]41#include"private/bionic_fortify.h"
Elliott Hughes3e898472013-02-12 16:40:24 +0000[diff] [blame]42#include"private/ErrnoRestorer.h"
43#include"private/ScopedPthreadMutexLocker.h"
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]44
Elliott Hughesd1ead2a2014-06-06 15:24:20 -0700[diff] [blame]45extern"C"int __getdents64(unsignedint, dirent*,unsignedint);
Elliott Hughes3d5cb302014-06-06 11:44:55 -0700[diff] [blame]46
Christopher Ferris5edb0f42015-06-04 13:30:45 -0700[diff] [blame]47// Apportable decided to copy the data structure from this file
48// and use it in their own code, but they also call into readdir.
49// In order to avoid a lockup, the structure must be maintained in
50// the exact same order as in L and below. New structure members
51// need to be added to the end of this structure.
52// See b/21037208 for more details.
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]53structDIR{
54int fd_;
55size_t available_bytes_;
56 dirent* next_;
57pthread_mutex_t mutex_;
58 dirent buff_[15];
Christopher Ferris5edb0f42015-06-04 13:30:45 -0700[diff] [blame]59long current_pos_;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]60};
61
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]62#define CHECK_DIR(d)if(d==nullptr) __fortify_fatal("%s: null DIR*", __FUNCTION__)
63
Josh Gaof6e5b582018-06-01 15:30:54 -0700[diff] [blame]64staticuint64_t __get_dir_tag(DIR* dir){
65return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_DIR,
66reinterpret_cast<uint64_t>(dir));
67}
68
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]69staticDIR* __allocate_DIR(int fd){
70DIR* d=reinterpret_cast<DIR*>(malloc(sizeof(DIR)));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]71if(d==nullptr){
72returnnullptr;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]73}
74 d->fd_= fd;
Josh Gaof6e5b582018-06-01 15:30:54 -0700[diff] [blame]75 android_fdsan_exchange_owner_tag(fd,0, __get_dir_tag(d));
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]76 d->available_bytes_=0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]77 d->next_=nullptr;
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800[diff] [blame]78 d->current_pos_=0L;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]79 pthread_mutex_init(&d->mutex_,nullptr);
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]80return d;
81}
82
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]83int dirfd(DIR* d){
84 CHECK_DIR(d);
85return d->fd_;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]86}
87
88DIR* fdopendir(int fd){
89// Is 'fd' actually a directory?
90struct stat sb;
91if(fstat(fd,&sb)==-1){
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]92returnnullptr;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]93}
94if(!S_ISDIR(sb.st_mode)){
95 errno= ENOTDIR;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]96returnnullptr;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]97}
98
99return __allocate_DIR(fd);
100}
101
102DIR* opendir(constchar* path){
Elliott Hughesf73183f2014-08-26 16:20:59 -0700[diff] [blame]103int fd= open(path, O_CLOEXEC| O_DIRECTORY| O_RDONLY);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]104return(fd!=-1)? __allocate_DIR(fd):nullptr;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]105}
106
107staticbool __fill_DIR(DIR* d){
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]108 CHECK_DIR(d);
Elliott Hughes3d5cb302014-06-06 11:44:55 -0700[diff] [blame]109int rc= TEMP_FAILURE_RETRY(__getdents64(d->fd_, d->buff_,sizeof(d->buff_)));
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]110if(rc<=0){
111returnfalse;
112}
113 d->available_bytes_= rc;
114 d->next_= d->buff_;
115returntrue;
116}
117
118static dirent* __readdir_locked(DIR* d){
119if(d->available_bytes_==0&&!__fill_DIR(d)){
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]120returnnullptr;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]121}
122
123 dirent* entry= d->next_;
124 d->next_=reinterpret_cast<dirent*>(reinterpret_cast<char*>(entry)+ entry->d_reclen);
125 d->available_bytes_-= entry->d_reclen;
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800[diff] [blame]126// The directory entry offset uses 0, 1, 2 instead of real file offset,
127// so the value range of long type is enough.
128 d->current_pos_=static_cast<long>(entry->d_off);
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]129return entry;
130}
131
132dirent* readdir(DIR* d){
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]133 CHECK_DIR(d);
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]134ScopedPthreadMutexLocker locker(&d->mutex_);
135return __readdir_locked(d);
136}
Elliott Hughesdb1ea342014-01-17 18:42:49 -0800[diff] [blame]137__strong_alias(readdir64, readdir);
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]138
139int readdir_r(DIR* d, dirent* entry, dirent** result){
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]140 CHECK_DIR(d);
141
Elliott Hughes3e898472013-02-12 16:40:24 +0000[diff] [blame]142ErrnoRestorer errno_restorer;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]143
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]144*result=nullptr;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]145 errno=0;
146
147ScopedPthreadMutexLocker locker(&d->mutex_);
148
149 dirent* next= __readdir_locked(d);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]150if(errno!=0&& next==nullptr){
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]151return errno;
152}
153
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]154if(next!=nullptr){
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]155 memcpy(entry, next, next->d_reclen);
156*result= entry;
157}
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]158return0;
159}
Elliott Hughesdb1ea342014-01-17 18:42:49 -0800[diff] [blame]160__strong_alias(readdir64_r, readdir_r);
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]161
162int closedir(DIR* d){
Yi Kong32bc0fc2018-08-02 17:31:13 -0700[diff] [blame]163if(d==nullptr){
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]164 errno= EINVAL;
165return-1;
166}
167
168int fd= d->fd_;
169 pthread_mutex_destroy(&d->mutex_);
Josh Gaof6e5b582018-06-01 15:30:54 -0700[diff] [blame]170int rc= android_fdsan_close_with_tag(fd, __get_dir_tag(d));
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]171 free(d);
Josh Gaof6e5b582018-06-01 15:30:54 -0700[diff] [blame]172return rc;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]173}
174
175void rewinddir(DIR* d){
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]176 CHECK_DIR(d);
177
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]178ScopedPthreadMutexLocker locker(&d->mutex_);
179 lseek(d->fd_,0, SEEK_SET);
180 d->available_bytes_=0;
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800[diff] [blame]181 d->current_pos_=0L;
182}
183
184void seekdir(DIR* d,long offset){
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]185 CHECK_DIR(d);
186
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800[diff] [blame]187ScopedPthreadMutexLocker locker(&d->mutex_);
188off_t ret= lseek(d->fd_, offset, SEEK_SET);
189if(ret!=-1L){
190 d->available_bytes_=0;
191 d->current_pos_= ret;
192}
193}
194
195long telldir(DIR* d){
Elliott Hughescc3d04f2017-10-26 15:38:06 -0700[diff] [blame]196 CHECK_DIR(d);
197
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800[diff] [blame]198return d->current_pos_;
Elliott Hughes063cfb22012-10-25 20:55:23 -0700[diff] [blame]199}
200
Elliott Hughes701bec22013-02-25 13:14:31 -0800[diff] [blame]201int alphasort(const dirent** a,const dirent** b){
David 'Digit' Turnerc30396f2012-10-29 15:32:54 +0100[diff] [blame]202return strcoll((*a)->d_name,(*b)->d_name);
203}
Elliott Hughesdb1ea342014-01-17 18:42:49 -0800[diff] [blame]204__strong_alias(alphasort64, alphasort);

[8]ページ先頭

©2009-2025 Movatter.jp