r284 - in trunk: . scripts

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Fri May 18 12:35:55 EDT 2007


Author: icculus
Date: 2007-05-18 12:35:55 -0400 (Fri, 18 May 2007)
New Revision: 284

Modified:
   trunk/docs.txt
   trunk/fileio.c
   trunk/lua_glue.c
   trunk/platform.h
   trunk/platform_unix.c
   trunk/scripts/mojosetup_init.lua
   trunk/scripts/mojosetup_mainline.lua
Log:
Permissions support...let mkdir set permissions, and let config file specify
 file/dir permissions.


Modified: trunk/docs.txt
===================================================================
--- trunk/docs.txt	2007-05-18 16:31:04 UTC (rev 283)
+++ trunk/docs.txt	2007-05-18 16:35:55 UTC (rev 284)
@@ -157,6 +157,7 @@
   mustBeFunction: Error if isn't a function (can be C or Lua).
   mustBeNumber: Error if isn't a number.
   mustBeUrl: Error if isn't a string that matches the regexp "^.+://.-/.*".
+  mustBePerms: Error if isn't a valid permissions string for the platform.
   mustBeStringOrTableOfStrings: Error if isn't a string or an array of strings.
 
  Attributes that aren't explicitly specified take on their default value. In
@@ -576,7 +577,21 @@
             return dest    -- everything else can go through as-is.
          end
 
+    Filters can optionally return a second argument, a string, that defines
+    the destination file's permissions. This can be omitted, or nil, to use
+    the default permissions:
 
+        filter = function(dest)
+            if dest == "mygame-binary" then
+                return dest, "0755"   -- make sure it's executable.
+            end
+            return dest   -- everything else just goes through as-is.
+        end
+
+    Please see the documentation for Setup.File's "permissions" attribute for
+    further discussion.
+
+
    allowoverwrite (no default, mustBeBool)
 
     If true, the installer will overwrite existing files without warning. If
@@ -587,6 +602,34 @@
     They are deleted only after a successful install.
 
 
+   permissions (no default, mustBePerms)
+
+    Override the permissions that these files will be created with. This is
+    a string for future expansion (non-Unix systems, extended attributes, etc),
+    and since Lua does not have syntax for specifying octal numbers directly.
+
+    Currently this string maps to Unix permissions as an octal number:
+    "0644" would be read/write access for the user, and read-only for the
+    group and everyone else.
+
+    If not specified, the permissions will be set to whatever is already
+    associated with the file (such as the Unix permissions in a .tar file's
+    entry).
+
+    Please note that files coming from a real filesystem will have their
+    defaults overridden by the installer (to "0644"), since operating systems
+    tend to report every file on a CD-ROMs as read-only and executable on some
+    Unix systems. Plan accordingly.
+
+    You can return a permissions string as the second value from your filter
+    function as well, which may be more efficient if you only need to change
+    a few files, as each Setup.File has to iterate the whole archive, or need
+    to adjust permissions in only a portion of a downloaded archive. This
+    attribute applies permissions to ever installed file through this element.
+    If this attribute is set and the filter returns a non-nil permission, the
+    filter takes precedence.
+
+
 Add any localized strings:
 
 If you added strings to the installer or your config file that you want

Modified: trunk/fileio.c
===================================================================
--- trunk/fileio.c	2007-05-18 16:31:04 UTC (rev 283)
+++ trunk/fileio.c	2007-05-18 16:35:55 UTC (rev 284)
@@ -387,11 +387,11 @@
     {
         ar->prevEnum.filesize = statbuf.st_size;
 
-        // !!! FIXME: not sure this is the best thing.
         // We currently force the perms from physical files, since CDs on
         //  Linux tend to mark every files as executable and read-only. If you
         //  want to install something with specific permissions, wrap it in a
-        //  tarball or chmod it from a postinstall hook in your config file.
+        //  tarball, or use Setup.File.permissions, or return a permissions
+        //  string from Setup.File.filter.
         //ar->prevEnum.perms = statbuf.st_mode;
         ar->prevEnum.perms = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 

Modified: trunk/lua_glue.c
===================================================================
--- trunk/lua_glue.c	2007-05-18 16:31:04 UTC (rev 283)
+++ trunk/lua_glue.c	2007-05-18 16:35:55 UTC (rev 284)
@@ -673,18 +673,37 @@
 {
     MojoArchive *archive = (MojoArchive *) lua_touserdata(L, 1);
     const char *path = luaL_checkstring(L, 2);
+    uint16 perms = archive->prevEnum.perms;
     boolean retval = false;
     MojoInput *in = archive->openCurrentEntry(archive);
     if (in != NULL)
     {
-        retval = MojoInput_toPhysicalFile(in, path, archive->prevEnum.perms,
-                                              writeCallback, L);
+        if (!lua_isnil(L, 3))
+        {
+            boolean valid = false;
+            const char *permstr = luaL_checkstring(L, 3);
+            perms = MojoPlatform_makePermissions(permstr, &valid);
+            if (!valid)
+                fatal(_("BUG: '%s' is not a valid permission string"), permstr);
+        } // if
+        retval = MojoInput_toPhysicalFile(in, path, perms, writeCallback, L);
     } // if
 
     return retvalBoolean(L, retval);
 } // luahook_writefile
 
 
+static int luahook_isvalidperms(lua_State *L)
+{
+    boolean valid = false;
+    const char *permstr = NULL;
+    if (!lua_isnil(L, 1))
+        permstr = luaL_checkstring(L, 1);
+    MojoPlatform_makePermissions(permstr, &valid);
+    return retvalBoolean(L, valid);
+} // luahook_isvalidperms
+
+
 static int luahook_download(lua_State *L)
 {
     boolean retval = false;
@@ -811,7 +830,18 @@
 static int luahook_platform_mkdir(lua_State *L)
 {
     const char *dir = luaL_checkstring(L, 1);
-    return retvalBoolean(L, MojoPlatform_mkdir(dir));
+    uint16 perms = 0;
+    if (lua_isnil(L, 2))
+        perms = MojoPlatform_defaultDirPerms();
+    else
+    {
+        boolean valid = false;
+        const char *permstr = luaL_checkstring(L, 2);
+        perms = MojoPlatform_makePermissions(permstr, &valid);
+        if (!valid)
+            fatal(_("BUG: '%s' is not a valid permission string"), permstr);
+    } // if
+    return retvalBoolean(L, MojoPlatform_mkdir(dir, perms));
 } // luahook_platform_mkdir
 
 
@@ -1330,6 +1360,7 @@
         set_cfunc(luaState, luahook_wildcardmatch, "wildcardmatch");
         set_cfunc(luaState, luahook_truncatenum, "truncatenum");
         set_cfunc(luaState, luahook_date, "date");
+        set_cfunc(luaState, luahook_isvalidperms, "isvalidperms");
 
         // Set some information strings...
         lua_newtable(luaState);

Modified: trunk/platform.h
===================================================================
--- trunk/platform.h	2007-05-18 16:31:04 UTC (rev 283)
+++ trunk/platform.h	2007-05-18 16:35:55 UTC (rev 284)
@@ -47,7 +47,7 @@
 boolean MojoPlatform_symlink(const char *src, const char *dst);
 
 // !!! FIXME: comment me.
-boolean MojoPlatform_mkdir(const char *path);
+boolean MojoPlatform_mkdir(const char *path, uint16 perms);
 
 // Move a file to a new name. This has to be a fast (if not atomic) operation,
 //  so if it would require a legitimate copy to another filesystem or device,
@@ -73,6 +73,20 @@
 // !!! FIXME: comment me.
 char *MojoPlatform_findMedia(const char *uniquefile);
 
+// Convert a string into a permissions bitmask. On Unix, this is currently
+//  expected to be an octal string like "0755", but may except other forms
+//  in the future, and other platforms may need to interpret permissions
+//  differently. (str) may be NULL for defaults, and is considered valid.
+// If (str) is not valid, return a reasonable default and set (*valid) to
+//  false. Otherwise, set (*valid) to true and return the converted value.
+uint16 MojoPlatform_makePermissions(const char *str, boolean *valid);
+
+// Return a default, sane set of permissions for a newly-created file.
+uint16 MojoPlatform_defaultFilePerms(void);
+
+// Return a default, sane set of permissions for a newly-created directory.
+uint16 MojoPlatform_defaultDirPerms(void);
+
 // Wrappers for Unix dlopen/dlsym/dlclose, sort of. Instead of a filename,
 //  these take a memory buffer for the library. If you can't load this
 //  directly in RAM, the platform should write it to a temporary file first,

Modified: trunk/platform_unix.c
===================================================================
--- trunk/platform_unix.c	2007-05-18 16:31:04 UTC (rev 283)
+++ trunk/platform_unix.c	2007-05-18 16:35:55 UTC (rev 284)
@@ -482,10 +482,10 @@
 } // MojoPlatform_symlink
 
 
-boolean MojoPlatform_mkdir(const char *path)
+boolean MojoPlatform_mkdir(const char *path, uint16 perms)
 {
     // !!! FIXME: error if already exists?
-    return (mkdir(path, 0755) == 0);
+    return (mkdir(path, perms) == 0);
 } // MojoPlatform_mkdir
 
 
@@ -544,6 +544,37 @@
 } // MojoPlatform_perms
 
 
