Some file plugin structures RAII'ed.

This commit is contained in:
2025-04-27 11:41:19 -04:00
parent c64846c02c
commit 0c350a85c1

View File

@ -38,6 +38,11 @@
#include "dpiutil.hh"
#include "d_size.h"
#include <memory>
#include <string>
#include <vector>
#include <compare>
/*
* Debugging macros
*/
@ -69,18 +74,20 @@ typedef enum {
st_err
} FileState;
typedef struct {
char *full_path;
struct FileInfo {
std::string full_path;
const char *filename;
off_t size;
mode_t mode;
time_t mtime;
} FileInfo;
typedef struct {
char *dirname;
Dlist *flist; /* List of files and subdirectories (for sorting) */
} DilloDir;
std::strong_ordering operator <=> ( const FileInfo & ) const;
};
struct DilloDir {
std::string dirname;
std::vector< std::unique_ptr< FileInfo > > flist; /* List of files and subdirectories (for sorting) */
};
typedef struct {
Dsh *sh;
@ -202,6 +209,17 @@ static int File_comp(const FileInfo *f1, const FileInfo *f2)
}
}
std::strong_ordering
FileInfo::operator <=> ( const FileInfo &rhs ) const
{
const auto &lhs= *this;
const auto result= File_comp( &lhs, &rhs );
if( result < 0 ) return std::strong_ordering::less;
if( result > 0 ) return std::strong_ordering::greater;
return std::strong_ordering::equal;
}
/*
* Allocate a DilloDir structure, set safe values in it and sort the entries.
*/
@ -210,19 +228,17 @@ static DilloDir *File_dillodir_new(char *dirname)
struct stat sb;
struct dirent *de;
DIR *dir;
DilloDir *Ddir;
FileInfo *finfo;
char *fname;
std::unique_ptr< FileInfo > fifo;
std::string fname;
int dirname_len;
if (!(dir = opendir(dirname)))
return NULL;
Ddir = dNew(DilloDir, 1);
Ddir->dirname = dStrdup(dirname);
Ddir->flist = dList_new(512);
auto Ddir = std::make_unique< DilloDir >();
Ddir->dirname = dirname;
dirname_len = strlen(Ddir->dirname);
dirname_len = Ddir->dirname.size();
/* Scan every name and sort them */
while ((de = readdir(dir)) != 0) {
@ -238,28 +254,28 @@ static DilloDir *File_dillodir_new(char *dirname)
continue;
}
fname = dStrconcat(Ddir->dirname, de->d_name, NULL);
if (stat(fname, &sb) == -1) {
dFree(fname);
fname = Ddir->dirname + de->d_name;
if (stat(fname.c_str(), &sb) == -1) {
continue; /* ignore files we can't stat */
}
finfo = dNew(FileInfo, 1);
auto finfo = std::make_unique< FileInfo >();
finfo->full_path = fname;
finfo->filename = fname + dirname_len;
finfo->filename = finfo->full_path.c_str() + dirname_len;
finfo->size = sb.st_size;
finfo->mode = sb.st_mode;
finfo->mtime = sb.st_mtime;
dList_append(Ddir->flist, finfo);
Ddir->flist.push_back( std::move( finfo ) );
}
closedir(dir);
/* sort the entries */
dList_sort(Ddir->flist, (dCompareFunc)File_comp);
std::sort( begin( Ddir->flist ), end( Ddir->flist ),
[]( const auto &lhs, const auto &rhs ) { return *lhs < *rhs; } );
return Ddir;
return Ddir.release();
}
/*
@ -267,20 +283,7 @@ static DilloDir *File_dillodir_new(char *dirname)
*/
static void File_dillodir_free(DilloDir *Ddir)
{
int i;
FileInfo *finfo;
dReturn_if (Ddir == NULL);
for (i = 0; i < dList_length(Ddir->flist); ++i) {
finfo = reinterpret_cast< FileInfo * >( dList_nth_data(Ddir->flist, i) );
dFree(finfo->full_path);
dFree(finfo);
}
dList_free(Ddir->flist);
dFree(Ddir->dirname);
dFree(Ddir);
delete Ddir;
}
/*
@ -359,7 +362,7 @@ static void File_info2html(ClientInfo *client, FileInfo *finfo, int n)
} else if (finfo->mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
filecont = "Executable";
} else {
filecont = File_content_type(finfo->full_path);
filecont = File_content_type(finfo->full_path.c_str());
if (!filecont || !strcmp(filecont, "application/octet-stream"))
filecont = "unknown";
}
@ -424,9 +427,9 @@ static void File_send_dir(ClientInfo *client)
/* send HTTP header and HTML top part */
/* Send page title */
auto Udirname = Escape_uri_str(Ddir->dirname, NULL);
auto Udirname = Escape_uri_str(Ddir->dirname.c_str(), NULL);
HUdirname = Escape_html_str(Udirname.c_str());
Hdirname = Escape_html_str(Ddir->dirname);
Hdirname = Escape_html_str(Ddir->dirname.c_str());
a_Dpip_dsh_printf(client->sh, 0,
"HTTP/1.1 200 OK\r\n"
@ -445,13 +448,13 @@ static void File_send_dir(ClientInfo *client)
}
/* Output the parent directory */
File_print_parent_dir(client, Ddir->dirname);
File_print_parent_dir(client, Ddir->dirname.c_str());
/* HTML style toggle */
a_Dpip_dsh_write_str(client->sh, 0,
"&nbsp;&nbsp;<a href='dpi:/file/toggle'>%</a>\n");
if (dList_length(Ddir->flist)) {
if (not Ddir->flist.empty()) {
if (client->old_style) {
a_Dpip_dsh_write_str(client->sh, 0, "\n\n");
} else {
@ -473,13 +476,13 @@ static void File_send_dir(ClientInfo *client)
} else if (client->state == st_http) {
/* send directories as HTML contents */
for (n = 0; n < dList_length(Ddir->flist); ++n) {
File_info2html(client, reinterpret_cast< FileInfo * >( dList_nth_data(Ddir->flist,n) ), n+1);
for (n = 0; n < Ddir->flist.size(); ++n) {
File_info2html(client, Ddir->flist.at( n ).get(), n+1);
}
if (client->old_style) {
a_Dpip_dsh_write_str(client->sh, 0, "</pre>\n");
} else if (dList_length(Ddir->flist)) {
} else if (not Ddir->flist.empty()) {
a_Dpip_dsh_write_str(client->sh, 0, "</table>\n");
}