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;
}







1












$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;
}









share|improve this question











$endgroup$












  • $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


















1












$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;
}









share|improve this question











$endgroup$












  • $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














1












1








1





$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;
}









share|improve this question











$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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago









Deduplicator

11.9k1950




11.9k1950










asked 2 days ago









prog511prog511

61




61












  • $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$
    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$
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










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
});


}
});














draft saved

draft discarded


















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
















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Webac Holding Inhaltsverzeichnis Geschichte | Organisationsstruktur | Tochterfirmen |...

What's the meaning of a knight fighting a snail in medieval book illustrations?What is the meaning of a glove...

Salamanca Inhaltsverzeichnis Lage und Klima | Bevölkerungsentwicklung | Geschichte | Kultur und...