Implementing std::filesystem::remove_all() for AndroidEPUB reader for AndroidMonitor filesystem for...
Could Giant Ground Sloths have been a good pack animal for the ancient Mayans?
Email Account under attack (really) - anything I can do?
Are white and non-white police officers equally likely to kill black suspects?
What happens when a metallic dragon and a chromatic dragon mate?
Information to fellow intern about hiring?
What does 'script /dev/null' do?
How to move the player while also allowing forces to affect it
Does the average primeness of natural numbers tend to zero?
Why was the "bread communication" in the arena of Catching Fire left out in the movie?
Is there a way to make member function NOT callable from constructor?
New order #4: World
Eliminate empty elements from a list with a specific pattern
When blogging recipes, how can I support both readers who want the narrative/journey and ones who want the printer-friendly recipe?
How to answer pointed "are you quitting" questioning when I don't want them to suspect
Is this relativistic mass?
Is domain driven design an anti-SQL pattern?
What do the Banks children have against barley water?
Manga about a female worker who got dragged into another world together with this high school girl and she was just told she's not needed anymore
Domain expired, GoDaddy holds it and is asking more money
LWC and complex parameters
What do you call something that goes against the spirit of the law, but is legal when interpreting the law to the letter?
Is there a familial term for apples and pears?
Is Social Media Science Fiction?
How can I fix this gap between bookcases I made?
Implementing std::filesystem::remove_all() for Android
EPUB reader for AndroidMonitor filesystem for continuous integration and buildValidating FileSystem StructureImplementing FusedLocationProvider for more than one Activity in Androidany_function using the upcoming std::any`std::move_as_tuple` and `std::when_all`Generalizing std::minmax_elementC++ std::array wrapperDisassembler for intel 8080Disassembler for intel 8080 v2
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
$begingroup$
I needed to use some c++ code on both standard Linux and the Android variant, and the code will use filesystem library but it isn't yet in the ndk.
So I'm making a one to use on Android
It will be also usable on Linux because working with files and dirs go through the linux api which is the same on android
So, this is my implementation of the remove_all() function.
It reports errors in int variable and may be wrapped later with a function that will translate expected errno to proper c++ err_code.
It can't delete a dir that contains subdir with files exceeding the file descriptors limit for current process.
Also it can take the whole stack if called recursively too many times.
My filesystem implementation uses a thread local variable (int filesystem_errno) to store errors if needed.
size_t remove_all(const filesystem::path& p, int& err = filesystem_errno)
{
int dir_fd = open(p.c_str(),O_RDONLY|O_DIRECTORY);
if (dir_fd < 0)
{
err = errno;
return 0;
}
if (p.native().length() > PATH_MAX)
{
close(dir_fd);
err = ENAMETOOLONG;
return 0;
}
const int BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];
char subdir[PATH_MAX];
int base_dir_len = strlen(p.c_str());
memcpy(subdir,p.c_str(),base_dir_len);
if (subdir[base_dir_len - 1] != '/')
{
subdir[base_dir_len] = '/';
++base_dir_len;
}
char *subdir_ptr = subdir;
subdir_ptr += base_dir_len;
struct linux_dirent
{
unsigned long inod;
off64_t off;
unsigned short len;
unsigned char type;
char name[];
};
struct linux_dirent32
{
unsigned long inod;
off_t off;
unsigned short len;
char name[];
};
linux_dirent *ldir_ptr;
linux_dirent32 *ldir_ptr32;
size_t fd_count = 0;
while(true)
{
int nread = syscall(SYS_getdents64,dir_fd,buffer,BUFF_SIZE);
if (!nread)
break;
if (nread == -1)
{
err = errno;
close(dir_fd);
return fd_count;
}
for (int pos = 0; pos < nread; pos += ldir_ptr->len)
{
ldir_ptr = (linux_dirent*)(buffer + pos);
// skip . and ..
if (ldir_ptr->name[0] == '.')
{
if (ldir_ptr->name[1] == 0)
continue;
else if (ldir_ptr->name[1] == '.')
if (ldir_ptr->name[2] == 0)
continue;
}
int subdir_len = strlen(ldir_ptr->name);
if ((subdir_len + base_dir_len) > PATH_MAX)
{
close(dir_fd);
err = ENAMETOOLONG;
return fd_count;
} memcpy(subdir_ptr,ldir_ptr->name,subdir_len);
subdir_ptr[subdir_len] = 0;
if (ldir_ptr->type == DT_DIR)
{
size_t deleted_dirs = 0;
if (!rmdir(subdir)) // empty dir
++deleted_dirs;
else if (!(deleted_dirs = filesystem::remove_all(subdir,err)))
{
close(dir_fd);
return fd_count;
}
fd_count += deleted_dirs;
}
else if (ldir_ptr->type != DT_UNKNOWN)
{
if(unlink(subdir))
{
err = errno;
close(dir_fd);
return fd_count;
}
++fd_count;
}
else
{
struct stat st;
if (stat(subdir,&st))
{
err = errno;
close(dir_fd);
return fd_count;
}
if (filesystem::is_directory(st))
{
size_t deleted_dirs = 0;
if (!rmdir(subdir))
++deleted_dirs;
else if (!(deleted_dirs = filesystem::remove_all(subdir,err)))
{
close(dir_fd);
return fd_count;
}
fd_count += deleted_dirs;
}
else
{
if (unlink(subdir))
{
err = errno;
close(dir_fd);
return fd_count;
}
++fd_count;
}
}
}
}
close(dir_fd);
if (rmdir(p.c_str()))
{
err = errno;
return fd_count;
}
err = 0;
++fd_count;
return fd_count;
}
c++ android file-system linux c++17
$endgroup$
add a comment |
$begingroup$
I needed to use some c++ code on both standard Linux and the Android variant, and the code will use filesystem library but it isn't yet in the ndk.
So I'm making a one to use on Android
It will be also usable on Linux because working with files and dirs go through the linux api which is the same on android
So, this is my implementation of the remove_all() function.
It reports errors in int variable and may be wrapped later with a function that will translate expected errno to proper c++ err_code.
It can't delete a dir that contains subdir with files exceeding the file descriptors limit for current process.
Also it can take the whole stack if called recursively too many times.
My filesystem implementation uses a thread local variable (int filesystem_errno) to store errors if needed.
size_t remove_all(const filesystem::path& p, int& err = filesystem_errno)
{
int dir_fd = open(p.c_str(),O_RDONLY|O_DIRECTORY);
if (dir_fd < 0)
{
err = errno;
return 0;
}
if (p.native().length() > PATH_MAX)
{
close(dir_fd);
err = ENAMETOOLONG;
return 0;
}
const int BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];
char subdir[PATH_MAX];
int base_dir_len = strlen(p.c_str());
memcpy(subdir,p.c_str(),base_dir_len);
if (subdir[base_dir_len - 1] != '/')
{
subdir[base_dir_len] = '/';
++base_dir_len;
}
char *subdir_ptr = subdir;
subdir_ptr += base_dir_len;
struct linux_dirent
{
unsigned long inod;
off64_t off;
unsigned short len;
unsigned char type;
char name[];
};
struct linux_dirent32
{
unsigned long inod;
off_t off;
unsigned short len;
char name[];
};
linux_dirent *ldir_ptr;
linux_dirent32 *ldir_ptr32;
size_t fd_count = 0;
while(true)
{
int nread = syscall(SYS_getdents64,dir_fd,buffer,BUFF_SIZE);
if (!nread)
break;
if (nread == -1)
{
err = errno;
close(dir_fd);
return fd_count;
}
for (int pos = 0; pos < nread; pos += ldir_ptr->len)
{
ldir_ptr = (linux_dirent*)(buffer + pos);
// skip . and ..
if (ldir_ptr->name[0] == '.')
{
if (ldir_ptr->name[1] == 0)
continue;
else if (ldir_ptr->name[1] == '.')
if (ldir_ptr->name[2] == 0)
continue;
}
int subdir_len = strlen(ldir_ptr->name);
if ((subdir_len + base_dir_len) > PATH_MAX)
{
close(dir_fd);
err = ENAMETOOLONG;
return fd_count;
} memcpy(subdir_ptr,ldir_ptr->name,subdir_len);
subdir_ptr[subdir_len] = 0;
if (ldir_ptr->type == DT_DIR)
{
size_t deleted_dirs = 0;
if (!rmdir(subdir)) // empty dir
++deleted_dirs;
else if (!(deleted_dirs = filesystem::remove_all(subdir,err)))
{
close(dir_fd);
return fd_count;
}
fd_count += deleted_dirs;
}
else if (ldir_ptr->type != DT_UNKNOWN)
{
if(unlink(subdir))
{
err = errno;
close(dir_fd);
return fd_count;
}
++fd_count;
}
else
{
struct stat st;
if (stat(subdir,&st))
{
err = errno;
close(dir_fd);
return fd_count;
}
if (filesystem::is_directory(st))
{
size_t deleted_dirs = 0;
if (!rmdir(subdir))
++deleted_dirs;
else if (!(deleted_dirs = filesystem::remove_all(subdir,err)))
{
close(dir_fd);
return fd_count;
}
fd_count += deleted_dirs;
}
else
{
if (unlink(subdir))
{
err = errno;
close(dir_fd);
return fd_count;
}
++fd_count;
}
}
}
}
close(dir_fd);
if (rmdir(p.c_str()))
{
err = errno;
return fd_count;
}
err = 0;
++fd_count;
return fd_count;
}
c++ android file-system linux c++17
$endgroup$
$begingroup$
Is there a reason to not useopendir/readdirAPI?
$endgroup$
– vnp
yesterday
$begingroup$
This is much faster for dirs with too many files .
$endgroup$
– prog511
yesterday
add a comment |
$begingroup$
I needed to use some c++ code on both standard Linux and the Android variant, and the code will use filesystem library but it isn't yet in the ndk.
So I'm making a one to use on Android
It will be also usable on Linux because working with files and dirs go through the linux api which is the same on android
So, this is my implementation of the remove_all() function.
It reports errors in int variable and may be wrapped later with a function that will translate expected errno to proper c++ err_code.
It can't delete a dir that contains subdir with files exceeding the file descriptors limit for current process.
Also it can take the whole stack if called recursively too many times.
My filesystem implementation uses a thread local variable (int filesystem_errno) to store errors if needed.
size_t remove_all(const filesystem::path& p, int& err = filesystem_errno)
{
int dir_fd = open(p.c_str(),O_RDONLY|O_DIRECTORY);
if (dir_fd < 0)
{
err = errno;
return 0;
}
if (p.native().length() > PATH_MAX)
{
close(dir_fd);
err = ENAMETOOLONG;
return 0;
}
const int BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];
char subdir[PATH_MAX];
int base_dir_len = strlen(p.c_str());
memcpy(subdir,p.c_str(),base_dir_len);
if (subdir[base_dir_len - 1] != '/')
{
subdir[base_dir_len] = '/';
++base_dir_len;
}
char *subdir_ptr = subdir;
subdir_ptr += base_dir_len;
struct linux_dirent
{
unsigned long inod;
off64_t off;
unsigned short len;
unsigned char type;
char name[];
};
struct linux_dirent32
{
unsigned long inod;
off_t off;
unsigned short len;
char name[];
};
linux_dirent *ldir_ptr;
linux_dirent32 *ldir_ptr32;
size_t fd_count = 0;
while(true)
{
int nread = syscall(SYS_getdents64,dir_fd,buffer,BUFF_SIZE);
if (!nread)
break;
if (nread == -1)
{
err = errno;
close(dir_fd);
return fd_count;
}
for (int pos = 0; pos < nread; pos += ldir_ptr->len)
{
ldir_ptr = (linux_dirent*)(buffer + pos);
// skip . and ..
if (ldir_ptr->name[0] == '.')
{
if (ldir_ptr->name[1] == 0)
continue;
else if (ldir_ptr->name[1] == '.')
if (ldir_ptr->name[2] == 0)
continue;
}
int subdir_len = strlen(ldir_ptr->name);
if ((subdir_len + base_dir_len) > PATH_MAX)
{
close(dir_fd);
err = ENAMETOOLONG;
return fd_count;
} memcpy(subdir_ptr,ldir_ptr->name,subdir_len);
subdir_ptr[subdir_len] = 0;
if (ldir_ptr->type == DT_DIR)
{
size_t deleted_dirs = 0;
if (!rmdir(subdir)) // empty dir
++deleted_dirs;
else if (!(deleted_dirs = filesystem::remove_all(subdir,err)))
{
close(dir_fd);
return fd_count;
}
fd_count += deleted_dirs;
}
else if (ldir_ptr->type != DT_UNKNOWN)
{
if(unlink(subdir))
{
err = errno;
close(dir_fd);
return fd_count;
}
++fd_count;
}
else
{
struct stat st;
if (stat(subdir,&st))
{
err = errno;
close(dir_fd);
return fd_count;
}
if (filesystem::is_directory(st))
{
size_t deleted_dirs = 0;
if (!rmdir(subdir))
++deleted_dirs;
else if (!(deleted_dirs = filesystem::remove_all(subdir,err)))
{
close(dir_fd);
return fd_count;
}
fd_count += deleted_dirs;
}
else
{
if (unlink(subdir))
{
err = errno;
close(dir_fd);
return fd_count;
}
++fd_count;
}
}
}
}
close(dir_fd);
if (rmdir(p.c_str()))
{
err = errno;
return fd_count;
}
err = 0;
++fd_count;
return fd_count;
}
c++ android file-system linux c++17
$endgroup$
I needed to use some c++ code on both standard Linux and the Android variant, and the code will use filesystem library but it isn't yet in the ndk.
So I'm making a one to use on Android
It will be also usable on Linux because working with files and dirs go through the linux api which is the same on android
So, this is my implementation of the remove_all() function.
It reports errors in int variable and may be wrapped later with a function that will translate expected errno to proper c++ err_code.
It can't delete a dir that contains subdir with files exceeding the file descriptors limit for current process.
Also it can take the whole stack if called recursively too many times.
My filesystem implementation uses a thread local variable (int filesystem_errno) to store errors if needed.
size_t remove_all(const filesystem::path& p, int& err = filesystem_errno)
{
int dir_fd = open(p.c_str(),O_RDONLY|O_DIRECTORY);
if (dir_fd < 0)
{
err = errno;
return 0;
}
if (p.native().length() > PATH_MAX)
{
close(dir_fd);
err = ENAMETOOLONG;
return 0;
}
const int BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];
char subdir[PATH_MAX];
int base_dir_len = strlen(p.c_str());
memcpy(subdir,p.c_str(),base_dir_len);
if (subdir[base_dir_len - 1] != '/')
{
subdir[base_dir_len] = '/';
++base_dir_len;
}
char *subdir_ptr = subdir;
subdir_ptr += base_dir_len;
struct linux_dirent
{
unsigned long inod;
off64_t off;
unsigned short len;
unsigned char type;
char name[];
};
struct linux_dirent32
{
unsigned long inod;
off_t off;
unsigned short len;
char name[];
};
linux_dirent *ldir_ptr;
linux_dirent32 *ldir_ptr32;
size_t fd_count = 0;
while(true)
{
int nread = syscall(SYS_getdents64,dir_fd,buffer,BUFF_SIZE);
if (!nread)
break;
if (nread == -1)
{
err = errno;
close(dir_fd);
return fd_count;
}
for (int pos = 0; pos < nread; pos += ldir_ptr->len)
{
ldir_ptr = (linux_dirent*)(buffer + pos);
// skip . and ..
if (ldir_ptr->name[0] == '.')
{
if (ldir_ptr->name[1] == 0)
continue;
else if (ldir_ptr->name[1] == '.')
if (ldir_ptr->name[2] == 0)
continue;
}
int subdir_len = strlen(ldir_ptr->name);
if ((subdir_len + base_dir_len) > PATH_MAX)
{
close(dir_fd);
err = ENAMETOOLONG;
return fd_count;
} memcpy(subdir_ptr,ldir_ptr->name,subdir_len);
subdir_ptr[subdir_len] = 0;
if (ldir_ptr->type == DT_DIR)
{
size_t deleted_dirs = 0;
if (!rmdir(subdir)) // empty dir
++deleted_dirs;
else if (!(deleted_dirs = filesystem::remove_all(subdir,err)))
{
close(dir_fd);
return fd_count;
}
fd_count += deleted_dirs;
}
else if (ldir_ptr->type != DT_UNKNOWN)
{
if(unlink(subdir))
{
err = errno;
close(dir_fd);
return fd_count;
}
++fd_count;
}
else
{
struct stat st;
if (stat(subdir,&st))
{
err = errno;
close(dir_fd);
return fd_count;
}
if (filesystem::is_directory(st))
{
size_t deleted_dirs = 0;
if (!rmdir(subdir))
++deleted_dirs;
else if (!(deleted_dirs = filesystem::remove_all(subdir,err)))
{
close(dir_fd);
return fd_count;
}
fd_count += deleted_dirs;
}
else
{
if (unlink(subdir))
{
err = errno;
close(dir_fd);
return fd_count;
}
++fd_count;
}
}
}
}
close(dir_fd);
if (rmdir(p.c_str()))
{
err = errno;
return fd_count;
}
err = 0;
++fd_count;
return fd_count;
}
c++ android file-system linux c++17
c++ android file-system linux c++17
edited 2 days ago
Deduplicator
11.9k1950
11.9k1950
asked 2 days ago
prog511prog511
61
61
$begingroup$
Is there a reason to not useopendir/readdirAPI?
$endgroup$
– vnp
yesterday
$begingroup$
This is much faster for dirs with too many files .
$endgroup$
– prog511
yesterday
add a comment |
$begingroup$
Is there a reason to not useopendir/readdirAPI?
$endgroup$
– vnp
yesterday
$begingroup$
This is much faster for dirs with too many files .
$endgroup$
– prog511
yesterday
$begingroup$
Is there a reason to not use
opendir/readdir API?$endgroup$
– vnp
yesterday
$begingroup$
Is there a reason to not use
opendir/readdir API?$endgroup$
– vnp
yesterday
$begingroup$
This is much faster for dirs with too many files .
$endgroup$
– prog511
yesterday
$begingroup$
This is much faster for dirs with too many files .
$endgroup$
– prog511
yesterday
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216986%2fimplementing-stdfilesystemremove-all-for-android%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216986%2fimplementing-stdfilesystemremove-all-for-android%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Is there a reason to not use
opendir/readdirAPI?$endgroup$
– vnp
yesterday
$begingroup$
This is much faster for dirs with too many files .
$endgroup$
– prog511
yesterday