1 /* $NetBSD: file.c,v 1.1.1.6 2011/02/18 22:32:30 aymeric Exp $ */
11 #include <sys/param.h>
14 #include <sys/queue.h>
16 __RCSID("$NetBSD: file.c,v 1.1.1.6 2011/02/18 22:32:30 aymeric Exp $");
19 * FreeBSD install - a package for the installation and maintainance
20 * of non-core utilities.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
25 * 1. Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
34 * Miscellaneous file access utilities.
65 * Quick check to see if a file (or dir ...) exists
68 fexists(const char *fname
)
71 if (!lstat(fname
, &dummy
))
77 * Quick check to see if something is a directory
80 isdir(const char *fname
)
84 if (lstat(fname
, &sb
) != FAIL
&& S_ISDIR(sb
.st_mode
))
91 * Check if something is a link to a directory
94 islinktodir(const char *fname
)
98 if (lstat(fname
, &sb
) != FAIL
&& S_ISLNK(sb
.st_mode
)) {
99 if (stat(fname
, &sb
) != FAIL
&& S_ISDIR(sb
.st_mode
))
100 return TRUE
; /* link to dir! */
102 return FALSE
; /* link to non-dir */
104 return FALSE
; /* non-link */
108 * Check if something is a link that points to nonexistant target.
111 isbrokenlink(const char *fname
)
115 if (lstat(fname
, &sb
) != FAIL
&& S_ISLNK(sb
.st_mode
)) {
116 if (stat(fname
, &sb
) != FAIL
)
117 return FALSE
; /* link target exists! */
119 return TRUE
; /* link target missing*/
121 return FALSE
; /* non-link */
125 * Check to see if file is a dir, and is empty
128 isemptydir(const char *fname
)
130 if (isdir(fname
) || islinktodir(fname
)) {
134 dirp
= opendir(fname
);
136 return FALSE
; /* no perms, leave it alone */
137 for (dp
= readdir(dirp
); dp
!= NULL
; dp
= readdir(dirp
)) {
138 if (strcmp(dp
->d_name
, ".") && strcmp(dp
->d_name
, "..")) {
143 (void) closedir(dirp
);
150 * Check if something is a regular file
153 isfile(const char *fname
)
156 if (stat(fname
, &sb
) != FAIL
&& S_ISREG(sb
.st_mode
))
162 * Check to see if file is a file and is empty. If nonexistent or not
163 * a file, say "it's empty", otherwise return TRUE if zero sized.
166 isemptyfile(const char *fname
)
169 if (stat(fname
, &sb
) != FAIL
&& S_ISREG(sb
.st_mode
)) {
176 /* This struct defines the leading part of a valid URL name */
177 typedef struct url_t
{
178 const char *u_s
; /* the leading part of the URL */
179 int u_len
; /* its length */
182 /* A table of valid leading strings for URLs */
183 static const url_t urls
[] = {
184 #define STR_AND_SIZE(str) { str, sizeof(str) - 1 }
185 STR_AND_SIZE("file://"),
186 STR_AND_SIZE("ftp://"),
187 STR_AND_SIZE("http://"),
188 STR_AND_SIZE("https://"),
194 * Returns length of leading part of any URL from urls table, or -1
197 URLlength(const char *fname
)
202 if (fname
!= (char *) NULL
) {
203 for (i
= 0; isspace((unsigned char) *fname
); i
++) {
206 for (up
= urls
; up
->u_s
; up
++) {
207 if (strncmp(fname
, up
->u_s
, up
->u_len
) == 0) {
208 return i
+ up
->u_len
; /* ... + sizeof(up->u_s); - HF */
216 * Takes a filename and package name, returning (in "try") the canonical
217 * "preserve" name for it.
220 make_preserve_name(char *try, size_t max
, const char *name
, const char *file
)
224 if ((len
= strlen(file
)) == 0)
227 strncpy(try, file
, max
);
228 if (try[i
] == '/') /* Catch trailing slash early and save checking in the loop */
233 strncpy(&try[i
+ 2], &file
[i
+ 1], max
- i
- 2);
239 strncpy(try + 1, file
, max
- 1);
241 /* I should probably be called rude names for these inline assignments */
242 strncat(try, ".", max
-= strlen(try));
243 strncat(try, name
, max
-= strlen(name
));
244 strncat(try, ".", max
--);
245 strncat(try, "backup", max
-= 6);
250 remove_files(const char *path
, const char *pattern
)
252 char fpath
[MaxPathSize
];
257 (void) snprintf(fpath
, sizeof(fpath
), "%s/%s", path
, pattern
);
258 if ((i
=glob(fpath
, GLOB_NOSORT
, NULL
, &globbed
)) != 0) {
261 warn("no files matching ``%s'' found", fpath
);
264 warn("globbing aborted");
267 warn("out-of-memory during globbing");
270 warn("unknown error during globbing");
276 /* deleting globbed files */
277 for (j
= 0; j
< globbed
.gl_pathc
; j
++)
278 if (unlink(globbed
.gl_pathv
[j
]) < 0)
279 warn("can't delete ``%s''", globbed
.gl_pathv
[j
]);
285 * Using fmt, replace all instances of:
287 * %F With the parameter "name"
288 * %D With the parameter "dir"
289 * %B Return the directory part ("base") of %D/%F
290 * %f Return the filename part of %D/%F
292 * Check that no overflows can occur.
295 format_cmd(char *buf
, size_t size
, const char *fmt
, const char *dir
, const char *name
)
297 size_t remaining
, quoted
;
301 for (bufp
= buf
, remaining
= size
; remaining
> 1 && *fmt
;) {
308 if (*++fmt
!= 'D' && name
== NULL
) {
309 warnx("no last file available for '%s' command", buf
);
314 quoted
= shquote(name
, bufp
, remaining
);
315 if (quoted
>= remaining
) {
316 warnx("overflow during quoting");
324 quoted
= shquote(dir
, bufp
, remaining
);
325 if (quoted
>= remaining
) {
326 warnx("overflow during quoting");
334 tmp
= xasprintf("%s/%s", dir
, name
);
335 cp
= strrchr(tmp
, '/');
337 quoted
= shquote(tmp
, bufp
, remaining
);
339 if (quoted
>= remaining
) {
340 warnx("overflow during quoting");
348 tmp
= xasprintf("%s/%s", dir
, name
);
349 cp
= strrchr(tmp
, '/') + 1;
350 quoted
= shquote(cp
, bufp
, remaining
);
352 if (quoted
>= remaining
) {
353 warnx("overflow during quoting");
361 if (remaining
== 1) {
362 warnx("overflow during quoting");