PRB: Call to utime() Can Cause a Program to Lose File Handles

ID Number: Q47962

5.10 6.00 6.00a 6.00ax 7.00 | 5.10 6.00 6.00a

MS-DOS | OS/2

buglist5.10 buglist6.00 buglist6.00a buglist6.00ax

Summary:

SYMPTOMS

The code below demonstrates a problem with the utime() function in

the Microsoft C Optimizing Compiler versions 5.1, 6.0, 6.0a, 6.0ax,

and C/C++ version 7.0. If the utime() function is passed a date

prior to January 1, 1980, the function will fail but will leave a

file handle open, thus reducing the number of file handles that

your program can use.

RESOLUTION

To work around this problem, call the localtime() function before

the call to utime(). Pass to localtime() the modification time that

you are going to pass to utime(). If localtime() returns a NULL

pointer, do not call utime().

STATUS

Microsoft has confirmed this to be a problem with C compiler

versions 5.1, 6.0, 6.0a, 6.0ax, and 7.0. We are researching this

problem and will post new information as it becomes available.

More Information:

The following code samples demonstrate this problem. The first code

sample shows that passing an invalid time to the utime() function will

cause the function to fail. You will lose one file handle each time

the function is called.

#include <sys\types.h>

#include <sys\utime.h>

#include <stdio.h>

#include <malloc.h>

#include <time.h>

struct utimbuf *times;

time_t ltime;

int count;

void main(void)

{

/* allocate memory for the times structure */

times = (struct utimbuf *)malloc(sizeof(struct utimbuf));

/* set the modification date prior to January 1, 1980 */

times->modtime = (time_t)300000000;

for (count = 0; count < 25; count++) {

if (utime("filename",times) == -1)

perror("utime of 300000000 failed");

else

printf("utime of 300000000 successful\n");

}

}

When this program is run, it will print the following:

utime of 300000000 failed: Invalid argument

(15 times in all)

utime of 300000000 failed: Too many open files

(10 times in all)

If the code is changed so that the modification time is set to

400000000, a date after January 1, 1980, the program will print the

following, indicating that all of the file handles were closed

correctly:

utime of 400000000 successful

(25 times in all)

The second code sample shows that a call to localtime() before the

call to utime() can be used to determine if the modification time is

valid before the utime() function is allowed to eat a file handle.

Because the localtime() function does not understand dates before

January 1, 1980, it will fail and return a NULL pointer to the calling

function.

#include <sys\types.h>

#include <sys\utime.h>

#include <stdio.h>

#include <malloc.h>

#include <time.h>

struct utimbuf *times;

time_t ltime;

void main(void)

{

/* allocate memory for the times structure */

times = (struct utimbuf *)malloc(sizeof(struct utimbuf));

/* Check to see if the time is valid by making a call to localtime()

If localtime() returns a NULL, do not call utime(). */

if (localtime(&(times->modtime)) == NULL)

perror("Invalid modtime");

else {

if (utime("filename",times) == -1)

perror("utime of 300000000 failed");

else

printf("utime of 300000000 successful\n");

}

}

This code will print the following:

Invalid modtime: Invalid argument

The following is a brief description of the utime() function and why

it is incorrect. Basically, the function operates as follows:

open the file using open()

if time parameter = NULL

set temporary time variable to current time using time();

else

set temporary time variable to time parameter

if localtime(temporary time variable) = NULL return to calling

program

call interrupt 21 function 57 to set file date and time

close the file using close()

return to calling function

As you can see, the utime() function uses the localtime() function to

check to see if the modification time is valid. If it is invalid, then

the utime() function returns to the calling function without closing

the file, thus taking a file handle. To correct this problem, do one

of the following:

- Call localtime() in your program before utime() does to make sure

the modification time is valid, as the code above demonstrates.

-or-

- Purchase the C Run-Time Library source by calling Microsoft

End User Sales and modify the source code to correct the error

by closing the file before you return via the failed localtime()

call or move the localtime() call above the open() call.

-or-

- Write your own file time-modification function, using Interrupt 21h

Function 57h.

Additional reference words: 5.00 5.10 6.00 6.00a 6.00ax buglist7.00