1 /* 2 ** This is the main header file for gentoo. Most source files will include this header, 3 ** since it declares many of the data types that are used. When including this header, 4 ** it should always be the first included file. The preferred order of inclusion is: 5 ** #include "gentoo.h" 6 ** #include <system stuff> (e.g. <stdio.h>, <stdlib.h>, ...) 7 ** #include "more gentoo stuff" (e.g. "fileutil.h", "xmlutil.h", ...) 8 ** #include "me.h" (for a module named "me.c", that is). 9 ** 10 ** The reason why this file should be the first included one is that it fixes some 11 ** system-dependent things which need to go before any system headers are included. 12 */ 13 14 #include "config.h" 15 16 #if !(defined __osf__ && defined __alpha__) && !defined __NetBSD__ && !defined __FreeBSD__ && !defined __DragonFly__ && !defined __sgi 17 #if !defined __EXTENSIONS__ 18 #define __EXTENSIONS__ 19 #endif 20 #if !defined _POSIX_C_SOURCE 21 #define _POSIX_C_SOURCE 3 /* This is for Solaris. */ 22 #endif 23 #define POSIX_C_SOURCE 3 24 #endif /* !__osf__ && !__alpha */ 25 26 #if defined __osf__ && defined __alpha__ /* On Tru64, this should bring in mknod(). */ 27 #define _XOPEN_SOURCE_EXTENDED 28 #define _OSF_SOURCE /* For MAXNAMLEN on Tru64. */ 29 #endif 30 31 #if !defined _BSD_SOURCE 32 #define _BSD_SOURCE /* For MAXNAMLEN on Linux. */ 33 #endif 34 35 #include <dirent.h> 36 #include <errno.h> 37 #include <glob.h> 38 #include <limits.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include <sys/types.h> 42 #include <sys/mman.h> 43 #include <sys/stat.h> 44 #include <sys/time.h> 45 #include <regex.h> 46 #include <time.h> 47 #include <unistd.h> 48 49 /* The various BSDs seem to have a lot in common. Let's try and use that, 50 ** and save some typing in various tests below. This should probably all 51 ** be replaced by proper Autoconfed stuff at some point. 52 */ 53 #if defined __OpenBSD__ || defined __FreeBSD__ || defined __NetBSD__ || defined __DragonFly__ 54 #define GENTOO_ON_BSD 55 #endif 56 57 /* BSD-specific mounting stuff. */ 58 #if defined GENTOO_ON_BSD 59 #include <sys/param.h> 60 #include <sys/mount.h> 61 #endif 62 63 #undef GTK_ENABLE_BROKEN /* We can't use autoconf to undefine symbols. */ 64 #include <gio/gio.h> 65 #include <gtk/gtk.h> 66 #include <gdk-pixbuf/gdk-pixbuf.h> 67 68 /* Fix for < Glib 2.20. */ 69 #ifndef G_GOFFSET_FORMAT 70 #define G_GOFFSET_FORMAT G_GINT64_FORMAT 71 #endif 72 73 /* Not all systems' <mman.h> seem to define this. */ 74 #if !defined MAP_FAILED 75 #define MAP_FAILED ((void *) -1) 76 #endif 77 78 #if !defined MAXNAMLEN /* Still no MAXNAMLEN? Then make one up. */ 79 #define MAXNAMLEN 255 80 #endif 81 82 /* ----------------------------------------------------------------------------------------- */ 83 84 #define RCNAME "gentoorc" 85 86 /* ----------------------------------------------------------------------------------------- */ 87 88 /* Sometimes, this does good stuff. I hope. That's about all you can do with GNU tools, 89 ** since actually understanding them requires way more time than I'm willing to spend. 90 */ 91 #include "gnu-gettext.h" 92 93 #if defined ENABLE_NLS 94 /* This provides the _() and N_() macros used to mark strings for translation. */ 95 #include <glib/gi18n.h> 96 #else 97 /* Provide transparent definitions if NLS is disabled. */ 98 #define _(str) str 99 #define N_(str) str 100 #endif /* ENABLE_NLS */ 101 102 /* ----------------------------------------------------------------------------------------- */ 103 104 typedef struct MainInfo MainInfo; 105 typedef struct DirPane DirPane; 106 typedef struct CmdSeq CmdSeq; 107 108 /* These are various subsystems whose includes we need here, since they define datatypes 109 ** that are needed below. This is a good point to include them, since MainInfo has been 110 ** introduced (above). 111 */ 112 #include "buttonlayout.h" 113 #include "keyboard.h" 114 #include "controls.h" 115 #include "iconutil.h" 116 #include "queue.h" 117 #include "cmdarg.h" 118 #include "styles.h" 119 #include "dirhistory.h" 120 #include "window.h" 121 #include "menus.h" 122 #include "sizeutil.h" 123 124 #define KEY_NAME_SIZE (32) 125 126 #define CSQ_NAME_SIZE (32) 127 128 /* FileType-related constants. */ 129 enum { 130 FT_NAME_SIZE = (32), 131 FT_SUFFIX_SIZE = (32), 132 FT_NAMERE_SIZE = (64), 133 FT_FILERE_SIZE = (64), 134 135 FTFL_REQPERM = (1<<0), 136 FTFL_REQSUFFIX = (1<<1), 137 FTFL_NAMEMATCH = (1<<2), 138 FTFL_NAMEGLOB = (1<<3), 139 FTFL_FILEMATCH = (1<<4), 140 FTFL_FILEGLOB = (1<<5), 141 FTFL_NAMENOCASE = (1<<6), 142 FTFL_FILENOCASE = (1<<7), 143 144 FTPM_SETUID = (1<<0), 145 FTPM_SETGID = (1<<1), 146 FTPM_STICKY = (1<<2), 147 FTPM_READ = (1<<3), 148 FTPM_WRITE = (1<<4), 149 FTPM_EXECUTE = (1<<5), 150 }; 151 152 typedef struct { /* Used to map stat() info onto names. */ 153 gchar name[FT_NAME_SIZE]; /* Human-readable name of filetype (e.g. "GIF image", "MP3 song"). */ 154 mode_t mode; /* Type flags, matched against stat()'s mode info. */ 155 guint32 flags; /* Various flags. */ 156 guint32 perm; /* Permissions to require. Not orthogonal with mode. */ 157 gchar suffix[FT_SUFFIX_SIZE]; /* Suffix to require (if FTFL_REQSUFFIX is set). */ 158 gchar name_re_src[FT_NAMERE_SIZE]; /* Regular expression to match against the name (if FTFL_MATCHNAME). */ 159 regex_t *name_re; /* Compiled version of the regular expression. */ 160 gchar file_re_src[FT_FILERE_SIZE]; /* RE to match against output of 'file' command (if FTFL_MATCHFILE). */ 161 regex_t *file_re; /* Again, a compiled version of the regular expression. */ 162 Style *style; /* Style to use for items matching this type. */ 163 } FType; 164 165 #define DP_TITLE_SIZE (32) 166 #define DP_FORMAT_SIZE (16) 167 #define DP_DATEFMT_SIZE (32) 168 #define DP_MAX_COLUMNS (32) 169 170 typedef enum { DPC_NAME, DPC_SIZE, DPC_BLOCKS, DPC_BLOCKSIZE, DPC_MODENUM, DPC_MODESTR, 171 DPC_NLINK, DPC_UIDNUM, DPC_UIDSTR, DPC_GIDNUM, DPC_GIDSTR, DPC_DEVICE, DPC_DEVMAJ, DPC_DEVMIN, 172 DPC_ATIME, DPC_MTIME, DPC_CRTIME, DPC_CHTIME, 173 DPC_TYPE, DPC_ICON, 174 DPC_URI_NOFILE, 175 DPC_NUM_TYPES } DPContent; 176 177 typedef struct { 178 guint show_type : 1; /* Append type-character (from "@ / * | =") to names? */ 179 guint show_linkname : 1; /* Append " -> destination" on symbolic links? */ 180 } DC_Name; 181 182 typedef struct { 183 SzUnit unit; 184 guint ticks : 1; 185 gchar tick; 186 gint digits; 187 gchar dformat[DP_FORMAT_SIZE]; /* Hidden from user, not saved, built by config code. */ 188 guint dir_show_fs_size : 1; /* Show filesystem size for directories? */ 189 } DC_Size; 190 191 typedef struct { 192 gchar format[DP_FORMAT_SIZE]; /* General numerical formatter (for size, mode, uid, etc). */ 193 } DC_Fmt; 194 195 typedef struct { 196 gchar format[DP_DATEFMT_SIZE]; /* A strftime() format specifier. */ 197 } DC_Time; 198 199 typedef union { 200 DC_Name name; 201 DC_Size size; 202 DC_Fmt blocks, blocksize; 203 DC_Fmt mode, nlink, uidnum, gidnum, device, devmaj, devmin; 204 DC_Time a_time, m_time, cr_time, ch_time; 205 } DpCExtra; 206 207 typedef struct { 208 gchar title[DP_TITLE_SIZE]; 209 DPContent content; 210 DpCExtra extra; /* Content-specific flags. */ 211 GtkJustification just; 212 gint width; 213 } DpCFmt; 214 215 typedef enum { DPS_DIRS_FIRST = 0, DPS_DIRS_LAST, DPS_DIRS_MIXED } SortMode; 216 217 typedef struct { 218 DPContent content; /* The content type we wish to sort on. */ 219 SortMode mode; /* Controls placement of directories. */ 220 gboolean invert; /* If set, we sort backwards (Z-A). */ 221 gboolean nocase; /* Set for case-insensitive string comparisons. Lame! */ 222 } DPSort; 223 224 typedef enum { SBP_IGNORE = 0, SBP_LEFT, SBP_RIGHT } SBarPos; 225 226 #define FONT_MAX 128 227 228 typedef struct { 229 guint num_columns; 230 DpCFmt format[DP_MAX_COLUMNS]; 231 DPSort sort; 232 gchar def_path[PATH_MAX]; 233 gboolean path_above; /* Set to get the path entry above the actual pane. */ 234 gboolean hide_allowed; /* Set to enable hiding (default). */ 235 gboolean scrollbar_always; /* Set to always show scrollbar, regardless of # of entries. */ 236 gboolean huge_parent; /* Set to enable huge, tall, Opus-like parent button. */ 237 SBarPos sbar_pos; /* Position of scrollbar. */ 238 gboolean set_font; /* Set to override GTK+'s default font. */ 239 gchar font_name[FONT_MAX]; /* Last-set font name, remains valid even when set_font == FALSE. */ 240 gboolean rubber_banding; /* Set to enable GTK+'s "rubberbanding" selection. */ 241 } DPFormat; 242 243 typedef enum { DPORIENT_HORIZ = 0, DPORIENT_VERT } DpOrient; 244 typedef enum { DPSPLIT_FREE = 0, DPSPLIT_RATIO, DPSPLIT_ABS_LEFT, DPSPLIT_ABS_RIGHT } DpSplit; 245 246 /* Allow user to control how gentoo should allocate window space between the panes. */ 247 typedef struct { 248 DpOrient orientation; 249 DpSplit mode; 250 gdouble value; /* Parameter interpreted depending on mode. */ 251 } DPPaning; 252 253 typedef struct { 254 gboolean select; /* Remember selections? */ 255 gboolean save; /* Save history lists on exit? */ 256 } DPHistory; 257 258 /* ----------------------------------------------------------------------------------------- */ 259 260 /* General command row flags. */ 261 enum { 262 CGF_RUNINBG = (1<<0), /* Run in command in background? */ 263 CGF_KILLPREV = (1<<1), /* Kill previous instance of program (only background)? */ 264 CGF_GRABOUTPUT = (1<<2), /* Capture the output into a special window? */ 265 CGF_SURVIVE = (1<<3) /* Survive when gentoo quits (only background)? */ 266 }; 267 268 /* These flags are for the before- and after-flag fields. */ 269 enum { 270 CBAF_RESCAN_SOURCE = (1<<0), /* Rescan the source dir pane? */ 271 CBAF_RESCAN_DEST = (1<<1), 272 CBAF_CD_SOURCE = (1<<2), /* These save some config work. */ 273 CBAF_CD_DEST = (1<<3), 274 CBAF_REQSEL_SOURCE = (1<<4), /* Command won't run if there's no source selection when invoked. */ 275 CBAF_REQSEL_DEST = (1<<5) /* Command won't run if there's no destination selection when invoked. */ 276 }; 277 278 typedef struct { /* Extra info for external commands. */ 279 guint32 gflags; /* General flags. */ 280 guint32 baflags[2]; /* Before and after flags. */ 281 } CX_Ext; 282 283 typedef enum { CRTP_BUILTIN, CRTP_EXTERNAL, 284 CRTP_NUM_TYPES } CRType; 285 286 287 typedef struct { /* A command "row". */ 288 CRType type; /* The type of the row. */ 289 GString *def; /* The row definition string. */ 290 guint32 flags; /* Flags common to all types. */ 291 union { /* Type-specific row info. */ 292 CX_Ext external; /* Extra info for external commands. */ 293 } extra; 294 } CmdRow; 295 296 #define CSFLG_REPEAT (1<<0) /* Repeat sequence until no selection? */ 297 298 struct CmdSeq { 299 gchar name[CSQ_NAME_SIZE]; /* Name of this command sequence, really. */ 300 guint32 flags; /* Flags for this sequence. */ 301 GList *rows; /* List of CmdRow definition rows. */ 302 }; 303 304 typedef struct { /* Information about commands lives here. */ 305 GHashTable *builtin; /* Built-in commands (actually CmdDesc structs -- see cmdseq.c). */ 306 GHashTable *cmdseq; /* Command sequences. */ 307 } CmdInfo; 308 309 /* ----------------------------------------------------------------------------------------- */ 310 311 #define BTN_LABEL_SIZE (32) 312 #define BTN_TOOLTIP_SIZE (64) /* Arbitrary, as always. */ 313 314 typedef struct { 315 GList *sheets; /* List of button sheets. */ 316 } ButtonInfo; 317 318 typedef struct { /* Options for overwrite-confirmation dialog module. */ 319 guint show_info : 1; /* Show info (sizes & dates) for conflicting files? */ 320 gchar datefmt[DP_DATEFMT_SIZE]; /* How to format dates? */ 321 } OptOverwrite; 322 323 typedef enum { HIDE_NONE, HIDE_DOT, HIDE_REGEXP } HMode; 324 325 typedef struct { /* Info about files hidden from user. Not ignored, just hidden. */ 326 HMode mode; 327 gchar hide_re_src[MAXNAMLEN]; /* Regular expression; matches are hidden if mode == HIDE_REGEXP. */ 328 regex_t *hide_re; /* Compiled version of the RE. */ 329 guint no_case : 1; /* Ignore case in the RE? */ 330 } HideInfo; 331 332 typedef enum { PTID_ICON = 0, PTID_GTKRC, PTID_FSTAB, PTID_MTAB, 333 PTID_NUM_PATHS } PathID; 334 335 typedef struct { /* Miscellanous paths. */ 336 GString *path[PTID_NUM_PATHS]; /* Just one GString per path, that's all. */ 337 HideInfo hideinfo; /* Info about which files should be hidden. */ 338 } PathInfo; 339 340 typedef struct { /* Configuration information for dialogs. */ 341 GtkWindowPosition pos; /* How should dialogs be positioned? */ 342 } DialogInfo; 343 344 typedef enum { 345 ERR_DISPLAY_STATUSBAR, 346 ERR_DISPLAY_TITLEBAR, 347 ERR_DISPLAY_DIALOG 348 } ErrDisplay; 349 350 typedef struct { 351 ErrDisplay display; /* How should error (and status messages) be shown? */ 352 gboolean beep; /* Do a gdk_beep() on error? */ 353 } ErrInfo; 354 355 typedef struct { 356 GHashTable *ignored; /* Keyed on 'tag', if present ignore the dialog. */ 357 } NagInfo; 358 359 #define CFLG_CHANGED (1<<0) /* Config has changed. Set on "OK", cleared by cfg_save_all(). */ 360 361 typedef struct { /* Holds all configuration info. */ 362 guint32 flags; 363 GList *type; /* List of types (FType structures). */ 364 StyleInfo *style; /* Opaque style container. */ 365 DPFormat dp_format[2]; 366 DPPaning dp_paning; /* Controls how the paned view acts. */ 367 DPHistory dp_history; /* History list option. */ 368 OptOverwrite opt_overwrite; 369 MenuInfo *menus; 370 ButtonInfo buttons; 371 ButtonLayout *buttonlayout; 372 CmdInfo commands; 373 PathInfo path; 374 WinInfo *wininfo; 375 DialogInfo dialogs; 376 CtrlInfo *ctrlinfo; 377 ErrInfo errors; 378 gboolean (*dir_filter)(const gchar *name); 379 NagInfo nag; 380 } CfgInfo; 381 382 typedef struct GuiInfo GuiInfo; 383 384 typedef struct { 385 GVfs *vfs; 386 } VfsInfo; 387 388 struct MainInfo { /* gentoo's single most central data structure. */ 389 gchar **run_commands; /* From the command line --run option, kept first for initializer in main(). */ 390 VfsInfo vfs; 391 CfgInfo cfg; 392 GuiInfo *gui; 393 IconInfo *ico; 394 QueueInfo *que; 395 }; 396 397 /* -- Directory content data structures -- */ 398 399 /* This is used for complete-as-you-type of paths. */ 400 typedef struct { 401 gchar prefix[PATH_MAX]; /* The path prefix that the GtkCompletion holds strings for. */ 402 guint change_sig; /* Signal for change handler on path entry widget. */ 403 GtkEntryCompletion *compl; /* A GTK+ 2.0 completion object, attached to the pane's path entry. */ 404 } PathComplete; 405 406 enum { DPRF_HAS_SIZE = 1 << 0, /* Set when a row has a "real" size (not set for directories unless GetSize:d). */ 407 DPRF_LINK_EXISTS = 1 << 1, /* Set when a symlink's target exists. */ 408 DPRF_LINK_TO_DIR = 1 << 2 /* Set when symlink points at (valid) directory. Implies DPRF_LINK_EXISTS. */ 409 }; 410 411 typedef struct { /* A filename, in both on-disk and display formats. */ 412 const gchar *disk; /* On-disk name, as read during directory scanning. */ 413 const gchar *display; /* Display, as returned by glib (generally, this will be UTF-8). */ 414 } DRName; 415 416 typedef struct { /* Representation of a single line in a directory (a file, typically). */ 417 DRName dr_names; /* Actual filename, in two representations. */ 418 DRName dr_linknames; /* Link name, again in two representations. */ 419 struct stat dr_lstat; /* From a call to lstat(). */ 420 struct stat *dr_stat; /* If link, this holds link target stats. Else, it points at dr_lstat. */ 421 guint32 dr_flags; /* Misc. flags. */ 422 const FType *dr_type; /* Type information. */ 423 } DirRow; 424 425 typedef GtkTreeIter DirRow2; 426 427 typedef struct { 428 guint num_dirs, num_files; 429 guint64 num_bytes; 430 } SelInfo; 431 432 typedef struct { /* Some trivial file system information. Updated on rescan. */ 433 gboolean valid; /* Set if the structure's contents are valid. */ 434 guint64 fs_size; /* Size of filesystem, in bytes. */ 435 guint64 fs_free; /* Free bytes in this filesystem. */ 436 } FsInfo; 437 438 #define URI_MAX (2000) /* This should only rarely be used, and hopefully ease out once GIO gets more mature. */ 439 440 typedef struct { 441 gchar path[URI_MAX]; /* Contents apply to this path. */ 442 gchar *pathd; /* Dynamically allocated display version of the path. Beware! */ 443 GtkListStore *store; /* Actual ListStore holding the pane's contents. Insert and clear here. */ 444 GFile *root; /* A GFile representing the current location shown. */ 445 gboolean is_local; /* Is the root considered local? Used to control 'file' etc. */ 446 guint num_rows; /* Number of valid rows. */ 447 guint tot_dirs, tot_files; /* Total number of entries in directory. */ 448 guint64 tot_bytes; /* Sum of all sizes, in bytes. */ 449 struct stat *stat; /* Info about link targets. */ 450 gsize stat_alloc, stat_use; /* Allocated and used link stat structs. */ 451 SelInfo sel; 452 FsInfo fs; 453 } DirContents; 454 455 /* -- Main DirPane structure --------------------------------------------------------------- */ 456 457 struct DirPane { 458 MainInfo *main; /* Handy to have around. */ 459 guint index; /* Index of *this* pane, in the grand scheme of things. */ 460 GtkWidget *vbox; 461 GtkWidget *notebook; /* Notebook holding (normally) path widgetry. */ 462 GtkWidget *parent; /* The common parent button. */ 463 GtkWidget *hparent; /* The "huge" parent button, if enabled in config. */ 464 GtkWidget *path; /* GTK+ 2.0 GtkComboBox showing path and path history. */ 465 PathComplete complete; /* Information for completing the path. */ 466 GtkWidget *hide; /* A toggle button showing (and controlling) hide status. Focus target! */ 467 GtkWidget *scwin; /* Scrolling window for clist to live in. */ 468 GtkWidget *view; /* GtkTreeView for viewing the pane. */ 469 GtkWidget *menu_top; /* The top-level menu, typically shown by right-clicking. */ 470 GtkWidget *mitem_action; /* The item in the top-level menu that contains the actions submenu. */ 471 GtkWidget *menu_action; /* The menu containing the intersection of all available actions on the selection. */ 472 DirContents dir; /* Contents of directory (list of names etc). */ 473 DirHistory *hist; /* Historic data about previously visited directories. */ 474 gint last_row; /* The last clicked row. */ 475 gint last_row2; /* The second last clicked row. */ 476 gint dbclk_row; /* The row that was double clicked, or -1. */ 477 guint sig_sel_changed; /* Signal for the "changed" event on the view's GtkTreeSelection. */ 478 guint sig_path_activate; /* Signal for the "activate" event on path entry combo box. */ 479 guint sig_path_changed; /* Signal for the "changed" event on the path entry combo box. */ 480 }; 481 482 /* -- Graphic user interface stuff --------------------------------------------------------- */ 483 484 struct GuiInfo { 485 GtkWidget *window; 486 guint sig_main_configure; 487 guint sig_main_delete; 488 KbdContext *kbd_ctx; /* Keyboard context, for shortcuts. */ 489 GtkWidget *vbox; /* Vbox that contains entire GUI. */ 490 GtkWidget *top; /* A label showing status (selections, free space, etc). */ 491 GtkWidget *panes; /* GtkPaned widget holding DirPanes. */ 492 guint sig_pane_notify; /* Signal handler ID for notify::position. */ 493 GtkWidget *middle; /* A box holding entire middle part. */ 494 GtkWidget *bottom; /* Bottom part of GUI. */ 495 DirPane pane[2]; 496 DirPane *cur_pane; 497 498 gboolean evt_button_valid; 499 GdkEventButton evt_button; 500 }; 501 502 /* ----------------------------------------------------------------------------------------- */ 503 504 /* These are defined in the main "gentoo.c" module, but really shouldn't be. Until they 505 ** get a module of their own, they need to be prototyped like this. :( 506 */ 507 extern void rebuild_top(MainInfo *min); 508 extern void rebuild_middle(MainInfo *min); 509 extern void rebuild_bottom(MainInfo *min); 510