sys_chmod()
[akaros.git] / kern / src / vfs.c
index 18052f9..2fa4e47 100644 (file)
@@ -974,8 +974,10 @@ struct file *do_file_open(char *path, int flags, int mode)
                /* Create the inode/file.  get a fresh dentry too: */
                file_d = get_dentry(nd->dentry->d_sb, nd->dentry, nd->last.name);
                parent_i = nd->dentry->d_inode;
-               /* TODO: mode should be & ~umask.  Note that mode technically should
-                * only apply to future opens, though we apply it immediately. */
+               /* Note that the mode technically should only apply to future opens,
+                * but we apply it immediately. */
+               if (current)
+                       mode &= ~current->fs_env.umask;
                if (create_file(parent_i, file_d, mode)) {
                        kref_put(&file_d->d_kref);
                        path_release(nd);
@@ -1167,9 +1169,9 @@ out_path_only:
        return retval;
 }
 
-/* Checks to see if path can be accessed via mode.  Doesn't do much now.  This
- * is an example of decent error propagation from the lower levels via int
- * retvals. */
+/* Checks to see if path can be accessed via mode.  Need to actually send the
+ * mode along somehow, so this doesn't do much now.  This is an example of
+ * decent error propagation from the lower levels via int retvals. */
 int do_file_access(char *path, int mode)
 {
        struct nameidata nd_r = {0}, *nd = &nd_r;
@@ -1180,6 +1182,24 @@ int do_file_access(char *path, int mode)
        return retval;
 }
 
+int do_file_chmod(char *path, int mode)
+{
+       struct nameidata nd_r = {0}, *nd = &nd_r;
+       int retval = 0;
+       retval = path_lookup(path, 0, nd);
+       if (!retval) {
+               #if 0
+               /* TODO: when we have notions of uid, check for the proc's uid */
+               if (nd->dentry->d_inode->i_uid != UID_OF_ME)
+                       retval = -EPERM;
+               else
+               #endif
+                       nd->dentry->d_inode->i_mode = mode & 0777;
+       }
+       path_release(nd);       
+       return retval;
+}
+
 /* Opens and returns the file specified by dentry */
 struct file *dentry_open(struct dentry *dentry, int flags)
 {
@@ -1514,6 +1534,50 @@ int do_chdir(struct fs_struct *fs_env, char *path)
        return retval;
 }
 
+/* Returns a null-terminated string of up to length cwd_l containing the
+ * absolute path of fs_env, (up to fs_env's root).  Be sure to kfree the char*
+ * "kfree_this" when you are done with it.  We do this since it's easier to
+ * build this string going backwards.  Note cwd_l is not a strlen, it's an
+ * absolute size. */
+char *do_getcwd(struct fs_struct *fs_env, char **kfree_this, size_t cwd_l)
+{
+       struct dentry *dentry = fs_env->pwd;
+       size_t link_len;
+       char *path_start, *kbuf;
+
+       if (cwd_l < 2) {
+               set_errno(ERANGE);
+               return 0;
+       }
+       kbuf = kmalloc(cwd_l, 0);
+       if (!kbuf) {
+               set_errno(ENOMEM);
+               return 0;
+       }
+       *kfree_this = kbuf;
+       kbuf[cwd_l - 1] = '\0';
+       kbuf[cwd_l - 2] = '/';
+       /* for each dentry in the path, all the way back to the root of fs_env, we
+        * grab the dentry name, push path_start back enough, and write in the name,
+        * using /'s to terminate.  We skip the root, since we don't want it's
+        * actual name, just "/", which is set before each loop. */
+       path_start = kbuf + cwd_l - 2;  /* the last byte written */
+       while (dentry != fs_env->root) {
+               link_len = dentry->d_name.len;          /* this does not count the \0 */
+               if (path_start - (link_len + 2) < kbuf) {
+                       kfree(kbuf);
+                       set_errno(ERANGE);
+                       return 0;
+               }
+               path_start -= link_len + 1;     /* the 1 is for the \0 */
+               strncpy(path_start, dentry->d_name.name, link_len);
+               path_start--;
+               *path_start = '/';
+               dentry = dentry->d_parent;      
+       }
+       return path_start;
+}
+
 static void print_dir(struct dentry *dentry, char *buf, int depth)
 {
        struct dentry *child_d;