summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-09-18 06:56:38 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-09-18 06:56:38 +0000
commitde5a85496ac4ae7bd24b5fc7acb8001a5e4d8b7d (patch)
tree0ad108b04b1012522217a02b8e7f7dd940943759 /dir.c
parent4c28c7d1af7ce6c30cc1bc9c0e5685c0ef17dc13 (diff)
* array.c (rb_ary_equal): element size might change during
comparison. [ruby-dev:24254] * array.c (rb_ary_diff): ditto. [ruby-dev:24274] * array.c (rb_ary_select): ditto. [ruby-dev:24278] * array.c (rb_ary_delete): ditto. [ruby-dev:24283] * array.c (rb_ary_rindex): ditto. [ruby-dev:24275] * array.c (rb_ary_initialize): element size might change during initializing block. [ruby-dev:24284] * dir.c (dir_s_chdir): avoid memory leak and unnecessary chdir to the original directory when exception has caused in changing direcotry or within block. thanks to Johan Holmberg <holmberg@iar.se> [ruby-core:03446] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6922 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c57
1 files changed, 37 insertions, 20 deletions
diff --git a/dir.c b/dir.c
index f4ec1fa..9327022 100644
--- a/dir.c
+++ b/dir.c
@@ -542,24 +542,42 @@ dir_close(dir)
static void
dir_chdir(path)
- const char *path;
+ VALUE path;
{
- if (chdir(path) < 0)
- rb_sys_fail(path);
+ if (chdir(RSTRING(path)->ptr) < 0)
+ rb_sys_fail(RSTRING(path)->ptr);
}
static int chdir_blocking = 0;
static VALUE chdir_thread = Qnil;
+struct chdir_data {
+ VALUE old_path, new_path;
+ int done;
+};
+
static VALUE
-chdir_restore(path)
- char *path;
+chdir_yield(args)
+ struct chdir_data *args;
{
- chdir_blocking--;
- if (chdir_blocking == 0)
- chdir_thread = Qnil;
- dir_chdir(path);
- free(path);
+ dir_chdir(args->new_path);
+ args->done = Qtrue;
+ chdir_blocking++;
+ if (chdir_thread == Qnil)
+ chdir_thread = rb_thread_current();
+ return rb_yield(args->new_path);
+}
+
+static VALUE
+chdir_restore(args)
+ struct chdir_data *args;
+{
+ if (args->done) {
+ chdir_blocking--;
+ if (chdir_blocking == 0)
+ chdir_thread = Qnil;
+ dir_chdir(args->old_path);
+ }
return Qnil;
}
@@ -609,19 +627,18 @@ dir_s_chdir(argc, argv, obj)
VALUE obj;
{
VALUE path = Qnil;
- char *dist = "";
rb_secure(2);
if (rb_scan_args(argc, argv, "01", &path) == 1) {
SafeStringValue(path);
- dist = RSTRING(path)->ptr;
}
else {
- dist = getenv("HOME");
+ const char *dist = getenv("HOME");
if (!dist) {
dist = getenv("LOGDIR");
if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
}
+ path = rb_str_new2(dist);
}
if (chdir_blocking > 0) {
@@ -630,14 +647,14 @@ dir_s_chdir(argc, argv, obj)
}
if (rb_block_given_p()) {
- char *cwd = my_getcwd();
- chdir_blocking++;
- if (chdir_thread == Qnil)
- chdir_thread = rb_thread_current();
- dir_chdir(dist);
- return rb_ensure(rb_yield, path, chdir_restore, (VALUE)cwd);
+ struct chdir_data args;
+
+ args.old_path = rb_str_new2(my_getcwd());
+ args.new_path = path;
+ args.done = Qfalse;
+ return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
}
- dir_chdir(dist);
+ dir_chdir(path);
return INT2FIX(0);
}