/* * $Source: /afs/dev.mit.edu/source/repository/athena/bin/delete/util.c,v $ * $Author: jik $ * * This program is a replacement for rm. Instead of actually deleting * files, it marks them for deletion by prefixing them with a ".#" * prefix. * * Copyright (c) 1989 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file "mit-copyright.h." */ #if (!defined(lint) && !defined(SABER)) static char rcsid_util_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/delete/util.c,v 1.10 1989-11-06 19:54:14 jik Exp $"; #endif #ifdef AFS_MOUNTPOINTS /* * I assume there's a "right" header file to include to get the symbol * VICE defined, but I can't find it, and if VICE isn't defined then * certain header files don't load properly, so I'm doing it by hand. */ #define VICE #endif #include #include #include #include #include #include #include #include #ifdef AFS_MOUNTPOINTS #include #include /* * there has to be a global header file that contains this * information, but once again, I can't find it, so this is the best I * can do. Sigh. */ #include "/afs/athena.mit.edu/astaff/project/afsdev/src/venus/uvenus.h" #endif #include "delete_errs.h" #include "directories.h" #include "util.h" #include "mit-copyright.h" #include "errors.h" extern char *getenv(); extern uid_t getuid(); extern int errno; char *convert_to_user_name(real_name, user_name) char real_name[]; char user_name[]; /* RETURN */ { char *ptr, *q; (void) strcpy(user_name, real_name); while (ptr = strrindex(user_name, ".#")) { for (q = ptr; *(q + 2); q++) *q = *(q + 2); *q = '\0'; } return (user_name); } char *strindex(str, sub_str) char *str, *sub_str; { char *ptr = str; while (ptr = index(ptr, *sub_str)) { if (! strncmp(ptr, sub_str, strlen(sub_str))) return(ptr); ptr++; } return ((char *) NULL); } char *strrindex(str, sub_str) char *str, *sub_str; { char *ptr; if (strlen(str)) ptr = &str[strlen(str) - 1]; else return((char *) NULL); while ((*ptr != *sub_str) && (ptr != str)) ptr--; while (ptr != str) { if (! strncmp(ptr, sub_str, strlen(sub_str))) return(ptr); ptr--; while ((*ptr != *sub_str) && (ptr != str)) ptr--; } if (! strncmp(ptr, sub_str, strlen(sub_str))) return(str); else return ((char *) NULL); } /* * NOTE: Append uses a static array, so its return value must be * copied immediately. */ char *append(filepath, filename) char *filepath, *filename; { static char buf[MAXPATHLEN]; (void) strcpy(buf, filepath); if ((! *filename) || (! *filepath)) { (void) strcpy(buf, filename); return(buf); } if (buf[strlen(buf) - 1] == '/') buf[strlen(buf) - 1] = '\0'; if (strlen(buf) + strlen(filename) + 2 > MAXPATHLEN) { set_error(ENAMETOOLONG); strncat(buf, "/", MAXPATHLEN - strlen(buf) - 1); strncat(buf, filename, MAXPATHLEN - strlen(buf) - 1); error(buf); *buf = '\0'; return buf; } (void) strcat(buf, "/"); (void) strcat(buf, filename); return buf; } yes() { char buf[BUFSIZ]; char *val; val = fgets(buf, BUFSIZ, stdin); if (! val) { printf("\n"); exit(1); } if (! index(buf, '\n')) do (void) fgets(buf + 1, BUFSIZ - 1, stdin); while (! index(buf + 1, '\n')); return(*buf == 'y'); } char *lastpart(filename) char *filename; { char *part; part = rindex(filename, '/'); if (! part) part = filename; else if (part == filename) part++; else if (part - filename + 1 == strlen(filename)) { part = rindex(--part, '/'); if (! part) part = filename; else part++; } else part++; return(part); } char *firstpart(filename, rest) char *filename; char *rest; /* RETURN */ { char *part; static char buf[MAXPATHLEN]; (void) strcpy(buf, filename); part = index(buf, '/'); if (! part) { *rest = '\0'; return(buf); } (void) strcpy(rest, part + 1); *part = '\0'; return(buf); } get_home(buf) char *buf; { char *user; struct passwd *psw; (void) strcpy(buf, getenv("HOME")); if (*buf) return(0); user = getenv("USER"); psw = getpwnam(user); if (psw) { (void) strcpy(buf, psw->pw_dir); return(0); } psw = getpwuid((int) getuid()); if (psw) { (void) strcpy(buf, psw->pw_dir); return(0); } set_error(NO_HOME_DIR); error("get_home"); return error_code; } timed_out(file_ent, current_time, min_days) filerec *file_ent; time_t current_time, min_days; { if ((current_time - file_ent->specs.st_mtime) / 86400 >= min_days) return(1); else return(0); } int directory_exists(dirname) char *dirname; { struct stat stat_buf; if (stat(dirname, &stat_buf)) return(0); else if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) return(1); else return(0); } is_link(name, oldbuf) char *name; struct stat *oldbuf; { struct stat statbuf; if (oldbuf) statbuf = *oldbuf; else if (lstat(name, &statbuf) < 0) { set_error(errno); error("is_link"); return(0); } if ((statbuf.st_mode & S_IFMT) == S_IFLNK) return 1; else return 0; } /* * This is one of the few procedures that is allowed to break the * rule of always returning an error value if an error occurs. That's * because it's stupid to expect a boolean function to do that, and * because defaulting to not being a mountpoint if there is an error * is a reasonable thing to do. */ /* * The second parameter is optional -- if it is non-NULL< it is * presumed to be a stat structure fo the file being passed in. */ int is_mountpoint(name, oldbuf) char *name; struct stat *oldbuf; { struct stat statbuf; dev_t device; char buf[MAXPATHLEN]; #ifdef AFS_MOUNTPOINTS struct ViceIoctl blob; char retbuf[MAXPATHLEN]; int retval; char *shortname; #endif /* First way to check for a mount point -- if the device number */ /* of name is different from the device number of name/.. */ if (oldbuf) statbuf = *oldbuf; else if (lstat(name, &statbuf) < 0) { set_error(errno); error("is_mountpoint"); return 0; } device = statbuf.st_dev; if (strlen(name) + 4 /* length of "/.." + a NULL */ > MAXPATHLEN) { set_error(ENAMETOOLONG); error("is_mountpoint"); return 0; } strcpy(buf, name); strcat(buf, "/.."); if (lstat(buf, &statbuf) < 0) { set_error(errno); error("is_mountpoint"); return 0; } if (statbuf.st_dev != device) return 1; #ifdef AFS_MOUNTPOINTS /* Check for AFS mountpoint using the AFS pioctl call. */ if ((shortname = lastpart(name)) == name) { strcpy(buf, "."); blob.in = name; blob.in_size = strlen(name) + 1; blob.out = retbuf; blob.out_size = MAXPATHLEN; bzero(retbuf, MAXPATHLEN); } else { strncpy(buf, name, shortname - name - 1); buf[shortname - name - 1] = '\0'; if (*buf == '\0') strcpy(buf, "/"); blob.in = shortname; blob.in_size = strlen(shortname) + 1; blob.out = retbuf; blob.out_size = MAXPATHLEN; bzero(retbuf, MAXPATHLEN); } retval = pioctl(buf, VIOC_AFS_STAT_MT_PT, &blob, 0); if (retval == 0) { #ifdef DEBUG printf("%s is an AFS mountpoint, is_mountpoint returning true.\n", name); #endif return 1; } else { if (errno != EINVAL) { set_error(errno); error("is_mountpoint"); } } #endif /* AFS_MOUNTPOINTS */ return 0; }