Roxen.git / server / modules / filesystems / filesystem.pike

version» Context lines:

Roxen.git/server/modules/filesystems/filesystem.pike:1:   // This is a roxen module. Copyright © 1996 - 1999, Idonex AB.      // This is a virtual "file-system".   // It will be located somewhere in the name-space of the server.   // Also inherited by some of the other filesystems.      inherit "module";   inherit "roxenlib";   inherit "socket";    - constant cvs_version= "$Id: filesystem.pike,v 1.69 2000/03/07 21:15:36 mast Exp $"; + constant cvs_version= "$Id: filesystem.pike,v 1.70 2000/03/07 22:42:17 mast Exp $";   constant thread_safe=1;      #include <module.h>   #include <roxen.h>   #include <stat.h>   #include <request_trace.h>      #if DEBUG_LEVEL > 20   # ifndef FILESYSTEM_DEBUG   # define FILESYSTEM_DEBUG
Roxen.git/server/modules/filesystems/filesystem.pike:83:       defvar("searchpath", "NONE", "Search path", TYPE_DIR|VAR_INITIAL,    "This is where the module will find the files in the real "+    "file system");       defvar(".files", 0, "Show hidden files", TYPE_FLAG|VAR_MORE,    "If set, hidden files will be shown in dirlistings and you "    "will be able to retrieve them.");       defvar("dir", 1, "Enable directory listings per default", TYPE_FLAG|VAR_MORE, -  "If set, you have to create a file named .www_not_browsable (" -  "or .nodiraccess) in a directory to disable directory listings." +  "If set, you have to create a file named .www_not_browsable " +  "or .nodiraccess in a directory to disable directory listings."    " If unset, a file named .www_browsable in a directory will "    "_enable_ directory listings.\n");       defvar("tilde", 0, "Show backup files", TYPE_FLAG|VAR_MORE,    "If set, files ending with '~' or '#' or '.bak' will "+    "be shown in directory listings");       defvar("put", 0, "Handle the PUT method", TYPE_FLAG,    "If set, PUT can be used to upload files to the server.");   
Roxen.git/server/modules/filesystems/filesystem.pike:118:    "use NFS, but it does use some memory.\n"    "<p>Also note that the cached results are only rechecked when the "    "file is fetched with the no-cache pragma (produced e.g. by "    "Alt-Ctrl-Reload in Netscape), when the module is reloaded "    "or when the cached entry has expired. "    "Thus, it's not recommended to use this on filesystems that "    "change a lot.");       defvar("access_as_user", 0, "Access file as the logged in user",    TYPE_FLAG|VAR_MORE, -  "EXPERIMENTAL. Access file as the logged in user.<br>\n" -  "This is useful for eg named-ftp."); +  "Access file as the logged in user. This is useful for eg " +  "named-ftp.<br>\n" +  "WARNING: This can have severe impact on performance when using " +  "threads, since all threads need to be locked every time such " +  "an access is done.");       defvar("no_symlinks", 0, "Forbid access to symlinks", TYPE_FLAG|VAR_MORE, -  "EXPERIMENTAL.\n" +     "Forbid access to paths containing symbolic links.<br>\n"    "NOTE: This can cause *alot* of lstat system-calls to be performed "    "and can make the server much slower.");       defvar("charset", "iso-8859-1", "File charset", TYPE_STRING,    "The charset the files on disk have.");       defvar("internal_files", "", "Internal files", TYPE_STRING,    "A comma separated list of glob patterns that matches files "    "which should be considered internal. Internal files can't be "
Roxen.git/server/modules/filesystems/filesystem.pike:154:    internal_files = map (val / ",", String.trim_whites);    return 0;   }         string path;   int stat_cache;      void start()   { - #ifdef THREADS -  if(QUERY(access_as_user)) -  report_warning("It is not possible to use 'Access as user' when " -  "running with threads. Remove -DENABLE_THREADS from " -  "the start script if you really need this function\n"); - #endif -  +     path = QUERY(searchpath);    stat_cache = QUERY(stat_cache);    internal_files = map (QUERY (internal_files) / ",", String.trim_whites);    FILESYSTEM_WERR("Online at "+QUERY(mountpoint)+" (path="+path+")");    cache_expire("stat_cache");   }      string query_location()   {    return QUERY(mountpoint);
Roxen.git/server/modules/filesystems/filesystem.pike:189:    array fs;       FILESYSTEM_WERR("stat_file for \""+f+"\"");       if (FILTER_INTERNAL_FILE (f, id)) return 0;       if(stat_cache && !id->pragma["no-cache"] &&    (fs=cache_lookup("stat_cache",path+f)))    return fs[0];    - #ifndef THREADS +     object privs;    if (((int)id->misc->uid) && ((int)id->misc->gid) &&    (QUERY(access_as_user))) {    // NB: Root-access is prevented.    privs=Privs("Statting file", (int)id->misc->uid, (int)id->misc->gid );    } - #endif +        fs = file_stat(path + f); /* No security currently in this function */ - #ifndef THREADS +     privs = 0; - #endif +     if(!stat_cache)    return fs;    cache_set("stat_cache", path+f, ({fs}));    return fs;   }      string real_file( string f, RequestID id )   {    if(this->stat_file( f, id ))   /* This filesystem might be inherited by other filesystem, therefore
Roxen.git/server/modules/filesystems/filesystem.pike:233:      array find_dir( string f, RequestID id )   {    mixed ret;    array dir;       FILESYSTEM_WERR("find_dir for \""+f+"\"");       object privs;    - #ifndef THREADS +     if (((int)id->misc->uid) && ((int)id->misc->gid) &&    (QUERY(access_as_user))) {    // NB: Root-access is prevented.    privs=Privs("Getting dir", (int)id->misc->uid, (int)id->misc->gid );    } - #endif +        if(!(dir = get_dir( path + f ))) {    privs = 0;    return 0;    }    privs = 0;       if(!QUERY(dir))    // Access to this dir is allowed.    if(search(dir, ".www_browsable") == -1)
Roxen.git/server/modules/filesystems/filesystem.pike:479:    && (tmp = (id->not_query/"/")[-1])    && tmp[0] == '.') {    TRACE_LEAVE("Is .-file");    return 0;    }    if (FILTER_INTERNAL_FILE (f, id)) {    TRACE_LEAVE ("Is internal file");    return 0;    }    } - #ifndef THREADS +  +  TRACE_ENTER("Opening file \"" + f + "\"", 0); +     object privs;    if (((int)id->misc->uid) && ((int)id->misc->gid) &&    (QUERY(access_as_user))) {    // NB: Root-access is prevented.    privs=Privs("Getting file", (int)id->misc->uid, (int)id->misc->gid );    } - #endif -  -  TRACE_ENTER("Opening file \"" + f + "\"", 0); +     o = open( f, "r" ); -  - #ifndef THREADS +     privs = 0; - #endif +        if(!o || (QUERY(no_symlinks) && (contains_symlinks(path, oldf))))    {    errors++;    report_error("Open of " + f + " failed. Permission denied.\n");       TRACE_LEAVE("");    TRACE_LEAVE("Permission denied.");    return http_low_answer(403, "<h2>File exists, but access forbidden "    "by user</h2>");
Roxen.git/server/modules/filesystems/filesystem.pike:539:    }       if(QUERY(check_auth) && (!id->auth || !id->auth[0])) {    TRACE_LEAVE("MKDIR: Permission denied");    return http_auth_required("foo",    "<h1>Permission to 'MKDIR' denied</h1>");    }    mkdirs++;    object privs;    - // #ifndef THREADS // Ouch. This is is _needed_. Well well... +     if (((int)id->misc->uid) && ((int)id->misc->gid)) {    // NB: Root-access is prevented.    privs=Privs("Creating directory",    (int)id->misc->uid, (int)id->misc->gid );    } - // #endif +        if (QUERY(no_symlinks) && (contains_symlinks(path, oldf))) {    privs = 0;    errors++;    report_error("Creation of " + f + " failed. Permission denied.\n");    TRACE_LEAVE("MKDIR: Contains symlinks. Permission denied");    return http_low_answer(403, "<h2>Permission denied.</h2>");    }    -  TRACE_ENTER("MKDIR: Accepted", 0); -  +     int code = mkdir( f ); -  +     privs = 0; -  +  +  TRACE_ENTER("MKDIR: Accepted", 0); +     if (code) {    chmod(f, 0777 & ~(id->misc->umask || 022));    TRACE_LEAVE("MKDIR: Success");    TRACE_LEAVE("Success");    return http_string_answer("Ok");    } else {    TRACE_LEAVE("MKDIR: Failed");    TRACE_LEAVE("Failure");    return 0;    }
Roxen.git/server/modules/filesystems/filesystem.pike:607:    !id->misc->quota_obj->check_quota(uri, id->misc->len)) {    errors++;    report_warning("Creation of " + f + " failed. Out of quota.\n");    TRACE_LEAVE("PUT: Out of quota.");    return http_low_answer(413, "<h2>Out of disk quota.</h2>",    "413 Out of disk quota");    }       object privs;    - // #ifndef THREADS // Ouch. This is is _needed_. Well well... +     if (((int)id->misc->uid) && ((int)id->misc->gid)) {    // NB: Root-access is prevented.    privs=Privs("Saving file", (int)id->misc->uid, (int)id->misc->gid );    } - // #endif +        if (QUERY(no_symlinks) && (contains_symlinks(path, oldf))) {    privs = 0;    errors++;    report_error("Creation of " + f + " failed. Permission denied.\n");    TRACE_LEAVE("PUT: Contains symlinks. Permission denied");    return http_low_answer(403, "<h2>Permission denied.</h2>");    }    -  TRACE_ENTER("PUT: Accepted", 0); -  +     rm( f );    mkdirhier( f );       if (id->misc->quota_obj) {    QUOTA_WERR("Checking if the file already exists.");    if (size > 0) {    QUOTA_WERR("Deallocating " + size + "bytes.");    id->misc->quota_obj->deallocate(uri, size);    }    if (size) {    QUOTA_WERR("Deleting old file.");    rm(f);    }    }    -  +  object to = open(f, "wct"); +  privs = 0; +  +  TRACE_ENTER("PUT: Accepted", 0); +     /* Clear the stat-cache for this file */    if (stat_cache) {    cache_set("stat_cache", f, 0);    }    -  object to = open(f, "wct"); -  -  privs = 0; -  +     if(!to)    {    id->misc->error_code = 403;    TRACE_LEAVE("PUT: Open failed");    TRACE_LEAVE("Failure");    return 0;    }       // FIXME: Race-condition.    chmod(f, 0666 & ~(id->misc->umask || 022));
Roxen.git/server/modules/filesystems/filesystem.pike:718:    }       if(QUERY(check_auth) && (!id->auth || !id->auth[0])) {    TRACE_LEAVE("CHMOD: Permission denied");    return http_auth_required("foo",    "<h1>Permission to 'CHMOD' files denied</h1>");    }       object privs;    - // #ifndef THREADS // Ouch. This is is _needed_. Well well... +     if (((int)id->misc->uid) && ((int)id->misc->gid)) {    // NB: Root-access is prevented.    privs=Privs("CHMODing file", (int)id->misc->uid, (int)id->misc->gid );    } -  // #endif +        if (QUERY(no_symlinks) && (contains_symlinks(path, oldf))) {    privs = 0;    errors++;    TRACE_LEAVE("CHMOD: Contains symlinks. Permission denied");    return http_low_answer(403, "<h2>Permission denied.</h2>");    }    -  +  array err = catch(chmod(f, id->misc->mode & 0777)); +  privs = 0; +     chmods++;       TRACE_ENTER("CHMOD: Accepted", 0);       if (stat_cache) {    cache_set("stat_cache", f, 0);    } - #ifdef DEBUG -  werror(sprintf("CHMODing file "+f+" to 0%o\n", id->misc->mode)); - #endif -  array err = catch(chmod(f, id->misc->mode & 0777)); -  privs = 0; +        if(err)    {    id->misc->error_code = 403;    TRACE_LEAVE("CHMOD: Failure");    TRACE_LEAVE("Failure");    return 0;    }    TRACE_LEAVE("CHMOD: Success");    TRACE_LEAVE("Success");
Roxen.git/server/modules/filesystems/filesystem.pike:802:    return 0;    }       if (FILTER_INTERNAL_FILE (movefrom, id) ||    FILTER_INTERNAL_FILE (f, id)) {    id->misc->error_code = 405;    TRACE_LEAVE("MV to or from internal file is disallowed");    return 0;    }    -  moves++; -  +     object privs;    - // #ifndef THREADS // Ouch. This is is _needed_. Well well... +     if (((int)id->misc->uid) && ((int)id->misc->gid)) {    // NB: Root-access is prevented.    privs=Privs("Moving file", (int)id->misc->uid, (int)id->misc->gid );    } - // #endif +        if (QUERY(no_symlinks) &&    ((contains_symlinks(path, oldf)) ||    (contains_symlinks(path, id->misc->move_from)))) {    privs = 0;    errors++;    TRACE_LEAVE("MV: Contains symlinks. Permission denied");    return http_low_answer(403, "<h2>Permission denied.</h2>");    }    -  +  int code = mv(movefrom, f); +  privs = 0; +  +  moves++; +     TRACE_ENTER("MV: Accepted", 0);       /* Clear the stat-cache for this file */ - #ifdef __NT__ -  // if(movefrom[-1] == '/') -  // movefrom = move_from[..strlen(movefrom)-2]; - #endif +     if (stat_cache) {    cache_set("stat_cache", movefrom, 0);    cache_set("stat_cache", f, 0);    } - #ifdef DEBUG -  werror("Moving file "+movefrom+" to "+ f+"\n"); - #endif +     -  int code = mv(movefrom, f); -  privs = 0; -  +     if(!code)    {    id->misc->error_code = 403;    TRACE_LEAVE("MV: Move failed");    TRACE_LEAVE("Failure");    return 0;    }    TRACE_LEAVE("MV: Success");    TRACE_LEAVE("Success");    return http_string_answer("Ok");
Roxen.git/server/modules/filesystems/filesystem.pike:915:    }       if(size < -1)    {    id->misc->error_code = 405;    TRACE_LEAVE("MOVE: Cannot overwrite directory");    return 0;    }       object privs; -  - // #ifndef THREADS // Ouch. This is is _needed_. Well well... +     if (((int)id->misc->uid) && ((int)id->misc->gid)) {    // NB: Root-access is prevented.    privs=Privs("Moving file", (int)id->misc->uid, (int)id->misc->gid );    } - // #endif +        if (QUERY(no_symlinks) &&    ((contains_symlinks(path, f)) ||    (contains_symlinks(path, moveto)))) {    privs = 0;    errors++;    TRACE_LEAVE("MOVE: Contains symlinks. Permission denied");    return http_low_answer(403, "<h2>Permission denied.</h2>");    }    -  +  int code = mv(f, moveto); +  privs = 0; +     TRACE_ENTER("MOVE: Accepted", 0);       moves++;       /* Clear the stat-cache for this file */ - #ifdef __NT__ -  // if(movefrom[-1] == '/') -  // movefrom = move_from[..strlen(movefrom)-2]; - #endif +     if (stat_cache) {    cache_set("stat_cache", moveto, 0);    cache_set("stat_cache", f, 0);    } - #ifdef DEBUG -  werror("Moving file " + f + " to " + moveto + "\n"); - #endif +     -  int code = mv(f, moveto); -  privs = 0; -  +     if(!code)    {    id->misc->error_code = 403;    TRACE_LEAVE("MOVE: Move failed");    TRACE_LEAVE("Failure");    return 0;    }    TRACE_LEAVE("MOVE: Success");    TRACE_LEAVE("Success");    return http_string_answer("Ok");