Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

If I do: touch file; mv file /dev/null as root, /dev/null disappears. ls -lad /dev/null results in no such file or directory. This breaks applications which depend on /dev/null like SSH and can be resolved by doing mknod /dev/null c 1 3; chmod 666 /dev/null. Why does moving a regular file to this special file result in the disappearance of /dev/null?

To clarify, this was for testing purposes, and I understand how the mv command works. What I am curious about is why ls -la /dev/null before replacing it with a regular file shows the expected output, but afterwards it shows that /dev/null does not exist even though a file was allegedly created via the original mv command and the file command shows ASCII Text. I think this must be a combination of the ls command behavior in conjunction with devfs when a non special file replaces a character/special file. This is on Mac OS X, behaviors may vary on other OS's.

share|improve this question
31  
Don't mess with /dev/null. –  devnull Mar 3 at 17:15
4  
so says @devnull –  Braiam Mar 3 at 17:19
2  
The proper way to delete files is the rm command. –  casey Mar 3 at 17:20
1  
Seems like that is the root of your problem, OSX devfs is funny about normal files. Strange you didn't get an error from mv though. How about this way: touch testfile; mv testfile /dev? –  Graeme Mar 3 at 17:58
2  
@Gregg, mv can only be atomic on the same filesystem. –  Graeme Mar 3 at 18:59

3 Answers 3

up vote 11 down vote accepted

Looking at the source code for mv, http://www.opensource.apple.com/source/file_cmds/file_cmds-220.7/mv/mv.c :

/*
 * If rename fails because we're trying to cross devices, and
 * it's a regular file, do the copy internally; otherwise, use
 * cp and rm.
 */
if (lstat(from, &sb)) {
    warn("%s", from);
    return (1);
}
return (S_ISREG(sb.st_mode) ?
    fastcopy(from, to, &sb) : copy(from, to));

...

int
fastcopy(char *from, char *to, struct stat *sbp)
{
...
while ((to_fd =
    open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) {
        if (errno == EEXIST && unlink(to) == 0)
            continue;
        warn("%s", to);
        (void)close(from_fd);
        return (1);
}

As you pointed out in your comment, regular files can't be created in /dev, so even after /dev/null is unlinked, the open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0) is still going to fail.

I'd file a bug report with Apple. The mv source code is mostly unchanged from the FreeBSD version, but because OSX's devfs has that non-POSIX behavior with regular files, Apple should fix their mv.

share|improve this answer
    
I am giving this best answer right now for providing source code and acknowledging this as a bug, which is what I was driving at. –  Gregg Leventhal Mar 7 at 16:45

Moving a file to the location of an already existing file replaces the existing file. In this case the /dev/null device file is replaced, just as any normal file would be. To avoid this use the -i (interactive, warns before overwriting) or -n (no clober) option for mv.

/dev/null only performs its special function as a bit-bucket then the device is opened as is. Eg, when the > shell operator is used, the file is opened then truncated (not removed an replaced, which may be what you expected). As mentioned by casey, the correct way to remove a file is with rm or even with unlink.

share|improve this answer
    
See my comments to terdon. –  Gregg Leventhal Mar 3 at 17:25
    
Understood, the -d was unneeded, that is just a bad habit however the file should still show up in the ls output, it should not show as nonexistent. –  Gregg Leventhal Mar 3 at 17:33
    
@Graeme - welcome to 3K, nice job! –  slm Mar 5 at 1:28
1  
@slm, thanks, nice to be here! –  Graeme Mar 5 at 1:53

Umm, because you overwrite the special file with normal one? What did you expect to happen? dev/null is not a directory, it is a file pointing to a null device. When you mv something to it, you delete the original and replace it with whatever you moved:

$ file /dev/null 
/dev/null: character special 
$ sudo mv file /dev/null 
$ file /dev/null 
/dev/null: ASCII text
share|improve this answer
2  
But I am saying /dev/null was showing as missing when running an ls -lad /dev/null. This must be something specific to the devfs, that it what I wanted to know about. –  Gregg Leventhal Mar 3 at 17:24
    
If I mv file /dev/null then /dev/null should contain what file contained but still exist. I want to know why this caused /dev/null to not be found in an ls. –  Gregg Leventhal Mar 3 at 17:25
    
Granted, I am doing this on a Mac, so it might be slightly different, but I did not expect the file to show as missing, I only expected it to show as changed to the source file. –  Gregg Leventhal Mar 3 at 17:31
    
@GreggLeventhal yes, it must be an OSX or BSD thing (please edit your Q and specify your OS). On my Linux I can still see /dev/null, it's just become the file I moved. –  terdon Mar 3 at 17:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.