#include #include #include #include #include #include "misc.h" #include #include "misc.m" #include #include static int file_setperm ( const char *dst, int uid, int gid, int mode, const char *src) // Will use { if (src != NULL){ struct stat st; if (stat(src,&st)!=-1){ if (uid == -1) uid = st.st_uid; if (gid == -1) gid = st.st_gid; if (mode == -1) mode = st.st_mode & 07777; } } int ret = 0; if (uid != -1 || gid != -1) ret = chown (dst,uid,gid); if (ret == 0 && mode != -1) ret = chmod (dst,mode); return ret; } static int file_copy_perm ( const char *src, const char *dst, int uid, int gid, int mode) { int ret = -1; FILE *fin = fopen (src,"r"); if (fin != NULL){ FILE *fout = fopen (dst,"w"); if (fout != NULL){ char buf[10000]; int n; while ((n=fread(buf,1,sizeof(buf),fin))>0) fwrite (buf,1,n,fout); ret = fclose (fout); fclose (fin); ret = file_setperm (dst,uid,gid,mode,src); } } return ret; } /* Create a directory and optionnally force ownership and mode */ int file_mkdir ( const char *dir, int uid, // or -1 int gid, // or -1 int mode, // or -1 const char *src) // Directory to use to copy ownership and permission // (overriden separatly by the above parameter) { int ret = mkdir (dir,0755); if (ret == 0){ ret = file_setperm (dir,uid,gid,mode,src); } return ret; } int file_mkdir ( const char *dir, const char *user, const char *group, int perm) { int ret = -1; char fixuser[100],fixgroup[100]; configf_mapowner (user,group,fixuser,fixgroup); PERMINFO p; if (fixperm_readperm (dir,p,fixuser,fixgroup,perm,true)!=-1){ ret = file_mkdir (dir,p.uid,p.gid,p.perm,NULL); } return ret; } /* Create a sub-directory and all parent directory if needed The directory may be already existing */ int file_mkdirp ( const char *dir, int uid, // or -1 int gid, // or -1 int mode) // or -1 { int ret = 0; if (file_type(dir)==-1){ char pdir[PATH_MAX]; strcpy (pdir,dir); char *pt = strrchr(pdir,'/'); if (pt != NULL){ *pt = '\0'; file_mkdirp (pdir,uid,gid,mode); } ret = file_mkdir (dir,uid,gid,mode,NULL); } return ret; } /* Create a sub-directory and all parent directory if needed The directory may be already existing */ int file_mkdirp ( const char *dir, const char *user, const char *group, int perm) { int ret = -1; PERMINFO p; char fixuser[100],fixgroup[100]; configf_mapowner (user,group,fixuser,fixgroup); if (fixperm_readperm (dir,p,fixuser,fixgroup,perm,true)!=-1){ ret = file_mkdirp (dir,p.uid,p.gid,p.perm); } return ret; } int file_mkdirp ( const char *dir, const char *user, const char *group, const char *perm) { int fixperm_int; int ret = -1; PERMINFO p; char fixuser[100],fixgroup[100],fixperm[100]; configf_mapowner (user,group,perm,fixuser,fixgroup,fixperm); sscanf(fixperm, "%o", &fixperm_int); if (fixperm_readperm (dir,p,fixuser,fixgroup,fixperm_int,true)!=-1){ ret = file_mkdirp (dir,p.uid,p.gid,p.perm); } return ret; } /* Copy one file. Check if user is allowed Return -1 if any error. */ int file_copy (const char *src, const char *dst) { int ret = -1; if (perm_rootaccess (MSG_U(P_COPYSYSFILES,"to copy system files"))){ if (strcmp(src,dst)==0){ ret = 0; }else{ ret = file_copy_perm (src,dst,-1,-1,-1); } } return ret; } /* Copy a complete directory tree into another optionnally for ownership and mode. If the owner and mode is not provided (-1), those of the source will be used. */ int file_copytree ( const char *src, const char *dst, int uid, int gid, int mode) { int ret = 0; SSTRINGS lst; int n = dir_getlist (src,lst); for (int i=0; iget(); char srcpath[PATH_MAX],dstpath[PATH_MAX]; snprintf (srcpath,sizeof(srcpath)-1,"%s/%s",src,name); snprintf (dstpath,sizeof(dstpath)-1,"%s/%s",dst,name); int type = file_type (srcpath); if (type == 0){ ret = file_copy_perm (srcpath,dstpath,uid,gid,mode); }else if (type == 1){ file_mkdir (dstpath,uid,gid,mode,srcpath); ret = file_copytree (srcpath,dstpath,uid,gid,mode); }else if (type == 2){ // Device special file struct stat st; stat (srcpath,&st); ret = mknod (dstpath,st.st_mode,st.st_rdev); if (ret != -1) ret = file_setperm (dstpath,uid,gid,mode,srcpath); }else if (type == 3){ // Symbolic link char linkpath[PATH_MAX]; int n = readlink (srcpath,linkpath,sizeof(linkpath)-1); if (n == -1){ ret = -1; }else{ linkpath[n] = '\0'; ret = symlink (linkpath,dstpath); } }else{ ret = -1; } } return ret; } /* Follow a symbolic link and extract the effective (real) path realpath will simply contain the original path if it is not a symlink. Return -1 if the link can't be read properly. Return 0 otherwise (even if fpath is not a symlink). */ int file_followlink (const char *fpath, char *realpath) { int ret = 0; strcpy (realpath,fpath); while (file_type(realpath)==3){ char newpath[PATH_MAX]; int len = readlink(realpath,newpath,PATH_MAX-1); if (len==-1){ ret = -1; break; }else{ newpath[len] = '\0'; if (newpath[0] != '/'){ // This is a relative path, we keep the base path // of realpath char basepath[PATH_MAX]; strcpy (basepath,realpath); char *pt = strrchr(basepath,'/'); if (pt != NULL){ *++pt = '\0'; }else{ basepath[0] = '\0'; } if (strlen(basepath) + strlen(newpath) < PATH_MAX){ strcat (basepath,newpath); // We could try to simplify the path by stripping // ../ further, Would it be useful ? strcpy (realpath,basepath); }else{ ret = -1; } }else{ strcpy (realpath,newpath); } } } return ret; }