Advanced Programming in the UNIX Environment: Second Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Advanced Programming in the UNIX Environment: Second Edition [Electronic resources] - نسخه متنی

W. Richard Stevens; Stephen A. Rago

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید



4.15. link, unlink, remove, and rename Functions


As we saw in the previous section, any file can have multiple directory entries pointing to its i-node. The way we create a link to an existing file is with the link function.


[View full width]

#include <unistd.h>
int link(const char *

existingpath , const char
*

newpath );

Returns: 0 if OK, 1 on error

This function creates a new directory entry,

newpath , that references the existing file

existingpath . If the

newpath already exists, an error is returned. Only the last component of the

newpath is created. The rest of the path must already exist.

The creation of the new directory entry and the increment of the link count must be an atomic operation. (Recall the discussion of atomic operations in Section 3.11.)

Most implementations require that both pathnames be on the same file system, although POSIX.1 allows an implementation to support linking across file systems. If an implementation supports the creation of hard links to directories, it is restricted to only the superuser. The reason is that doing this can cause loops in the file system, which most utilities that process the file system aren't capable of handling. (We show an example of a loop introduced by a symbolic link in Section 4.16.) Many file system implementations disallow hard links to directories for this reason.

To remove an existing directory entry, we call the unlink function.

#include <unistd.h>
int unlink(const char *

pathname );

Returns: 0 if OK, 1 on error

This function removes the directory entry and decrements the link count of the file referenced by

pathname . If there are other links to the file, the data in the file is still accessible through the other links. The file is not changed if an error occurs.

We've mentioned before that to unlink a file, we must have write permission and execute permission in the directory containing the directory entry, as it is the directory entry that we will be removing. Also, we mentioned in Section 4.10 that if the sticky bit is set in this directory we must have write permission for the directory and one of the following:

  • Own the file

  • Own the directory

  • Have superuser privileges


Only when the link count reaches 0 can the contents of the file be deleted. One other condition prevents the contents of a file from being deleted: as long as some process has the file open, its contents will not be deleted. When a file is closed, the kernel first checks the count of the number of processes that have the file open. If this count has reached 0, the kernel then checks the link count; if it is 0, the file's contents are deleted.


Example

The program shown in Figure 4.16 opens a file and then unlinks it. The program then goes to sleep for 15 seconds before terminating.

Running this program gives us

$

ls -l tempfile

look at how big the file is
-rw-r----- 1 sar 413265408 Jan 21 07:14 tempfile
$

df /home

check how much free space is available
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda4 11021440 1956332 9065108 18% /home
$

./a.out &

run the program in Figure 4.16 in the background
1364

the shell prints its process ID
$ file unlinked

the file is unlinked

ls -l tempfile

see if the filename is still there
ls: tempfile: No such file or directory

the directory entry is gone
$

df /home

see if the space is available yet
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda4 11021440 1956332 9065108 18% /home
$ done

the program is done, all open files are closed

df /home

now the disk space should be available
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda4 11021440 1552352 9469088 15% /home

now the 394.1 MB of disk space are available


Figure 4.16. Open a file and then unlink it

#include "apue.h"
#include <fcntl.h>
int
main(void)
{
if (open("tempfile", O_RDWR) < 0)
err_sys("open error");
if (unlink("tempfile") < 0)
err_sys("unlink error");
printf("file unlinked\n");
sleep(15);
printf("done\n");
exit(0);
}

This property of unlink is often used by a program to ensure that a temporary file it creates won't be left around in case the program crashes. The process creates a file using either open or creat and then immediately calls unlink. The file is not deleted, however, because it is still open. Only when the process either closes the file or terminates, which causes the kernel to close all its open files, is the file deleted.

If

pathname is a symbolic link, unlink removes the symbolic link, not the file referenced by the link. There is no function to remove the file referenced by a symbolic link given the name of the link.

Section 4.20.

We can also unlink a file or a directory with the remove function. For a file, remove is identical to unlink. For a directory, remove is identical to rmdir.

#include <stdio.h>
int remove(const char *

pathname );

Returns: 0 if OK, 1 on error

ISO C specifies the remove function to delete a file. The name was changed from the historical UNIX name of unlink because most non-UNIX systems that implement the C standard didn't support the concept of links to a file at the time.

A file or a directory is renamed with the rename function.

#include <stdio.h>
int rename(const char *

oldname , const char *

newname );

Returns: 0 if OK, 1 on error

This function is defined by ISO C for files. (The C standard doesn't deal with directories.) POSIX.1 expanded the definition to include directories and symbolic links.

There are several conditions to describe, depending on whether

oldname refers to a file, a directory, or a symbolic link. We must also describe what happens if

newname already exists.

  • If

    oldname specifies a file that is not a directory, then we are renaming a file or a symbolic link. In this case, if

    newname exists, it cannot refer to a directory. If

    newname exists and is not a directory, it is removed, and

    oldname is renamed to

    newname . We must have write permission for the directory containing

    oldname and for the directory containing

    newname , since we are changing both directories.

  • If

    oldname specifies a directory, then we are renaming a directory. If

    newname exists, it must refer to a directory, and that directory must be empty. (When we say that a directory is empty, we mean that the only entries in the directory are dot and dot-dot.) If

    newname exists and is an empty directory, it is removed, and

    oldname is renamed to

    newname . Additionally, when we're renaming a directory,

    newname cannot contain a path prefix that names

    oldname . For example, we can't rename /usr/foo to /usr/foo/testdir, since the old name (/usr/foo) is a path prefix of the new name and cannot be removed.

  • If either

    oldname or

    newname refers to a symbolic link, then the link itself is processed, not the file to which it resolves.

  • As a special case, if the

    oldname and

    newname refer to the same file, the function returns successfully without changing anything.

  • If

    newname already exists, we need permissions as if we were deleting it. Also, because we're removing the directory entry for

    oldname and possibly creating a directory entry for

    newname , we need write permission and execute permission in the directory containing

    oldname and in the directory containing

    newname .


      / 369