📄 file.c
字号:
/* * File: file.c :) * * Copyright (C) 2000, 2001 Jorge Arellano Cid <jcid@inf.utfsm.cl> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *//* * Directory scanning is no longer streamed, but it gets sorted instead! * Directory entries on top, files next. * Not forked anymore; pthread handled. * With new HTML layout. */#include <pthread.h>#include <ctype.h> /* for tolower */#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <fcntl.h>#include <string.h>#include <time.h>#include <stdio.h>#include <signal.h>#include <math.h> /* for rint */#include <errno.h> /* for errno */#include "Url.h"#include "IO.h"#include "../list.h"#include "../web.h"#include "../interface.h"typedef struct _DilloDir { gint FD_Write, FD_Read; char *dirname; DIR *dir; gboolean scanned; /* Flag: Have we scanned it? */ char **dlist; /* List of subdirectories (for sorting) */ gint dlist_size; gint dlist_max; gint dlist_idx; char **flist; /* List of files (for sorting) */ gint flist_size; gint flist_max; gint flist_idx; pthread_t th1; /* This transfer's thread id. */} DilloDir;typedef struct { gint FD_Write, /* Where we write */ FD_Read; /* Where our clients read */ gint FD; /* Our local-file descriptor */ char *Filename; const char *ContentType; glong FileSize; pthread_t th1; /* This transfer's thread id. */} DilloFile;/* * Local data *//* * Forward references */static char *File_content_type(const char *filename);static gint File_get_file(const gchar *FileName);static gint File_get_dir(const gchar *DirName);static char *File_dir2html(DilloDir *Ddir);static void File_not_found_msg(DilloWeb *web, const char *filename, int fd);/* * Allocate a DilloFile structure, and set working values in it. */static DilloFile *File_dillofile_new(const char *filename){ gint fds[2], fd; struct stat sb; DilloFile *Dfile; if ( (fd = open(filename, O_RDONLY)) < 0 || pipe(fds) ) return NULL; Dfile = g_new(DilloFile, 1); Dfile->FD_Read = fds[0]; Dfile->FD_Write = fds[1]; Dfile->FD = fd; Dfile->Filename = g_strdup(filename); Dfile->ContentType = File_content_type(filename); Dfile->FileSize = fstat(fd, &sb) ? -1 : (glong) sb.st_size; return Dfile;}/* * Deallocate a DilloFile structure. */static void File_dillofile_free(DilloFile *Dfile){ g_free(Dfile->Filename); g_free(Dfile);}/* * Allocate a DilloDir structure, and set safe values in it. */static DilloDir *File_dillodir_new(char *dirname){ DIR *dir; gint fds[2]; DilloDir *Ddir; if ( !(dir = opendir(dirname)) || pipe(fds) ) return NULL; Ddir = g_new(DilloDir, 1); Ddir->dir = dir; Ddir->scanned = FALSE; Ddir->dirname = g_strdup(dirname); Ddir->FD_Read = fds[0]; Ddir->FD_Write = fds[1]; Ddir->dlist = NULL; Ddir->dlist_size = 0; Ddir->dlist_max = 256; Ddir->dlist_idx = 0; Ddir->flist = NULL; Ddir->flist_size = 0; Ddir->flist_max = 256; Ddir->flist_idx = 0; return Ddir;}/* * Deallocate a DilloDir structure. */static void File_dillodir_free(DilloDir *Ddir){ g_free(Ddir->dirname); g_free(Ddir);}/* * Read a local file, and send it through a pipe. * (This function runs on its own thread) */static void *File_transfer_file(void *data){ char buf[8192]; DilloFile *Dfile = data; ssize_t nbytes; /* Set this thread to detached state */ pthread_detach(Dfile->th1); /* Send content type info */ sprintf(buf, "Content-Type: %s\n", Dfile->ContentType); write(Dfile->FD_Write, buf, strlen(buf)); /* Send File Size info */ if (Dfile->FileSize != -1) { sprintf(buf, "Content-length: %ld\n", Dfile->FileSize); write(Dfile->FD_Write, buf, strlen(buf)); } /* Send end-of-header */ strcpy(buf, "\n"); write(Dfile->FD_Write, buf, strlen(buf)); /* Append raw file contents */ while ( (nbytes = read(Dfile->FD, buf, 8192)) != 0 ) { write(Dfile->FD_Write, buf, nbytes); } close(Dfile->FD); close(Dfile->FD_Write); File_dillofile_free(Dfile); return NULL;}/* * Read a local directory, translate it to html, and send it through a pipe. * (This function runs on its own thread) */static void *File_transfer_dir(void *data){ char buf[8192], *s; DilloDir *Ddir = data; /* Set this thread to detached state */ pthread_detach(Ddir->th1); /* Send MIME content/type info */ sprintf(buf, "Content-Type: %s\n\n", File_content_type("dir.html")); write(Ddir->FD_Write, buf, strlen(buf)); /* Send page title */ sprintf(buf, "<HTML><HEAD><TITLE>%s%s</TITLE></HEAD>\n", "file:", Ddir->dirname); write(Ddir->FD_Write, buf, strlen(buf)); sprintf(buf, "<BODY><H1>%s %s</H1>\n<pre>\n", "Directory listing of", Ddir->dirname); write(Ddir->FD_Write, buf, strlen(buf)); /* Append formatted directory contents */ while ( (s = File_dir2html(Ddir)) ){ write(Ddir->FD_Write, s, strlen(s)); } /* Close open HTML tags */ sprintf(buf, "\n</pre></BODY></HTML>\n"); write(Ddir->FD_Write, buf, strlen(buf)); close(Ddir->FD_Write); closedir(Ddir->dir); Ddir->dir = NULL; File_dillodir_free(Ddir); return NULL;}/* * Return 1 if the extension matches that of the filename. */static gint File_ext(const char *filename, const char *ext){ char *e; if ( !(e = strrchr(filename, '.')) ) return 0; return (strcasecmp(ext, ++e) == 0);}/* * Based on the extension, return the content_type for the file. */static char *File_content_type(const char *filename){ if (File_ext(filename, "gif")) { return "image/gif"; } else if (File_ext(filename, "jpg") || File_ext(filename, "jpeg")) { return "image/jpeg"; } else if (File_ext(filename, "png")) { return "image/png"; } else if (File_ext(filename, "html") || File_ext(filename, "htm") || File_ext(filename, "shtml")) { return "text/html"; } return "text/plain";}/* * Create a new file connection for 'Url', and asynchronously * feed the bytes that come back to the cache. * ( Data = Requested Url; ExtraData = Web structure ) */static void File_get(ChainLink *Info, void *Data, void *ExtraData){ const gchar *path; gchar *filename; gint fd; struct stat sb; IOData_t *io; const DilloUrl *Url = Data; DilloWeb *web = ExtraData; path = URL_PATH_(Url); if (!path || !strcmp(path, ".") || !strcmp(path, "./")) /* if there's no path in the URL, show current directory */ filename = g_get_current_dir(); else if (!strcmp(path, "~") || !strcmp(path, "~/")) filename = g_strdup(g_get_home_dir()); else filename = a_Url_parse_hex_path(Url); if ( stat(filename, &sb) != 0 ) { /* stat failed, prepare a file-not-found error. */ fd = -2; } else if (S_ISDIR(sb.st_mode)) { /* set up for reading directory */ fd = File_get_dir(filename); } else { /* set up for reading a file */ fd = File_get_file(filename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -