From: Russell M. <rus...@ya...> - 2005-06-05 01:11:10
|
While writing some code using run-program, I came upon the need for the following: (defmacro with-current-directory ((new-dir) &body body) (let ((start (gensym))) `(let ((,start (sb-unix:posix-getcwd))) (unless (char= #\\ (aref ,start (1- (length ,start)))) (setf ,start (concatenate 'string ,start "/"))) (setf ,start (parse-namestring ,start)) (unwind-protect (progn (sb-posix:chdir ,new-dir) ,@body) (sb-posix:chdir ,start))))) Is there an already existing way to do this sort of thing? -russ |
From: Christophe R. <cs...@ca...> - 2005-06-05 08:38:40
|
Russell McManus <rus...@ya...> writes: > While writing some code using run-program, I came upon the need for > the following: > > (defmacro with-current-directory ((new-dir) &body body) > (let ((start (gensym))) > `(let ((,start (sb-unix:posix-getcwd))) > (unless (char= #\\ (aref ,start (1- (length ,start)))) > (setf ,start (concatenate 'string ,start "/"))) > (setf ,start (parse-namestring ,start)) > (unwind-protect > (progn > (sb-posix:chdir ,new-dir) > ,@body) > (sb-posix:chdir ,start))))) > > Is there an already existing way to do this sort of thing? No. There is at least a plausible argument that RUN-PROGRAM should respect *DEFAULT-PATHNAME-DEFAULTS* by chdir()ing to the directory component, which would allow the user to request a different directory for run-program simply by binding it. On the other hand, RUN-PROGRAM is already a deeply scary mess of options, and adding another doesn't really appeal... Cheers, Christophe |
From: Russell M. <rus...@ya...> - 2005-06-05 17:42:15
|
Christophe Rhodes <cs...@ca...> writes: > Russell McManus <rus...@ya...> writes: > >> While writing some code using run-program, I came upon the need for >> the following: >> >> (defmacro with-current-directory ((new-dir) &body body) >> (let ((start (gensym))) >> `(let ((,start (sb-unix:posix-getcwd))) >> (unless (char= #\\ (aref ,start (1- (length ,start)))) >> (setf ,start (concatenate 'string ,start "/"))) >> (setf ,start (parse-namestring ,start)) >> (unwind-protect >> (progn >> (sb-posix:chdir ,new-dir) >> ,@body) >> (sb-posix:chdir ,start))))) >> >> Is there an already existing way to do this sort of thing? > > No. There is at least a plausible argument that RUN-PROGRAM should > respect *DEFAULT-PATHNAME-DEFAULTS* by chdir()ing to the directory > component, which would allow the user to request a different directory > for run-program simply by binding it. On the other hand, RUN-PROGRAM > is already a deeply scary mess of options, and adding another doesn't > really appeal... I agree about *DEFAULT-PATHNAME-DEFAULTS*, and indeed I tried this first, hoping that it would "just work". I would be willing the change run-program to work in this way: is this of interest? The reason I didn't do this first is because I wasn't sure whether there was an existing way to achieve what I wanted. I agree that this probably should not be an additional keyword option to RUN-PROGRAM. If a patch to RUN-PROGRAM is not desired, then I put the above code in the public domain, hopefully to be included with sbcl. -russ |
From: Andreas F. <as...@bo...> - 2005-06-05 19:46:39
|
Today, Russell McManus <rus...@ya...> wrote: > > While writing some code using run-program, I came upon the need for > the following: autobench uses a similar macro, so I have a few questions about your code. One, wouldn't it be better if the macro also bound *default-pathname-defaults* to the new-dir? (My implementation assumes that the user(me) will consistently use with-current-directory and so skips the whole getcwd thing in favor of just chdir-ing back into *d-p-defaults*) > (defmacro with-current-directory ((new-dir) &body body) > (let ((start (gensym))) > `(let ((,start (sb-unix:posix-getcwd))) > (unless (char= #\\ (aref ,start (1- (length ,start)))) > (setf ,start (concatenate 'string ,start "/"))) Two, what's with that #\\ check? In which cases does getcwd return the \ character as the last element? > (setf ,start (parse-namestring ,start)) > (unwind-protect > (progn > (sb-posix:chdir ,new-dir) > ,@body) > (sb-posix:chdir ,start))))) Cheers, -- Andreas Fuchs, <as...@bo...>, as...@ja..., antifuchs |
From: Russell M. <rus...@ya...> - 2005-06-06 12:22:10
|
Andreas Fuchs <as...@bo...> writes: > Today, Russell McManus <rus...@ya...> wrote: >> >> While writing some code using run-program, I came upon the need for >> the following: > > autobench uses a similar macro, so I have a few questions about your > code. > > One, wouldn't it be better if the macro also bound > *default-pathname-defaults* to the new-dir? (My implementation > assumes that the user(me) will consistently use > with-current-directory and so skips the whole getcwd thing in favor > of just chdir-ing back into *d-p-defaults*) I can easily be convinced that *default-pathname-defaults* should be magical in some sneaky way. I just threw together the macro that I wrote based on an immediate need, and wondered whether someone else had a fully baked solution. >> (defmacro with-current-directory ((new-dir) &body body) >> (let ((start (gensym))) >> `(let ((,start (sb-unix:posix-getcwd))) >> (unless (char= #\\ (aref ,start (1- (length ,start)))) >> (setf ,start (concatenate 'string ,start "/"))) > > Two, what's with that #\\ check? In which cases does getcwd return the > \ character as the last element? This is an error in my code, the constant should be #\/, because getcwd sometimes returns a path without a trailing slash, which when parsed with parse-namestring will put the last path component into the pathname's name field rather than the final component in the directory field. -russ |
From: Florian W. <fw...@de...> - 2005-06-06 09:49:26
|
* Russell McManus: > (sb-posix:chdir ,start))))) I think you should use fchdir instead because it works in more cases (deleted directory, unmount is prevented). |
From: Russell M. <rus...@ya...> - 2005-06-06 11:39:07
|
Florian Weimer <fw...@de...> writes: > * Russell McManus: > >> (sb-posix:chdir ,start))))) > > I think you should use fchdir instead because it works in more cases > (deleted directory, unmount is prevented). I'm not a unix guru; how do you recommend to acquire the necessary fd to pass to fchdir? -russ |
From: Florian W. <fw...@de...> - 2005-06-06 11:51:24
|
* Russell McManus: >> * Russell McManus: >> >>> (sb-posix:chdir ,start))))) >> >> I think you should use fchdir instead because it works in more cases >> (deleted directory, unmount is prevented). > > I'm not a unix guru; how do you recommend to acquire the necessary fd > to pass to fchdir? Ah, this is somewhat messy. According to POSIX, the open syscall would do it (in O_RDONLY mode), but unfortunately it breaks on Linux, where O_DIRECTORY is required. Maybe it's not such a great idea to use fchdir after all. |