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

version» Context lines:

Roxen.git/server/modules/filesystems/filesystem.pike:861:    if (rr[1] == -3) {    return(1);    }    } else {    return(0);    }    }    return(0);   }    + //! Return @expr{1@} if both arguments refer to the same inode. + int is_same_inode(Stdio.Stat a_st, Stdio.Stat b_st) + { +  if (a_st == b_st) return 1; +  if ((a_st->mode == b_st->mode) && +  (a_st->size == b_st->size) && +  (a_st->ino == b_st->ino) && +  (a_st->dev == b_st->dev)) { +  return 1; +  } +  return 0; + } +    //! @[chmod()] that doesn't throw errors.   string safe_chmod(string path, int mask)   {    return describe_error(catch {    chmod(path, mask);    return 0;    });   }      mapping make_collection(string coll, RequestID id)
Roxen.git/server/modules/filesystems/filesystem.pike:1233:    if (size > 0) {    QUOTA_WERR("Deallocating " + size + "bytes.");    id->misc->quota_obj->deallocate(URI, size);    }    }       object to = Stdio.File();       TRACE_ENTER("PUT: Accepted", 0);    +  if ((size > -1) && (< "Darwin", "Win32" >)[System.uname()->sysname]) { +  // File exists, and we're on an OS where we assume a +  // case insensitive filesystem. +  // +  // NB: At least MacOS X has the misbehavior of renaming +  // preexisting files when opening with "wct". +  // +  // Avoid this by looking up the name from the filesystem. +  TRACE_ENTER(sprintf("Looking up path %O in real filesystem.", norm_f), 0); +  norm_f = Roxen.lookup_real_path_case_insens(norm_f, 1); +  TRACE_LEAVE(sprintf("FOund path: %O\n", norm_f)); +  } +     /* Clear the stat-cache for this file */    if (stat_cache) {    cache_set("stat_cache", norm_f, 0);    }       if(!to->open(norm_f, "wct", 0666))    {    int err = to->errno();    privs = 0;    TRACE_LEAVE("PUT: Open failed");
Roxen.git/server/modules/filesystems/filesystem.pike:1540:    TRACE_LEAVE("");    TRACE_LEAVE("MOVE disallowed (DELE disabled)");    return 0;    }    TRACE_LEAVE("Overwrite allowed.");    if (overwrite || (size > -1)) {    Stdio.Stat src_st = stat_file(f, id);    Stdio.Stat dst_st = stat_file(new_uri, id);    // Check that src and dst refers to different inodes.    // Needed on case insensitive filesystems. -  if (src_st->mode != dst_st->mode || -  src_st->size != dst_st->size || -  src_st->ino != dst_st->ino || -  src_st->dev != dst_st->dev) { +  if (!is_same_inode(src_st, dst_st)) {    TRACE_ENTER(sprintf("Deleting destination: %O...\n", new_uri), 0);    mapping(string:mixed) res = recurse_delete_files(new_uri, id);    if (res && (!sizeof (res) || res->error >= 300)) {    privs = 0;    TRACE_LEAVE("");    TRACE_LEAVE("MOVE: Recursive delete failed.");    if (sizeof (res))    set_status_for_path (new_uri, res->error, res->rettext);    return ([]);    }
Roxen.git/server/modules/filesystems/filesystem.pike:1749:    if (query("no_symlinks") && (contains_symlinks(path, dest))) {    errors++;    report_error(LOCALE(57,"Copy to %O failed. Permission denied.\n"),    dest);    TRACE_LEAVE("COPY: Contains symlinks. Permission denied");    return Roxen.http_status(403, "Permission denied.");    }    Stat dest_st = stat_file(dest, id);    if (dest_st) {    SIMPLE_TRACE_ENTER (this, "COPY: Destination exists"); +  if (is_same_inode(source_st, dest_st)) { +  TRACE_LEAVE("Source and destination are the same inode."); +  TRACE_LEAVE(""); +  return Roxen.http_status(403, "Permission denied."); +  } +  if (has_prefix(source, dest)) { +  TRACE_LEAVE("Destination contains source."); +  TRACE_LEAVE(""); +  return Roxen.http_status(403, "Permission denied."); +  }    switch(overwrite) {    case NEVER_OVERWRITE:    TRACE_LEAVE("");    TRACE_LEAVE("");    return Roxen.http_status(412, "Destination already exists.");    case DO_OVERWRITE:    if (!query("delete")) {    TRACE_LEAVE("COPY: Deletion not allowed.");    TRACE_LEAVE("");    return Roxen.http_status(405, "Not allowed.");
Roxen.git/server/modules/filesystems/filesystem.pike:1833:    } else if (source_st->isdir) {    TRACE_LEAVE("Already done (both are directories).");    TRACE_LEAVE("");    return Roxen.http_status(204, "Destination already existed.");    }    break;    }    }       if (source_st->isdir) { +  if (has_prefix(dest, source)) { +  TRACE_LEAVE("Source contains destination."); +  return Roxen.http_status(403, "Permission denied."); +  } +     mkdirs++;    object privs;    SETUID_TRACE("Creating directory/collection", 0);       int code = mkdir(dest_path);    int err_code = errno();       if (code) {    string msg = safe_chmod(dest_path, 0777 & ~(id->misc->umask || 022));    privs = 0;