Dumb Q #1

Grant Edwards grante at visi.com
Tue Jan 28 05:47:45 CET 2003


In article <3e360342_3 at corp.newsgroups.com>, Norm wrote:
> I should have mentioned that I tried "199" as well.  No luck no error.
> 
> Am I opening the file in the correct mode  r+   ?

I'm not sure what you mean.  Are you expecting the change to show up in the
file?  There's no code in your program to write the changed data to a file.

OK. The canonical way to do this is to write the data back out to a
temporary file.  When you're done, close the temporary file and rename it.
That way if your system crashes while the program is running you always have
a valid passwd file.  You _want_ to have a valid passwd file at all times.

WARNING: I haven't actually tested this. You may need to add some code to
make sure the new file has proper permissions, etc.  You should also use one
of the library routines to generate a nice temporary filename for you.  But,
make sure the temporary file is in the same filesystem as /etc/passwd.  That
way the mv() system call used by os.rename() will have as small a critical
region as possible.

    pw = "/etc/passwd"
    tmp = "/etc/tempfilename"
    infile = open(pw,"r")
    outfile = open(tmp,"w")
    while 1:
        record = infile.readline()
	if not record:
  	    break
        fields = record.split(':')
        if fields[3] == "200":
            print fields[0], " has a GID of 200"
            print "now changing it to 199"
            fields[3] = "199"
        file.write(":".join(fields))
    infile.close()
    outfile.close()
    os.rename(tmp,pw)

You may want to make a backup copy of the original file.  You *could* just
rename it like this:

    infile.close()
    outfile.close()
    os.rename(pw,"/etc/passwd.old")
    os.rename(tmp,pw)
    
But, during the time between the two "os.rename" calls, you don't have any
passwd file at all.  If a program tries to read /etc/passwd at that exact
moment, it will fail.  If your program/system dies at that exact point,
you're going to have to get out a rescue CD.  

It's less risky to do something like this:

    infile.close()
    outfile.close()
    shutil.copyfile(pw,"/etc/passwd.old")
    os.rename(tmp,pw)

The mv() system call used by os.rename() is atomic (from a filesystem point
of view) as long as the temp file is on the same fs as /etc/passwd.  That
means that at all times any program can open /etc/passwd and get either the
old file or the new file.  There is no way for a program to get an
intermediate or incomplete file as could happen if you just wrote to
/etc/passwd directly.  Even if your system crashed during the os.rename(),
you should be able to recover the filesystem and have either a valid file
(either the old or new one, it doesn't really matter at that point).

-- 
Grant Edwards                   grante             Yow!  Mr and Mrs PED, can
                                  at               I borrow 26.7
                               visi.com            




More information about the Python-list mailing list