From: Hongli Lai Date: 2008-03-07T21:01:39+09:00 Subject: Re: PATCH: mknod and mkfifo support [Was: Ruby does not support mkfifo] This is a multi-part message in MIME format. --------------000803010500090301000607 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hongli Lai wrote: > In my last email, I mentioned that there was an old patch that > implements mknod() and mkfifo() support. That patch no longer works. > I've ported the patch to Ruby 1.9, improved its documentation, and wrote > unit tests. Please review the attached patch. > > Regards, > Hongli Lai > Here is the same patch, backported to Ruby 1.8. --------------000803010500090301000607 Content-Type: text/x-patch; name="ruby-mkfifo-mknod-1.8.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="ruby-mkfifo-mknod-1.8.diff" diff --git a/configure.in b/configure.in index 63ccb61..db3d0c1 100644 --- a/configure.in +++ b/configure.in @@ -561,7 +561,8 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid syscall chroot fsync getcwd eaccess\ group_member dlopen sigprocmask\ sigaction sigsetjmp _setjmp setsid telldir seekdir fchmod\ mktime timegm gettimeofday\ - cosh sinh tanh round setuid setgid setenv unsetenv) + cosh sinh tanh round setuid setgid setenv unsetenv\ + mkfifo mknod) AC_ARG_ENABLE(setreuid, [ --enable-setreuid use setreuid()/setregid() according to need even if obsolete.], [use_setreuid=$enableval]) diff --git a/file.c b/file.c index 85ae53b..897dd7d 100644 --- a/file.c +++ b/file.c @@ -3465,6 +3465,114 @@ rb_f_test(argc, argv) return Qnil; /* not reached */ } +/* + * call-seq: + * File.mknod(file_name, [type, [mode, [dev]]]) => 0 + * + * Create a filesystem node (file, device special file or named pipe) + * named _file_name_, specified by _mode_ and _dev_. + * + * _type_ and _mode_ specifies the type and the permissions of node to + * be created respectively. + * + * The permissions are modified by the process's umask in the usual + * way: the permissions of the created node are (mode & ~umask). + * + * _type_ should be one of: + * - +?f+ - normal file (which will be created empty) + * - +?c+ - character special file + * - +?b+ - block special file + * - +?p+ - FIFO (named pipe) + * - +nil+ - normal file + * + * Raises: + * - +ArgumentError+ - _type_ is unknown or not supported on the current platform. + * - +SystemCallError+ - Something went wrong during the creation of the node. + * - +NotImplementedError+ - This call is not supported on the current platform. + */ + +static VALUE +rb_file_s_mknod(argc, argv) + int argc; + VALUE *argv; +{ +#ifdef HAVE_MKNOD + VALUE path, type, vmode, vdev; + int mode = 0666, dev = 0, t; + + rb_secure(4); + switch (rb_scan_args(argc, argv, "13", &path, &type, &vmode, &vdev)) { + case 4: + dev = NUM2INT(vdev); + case 3: + mode = NUM2INT(vmode) & ~S_IFMT; + } + SafeStringValue(path); + if (!NIL_P(type)) { + rb_check_safe_obj(type); + switch (t = NUM2CHR(type)) { + case 'f': mode |= S_IFREG; break; + case 'c': mode |= S_IFCHR; break; +#ifdef S_IFBLK + case 'b': mode |= S_IFBLK; break; +#endif +#ifdef S_IFIFO + case 'p': mode |= S_IFIFO; break; +#endif + default: + rb_raise(rb_eArgError, "unknown node type - %c", t); + } + } + if (mknod(StringValueCStr(path), mode, dev)) { + rb_sys_fail("mknod"); + } +#else + rb_notimplement(); +#endif + return INT2FIX(0); +} + +/* + * call-seq: + * File.mkfifo(file_name, mode) => 0 + * + * Creates a FIFO special file (named pipe) with name _file_name_. _mode_ + * specifies the FIFO's permissions. It is modified by the process's + * umask in the usual way: the permissions of the created file are + * (mode & ~umask). + * + * Raises: + * - +SystemCallError+ - Something went wrong during the creation of the FIFO. + * - +NotImplementedError+ - This call is not supported on the current platform. + */ + +static VALUE +rb_file_s_mkfifo(argc, argv) + int argc; + VALUE *argv; +{ +#if !defined HAVE_MKFIFO && defined HAVE_MKNOD && defined S_IFIFO + #define mkfifo(path, mode) mknod(path, (mode)&~S_IFMT|S_IFIFO, 0) + #define HAVE_MKFIFO +#endif +#ifdef HAVE_MKFIFO + VALUE path, vmode; + int mode = 0666; + + rb_secure(4); + if (rb_scan_args(argc, argv, "11", &path, &vmode) > 1) { + mode = NUM2INT(vmode); + } + SafeStringValue(path); + if (mkfifo(StringValueCStr(path), mode)) { + rb_sys_fail("mkfifo"); + } +#else + rb_notimplement(); +#endif + return INT2FIX(0); +} + /* @@ -4461,6 +4569,8 @@ Init_File() rb_define_singleton_method(rb_cFile, "rename", rb_file_s_rename, 2); rb_define_singleton_method(rb_cFile, "umask", rb_file_s_umask, -1); rb_define_singleton_method(rb_cFile, "truncate", rb_file_s_truncate, 2); + rb_define_singleton_method(rb_cFile, "mknod", rb_file_s_mknod, -1); + rb_define_singleton_method(rb_cFile, "mkfifo", rb_file_s_mkfifo, -1); rb_define_singleton_method(rb_cFile, "expand_path", rb_file_s_expand_path, -1); rb_define_singleton_method(rb_cFile, "basename", rb_file_s_basename, -1); rb_define_singleton_method(rb_cFile, "dirname", rb_file_s_dirname, 1); --------------000803010500090301000607--