#include #include #include #include #include #include #include #include #include #include "fsbrowser.h" #include #include #include #include "fsbrowser.m" #include static HELP_FILE help_locate ("fsbrowser","locate"); static HELP_FILE help_attrib ("fsbrowser","attrib"); #define _TLMP_fsedit_locate struct _F_fsedit_locate{ #define _F_fsedit_locate_editfile(nom) void nom editfile(const char *path) virtual _F_fsedit_locate_editfile( )=0; }; static void fsedit_locate(_F_fsedit_locate &c) { SSTRING dir; SSTRING file; SSTRINGS founds; int len; _F_fsedit_locate *c; glocal.c = &c; DIALOG dia; dia.settype (DIATYPE_POPUP); dia.newf_str (MSG_U(F_FILE,"File(s) to locate"),glocal.file); dia.last_noempty(); glocal.dir.setfrom ("/"); dia.newf_str (MSG_U(F_DIR,"Seach in directory"),glocal.dir); dia.last_noempty(); char use_locate = 0; dia.newf_chk (MSG_U(F_USEDB,"Use the locate"),use_locate ,MSG_U(I_USEDB,"command")); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_LOCATE,"Locate files") ,MSG_U(I_LOCATE ,"You can search for a file or directory\n" "starting in a given directory.\n" "You may use the \"locate\" command, which is\n" "faster, but less acurate.") ,help_locate,nof); if (code == MENU_ESCAPE || code == MENU_CANCEL){ break; }else{ glocal.founds.remove_all(); SSTRINGS patterns; str_splitline (glocal.file.get(),' ',patterns); if (use_locate){ glocal.len = glocal.dir.getlen(); if (glocal.len == 1) glocal.len = 0; for (int i=0; iget(); ("locate",file,20); if (strncmp(line,glocal.dir.get(),glocal.len)==0 && line[glocal.len] == '/'){ glocal.founds.add (new SSTRING(line)); } return 0; } }else{ (glocal.dir.get()); const char *pt = strrchr (path,'/'); if (pt != NULL && glocal.file.cmp(pt+1)==0){ glocal.founds.add (new SSTRING(path)); } return true; } if (glocal.founds.getnb()==0){ xconf_notice (MSG_U(N_NOMATCH,"No match")); }else{ (MSG_U(T_LOCATERESULT,"Results") ,"",help_nil); for (int i=0; iget(),""); } newf_head (MSG_U(H_LOCATED,"Located files")); glocal.c->editfile (glocal.founds.getitem(no)->get()); } } } } static uid_t fsedit_name2uid(const char *id) { uid_t uid = (uid_t)-1; struct passwd *p = getpwnam(id); if (p != NULL){ uid = p->pw_uid; }else{ uid = atoi(id); // Check that all character are digits while (*id != '\0'){ if (!isdigit(*id)) uid = (uid_t)-1; id++; } } return uid; } static gid_t fsedit_name2gid(const char *id) { gid_t gid = (gid_t)-1; struct group *g = getgrnam(id); if (g != NULL){ gid = g->gr_gid; }else{ gid = atoi(id); // Check that all character are digits while (*id != '\0'){ if (!isdigit(*id)) gid = (gid_t)-1; id++; } } return gid; } static void fsedit_guilabel (DIALOG &dia, const char *s) { char tmp[1000]; dia.gui_label ("%s",diagui_quote(s,tmp)); } void fsedit_setting (const char *path) { struct stat st; if (stat(path,&st)!=-1){ DIALOG dia; dia.setcontext (""); SSTRING newname,user,group; TIMESTR modified(st.st_mtime),status(st.st_atime),accessed(st.st_ctime); int size = (int)st.st_size; dia.gui_passthrough(P_Book,"book"); dia.gui_passthrough(P_Page,"info \"%s\"",MSG_U(T_BASICINFO,"Base info.")); dia.newf_info (MSG_U(F_NAME,"File name"),path); dia.newline(); dia.newf_str (MSG_U(F_RENAME,"Rename to"),newname,60); dia.newline(); int field_user = dia.getnb(); { struct passwd *p = getpwuid (st.st_uid); if (p != NULL){ user.setfrom (p->pw_name); }else{ user.setfromf("%d",st.st_uid); } struct group *g = getgrgid (st.st_gid); if (g != NULL){ group.setfrom (g->gr_name); }else{ group.setfromf("%d",st.st_gid); } } FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_OWNER,"Owner"),user); { setpwent(); struct passwd *p; while ((p=getpwent())!=NULL) comb->addopt (p->pw_name,p->pw_gecos); endpwent(); } dia.newline(); comb = dia.newf_combo (MSG_U(F_GROUP,"Group"),group); { setgrent(); struct group *g; while ((g=getgrent())!=NULL) comb->addopt (g->gr_name); endgrent(); } dia.newline(); dia.newf_num (MSG_U(F_SIZE,"Size"),size); dia.set_lastreadonly(); dia.newline(); dia.newf_str (MSG_U(F_MODIFIED,"Modified"),modified); dia.newline(); dia.newf_str (MSG_U(F_ACCESSED,"Accessed"),accessed); dia.newline(); dia.newf_str (MSG_U(F_STATUS,"Status"),status); dia.newline(); dia.gui_end (); // lien symbolic // rafine le critere // faire un operation sur le resultat avec un select et des check-box dia.gui_passthrough(P_Page,"perm \"%s\"",MSG_U(I_PERMS,"Permissions bits")); char tbmode[12]; for (int i=0; i<12; i++){ tbmode[i] = (st.st_mode & (1<<(11-i))) != 0; } static const char *tbperm[]={ MSG_R(F_OWNER),MSG_R(F_GROUP), MSG_U(F_OTHER,"Others") }; if (dialog_mode == DIALOG_GUI){ #if 0 fsedit_guilabel (dia,MSG_U(I_USER,"User")); dia.gui_dispolast (GUI_H_CENTER,3,GUI_V_TOP,1); fsedit_guilabel (dia,""); fsedit_guilabel (dia,MSG_U(I_GROUP,"Group")); dia.gui_dispolast (GUI_H_CENTER,3,GUI_V_TOP,1); fsedit_guilabel (dia,""); fsedit_guilabel (dia,MSG_U(I_OTHER,"Other")); dia.gui_dispolast (GUI_H_CENTER,3,GUI_V_TOP,1); fsedit_guilabel (dia,""); fsedit_guilabel (dia,MSG_U(I_SPECIALS,"Special bits")); dia.gui_dispolast (GUI_H_CENTER,3,GUI_V_TOP,1); dia.newline(); for (int i=0; i<3; i++){ fsedit_guilabel (dia,MSG_U(I_READ,"Read")); fsedit_guilabel (dia,MSG_U(I_WRITE,"Write")); fsedit_guilabel (dia,MSG_U(I_EXEC,"Exec")); fsedit_guilabel (dia,""); } fsedit_guilabel (dia,MSG_U(I_SETUID,"SetUid")); fsedit_guilabel (dia,MSG_U(I_SETGID,"SetGid")); fsedit_guilabel (dia,MSG_U(I_STICKY,"Sticky")); dia.newline(); for (int i=3; i<12; i++){ if (i==6 || i==9) fsedit_guilabel (dia,""); dia.newf_chk (NULL,tbmode[i],""); dia.gui_dispolast (GUI_H_CENTER,1,GUI_V_TOP,1); } fsedit_guilabel (dia,""); for (int i=0; i<3; i++){ dia.newf_chk (NULL,tbmode[i],""); dia.gui_dispolast (GUI_H_CENTER,1,GUI_V_TOP,1); } dia.newline(); #else dia.gui_group (""); fsedit_guilabel (dia,""); fsedit_guilabel (dia,MSG_R(I_READ)); fsedit_guilabel (dia,MSG_R(I_WRITE)); fsedit_guilabel (dia,MSG_R(I_EXEC)); dia.newline(); for (int i=0; i<9; i+=3){ dia.newf_chk (tbperm[i/3],tbmode[i+3],""); dia.newf_chk (NULL,tbmode[i+4],""); dia.newf_chk (NULL,tbmode[i+5],""); dia.newline(); } dia.gui_end(); dia.gui_passthrough(P_Groupfit,"special \"%s\"" ,MSG_R(I_SPECIALS)); fsedit_guilabel (dia,""); dia.newline(); for (int i=0; i<3; i++){ static const char *tbspc[]={ MSG_U(F_SETUID,"Setuid"),MSG_U(F_SETGID,"Setgid"), MSG_U(F_STICKY,"Sticky") }; dia.newf_chk (NULL,tbmode[i],tbspc[i]); dia.newline(); } dia.gui_end (); #endif }else{ dia.newf_title ("",MSG_R(I_PERMS)); for (int i=0; i<9; i+=3){ dia.newf_chk (tbperm[i/3],tbmode[i+3],MSG_R(I_READ)); dia.newf_chk ("",tbmode[i+4],MSG_R(I_WRITE)); dia.newf_chk ("",tbmode[i+5],MSG_R(I_EXEC)); } dia.newf_chk (MSG_R(I_SPECIALS),tbmode[0],MSG_R(F_SETUID)); dia.newf_chk ("",tbmode[1],MSG_R(F_SETGID)); dia.newf_chk ("",tbmode[2],MSG_R(F_STICKY)); } dia.gui_end (); dia.gui_end (); dia.delwhat (MSG_U(B_DEL,"Select [Del] to delete the file")); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_FILE,"File attributes") ,MSG_U(I_FILE,"You can change the various file attributes") ,help_attrib,nof ,MENUBUT_ACCEPT|MENUBUT_CANCEL|MENUBUT_DEL); if (code == MENU_ESCAPE || code == MENU_CANCEL){ break; }else if (code == MENU_DEL){ }else if (perm_rootaccess(MSG_U(P_MNGFILES ,"to manage file settings"))){ uid_t uid = fsedit_name2uid(user.get()); gid_t gid = fsedit_name2gid(group.get()); if (uid == (uid_t)-1){ nof = field_user; xconf_error (MSG_U(E_IVLDUSER,"Invalid user id")); }else if (gid == (gid_t)-1){ nof = field_user+1; }else{ for (int i=0; i<12; i++){ int bit = (1<<(11-i)); if (tbmode[i]){ st.st_mode |= bit; }else{ st.st_mode &= ~bit; } } chmod (path,st.st_mode); chown (path,uid,gid); if (!newname.is_empty()){ if (rename(path,newname.get())==-1){ xconf_error (MSG_U(E_CANTRENAME,"Can't rename: %s") ,strerror(errno)); }else{ break; } }else{ break; } } } } } } static void fsedit_getlist ( const char *dir, bool extract_subdir, // Pick sub-dirs or files SSTRINGS &tb) { dir_getlist (dir,tb); for (int i=0; iget(); char path[PATH_MAX]; snprintf (path,sizeof(path)-1,"%s/%s",dir,f); struct stat st; stat(path,&st); bool erase; if (S_ISDIR(st.st_mode)){ erase = !extract_subdir; }else{ erase = extract_subdir; } if (erase){ tb.remove_del(i); i--; } } tb.sort(); } void fsedit_browsefiles(const char *dir, const char *context) { const char *dir; SSTRINGS tb; const char *context; glocal.dir = dir; glocal.context = context; char title[100]; snprintf (title,sizeof(title)-1,MSG_R(T_BROWSDIR),dir); (title,"",help_nil); newf_head (MSG_U(H_FILES,"Name\tSize\tOwner\tGroup")); setcontext (glocal.context); setbutinfo (MENU_USR1,MSG_U(B_REFRESH,"Refresh"),MSG_R(B_REFRESH)); sethdispo ("lrrr"); sortable(); sortpolicy ("annn"); glocal.tb.remove_all(); fsedit_getlist (glocal.dir,false,glocal.tb); for (int i=0; iget(); char path[PATH_MAX]; snprintf (path,sizeof(path)-1,"%s/%s",glocal.dir,f); struct stat st; stat(path,&st); char buf[100]; snprintf (buf,sizeof(buf)-1,"%ld\t%u\t%u" ,st.st_size,st.st_uid,st.st_gid); new_menuitem(f,buf); } const char *f = glocal.tb.getitem(no)->get(); char path[PATH_MAX]; snprintf (path,sizeof(path)-1,"%s/%s",glocal.dir,f); fsedit_setting (path); } /* Used to communicate with new threads */ struct FSEDIT_INFO{ PRIVATE_MESSAGE &msg; int &nbdirshown; char *path; char *guictx; FSEDIT_INFO( int &_nbdirshown, PRIVATE_MESSAGE &_msg, const char *_path, const char *_guictx) : msg(_msg), nbdirshown(_nbdirshown) { path = strdup(_path); guictx = strdup(_guictx); nbdirshown++; } ~FSEDIT_INFO() { free (path); free (guictx); nbdirshown--; } }; static void ft (void *p) { FSEDIT_INFO *info = (FSEDIT_INFO *)p; fsedit_browsefiles (info->path,info->guictx); dialog_sendmessage (info->msg); delete info; } static void fsedit_showdir ( int &nbdirshown, PRIVATE_MESSAGE &msg, const char *path, const char *guictx) { FSEDIT_INFO *info = new FSEDIT_INFO (nbdirshown,msg,path,guictx); uithread (ft,info); } void fsedit_browsedirs(const char *dir) { const char *dir; SSTRINGS tb; SSTRING context; PRIVATE_MESSAGE endthread; int nbdirshown; glocal.nbdirshown = 0; glocal.dir = dir; glocal.context.setfromf ("fsbr-%d",uithread_id); if (dialog_mode == DIALOG_GUI){ diagui_sendcmd (P_MainForm,"%s \"%s\"\n",glocal.context.get() ,MSG_U(T_FSBROWSE,"File browser")); diagui_sendcmd (P_Form,"left\n"); diagui_sendcmd (P_End,"\n"); diagui_sendcmd (P_Book,"book\n"); diagui_sendcmd (P_End,"\n"); diagui_sendcmd (P_End,"$nopopup=1\n"); } fsedit_getlist (glocal.dir,true,glocal.tb); char title[100]; snprintf (title,sizeof(title)-1,MSG_U(T_BROWSDIR,"Browsing %s") ,dir); (title,"",help_nil); newf_head (MSG_U(H_DIRS,"\tDirectories")); SSTRING ctx; ctx.setfromf ("%s.left",glocal.context.get()); setcontext (ctx.get()); for (int i=0; iget(); int level = 0; const char *name = d; while (*d != '\0'){ if (*d == '/'){ name = d+1; level++; } d++; } char buf[100]; snprintf (buf,sizeof(buf)-1,"%*s%s",level*3,"",name); new_menuitem ("",buf); } const char *f = glocal.tb.getitem(no)->get(); SSTRINGS subs; SSTRING path; path.setfromf("%s/%s",glocal.dir,f); SSTRING subctx; subctx.setfromf("%s.book",glocal.context.get()); if (glocal.tb.getnb()==no+1){ // We must expand the directory fsedit_getlist (path.get(),true,subs); fsedit_showdir (glocal.nbdirshown,glocal.endthread ,path.get(),subctx.get()); }else{ int len = strlen(f); const char *n = glocal.tb.getitem(no+1)->get(); if (strncmp(f,n,len)!=0 || n[len] != '/'){ // We must expand fsedit_getlist (path.get(),true,subs); fsedit_showdir (glocal.nbdirshown,glocal.endthread ,path.get(),subctx.get()); }else{ // We must remove the subdirs for (int i=no+1; iget(); if (strncmp(f,n,len)==0 && n[len] == '/'){ glocal.tb.remove_del(i); i--; }else{ break; } } } } // We insert the new stuff for (int i=0; iget(); SSTRING *ns = new SSTRING; ns->setfromf ("%s/%s",f,s); glocal.tb.insert (no+1+i,ns); } fprintf (stderr,"Other\n"); if (dialog_mode == DIALOG_GUI){ while (glocal.nbdirshown > 0){ dialog_waitformessage (glocal.endthread); } diagui_sendcmd (P_Delete,"%s\n",glocal.context.get()); } } void fsedit_browse() { SSTRING dir; bool ok = false; { DIALOG dia; dia.settype (DIATYPE_POPUP); dia.newf_str (MSG_U(F_STARTDIR,"Start directory"),dir); int nof = 0; ok = dia.edit ("","",help_nil,nof)==MENU_ACCEPT; } if (ok){ fsedit_browsedirs (dir.get()); } } void fsedit() { const char *f_locate; const char *f_browse; glocal.f_locate = MSG_U(M_LOCATE,"Locate files"); glocal.f_browse = MSG_U(M_BROWSE,"Browse a directory"); static const char *menuopt[]={ "", glocal.f_locate, "", glocal.f_browse, NULL }; (MSG_U(T_FSBROWSER,"File system browser") ,"",help_nil ,menuopt); if (perm_rootaccess (MSG_R(P_MNGFILES))){ if (key == glocal.f_locate){ (); fsedit_setting (path); }else if (key == glocal.f_browse){ fsedit_browse(); } } }