Some file plugin structures RAII'ed.
This commit is contained in:
91
dpi/file.cc
91
dpi/file.cc
@ -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,
|
||||
" <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");
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user