+uint16 MojoPlatform_defaultFilePerms(void)
+{
+    return 0644;
+} // MojoPlatform_defaultFilePerms
+
+
+uint16 MojoPlatform_defaultDirPerms(void)
+{
+    return 0755;
+} // MojoPlatform_defaultDirPerms
+
+
+uint16 MojoPlatform_makePermissions(const char *str, boolean *_valid)
+{
+    uint16 retval = 0644;
+    boolean valid = true;
+    if (str != NULL)
+    {
+        char *endptr = NULL;
+        long strval = strtol(str, &endptr, 8);
+        // complete string was a valid number?
+        valid = ((*endptr == '\0') && (strval >= 0) && (strval <= 0xFFFF));
+        if (valid)
+            retval = (uint16) strval;
+    } // if
+
+    *_valid = valid;
+    return retval;
+} // MojoPlatform_makePermissions
+
+
 boolean MojoPlatform_chmod(const char *fname, uint16 p)
 {
     return (chmod(fname, p) != -1);

Modified: trunk/scripts/mojosetup_init.lua
===================================================================
--- trunk/scripts/mojosetup_init.lua	2007-05-18 16:31:04 UTC (rev 283)
+++ trunk/scripts/mojosetup_init.lua	2007-05-18 16:35:55 UTC (rev 284)
@@ -128,6 +128,7 @@
 
 local function schema_assert(test, fnname, elem, errstr)
     if not test then
+        -- !!! FIXME: error()? localization?
         error(fnname .. "::" .. elem .. " " .. errstr .. ".", 0)
     end
 end
@@ -209,6 +210,12 @@
     end
 end
 
+local function mustBePerms(fnname, elem, val)
+    mustBeString(fnname, elem, val)
+    local valid = MojoSetup.isvalidperms(val)
+    schema_assert(valid, fnname, elem, "Permission string is invalid")
+end
+
 local function sanitize(fnname, tab, elems)
     mustBeTable(fnname, "", tab)
     tab._type_ = string.lower(fnname) .. "s";   -- "Eula" becomes "eulas".
@@ -412,6 +419,7 @@
         { "wildcards", nil, mustBeStringOrTableOfStrings },
         { "filter", nil, mustBeFunction },
         { "allowoverwrite", nil, mustBeBool },
+        { "permissions", nil, mustBePerms },
     })
 end
 

Modified: trunk/scripts/mojosetup_mainline.lua
===================================================================
--- trunk/scripts/mojosetup_mainline.lua	2007-05-18 16:31:04 UTC (rev 283)
+++ trunk/scripts/mojosetup_mainline.lua	2007-05-18 16:35:55 UTC (rev 284)
@@ -226,7 +226,7 @@
 end
 
 
-local function install_file(path, archive, file, option)
+local function install_file(path, archive, file, option, perms)
     -- Upvalued so we don't look these up each time...
     local fname = string.gsub(path, "^.*/", "", 1)  -- chop the dirs off...
     local ptype = _("Installing")  -- !!! FIXME: localization.
@@ -245,7 +245,7 @@
     end
 
     MojoSetup.installed_files[#MojoSetup.installed_files+1] = path
-    if not MojoSetup.writefile(archive, path, callback) then
+    if not MojoSetup.writefile(archive, path, perms, callback) then
         -- !!! FIXME: formatting!
         if not keepgoing then
             MojoSetup.logerror("User cancelled install during file write.")
@@ -270,9 +270,9 @@
 end
 
 
-local function install_directory(path)
+local function install_directory(path, perms)
     MojoSetup.installed_files[#MojoSetup.installed_files+1] = path
-    if not MojoSetup.platform.mkdir(path) then
+    if not MojoSetup.platform.mkdir(path, perms) then
         -- !!! FIXME: formatting
         MojoSetup.logerror("Failed to create dir '" .. path .. "'")
         MojoSetup.fatal(_("mkdir failed"))
@@ -291,7 +291,7 @@
         if item ~= "" then
             fullpath = fullpath .. "/" .. item
             if not MojoSetup.platform.exists(fullpath) then
-                install_directory(fullpath)
+                install_directory(fullpath, nil)
             end
         end
     end
@@ -361,8 +361,14 @@
         dest = dest .. "/" .. entdest
     end
 
+    local perms = file.permissions   -- may be nil
+
     if file.filter ~= nil then
-        dest = file.filter(dest)
+        local filterperms
+        dest, filterperms = file.filter(dest)
+        if filterperms ~= nil then
+            perms = filterperms
+        end
     end
 
     if dest ~= nil then  -- Only install if file wasn't filtered out
@@ -370,9 +376,9 @@
         if permit_write(dest, ent, file) then
             install_parent_dirs(dest)
             if ent.type == "file" then
-                install_file(dest, archive, file, option)
+                install_file(dest, archive, file, option, perms)
             elseif ent.type == "dir" then
-                install_directory(dest)
+                install_directory(dest, perms)
             elseif ent.type == "symlink" then
                 install_symlink(dest, ent.linkdest)
             else  -- !!! FIXME: device nodes, etc...




More information about the mojosetup-commits mailing list