/************************************************************************** * Copyright (c) 2001 Southeastern Universities Research Association, * Thomas Jefferson National Accelerator Facility * * This software was developed under a United States Government license * described in the NOTICE file included as part of this distribution. * * Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 ************************************************************************** * * Description: * File utility to handle some functionalities that are missing * from java.io.File * * Author: * Jie Chen * Jefferson Lab HPC Group * * * * */ #include #include #include #include #include #include #include #include #include #include #include #include #define UNKNOWN "UNKNOWN" /* Generated header file from javah */ #include "JFile.h" /** * Get group count for a user with username */ static int getugroups (int maxcount, gid_t grouplist[], char *username, gid_t gid) { struct group *grp; register char **cp; register int count = 0; if (gid != -1) { if (maxcount != 0) grouplist[count] = gid; ++count; } setgrent (); while ((grp = getgrent ()) != 0) { for (cp = grp->gr_mem; *cp; ++cp) { int n; if ( strcmp (username, *cp) != 0) continue; /* See if this group number is already on the list. */ for (n = 0; n < count; ++n) if (grouplist && grouplist[n] == grp->gr_gid) break; /* If it's a new group number, then try to add it to the list. */ if (n == count) { if (maxcount != 0) { if (count >= maxcount) { endgrent (); return count; } grouplist[count] = grp->gr_gid; } count++; } } } endgrent (); return count; } /** * Set supplemental groups to a user id and a group id * * On success 0 is returned. * On error, -1 is returned */ static int setsupgroups (const char* username, gid_t gid) { int maxcount, count; gid_t sgrps[32]; maxcount = 32; count = getugroups (maxcount, sgrps, username, gid); if (count <= 0) return -1; if (setgroups (count, sgrps) != 0) { printf ("Set groups failed, errno is %d\n", errno); perror (" Set groups: "); return -1; } return 0; } jboolean Java_jlab_hpc_util_JFile_isLink (JNIEnv * env, jclass cl, jstring fname) { struct stat st; char* filename; /* Obtain a C-copy of the Java string */ filename = strdup((*env)->GetStringUTFChars(env, fname, 0)); if(filename[strlen(filename)-1]=='/' && strlen(filename)>1) filename[strlen(filename)-1] = 0; if (lstat (filename, &st) == 0) { free(filename); return ((st.st_mode & (S_IFLNK | S_IFREG)) == S_IFLNK); } else { free(filename); return 0; } } jstring Java_jlab_hpc_util_JFile_getLinkTarget (JNIEnv *env, jclass cl, jstring fname) { char buf[1024]; char* filename; char * ptr; int len = 0; /* Obtain a C-copy of the Java string */ filename = strdup((*env)->GetStringUTFChars(env, fname, 0)); if(filename[strlen(filename)-1]=='/' && strlen(filename)>1) filename[strlen(filename)-1] = 0; if ((len=readlink(filename, buf, 1024)) <= 0) { free(filename); return NULL; } else { buf[len]=0; if (*buf != '/' && (ptr=strrchr(filename, '/'))!=NULL) { *(ptr+1)=0; memmove(buf+strlen(filename), buf, strlen(buf)+1); memmove(buf, filename, strlen(filename)); } free(filename); return (*env)->NewStringUTF(env, buf); } } jboolean Java_jlab_hpc_util_JFile_allocate (JNIEnv * env, jclass cl, jstring fname, jstring user, jlong bytes) { const char* filename; const char* username; struct passwd* pwsd = 0; uid_t userid; long size; struct mem_dqblk mb; return 1; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); username = (*env)->GetStringUTFChars(env, user, 0); /* Find user id information for username */ if ((pwsd = getpwnam (username)) != 0) userid = pwsd->pw_uid; if (quotactl(Q_GETQUOTA, filename, userid, (caddr_t)&mb) == 0) { size = mb.dqb_bsoftlimit - mb.dqb_curspace; if (size >= bytes) return 1; } return 0; } jint Java_jlab_hpc_util_JFile_createFile (JNIEnv *env, jclass cl, jstring fname, jstring user) { const char* filename; const char* username; struct passwd* pwsd = 0; uid_t userid; gid_t grpid; int ok = 1; int fd = 0; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); username = (*env)->GetStringUTFChars(env, user, 0); /* Find user id information for username */ if ((pwsd = getpwnam (username)) != 0) { userid = pwsd->pw_uid; grpid = pwsd->pw_gid; /* do seteuid: cannot setuid since we have to switch back to root */ if (setsupgroups (username, grpid) != 0 || setegid (grpid) != 0 || seteuid (userid) != 0) ok = 0; } else ok = 0; if (ok) { if ((fd = creat (filename, 0644)) == -1) ok = 0; else close (fd); /* set uid back to root */ if (seteuid (0) != 0 || setegid (0) != 0 || setsupgroups ("root", 0) != 0) { ok = 0; } } /* Now we are done with str */ (*env)->ReleaseStringUTFChars(env, fname, filename); (*env)->ReleaseStringUTFChars(env, user, username); return ok; } jint Java_jlab_hpc_util_JFile_deleteFile (JNIEnv *env, jclass cl, jstring fname, jstring user) { const char* filename; const char* username; struct passwd* pwsd = 0; struct stat st; uid_t userid; gid_t grpid; int ok = 1; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); username = (*env)->GetStringUTFChars(env, user, 0); /* Find user id information for username */ if ((pwsd = getpwnam (username)) != 0) { userid = pwsd->pw_uid; grpid = pwsd->pw_gid; if (stat (filename, &st) != 0) ok = 0; else { if (st.st_uid != userid) ok = 0; } } else ok = 0; if (ok) { if (setsupgroups (username, grpid) != 0 || setegid (grpid) != 0 || seteuid (userid) != 0) ok = 0; else if (remove (filename) == -1) ok = 0; /* set uid back to root */ if (seteuid (0) != 0 || setegid (0) != 0 || setsupgroups ("root", 0) != 0) ok = 0; } /* Now we are done with str */ (*env)->ReleaseStringUTFChars(env, fname, filename); (*env)->ReleaseStringUTFChars(env, user, username); return ok; } jstring Java_jlab_hpc_util_JFile_getOwner (JNIEnv *env, jclass cl, jstring fname) { const char* filename; struct stat st; struct passwd* pwst; const char* username = NULL; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); if (stat (filename, &st) == 0) { pwst = getpwuid(st.st_uid); if (pwst != NULL) username = pwst->pw_name; } return (*env)->NewStringUTF(env, username); } jstring Java_jlab_hpc_util_JFile_getGroup (JNIEnv *env, jclass cl, jstring fname) { const char* filename; struct stat st; struct group* gst; const char* grname = NULL; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); if (stat (filename, &st) == 0) { gst = getgrgid(st.st_gid); if (gst != NULL) grname = gst->gr_name; } return (*env)->NewStringUTF(env, grname); } /** * change owner of a given file. * return 1: success. * return 0: failure. */ jint Java_jlab_hpc_util_JFile_changeOwner (JNIEnv *env, jclass cl, jstring fname, jstring owner) { const char* filename; const char* username; struct passwd* pwsd = 0; uid_t userid; gid_t grpid; int ok = 1; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); username = (*env)->GetStringUTFChars(env, owner, 0); /* Find user id information for username */ if ((pwsd = getpwnam (username)) != 0) { userid = pwsd->pw_uid; grpid = pwsd->pw_gid; if (chown (filename, userid, grpid) != 0) ok = 0; } return ok; } /** * Create directory 'path' amd make parent directory when needed. * return 1: success. * return 0: failure. */ static int createUserDirs (const char* path) { /* This code is for unix only */ int done = 0; int ok = 1; struct stat st; char* slash = 0; char tmp[1024]; char *q, *p; /* if there is separator, this is a relative path */ slash = strchr (path, '/'); if (!slash) return mkdir (path, 0755); while (!done && slash) { slash = slash + 1; if (!slash || !*slash) done = 1; else { /* find out each individual path leading to the final path 'path' */ q = tmp; p = (char *)path; slash = strchr (slash + 1, '/'); if (!slash) { /* this is last segment of file path */ strcpy (tmp, path); done = 1; } else { while (p != slash) { *q = *p; q++; p++; } *q = '\0'; } /* now tmp should a path */ if (stat (tmp, &st) == 0) { if (!S_ISDIR (st.st_mode)) { /* this path exisits but it is not a directory */ done = 1; ok = 0; } } else { /* now try to create a new directory */ if (mkdir (tmp, 0755) == -1) { /* failed to create new directory */ done = 1; ok = 0; } } } } return ok; } jint Java_jlab_hpc_util_JFile_createDir (JNIEnv *env, jclass cls, jstring fname, jstring user) { const char* filename; const char* username; struct passwd* pwsd = 0; struct stat st; uid_t userid; gid_t grpid; int ok = 1; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); username = (*env)->GetStringUTFChars(env, user, 0); /* Find user id information for username */ if ((pwsd = getpwnam (username)) != 0) { userid = pwsd->pw_uid; grpid = pwsd->pw_gid; if (setsupgroups (username, grpid) != 0 || setegid (grpid) != 0 || seteuid (userid) != 0) ok = 0; else { if (mkdir (filename, 0755) == 0) ok = 1; } /* set uid back to root */ if (seteuid (0) != 0 || setegid (0) != 0 || setsupgroups ("root", 0) != 0) ok = 0; } /* Now we are done with str */ (*env)->ReleaseStringUTFChars(env, fname, filename); (*env)->ReleaseStringUTFChars(env, user, username); return ok; } jint Java_jlab_hpc_util_JFile_createDirs (JNIEnv *env, jclass cls, jstring fname, jstring user) { const char* filename; const char* username; struct passwd* pwsd = 0; struct stat st; uid_t userid; gid_t grpid; int ok = 1; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); username = (*env)->GetStringUTFChars(env, user, 0); /* Find user id information for username */ if ((pwsd = getpwnam (username)) != 0) { userid = pwsd->pw_uid; grpid = pwsd->pw_gid; if (setsupgroups (username, grpid) != 0 || setegid (grpid) != 0 || seteuid (userid) != 0) ok = 0; else ok = createUserDirs (filename); /* set uid back to root */ if (seteuid (0) != 0 || setegid (0) != 0 || setsupgroups ("root", 0) != 0) ok = 0; } /* Now we are done with str */ (*env)->ReleaseStringUTFChars(env, fname, filename); (*env)->ReleaseStringUTFChars(env, user, username); return ok; } /** * Remove a user directory recursively. * return 1: success. * return 0: failure. */ static int deleteUserDirs (const char* path) { struct stat st; DIR* dir; struct dirent* ent; char fname[1024]; if (stat (path, &st) == 0) { if (!S_ISLNK(st.st_mode) && S_ISDIR (st.st_mode)) { /* open this directory */ dir = opendir (path); if (!dir) return 0; while ((ent = readdir(dir))) { /* do not count the following directories */ if (strcmp (ent->d_name, ".") == 0 || strcmp (ent->d_name, "..") == 0) continue; sprintf (fname, "%s/%s", path, ent->d_name); if (deleteUserDirs (fname) == 0) return 0; } closedir (dir); /* delete this directory */ if (rmdir(path) == -1) return 0; } if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) if (unlink (path) == -1) return 0; } return 1; } jint Java_jlab_hpc_util_JFile_deleteDirs (JNIEnv *env, jclass cls, jstring fname, jstring user) { const char* filename; const char* username; struct passwd* pwsd = 0; uid_t userid; gid_t grpid; int ok = 1; /* Obtain a C-copy of the Java string */ filename = (*env)->GetStringUTFChars(env, fname, 0); username = (*env)->GetStringUTFChars(env, user, 0); /* Find user id information for username */ if ((pwsd = getpwnam (username)) != 0) { userid = pwsd->pw_uid; grpid = pwsd->pw_gid; if (setsupgroups (username, grpid) != 0 || setegid (grpid) != 0 || seteuid (userid) != 0) ok = 0; else ok = deleteUserDirs (filename); /* set uid back to root */ if (seteuid (0) != 0 || setegid (0) != 0 || setsupgroups ("root", 0) != 0) ok = 0; } /* Now we are done with str */ (*env)->ReleaseStringUTFChars(env, fname, filename); (*env)->ReleaseStringUTFChars(env, user, username); return ok; } jstring Java_jlab_hpc_util_JFile_homeDir (JNIEnv *env, jclass cls, jstring user) { const char* username; struct passwd* pwsd = 0; /* Obtain a C-copy of the Java string */ username = (*env)->GetStringUTFChars(env, user, 0); /* Find user id information for username */ if ((pwsd = getpwnam (username)) != 0) return (*env)->NewStringUTF(env, pwsd->pw_dir); return (*env)->NewStringUTF(env, UNKNOWN); } jlong Java_jlab_hpc_util_JFile_getTotalSpace (JNIEnv *env, jclass cls, jstring path) { const char* disk; struct statfs buff; long size; /* Obtain a C-copy of the Java string */ disk = (*env)->GetStringUTFChars(env, path, 0); if (statfs (disk, &buff) == 0) { size = buff.f_bsize/1024; return buff.f_blocks*size; } else { printf ("statfs failed, errno is %d\n", errno); return -1; } } jlong Java_jlab_hpc_util_JFile_getAvailableSpace (JNIEnv *env, jclass cls, jstring path) { const char* disk; struct statfs buff; long size; /* Obtain a C-copy of the Java string */ disk = (*env)->GetStringUTFChars(env, path, 0); if (statfs (disk, &buff) == 0) { size = buff.f_bsize/1024; return buff.f_bavail*size; } else return -1; }