Index: Makefile =================================================================== --- Makefile (revision 341286) +++ Makefile (working copy) @@ -2,6 +2,6 @@ PROG= trim MAN= trim.8 -LIBADD= util +LIBADD= geom util .include Index: trim.c =================================================================== --- trim.c (revision 341286) +++ trim.c (working copy) @@ -42,13 +42,14 @@ #include #include +#include + #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ -static int trim(char *path, off_t offset, off_t length, int dryrun, int verbose); -static off_t getsize(char *path); +static off_t getsize(const char *path, int fd); static void usage(char *name) __dead2; int @@ -56,7 +57,7 @@ { off_t offset, length; uint64_t usz; - int ch, dryrun, error, verbose; + int fd, ch, dryrun, error, verbose; char *fname, *name; error = 0; @@ -91,10 +92,14 @@ verbose = 0; break; case 'r': - if ((length = getsize(optarg)) == 0) + fd = open(optarg, O_RDONLY); + if (fd < 0) + err(EX_NOINPUT, "couldn't open '%s'", optarg); + if ((length = getsize(optarg, fd)) == 0) errx(EX_USAGE, "invalid zero length reference file" " for the region: `%s'", optarg); + close(fd); break; case 'v': verbose = 1; @@ -110,98 +115,51 @@ if (argc < 1) usage(name); - while ((fname = *argv++) != NULL) - if (trim(fname, offset, length, dryrun, verbose) < 0) + /* + * XXX it seems really dubious to apply the same offset/length TRIM to + * more than one device/file ... + */ + while ((fname = *argv++) != NULL) { + fd = open(fname, O_RDONLY); + if (fd < 0) { + warn("couldn't open '%s'", optarg); error++; + continue; + } + if (verbose) + printf("trim '%s' offset %ju length %ju\n", fname, + (uintmax_t)offset, (uintmax_t)length); + if (!dryrun && g_delete(fd, offset, length) < 0) + error++; + } + return (error ? EXIT_FAILURE : EXIT_SUCCESS); } static off_t -getsize(char *path) +getsize(const char *path, int fd) { struct stat sb; - char *tstr; off_t mediasize; - int fd; - if ((fd = open(path, O_RDONLY | O_DIRECT)) < 0) { - if (errno == ENOENT && path[0] != '/') { - if (asprintf(&tstr, "%s%s", _PATH_DEV, path) < 0) - errx(EX_OSERR, "no memory"); - fd = open(tstr, O_RDONLY | O_DIRECT); - free(tstr); - } - } - - if (fd < 0) - err(EX_NOINPUT, "`%s'", path); - if (fstat(fd, &sb) < 0) - err(EX_IOERR, "`%s'", path); + err(EX_OSERR, "stat"); - if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode)) { - close(fd); + if (S_ISREG(sb.st_mode)) return (sb.st_size); - } - if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode)) + if (!S_ISCHR(sb.st_mode)) errx(EX_DATAERR, - "invalid type of the file " - "(not regular, directory nor special device): `%s'", - path); + "%s: invalid type (not regular nor special device)", path); - if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) - errx(EX_UNAVAILABLE, - "ioctl(DIOCGMEDIASIZE) failed, probably not a disk: " - "`%s'", path); - close(fd); + mediasize = g_mediasize(fd); + if (mediasize < 0) + errx(EX_UNAVAILABLE, "%s: g_mediasize", path); return (mediasize); } -static int -trim(char *path, off_t offset, off_t length, int dryrun, int verbose) -{ - off_t arg[2]; - char *tstr; - int error, fd; - - if (length == 0) - length = getsize(path); - - if (verbose) - printf("trim `%s' offset %ju length %ju\n", - path, (uintmax_t)offset, (uintmax_t)length); - - if (dryrun) { - printf("dry run: add -f to actually perform the operation\n"); - return (0); - } - - if ((fd = open(path, O_WRONLY | O_DIRECT)) < 0) { - if (errno == ENOENT && path[0] != '/') { - if (asprintf(&tstr, "%s%s", _PATH_DEV, path) < 0) - errx(EX_OSERR, "no memory"); - fd = open(tstr, O_WRONLY | O_DIRECT); - free(tstr); - } - } - - if (fd < 0) - err(EX_NOINPUT, "`%s'", path); - - arg[0] = offset; - arg[1] = length; - - error = ioctl(fd, DIOCGDELETE, arg); - if (error < 0) - warn("ioctl(DIOCGDELETE) failed for `%s'", path); - - close(fd); - return (error); -} - static void usage(char *name) {