SDDSlib
Loading...
Searching...
No Matches
filestat.c File Reference

Utility functions for handling file links and retrieving file information. More...

#include <unistd.h>
#include "mdb.h"

Go to the source code of this file.

Functions

char * dir_name (const char *path)
 Retrieves the leading directories from a given path.
 
char * read_file_link (const char *filename)
 Reads the first link of a file.
 
const char * read_file_lastlink (const char *filename)
 Retrieves the last link in a chain of symbolic links.
 
char * read_last_link_to_file (const char *filename)
 Resolves the final target file that a symbolic link points to.
 
long get_file_stat (const char *filename, const char *final_file, struct stat *filestat)
 Retrieves the file status of a given file or its final link target.
 
long file_is_modified (const char *inputfile, char **final_file, struct stat *input_stat)
 Checks if a file has been modified.
 

Detailed Description

Utility functions for handling file links and retrieving file information.

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
H. Shang, M. Borland, R. Soliday

Definition in file filestat.c.

Function Documentation

◆ dir_name()

char * dir_name ( const char * path)

Retrieves the leading directories from a given path.

Allocates memory for the leading directories part of the provided PATH. If memory allocation fails, returns NULL. Assumes that any trailing slashes in PATH have already been removed. This function avoids using the dirname builtin to maintain consistent behavior across different environments.

Parameters
pathThe file path from which to extract the leading directories.
Returns
A newly allocated string containing the leading directories, or NULL if out of memory.

Definition at line 33 of file filestat.c.

33 {
34 char *newpath = NULL;
35 const char *slash = NULL;
36 int length; /* Length of result, not including NUL. */
37
38 slash = strrchr(path, '/');
39 if (slash == 0) {
40 /* File is in the current directory. */
41 path = ".";
42 length = 1;
43 } else {
44 /* Remove any trailing slashes from the result. */
45 while (slash > path && *slash == '/')
46 --slash;
47 length = slash - path + 1;
48 }
49 newpath = (char *)malloc(length + 1);
50 if (newpath == 0)
51 return 0;
52 strncpy(newpath, path, length);
53 newpath[length] = 0;
54 return newpath;
55}

◆ file_is_modified()

long file_is_modified ( const char * inputfile,
char ** final_file,
struct stat * input_stat )

Checks if a file has been modified.

Determines whether the specified input file has been modified by comparing its current state against a previously recorded state. If the file is a symbolic link, it checks the final target file for modifications. The function updates the final_file pointer if the link target has changed.

Parameters
inputfileThe path to the input file to check for modifications.
final_filePointer to a string containing the final target file name. May be updated.
input_statPointer to a struct stat containing the previous state of the file.
Returns
1 if the file has been modified or the link target has changed, 0 otherwise.

Definition at line 191 of file filestat.c.

191 {
192 struct stat filestat;
193 char *tempfile = NULL;
194 const char *tmpinput = NULL;
195
196 if (!fexists(inputfile)) {
197 fprintf(stderr, "%s file does not exist!\n", inputfile);
198 return (1);
199 }
200 if (*final_file && !fexists(*final_file)) {
201 fprintf(stderr, "linked file %s of inputfile %s does not exist!\n", *final_file, inputfile);
202 return (1);
203 }
204 if (!input_stat) {
205 fprintf(stderr, "The previous state of file %s is not known.\n", inputfile);
206 return (1);
207 }
208
209 tempfile = read_last_link_to_file(inputfile);
210
211 /*the final link name changed */
212 if (tempfile && *final_file && strcmp(tempfile, *final_file)) {
213 if (*final_file)
214 free(*final_file);
215 *final_file = tempfile;
216 return 1;
217 }
218 if ((tempfile && !(*final_file)) || (!tempfile && *final_file)) {
219 if (*final_file)
220 free(*final_file);
221 *final_file = tempfile;
222 return 1;
223 }
224 /* the final link name did not change, check if the file state changed */
225 if (tempfile)
226 free(tempfile);
227 if (*final_file)
228 tmpinput = *final_file;
229 else
230 tmpinput = inputfile;
231 filestat = *input_stat;
232 if (stat(tmpinput, input_stat) != 0) {
233 fprintf(stderr, "Problem getting modification time for %s\n", tmpinput);
234 exit(1);
235 }
236 if (input_stat->st_ctime != filestat.st_ctime) {
237 /* file state is changed */
238 return 1;
239 }
240 return 0;
241}
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27
char * read_last_link_to_file(const char *filename)
Resolves the final target file that a symbolic link points to.
Definition filestat.c:134

◆ get_file_stat()

long get_file_stat ( const char * filename,
const char * final_file,
struct stat * filestat )

Retrieves the file status of a given file or its final link target.

Obtains the file status information for the specified filename. If the file is a symbolic link and a final_file is provided, it retrieves the status of the final target file. If the file does not exist or an error occurs during the retrieval, an error message is printed to stderr.

Parameters
filenameThe name of the file to retrieve the status for.
final_fileOptional parameter specifying the final target file if filename is a link.
filestatPointer to a struct stat where the file status will be stored.
Returns
0 on success, 1 on failure.

Definition at line 162 of file filestat.c.

162 {
163 const char *input = NULL;
164 if (!fexists(filename)) {
165 fprintf(stderr, "%s file does not exist, unable to get the state of it!\n", filename);
166 return (1);
167 }
168 input = filename;
169 if (final_file)
170 input = final_file;
171 if (stat(input, filestat) != 0) {
172 fprintf(stderr, "Problem getting state of file %s\n", input);
173 return (1);
174 }
175 return 0;
176}

◆ read_file_lastlink()

const char * read_file_lastlink ( const char * filename)

Retrieves the last link in a chain of symbolic links.

Traverses the chain of symbolic links starting from the given filename and returns the name of the last link that directly points to the final target file. If the file is not a link, returns the original filename.

Parameters
filenameThe starting file name to resolve the last link from.
Returns
The name of the last link in the chain, or the original filename if not a link.

Definition at line 112 of file filestat.c.

112 {
113 char *linkname = NULL;
114 const char *lastlink = NULL;
115 lastlink = filename;
116 while ((linkname = read_file_link(filename)) != NULL) {
117 lastlink = filename;
118 filename = linkname;
119 }
120 return lastlink;
121}
char * read_file_link(const char *filename)
Reads the first link of a file.
Definition filestat.c:68

◆ read_file_link()

char * read_file_link ( const char * filename)

Reads the first link of a file.

Returns the first link of the specified file. If the file is not a link or if an error occurs (including unsupported platforms), returns NULL. On successful retrieval, the returned string is dynamically allocated and should be freed by the caller.

Parameters
filenameThe name of the file to read the link from.
Returns
A newly allocated string containing the link target, or NULL if not a link or on error.

Definition at line 68 of file filestat.c.

68 {
69#if defined(_WIN32) || defined(vxWorks)
70 return (NULL);
71#else
72 int size = 100, nchars = -1;
73 char *tmpbuf = NULL, *dir = NULL, *tempname = NULL;
74 tmpbuf = (char *)calloc(size, sizeof(char));
75 while (1) {
76 nchars = readlink(filename, tmpbuf, size);
77 if (nchars < 0) {
78 free(tmpbuf);
79 return NULL;
80 }
81 if (nchars < size) {
82 if (tmpbuf[0] == '/')
83 return tmpbuf;
84 else {
85 dir = dir_name(filename);
86 tempname = (char *)malloc(sizeof(char) * (strlen(filename) + strlen(tmpbuf) + 2));
87 tempname[0] = 0;
88 strcat(tempname, dir);
89 strcat(tempname, "/");
90 strcat(tempname, tmpbuf);
91 free(tmpbuf);
92 free(dir);
93 return tempname;
94 }
95 }
96 size *= 2;
97 tmpbuf = (char *)realloc(tmpbuf, sizeof(char) * size);
98 }
99#endif
100}
char * dir_name(const char *path)
Retrieves the leading directories from a given path.
Definition filestat.c:33

◆ read_last_link_to_file()

char * read_last_link_to_file ( const char * filename)

Resolves the final target file that a symbolic link points to.

Follows the chain of symbolic links starting from the given filename and returns the name of the final target file. The returned string is dynamically allocated and should be freed by the caller. If the filename is not a link, returns NULL.

Parameters
filenameThe starting file name to resolve to the final target.
Returns
A newly allocated string containing the final target file name, or NULL if not a link.

Definition at line 134 of file filestat.c.

134 {
135 char *linkname = NULL;
136 char *tmpname = NULL;
137
138 if ((linkname = read_file_link(filename)) == NULL)
139 return NULL;
140 tmpname = (char *)calloc(1024, sizeof(char));
141 do {
142 strcpy_ss(tmpname, linkname);
143 free(linkname);
144 linkname = read_file_link(tmpname);
145 } while (linkname != NULL);
146 return tmpname;
147}
char * strcpy_ss(char *dest, const char *src)
Safely copies a string, handling memory overlap.
Definition str_copy.c:34
char * tmpname(char *s)
Supplies a unique temporary filename.
Definition tmpname.c:34