From: Thomas Walker Lynch Date: Fri, 6 Dec 2024 14:11:53 +0000 (+0000) Subject: makefile for C, core util rm that does not delete penciled files X-Git-Url: https://git.reasoningtechnology.com/fossil/%7Bstyle.link%7D?a=commitdiff_plain;h=d5424b49e2a78a8a68cd59a142348046889f6fc0;p=RT-project-share makefile for C, core util rm that does not delete penciled files --- diff --git a/README.md b/README.md index 915a0df..b9e9fca 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,28 @@  This project holds the builds for simple tools and scripts tha are common to -projects, documents that are shared by projects, and useful configuration files. -It will also serves as a project skeleton when it is copmleted. +multiple projects, documents that are on general topics or shared by projects, +and useful configuration files. + +Currently RT-incommon does not implement the full project skeleton and work flows. +For example, instead of releasing developed work product from the developer directory, +there are symbolic links into the developer directory. Also the tester directory +is empty. + +I've avoided using Mosaic or Ariadne here so as to avoid hard to think about +circular dependencies. At some point we plan to christen a release of Mosaic +and Ariadne as the go-to versions, then incorproate those go-to versions into +later versions of themselves, and here in the RT-incommon project. + +This project is used by including it as a third party tool, then picking +and choosing what is to be used in the adopting project by creating +symbolic links to the chosen items in the Rt-incommon release directory. + + + + + + + + diff --git a/developer/amd64/rm_na b/developer/amd64/rm_na new file mode 100755 index 0000000..57bd08d Binary files /dev/null and b/developer/amd64/rm_na differ diff --git "a/developer/bash\360\237\226\211/bash\360\237\226\211" "b/developer/bash\360\237\226\211/bash\360\237\226\211" new file mode 120000 index 0000000..97464d3 --- /dev/null +++ "b/developer/bash\360\237\226\211/bash\360\237\226\211" @@ -0,0 +1 @@ +/var/user_data/Thomas-developer/RT-incommon/developer/bash🖉 \ No newline at end of file diff --git "a/developer/cc\360\237\226\211/home.cli.c" "b/developer/cc\360\237\226\211/home.cli.c" index 4395a60..d990d96 100644 --- "a/developer/cc\360\237\226\211/home.cli.c" +++ "b/developer/cc\360\237\226\211/home.cli.c" @@ -1,3 +1,4 @@ +#define IFACE #include #include #include diff --git "a/developer/cc\360\237\226\211/is_authored_fs_obj.c" "b/developer/cc\360\237\226\211/is_authored_fs_obj.c" new file mode 100644 index 0000000..1c82e9a --- /dev/null +++ "b/developer/cc\360\237\226\211/is_authored_fs_obj.c" @@ -0,0 +1,56 @@ +#include +#include + +static bool is_authored_fs_obj(const char *path) { + if (!path || strlen(path) == 0) { + return false; + } + + // Check if the last character is the pencil + size_t len = strlen(path); + return path[len - 1] == '🖉'; +} + + +#include +#include +#include +#include + +static bool is_authored(const char *path) { + if (!path || strlen(path) == 0) { + return false; + } + + // Check the path itself + if (is_authored_fs_obj(path)) { + return true; + } + + // Check each parent directory up to the root + char *path_copy = strdup(path); + if (!path_copy) { + return false; // Memory allocation failure + } + + char *parent = path_copy; + bool authored = false; + + while (true) { + parent = dirname(parent); + + // Check if the current directory is authored + if (is_authored_fs_obj(parent)) { + authored = true; + break; + } + + // If we reach the root, stop + if (strcmp(parent, "/") == 0) { + break; + } + } + + free(path_copy); + return authored; +} diff --git "a/developer/cc\360\237\226\211/remove.c" "b/developer/cc\360\237\226\211/remove.c" new file mode 100644 index 0000000..3ce98f9 --- /dev/null +++ "b/developer/cc\360\237\226\211/remove.c" @@ -0,0 +1,762 @@ +#include +#include +#include + +#include +#include + +static bool is_authored_fs_obj(const char *path) { + if (!path || strlen(path) == 0) { + return false; + } + + // Check if the last character is the pencil (as a string) + const char *suffix = "🖉"; + size_t len = strlen(path); + size_t suffix_len = strlen(suffix); + + if (len < suffix_len) { + return false; + } + + return strcmp(path + len - suffix_len, suffix) == 0; +} + +#include +#include +#include +#include +#include +#include +#include + +static bool is_authored(const char *path) { + if (!path || strlen(path) == 0) { + fprintf(stderr, "DEBUG: Invalid path provided\n"); + return false; + } + + // Convert to an absolute path + char abs_path[PATH_MAX]; + if (!realpath(path, abs_path)) { + fprintf(stderr, "DEBUG: Failed to resolve absolute path for: %s\n", path); + return false; + } + + fprintf(stderr, "DEBUG: Starting check for path: %s (resolved: %s)\n", path, abs_path); + + // Allocate and copy for safe modifications + char *current_path = strdup(abs_path); + if (!current_path) { + fprintf(stderr, "DEBUG: Memory allocation failed for current_path\n"); + return false; + } + + bool authored = false; + int iteration_count = 0; + + while (true) { + fprintf(stderr, "DEBUG: Iteration %d, checking path: %s\n", iteration_count, current_path); + + // Check if the current path is authored + if (is_authored_fs_obj(current_path)) { + fprintf(stderr, "DEBUG: Found authored path: %s\n", current_path); + authored = true; + break; + } + + // Get parent directory + char *parent_path = strdup(current_path); + if (!parent_path) { + fprintf(stderr, "DEBUG: Memory allocation failed for parent_path\n"); + break; + } + char *parent = dirname(parent_path); + + // Stop condition: root or no change in path + if (strcmp(parent, "/") == 0 || strcmp(parent, current_path) == 0) { + fprintf(stderr, "DEBUG: Reached stop condition at parent: %s\n", parent); + free(parent_path); + break; + } + + // Update current_path for the next iteration + free(current_path); + current_path = strdup(parent); + if (!current_path) { + fprintf(stderr, "DEBUG: Memory allocation failed while updating current_path\n"); + free(parent_path); + break; + } + + free(parent_path); + iteration_count++; + + // Failsafe for infinite loops + if (iteration_count > 100) { + fprintf(stderr, "DEBUG: Too many iterations, exiting to avoid infinite loop\n"); + break; + } + } + + free(current_path); + return authored; +} + + +/* remove.c -- core functions for removing files and directories + Copyright (C) 1988-2024 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Extracted from rm.c, librarified, then rewritten twice by Jim Meyering. */ + +#include +#include +#include + +#include "system.h" +#include "assure.h" +#include "file-type.h" +#include "filenamecat.h" +#include "ignore-value.h" +#include "remove.h" +#include "root-dev-ino.h" +#include "stat-time.h" +#include "write-any-file.h" +#include "xfts.h" +#include "yesno.h" + +/* The prompt function may be called twice for a given directory. + The first time, we ask whether to descend into it, and the + second time, we ask whether to remove it. */ +enum Prompt_action + { + PA_DESCEND_INTO_DIR = 2, + PA_REMOVE_DIR + }; + +/* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN + otherwise. */ +#if ! HAVE_STRUCT_DIRENT_D_TYPE +/* Any int values will do here, so long as they're distinct. + Undef any existing macros out of the way. */ +# undef DT_UNKNOWN +# undef DT_DIR +# undef DT_LNK +# define DT_UNKNOWN 0 +# define DT_DIR 1 +# define DT_LNK 2 +#endif + +/* Like fstatat, but cache on POSIX-compatible systems. */ +static int +cache_fstatat (int fd, char const *file, struct stat *st, int flag) +{ +#if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC + /* If ST->st_atim.tv_nsec is -1, the status has not been gotten yet. + If less than -1, fstatat failed with errno == ST->st_ino. + Otherwise, the status has already been gotten, so return 0. */ + if (0 <= st->st_atim.tv_nsec) + return 0; + if (st->st_atim.tv_nsec == -1) + { + if (fstatat (fd, file, st, flag) == 0) + return 0; + st->st_atim.tv_nsec = -2; + st->st_ino = errno; + } + errno = st->st_ino; + return -1; +#else + return fstatat (fd, file, st, flag); +#endif +} + +/* Initialize a fstatat cache *ST. Return ST for convenience. */ +static inline struct stat * +cache_stat_init (struct stat *st) +{ +#if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC + st->st_atim.tv_nsec = -1; +#endif + return st; +} + +/* Return 1 if FILE is an unwritable non-symlink, + 0 if it is writable or some other type of file, + -1 and set errno if there is some problem in determining the answer. + Set *BUF to the file status. */ +static int +write_protected_non_symlink (int fd_cwd, + char const *file, + struct stat *buf) +{ + if (can_write_any_file ()) + return 0; + if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0) + return -1; + if (S_ISLNK (buf->st_mode)) + return 0; + /* Here, we know FILE is not a symbolic link. */ + + /* In order to be reentrant -- i.e., to avoid changing the working + directory, and at the same time to be able to deal with alternate + access control mechanisms (ACLs, xattr-style attributes) and + arbitrarily deep trees -- we need a function like eaccessat, i.e., + like Solaris' eaccess, but fd-relative, in the spirit of openat. */ + + /* In the absence of a native eaccessat function, here are some of + the implementation choices [#4 and #5 were suggested by Paul Eggert]: + 1) call openat with O_WRONLY|O_NOCTTY + Disadvantage: may create the file and doesn't work for directory, + may mistakenly report 'unwritable' for EROFS or ACLs even though + perm bits say the file is writable. + + 2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd) + Disadvantage: changes working directory (not reentrant) and can't + work if save_cwd fails. + + 3) if (euidaccess (full_name, W_OK) == 0) + Disadvantage: doesn't work if full_name is too long. + Inefficient for very deep trees (O(Depth^2)). + + 4) If the full pathname is sufficiently short (say, less than + PATH_MAX or 8192 bytes, whichever is shorter): + use method (3) (i.e., euidaccess (full_name, W_OK)); + Otherwise: vfork, fchdir in the child, run euidaccess in the + child, then the child exits with a status that tells the parent + whether euidaccess succeeded. + + This avoids the O(N**2) algorithm of method (3), and it also avoids + the failure-due-to-too-long-file-names of method (3), but it's fast + in the normal shallow case. It also avoids the lack-of-reentrancy + and the save_cwd problems. + Disadvantage; it uses a process slot for very-long file names, + and would be very slow for hierarchies with many such files. + + 5) If the full file name is sufficiently short (say, less than + PATH_MAX or 8192 bytes, whichever is shorter): + use method (3) (i.e., euidaccess (full_name, W_OK)); + Otherwise: look just at the file bits. Perhaps issue a warning + the first time this occurs. + + This is like (4), except for the "Otherwise" case where it isn't as + "perfect" as (4) but is considerably faster. It conforms to current + POSIX, and is uniformly better than what Solaris and FreeBSD do (they + mess up with long file names). */ + + { + if (faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0) + return 0; + + return errno == EACCES ? 1 : -1; + } +} + +/* Return the status of the directory identified by FTS and ENT. + This is -1 if the directory is empty, 0 if it is nonempty, + and a positive error number if there was trouble determining the status, + e.g., it is not a directory, or permissions problems, or I/O errors. + Use *DIR_STATUS as a cache for the status. */ +static int +get_dir_status (FTS const *fts, FTSENT const *ent, int *dir_status) +{ + if (*dir_status == DS_UNKNOWN) + *dir_status = directory_status (fts->fts_cwd_fd, ent->fts_accpath); + return *dir_status; +} + +/* Prompt whether to remove FILENAME, if required via a combination of + the options specified by X and/or file attributes. If the file may + be removed, return RM_OK or RM_USER_ACCEPTED, the latter if the user + was prompted and accepted. If the user declines to remove the file, + return RM_USER_DECLINED. If not ignoring missing files and we + cannot lstat FILENAME, then return RM_ERROR. + + IS_DIR is true if ENT designates a directory, false otherwise. + + Depending on MODE, ask whether to 'descend into' or to 'remove' the + directory FILENAME. MODE is ignored when FILENAME is not a directory. + Use and update *DIR_STATUS as needed, via the conventions of + get_dir_status. */ +static enum RM_status +prompt (FTS const *fts, FTSENT const *ent, bool is_dir, + struct rm_options const *x, enum Prompt_action mode, + int *dir_status) +{ + int fd_cwd = fts->fts_cwd_fd; + char const *full_name = ent->fts_path; + char const *filename = ent->fts_accpath; + struct stat st; + struct stat *sbuf = &st; + cache_stat_init (sbuf); + + int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN; + int write_protected = 0; + + /* When nonzero, this indicates that we failed to remove a child entry, + either because the user declined an interactive prompt, or due to + some other failure, like permissions. */ + if (ent->fts_number) + return RM_USER_DECLINED; + + if (x->interactive == RMI_NEVER) + return RM_OK; + + int wp_errno = 0; + if (!x->ignore_missing_files + && (x->interactive == RMI_ALWAYS || x->stdin_tty) + && dirent_type != DT_LNK) + { + write_protected = write_protected_non_symlink (fd_cwd, filename, sbuf); + wp_errno = errno; + } + + if (write_protected || x->interactive == RMI_ALWAYS) + { + if (0 <= write_protected && dirent_type == DT_UNKNOWN) + { + if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0) + { + if (S_ISLNK (sbuf->st_mode)) + dirent_type = DT_LNK; + else if (S_ISDIR (sbuf->st_mode)) + dirent_type = DT_DIR; + /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */ + } + else + { + /* This happens, e.g., with 'rm '''. */ + write_protected = -1; + wp_errno = errno; + } + } + + if (0 <= write_protected) + switch (dirent_type) + { + case DT_LNK: + /* Using permissions doesn't make sense for symlinks. */ + if (x->interactive != RMI_ALWAYS) + return RM_OK; + break; + + case DT_DIR: + /* Unless we're either deleting directories or deleting + recursively, we want to raise an EISDIR error rather than + prompting the user */ + if ( ! (x->recursive + || (x->remove_empty_directories + && get_dir_status (fts, ent, dir_status) != 0))) + { + write_protected = -1; + wp_errno = *dir_status <= 0 ? EISDIR : *dir_status; + } + break; + } + + char const *quoted_name = quoteaf (full_name); + + if (write_protected < 0) + { + error (0, wp_errno, _("cannot remove %s"), quoted_name); + return RM_ERROR; + } + + /* Issue the prompt. */ + if (dirent_type == DT_DIR + && mode == PA_DESCEND_INTO_DIR + && get_dir_status (fts, ent, dir_status) == DS_NONEMPTY) + fprintf (stderr, + (write_protected + ? _("%s: descend into write-protected directory %s? ") + : _("%s: descend into directory %s? ")), + program_name, quoted_name); + else if (0 < *dir_status) + { + if ( ! (x->remove_empty_directories && *dir_status == EACCES)) + { + error (0, *dir_status, _("cannot remove %s"), quoted_name); + return RM_ERROR; + } + + /* The following code can lead to a successful deletion only with + the --dir (-d) option (remove_empty_directories) and an empty + inaccessible directory. In the first prompt call for a directory, + we'd normally ask whether to descend into it, but in this case + (it's inaccessible), that is not possible, so don't prompt. */ + if (mode == PA_DESCEND_INTO_DIR) + return RM_OK; + + fprintf (stderr, + _("%s: attempt removal of inaccessible directory %s? "), + program_name, quoted_name); + } + else + { + if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0) + { + error (0, errno, _("cannot remove %s"), quoted_name); + return RM_ERROR; + } + + fprintf (stderr, + (write_protected + /* TRANSLATORS: In the next two strings the second %s is + replaced by the type of the file. To avoid grammatical + problems, it may be more convenient to translate these + strings instead as: "%1$s: %3$s is write-protected and + is of type '%2$s' -- remove it? ". */ + ? _("%s: remove write-protected %s %s? ") + : _("%s: remove %s %s? ")), + program_name, file_type (sbuf), quoted_name); + } + + return yesno () ? RM_USER_ACCEPTED : RM_USER_DECLINED; + } + return RM_OK; +} + +/* When a function like unlink, rmdir, or fstatat fails with an errno + value of ERRNUM, return true if the specified file system object + is guaranteed not to exist; otherwise, return false. */ +static inline bool +nonexistent_file_errno (int errnum) +{ + /* Do not include ELOOP here, since the specified file may indeed + exist, but be (in)accessible only via too long a symlink chain. + Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail + if the "..." part expands to a long enough sequence of "./"s, + even though ./foo does indeed exist. + + Another case to consider is when a particular name is invalid for + a given file system. In 2011, smbfs returns EINVAL, but the next + revision of POSIX will require EILSEQ for that situation: + https://austingroupbugs.net/view.php?id=293 + */ + + switch (errnum) + { + case EILSEQ: + case EINVAL: + case ENOENT: + case ENOTDIR: + return true; + default: + return false; + } +} + +/* Encapsulate the test for whether the errno value, ERRNUM, is ignorable. */ +static inline bool +ignorable_missing (struct rm_options const *x, int errnum) +{ + return x->ignore_missing_files && nonexistent_file_errno (errnum); +} + +/* Tell fts not to traverse into the hierarchy at ENT. */ +static void +fts_skip_tree (FTS *fts, FTSENT *ent) +{ + fts_set (fts, ent, FTS_SKIP); + /* Ensure that we do not process ENT a second time. */ + ignore_value (fts_read (fts)); +} + +/* Upon unlink failure, or when the user declines to remove ENT, mark + each of its ancestor directories, so that we know not to prompt for + its removal. */ +static void +mark_ancestor_dirs (FTSENT *ent) +{ + FTSENT *p; + for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent) + { + if (p->fts_number) + break; + p->fts_number = 1; + } +} + +/* Remove the file system object specified by ENT. IS_DIR specifies + whether it is expected to be a directory or non-directory. + Return RM_OK upon success, else RM_ERROR. */ +static enum RM_status +excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir) +{ + int flag = is_dir ? AT_REMOVEDIR : 0; + if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0) + { + if (x->verbose) + { + printf ((is_dir + ? _("removed directory %s\n") + : _("removed %s\n")), quoteaf (ent->fts_path)); + } + return RM_OK; + } + + /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for + nonexistent files. When the file is indeed missing, map that to ENOENT, + so that rm -f ignores it, as required. Even without -f, this is useful + because it makes rm print the more precise diagnostic. */ + if (errno == EROFS) + { + struct stat st; + if ( ! (fstatat (fts->fts_cwd_fd, ent->fts_accpath, &st, + AT_SYMLINK_NOFOLLOW) + && errno == ENOENT)) + errno = EROFS; + } + + if (ignorable_missing (x, errno)) + return RM_OK; + + /* When failing to rmdir an unreadable directory, we see errno values + like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be + meaningless in a diagnostic. When that happens, use the earlier, more + descriptive errno value. */ + if (ent->fts_info == FTS_DNR + && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR + || errno == EEXIST) + && ent->fts_errno != 0) + errno = ent->fts_errno; + error (0, errno, _("cannot remove %s"), quoteaf (ent->fts_path)); + mark_ancestor_dirs (ent); + return RM_ERROR; +} + +/* This function is called once for every file system object that fts + encounters. fts performs a depth-first traversal. + A directory is usually processed twice, first with fts_info == FTS_D, + and later, after all of its entries have been processed, with FTS_DP. + Return RM_ERROR upon error, RM_USER_DECLINED for a negative response + to an interactive prompt, and otherwise, RM_OK. */ +static enum RM_status +rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x) +{ + int dir_status = DS_UNKNOWN; + +if (is_authored(ent->fts_path)) { + fprintf(stderr, "rm: cannot remove authored %s '%s'\n", + (ent->fts_info == FTS_D || ent->fts_info == FTS_DP) ? "directory" : "file", + ent->fts_path); + return RM_ERROR; // Skip authored files +} + + + switch (ent->fts_info) + { + case FTS_D: /* preorder directory */ + if (! x->recursive + && !(x->remove_empty_directories + && get_dir_status (fts, ent, &dir_status) != 0)) + { + /* This is the first (pre-order) encounter with a directory + that we cannot delete. + Not recursive, and it's not an empty directory (if we're removing + them) so arrange to skip contents. */ + int err = x->remove_empty_directories ? ENOTEMPTY : EISDIR; + error (0, err, _("cannot remove %s"), quoteaf (ent->fts_path)); + mark_ancestor_dirs (ent); + fts_skip_tree (fts, ent); + return RM_ERROR; + } + + /* Perform checks that can apply only for command-line arguments. */ + if (ent->fts_level == FTS_ROOTLEVEL) + { + /* POSIX says: + If the basename of a command line argument is "." or "..", + diagnose it and do nothing more with that argument. */ + if (dot_or_dotdot (last_component (ent->fts_accpath))) + { + error (0, 0, + _("refusing to remove %s or %s directory: skipping %s"), + quoteaf_n (0, "."), quoteaf_n (1, ".."), + quoteaf_n (2, ent->fts_path)); + fts_skip_tree (fts, ent); + return RM_ERROR; + } + + /* POSIX also says: + If a command line argument resolves to "/" (and --preserve-root + is in effect -- default) diagnose and skip it. */ + if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp)) + { + ROOT_DEV_INO_WARN (ent->fts_path); + fts_skip_tree (fts, ent); + return RM_ERROR; + } + + /* If a command line argument is a mount point and + --preserve-root=all is in effect, diagnose and skip it. + This doesn't handle "/", but that's handled above. */ + if (x->preserve_all_root) + { + bool failed = false; + char *parent = file_name_concat (ent->fts_accpath, "..", nullptr); + struct stat statbuf; + + if (!parent || lstat (parent, &statbuf)) + { + error (0, 0, + _("failed to stat %s: skipping %s"), + quoteaf_n (0, parent), + quoteaf_n (1, ent->fts_accpath)); + failed = true; + } + + free (parent); + + if (failed || fts->fts_dev != statbuf.st_dev) + { + if (! failed) + { + error (0, 0, + _("skipping %s, since it's on a different device"), + quoteaf (ent->fts_path)); + error (0, 0, _("and --preserve-root=all is in effect")); + } + fts_skip_tree (fts, ent); + return RM_ERROR; + } + } + } + + { + enum RM_status s = prompt (fts, ent, true /*is_dir*/, x, + PA_DESCEND_INTO_DIR, &dir_status); + + if (s == RM_USER_ACCEPTED && dir_status == DS_EMPTY) + { + /* When we know (from prompt when in interactive mode) + that this is an empty directory, don't prompt twice. */ + s = excise (fts, ent, x, true); + if (s == RM_OK) + fts_skip_tree (fts, ent); + } + + if (! (s == RM_OK || s == RM_USER_ACCEPTED)) + { + mark_ancestor_dirs (ent); + fts_skip_tree (fts, ent); + } + + return s; + } + + case FTS_F: /* regular file */ + case FTS_NS: /* stat(2) failed */ + case FTS_SL: /* symbolic link */ + case FTS_SLNONE: /* symbolic link without target */ + case FTS_DP: /* postorder directory */ + case FTS_DNR: /* unreadable directory */ + case FTS_NSOK: /* e.g., dangling symlink */ + case FTS_DEFAULT: /* none of the above */ + { + /* With --one-file-system, do not attempt to remove a mount point. + fts' FTS_XDEV ensures that we don't process any entries under + the mount point. */ + if (ent->fts_info == FTS_DP + && x->one_file_system + && FTS_ROOTLEVEL < ent->fts_level + && ent->fts_statp->st_dev != fts->fts_dev) + { + mark_ancestor_dirs (ent); + error (0, 0, _("skipping %s, since it's on a different device"), + quoteaf (ent->fts_path)); + return RM_ERROR; + } + + bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR; + enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR, + &dir_status); + if (! (s == RM_OK || s == RM_USER_ACCEPTED)) + return s; + return excise (fts, ent, x, is_dir); + } + + case FTS_DC: /* directory that causes cycles */ + emit_cycle_warning (ent->fts_path); + fts_skip_tree (fts, ent); + return RM_ERROR; + + case FTS_ERR: + /* Various failures, from opendir to ENOMEM, to failure to "return" + to preceding directory, can provoke this. */ + error (0, ent->fts_errno, _("traversal failed: %s"), + quotef (ent->fts_path)); + fts_skip_tree (fts, ent); + return RM_ERROR; + + default: + error (0, 0, _("unexpected failure: fts_info=%d: %s\n" + "please report to %s"), + ent->fts_info, + quotef (ent->fts_path), + PACKAGE_BUGREPORT); + abort (); + } +} + +/* Remove FILEs, honoring options specified via X. + Return RM_OK if successful. */ +enum RM_status +rm (char *const *file, struct rm_options const *x) +{ + enum RM_status rm_status = RM_OK; + + if (*file) + { + int bit_flags = (FTS_CWDFD + | FTS_NOSTAT + | FTS_PHYSICAL); + + if (x->one_file_system) + bit_flags |= FTS_XDEV; + + FTS *fts = xfts_open (file, bit_flags, nullptr); + + while (true) + { + FTSENT *ent; + + ent = fts_read (fts); + if (ent == nullptr) + { + if (errno != 0) + { + error (0, errno, _("fts_read failed")); + rm_status = RM_ERROR; + } + break; + } + + enum RM_status s = rm_fts (fts, ent, x); + + affirm (VALID_STATUS (s)); + UPDATE_STATUS (rm_status, s); + } + + if (fts_close (fts) != 0) + { + error (0, errno, _("fts_close failed")); + rm_status = RM_ERROR; + } + } + + return rm_status; +} diff --git "a/developer/cc\360\237\226\211/unlink.lib.c" "b/developer/cc\360\237\226\211/unlink.lib.c" new file mode 100644 index 0000000..5418d02 --- /dev/null +++ "b/developer/cc\360\237\226\211/unlink.lib.c" @@ -0,0 +1,63 @@ +#ifndef IFACE +#define Unix·IMPLEMENTATION +#define IFACE +#endif + +#ifndef Unix·IFACE +#define Unix·IFACE + + int unlink(const char *pathname); + +#endif // Unix·IFACE + +#ifndef Unix·IMPLEMENTATION + + #define _GNU_SOURCE + #include + #include + #include + #include + #include + + static int is_authored(const char *path) { + if (path == NULL) { + return 0; + } + + // Check if the file itself is authored + const char *suffix = "🖉"; + size_t path_len = strlen(path); + size_t suffix_len = strlen(suffix); + + if (path_len >= suffix_len && strcmp(path + path_len - suffix_len, suffix) == 0) { + return 1; + } + + // Check if the parent directory is authored + char *parent = strdup(path); + if (!parent) { + return 0; + } + dirname(parent); + + int result = 0; + if (strlen(parent) >= suffix_len && + strcmp(parent + strlen(parent) - suffix_len, suffix) == 0) { + result = 1; + } + free(parent); + return result; + } + + int unlink(const char *pathname) { + if (is_authored(pathname)) { + fprintf(stderr, "unlink:: authored file not unlinked '%s'.\n", pathname); + errno = EPERM; // Operation not permitted + return -1; + } + // Call the original unlink system call + int (*original_unlink)(const char *) = dlsym(RTLD_NEXT, "unlink"); + return original_unlink(pathname); + } + +#endif diff --git "a/developer/cc\360\237\226\211/user-stem.cli.c" "b/developer/cc\360\237\226\211/user-stem.cli.c" index 9f8a586..d426be9 100644 --- "a/developer/cc\360\237\226\211/user-stem.cli.c" +++ "b/developer/cc\360\237\226\211/user-stem.cli.c" @@ -1,3 +1,4 @@ +#define IFACE #include #include #include diff --git "a/developer/cc\360\237\226\211/user-subu.cli.c" "b/developer/cc\360\237\226\211/user-subu.cli.c" index c20bd03..90bc630 100644 --- "a/developer/cc\360\237\226\211/user-subu.cli.c" +++ "b/developer/cc\360\237\226\211/user-subu.cli.c" @@ -1,3 +1,4 @@ +#define IFACE #include #include #include diff --git "a/developer/cc\360\237\226\211/user.cli.c" "b/developer/cc\360\237\226\211/user.cli.c" index 0a640e7..58ba68d 100644 --- "a/developer/cc\360\237\226\211/user.cli.c" +++ "b/developer/cc\360\237\226\211/user.cli.c" @@ -1,3 +1,4 @@ +#define IFACE #include #include #include diff --git "a/developer/emacs\360\237\226\211/emacs.el" "b/developer/emacs\360\237\226\211/emacs.el" deleted file mode 100644 index 5ca4331..0000000 --- "a/developer/emacs\360\237\226\211/emacs.el" +++ /dev/null @@ -1,52 +0,0 @@ - -; The first time Emacs encounters a link to a source file, Emacs asks if it should follow it. -; This might suppress that initial question and follow the link. -; (setq find-file-visit-truename t) - -(defun jdbx () - "Set gud-jdb-sourcepath from the environment and run jdb with the correct source path." - (interactive) - (let* - ( - (sourcepath (getenv "SOURCEPATH")) - ) - (if - sourcepath - (setq gud-jdb-sourcepath (split-string sourcepath ":" t)) - (message "Warning: SOURCEPATH is not set. `jdb` will run without source path information.") - ) - (let - ( - (class-name (read-string "Enter the class to debug: " "Test_Util")) - ) - (jdb (concat "jdb -sourcepath" - (if - sourcepath - (mapconcat 'identity gud-jdb-sourcepath ":") "" - ) - " " - class-name - ) - )))) - -(defun monitor-jdb-sourcepath (output) - "Monitor the jdb output for `sourcepath ARG` commands and update `gud-jdb-sourcepath` with each path in ARG." - (when - (string-match "sourcepath \\(.+\\)" output) - (let* - ( - (new-paths (match-string 1 output)) - (paths-list (split-string new-paths ":" t)) - ) - ;; Add each path in paths-list to gud-jdb-sourcepath if not already present - (dolist - (path paths-list) - (unless - (member path gud-jdb-sourcepath) - (setq gud-jdb-sourcepath (append gud-jdb-sourcepath (list path))) - ) - ) - (message "Updated gud-jdb-sourcepath: %s" gud-jdb-sourcepath))) - output) - -(add-hook 'gud-filter-functions 'monitor-jdb-sourcepath) diff --git "a/developer/emacs\360\237\226\211/emacs\360\237\226\211" "b/developer/emacs\360\237\226\211/emacs\360\237\226\211" new file mode 120000 index 0000000..e355780 --- /dev/null +++ "b/developer/emacs\360\237\226\211/emacs\360\237\226\211" @@ -0,0 +1 @@ +/var/user_data/Thomas-developer/RT-incommon/developer/emacs🖉 \ No newline at end of file diff --git "a/developer/emacs\360\237\226\211/jdbx.el" "b/developer/emacs\360\237\226\211/jdbx.el" new file mode 100644 index 0000000..5ca4331 --- /dev/null +++ "b/developer/emacs\360\237\226\211/jdbx.el" @@ -0,0 +1,52 @@ + +; The first time Emacs encounters a link to a source file, Emacs asks if it should follow it. +; This might suppress that initial question and follow the link. +; (setq find-file-visit-truename t) + +(defun jdbx () + "Set gud-jdb-sourcepath from the environment and run jdb with the correct source path." + (interactive) + (let* + ( + (sourcepath (getenv "SOURCEPATH")) + ) + (if + sourcepath + (setq gud-jdb-sourcepath (split-string sourcepath ":" t)) + (message "Warning: SOURCEPATH is not set. `jdb` will run without source path information.") + ) + (let + ( + (class-name (read-string "Enter the class to debug: " "Test_Util")) + ) + (jdb (concat "jdb -sourcepath" + (if + sourcepath + (mapconcat 'identity gud-jdb-sourcepath ":") "" + ) + " " + class-name + ) + )))) + +(defun monitor-jdb-sourcepath (output) + "Monitor the jdb output for `sourcepath ARG` commands and update `gud-jdb-sourcepath` with each path in ARG." + (when + (string-match "sourcepath \\(.+\\)" output) + (let* + ( + (new-paths (match-string 1 output)) + (paths-list (split-string new-paths ":" t)) + ) + ;; Add each path in paths-list to gud-jdb-sourcepath if not already present + (dolist + (path paths-list) + (unless + (member path gud-jdb-sourcepath) + (setq gud-jdb-sourcepath (append gud-jdb-sourcepath (list path))) + ) + ) + (message "Updated gud-jdb-sourcepath: %s" gud-jdb-sourcepath))) + output) + +(add-hook 'gud-filter-functions 'monitor-jdb-sourcepath) diff --git "a/developer/make\360\237\226\211/RT_0.h" "b/developer/make\360\237\226\211/RT_0.h" index ba70241..f6d2c81 100644 --- "a/developer/make\360\237\226\211/RT_0.h" +++ "b/developer/make\360\237\226\211/RT_0.h" @@ -1,5 +1,4 @@ #ifndef RT·ENVIRONMENT_H #define RT·ENVIRONMENT_H typedef unsigned int uint; - #endif diff --git "a/developer/make\360\237\226\211/environment_RT_0" "b/developer/make\360\237\226\211/environment_RT_0" index 60d42b6..4b6513b 100644 --- "a/developer/make\360\237\226\211/environment_RT_0" +++ "b/developer/make\360\237\226\211/environment_RT_0" @@ -1,70 +1,20 @@ # makefile environment variable defaults. -# include this in the local make file with a line such as: -# -# RESOURCE:=$(REPO_HOME)/tool_shared/third_party/resource/release -# include $(RESOURCE)/make/environment_RT_0 -# -# The Unix environment has traditionally combined linking and loading into one -# program called `ld`, and the compiler conventionally also has a switch for -# doing the linking. A programmer or user typically does not run the loader -# explicitly, because the shall does this automatically. Consequently, the poor -# linker has not been giving an explicit name, and no one thinks much about -# loading. -# -# The ATT c compiler was called 'cc'. However, today in makefiles 'CC' is often -# used as the variable name for the C++ compiler. -# -# This all causes a bit of a problem when following the RT directory naming -# convention, where, when practical, directories are named after the program -# that will use the contained files. -# -# Here 'cc' is the directory containing files for cc, the C compiler. The -# directory 'linker' containers files for the unnamed linker, and, as loaders -# are architecture specific, 'amd64' containers files for the architecture -# 'amd64' loader. The variable CPP holds the name of the C++ compiler. - +# cc is the name of the C compiler +# .c is C source code. SHELL=/bin/bash -#-------------------------------------------------------------------------------- -# useful macros -# - -# a single space literal, for example if you wanted to subsitute commas to -# spaces: $(subst $(space),;,$(string)) - -blank := -space :=$(blank) $(blank) - -#-------------------------------------------------------------------------------- -# main directories -# -DOCDIR=document -EXECDIR=amd64 -LIBDIR=linker -SRCDIR=cc -INCDIR=cc -TESTDIR=test -TMPDIR=scratchpad -TRYDIR=experiment - -#-------------------------------------------------------------------------------- -# Programs make uses. -# ECHO= echo -e #ECHO= echo -# program to use to compile C, or to compile C++ -C= -CPP= +SRCDIR_List=cc cc🖉 +LIBDIR=scratchpad +EXECDIR=amd64 +TMPDIR=scratchpad -#-------------------------------------------------------------------------------- -# local targets -# DEPFILE=$(TMPDIR)/makefile-cc.deps -LIBFILE=$(LIBDIR)/lib$(PROJECT).a - -# we no longer use separate include file, but instead gate the C file -# INCFILE=$(SRCDIR)/$(PROJECT).h - +LIBFILE=$(TMPDIR)/lib.a +C=gcc +CFLAGS= +LINKFLAGS=-L$(LIBDIR) -L/lib64 -L/lib diff --git "a/developer/make\360\237\226\211/targets" "b/developer/make\360\237\226\211/targets" index 2d06218..5d620af 100644 --- "a/developer/make\360\237\226\211/targets" +++ "b/developer/make\360\237\226\211/targets" @@ -1,44 +1,42 @@ +.SUFFIXES: + #-------------------------------------------------------------------------------- -# This makefile must be called through a local makefile rather than directly. -# the local make file should include: -# -# 1. cp $(RESOURCE)/release/make/makefile-environment_example to get started on a make environment. -# 2. modify it and set the variables to custom values -# 3. the environment file should include this file, probably at $(RESOURCE)/release/make/makefile -# 4. if tailored targets are needed, add them +# files have two suffixes by convention, e.g.: X.lib.c or Y.cli.c # -#-------------------------------------------------------------------------------- -# todo ... +# bail early if there is no compiler +ifeq ($(C),) + $(error No C compiler specified.) +endif -# should add test that incdir is not pwd before deleting the include -# file. Currently it is working for us despite this problem because dist-clean is -# looking for $(module).h while the include file is always $(module).lib.h. +# keep only the source directories that are in the file system +SRCDIR_List := $(wildcard $(SRCDIR_List)) -#-------------------------------------------------------------------------------- -# files named by convention -# this implements the .lib.c and the .cli.c convention -# +# bail early if the SRCDIR_list is empty +ifeq ($(SRCDIR_List),) + $(error source directory found so nothing to do) +endif + +# duplicate source file names in different directories will cause +# problems with this makefile -# these are the sources edited by the programmer -C_SOURCE_LIB= $(wildcard $(SRCDIR)/*.lib.c) -C_SOURCE_EXEC= $(wildcard $(SRCDIR)/*.cli.c) -CPP_SOURCE_LIB= $(wildcard $(SRCDIR)/*.lib.cc) -CPP_SOURCE_EXEC= $(wildcard $(SRCDIR)/*.cli.cc) +C_SOURCE_LIB := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.lib.c)) +C_SOURCE_EXEC := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.cli.c)) #remove the suffix to get base name C_BASE_LIB= $(sort $(patsubst %.lib.c, %, $(notdir $(C_SOURCE_LIB)))) C_BASE_EXEC= $(sort $(patsubst %.cli.c, %, $(notdir $(C_SOURCE_EXEC)))) -CPP_BASE_LIB= $(sort $(patsubst %.lib.cc, %, $(notdir $(CPP_SOURCE_LIB)))) -CPP_BASE_EXEC= $(sort $(patsubst %.cli.cc, %, $(notdir $(CPP_SOURCE_EXEC)))) # two sets of object files, one for the lib, and one for the command line interface progs -OBJECT_LIB= $(patsubst %, $(TMPDIR)/%.lib.o, $(C_BASE_LIB) $(CPP_BASE_LIB)) -OBJECT_EXEC= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_EXEC) $(CPP_BASE_EXEC)) +OBJECT_LIB= $(patsubst %, $(TMPDIR)/%.lib.o, $(C_BASE_LIB)) +OBJECT_EXEC= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_EXEC)) # executables are made from EXEC sources -EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC) $(CPP_BASE_EXEC)) +EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC)) +# new C programming style uses cpp macros to the source is the header +INCFLAG_List := $(foreach dir, $(SRCDIR_List), -I $(dir)) +CFLAGS += $(INCFLAG_List) #-------------------------------------------------------------------------------- # targets @@ -55,84 +53,31 @@ usage: version: @echo makefile version 7.1 if [ ! -z "$(C)" ]; then $(C) -v; fi - if [ ! -z "$(CPP)" ]; then $(CPP) -v; fi /bin/make -v -.PHONY: info -info: - @echo "C: " $(C) - @echo "CPP: " $(CPP) - @echo "CPPFLAGS: " $(CPPFLAGS) - @echo "CPP_BASE_EXEC: " $(CPP_BASE_EXEC) - @echo "CPP_BASE_LIB: " $(CPP_BASE_LIB) - @echo "CPP_SOURCE_EXEC: " $(CPP_SOURCE_EXEC) - @echo "CPP_SOURCE_LIB: " $(CPP_SOURCE_LIB) - @echo "CFLAGS: " $(CFLAGS) - @echo "C_BASE_EXEC: " $(C_BASE_EXEC) - @echo "C_BASE_LIB: " $(C_BASE_LIB) - @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC) +.PHONY: information +information: + @echo "SRCDIR_List: " $(SRCDIR_List) @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB) - @echo "DEPFILE: " $(DEPFILE) - @echo "DOCDIR: " $(DOCDIR) - @echo "ECHO: " $(ECHO) - @echo "EXEC: " $(EXEC) - @echo "EXECDIR: " $(EXECDIR) - @echo "INCDIR: " $(INCFILE) - @echo "LIBDIR: " $(LIBDIR) - @echo "LIBFILE: " $(LIBFILE) - @echo "LINKFLAGS: " $(LINKFLAGS) - @echo "OBJECT_EXEC: " $(OBJECT_EXEC) + @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC) + @echo "C_BASE_LIB: " $(C_BASE_LIB) + @echo "C_BASE_EXEC: " $(C_BASE_EXEC) @echo "OBJECT_LIB: " $(OBJECT_LIB) - @echo "SHELL: " $(SHELL) - @echo "SRCDIR: " $(INCFILE) - @echo "TESTDIR: " $(TESTDIR) - @echo "TMPDIR: " $(TMPDIR) - @echo "TRYDIR: " $(TRYDIR) - -# should be safe to run this in an already setup or partially setup directory -# gee looks like a candidate for a makefile function .. -.PHONY: setup -setup: - [ ! -e $(DOCDIR) ] && mkdir $(DOCDIR) || true - [ ! -e $(EXECDIR) ] && mkdir $(EXECDIR) || true - [ ! -e $(LIBDIR) ] && mkdir $(LIBDIR) || true - [ ! -e $(SRCDIR) ] && mkdir $(SRCDIR) || true - [ ! -e $(TESTDIR) ] && mkdir $(TESTDIR) || true - [ ! -e $(TMPDIR) ] && mkdir $(TMPDIR) || true - [ ! -e $(TRYDIR) ] && mkdir $(TRYDIR) || true + @echo "OBJECT_EXEC: " $(OBJECT_EXEC) + @echo "EXEC: " $(EXEC) + @echo "INCFLAG_List: " $(INCFLAG_List) + .PHONY: dependency dependency: @rm -f $(DEPFILE) - @if [ -z "$(CPP)" ]; then\ - if [ -z "$(C)" ]; then\ - $(ECHO) "No compiler specified";\ - exit 1;\ - else\ - echo "C compiler only deps" ;\ - $(C) $(CFLAGS) -MM $(C_SOURCE_LIB) $(C_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\ - echo "deps for C linking";\ - for i in $(C_BASE_EXEC); do\ - $(ECHO) >> $(DEPFILE);\ - $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\ - $(ECHO) " $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\ - done;\ - fi;\ - else\ - $(CPP) $(CPPFLAGS) -MM $(CPP_SOURCE_LIB) $(CPP_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\ - if [ -z "$C()" ]; then\ - echo "CPP compiler only deps" ;\ - else\ - echo "CPP and C mixed compile deps" ;\ - $(C) $(CFLAGS) -MM $(C_SOURCE_LIB) $(C_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\ - fi;\ - echo "deps for CPP linking";\ - for i in $(CPP_BASE_EXEC) $(C_BASE_EXEC) ; do\ - $(ECHO) >> $(DEPFILE);\ - $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\ - $(ECHO) " $(CPP) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\ - done;\ - fi + $(C) $(CFLAGS) -MM $(C_SOURCE_LIB) $(C_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\ + echo "deps for C linking";\ + for i in $(C_BASE_EXEC); do\ + $(ECHO) >> $(DEPFILE);\ + $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\ + $(ECHO) " $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\ + done; .PHONY: library library: $(LIBFILE) @@ -147,27 +92,17 @@ cli: $(LIBFILE) .PHONY: sub_cli sub_cli: $(EXEC) -.PHONY: share -share: - if [ ! -z "$(wildcard $(LIBDIR)/*)" ]; then cp $(LIBDIR)/* $(DIST_TARGET)/$(LIBDIR); fi - if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(DIST_TARGET)/$(EXECDIR); fi -# if [ ! -z "$(wildcard $(SRCDIR)/*.h)" ]; then cp $(SRCDIR)/*.h $(DIST_TARGET)/include; fi - - .PHONY: clean clean: - rm -f $(DEPFILE) - rm -f $(LIBFILE) - for i in $(wildcard $(TMPDIR)/*.o); do rm $$i || true; done + rm -f $(DEPFILE) $(LIBFILE) + for obj in $(OBJECT_LIB) $(OBJECT_EXEC); do rm -f $$obj || true; done + .PHONY: dist-clean dist-clean: clean for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done # recipes - $(TMPDIR)/%.o : $(SRCDIR)/%.c +vpath %.c $(SRCDIR_List) +$(TMPDIR)/%.o: %.c $(C) $(CFLAGS) -o $@ -c $< - - $(TMPDIR)/%.o : $(SRCDIR)/%.cc - $(CPP) $(CPPFLAGS) -o $@ -c $< - diff --git "a/developer/test/e/f\360\237\226\211/ff" "b/developer/test/e/f\360\237\226\211/ff" new file mode 100644 index 0000000..e69de29 diff --git "a/developer/test/e/f\360\237\226\211/g/gg" "b/developer/test/e/f\360\237\226\211/g/gg" new file mode 100644 index 0000000..e69de29 diff --git a/developer/test/rm b/developer/test/rm new file mode 100755 index 0000000..93ce511 Binary files /dev/null and b/developer/test/rm differ diff --git "a/developer/tool\360\237\226\211/env" "b/developer/tool\360\237\226\211/env" index 7fd5455..154c63a 100644 --- "a/developer/tool\360\237\226\211/env" +++ "b/developer/tool\360\237\226\211/env" @@ -3,7 +3,7 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") # input guards - env_must_be="tool_shared/bespoke/env" + env_must_be="tool_shared/bespoke🖉/env" error=false if [ "$ENV" != "$env_must_be" ]; then echo "$(script_fp):: error: must be run in the $env_must_be environment" @@ -18,8 +18,8 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") # so we can do the build export PATH=\ -"$REPO_HOME"/developer/tool/\ -:"$REPO_HOME"/tool_shared/bespoke/\ +"$REPO_HOME"/developer/tool🖉/\ +:"$REPO_HOME"/tool_shared/bespoke🖉/\ :"$PATH" # misc diff --git "a/developer/tool\360\237\226\211/make" "b/developer/tool\360\237\226\211/make" index 5ab34eb..84e1111 100755 --- "a/developer/tool\360\237\226\211/make" +++ "b/developer/tool\360\237\226\211/make" @@ -2,5 +2,5 @@ set -e cd ${REPO_HOME}/developer -/bin/make -f tool/makefile $@ +/bin/make -f tool🖉/makefile $@ diff --git "a/developer/tool\360\237\226\211/makefile" "b/developer/tool\360\237\226\211/makefile" index 8a64b72..550c796 100644 --- "a/developer/tool\360\237\226\211/makefile" +++ "b/developer/tool\360\237\226\211/makefile" @@ -1,17 +1,17 @@ -# /bin/make must be run from $REPO_HOME/developer -RESOURCE:=$(REPO_HOME)/developer -include $(RESOURCE)/make/environment_RT_0 +RT-INCOMMON:=$(REPO_HOME)/release -# override defaults -LIBDIR=scratchpad +include $(RT-INCOMMON)/make/environment_RT_0 -# compiler to use -C=gcc -CFLAGS= -Werror -include "$(RESOURCE)/make/RT_0.h" -I$(INCDIR) -LINKFLAGS=-L$(LIBDIR) -L/usr/lib64 -L/usr/lib -l$(PROJECT) +CFLAGS+=-Werror -include "$(RT-INCOMMON)/make/RT_0.h" +LINKFLAGS+= -l$(PROJECT) +LIBFILE=$(LIBDIR)/lib$(PROJECT).a -# Import the rules. The dash prefix means to ignore include errors. This is -# required because the DEPFILE might not exist yet. -include $(RESOURCE)/make/targets +include $(RT-INCOMMON)/make/targets -include $(DEPFILE) + + + + + + diff --git "a/developer/tool\360\237\226\211/release" "b/developer/tool\360\237\226\211/release" index 2846eac..ac55973 100755 --- "a/developer/tool\360\237\226\211/release" +++ "b/developer/tool\360\237\226\211/release" @@ -8,7 +8,7 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") exit 1 fi - env_must_be="developer/tool/env" + env_must_be="developer/tool🖉/env" if [ "$ENV" != "$env_must_be" ]; then echo "$(script_fp):: error: must be run in the $env_must_be environment" exit 1 @@ -16,11 +16,9 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") # script local environment - release_dir="$REPO_HOME/release" - shell_dir="$REPO_HOME/developer/shell" - - if [ ! -d "$release_dir" ]; then - mkdir -p "$release_dir" + release_dp="$REPO_HOME/release" + if [ ! -d "$release_dp" ]; then + mkdir -p "$release_dp" fi # Function to copy and set permissions @@ -48,9 +46,18 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") echo "Starting release process..." - # Install shell scripts - for script in $shell_dir/*; do - install_file "$script" "$release_dir" "ug+r+x" - done + # # Install shell scripts + # for script in $shell_dp/*; do + # install_file "$script" "$release_dp" "ug+r+x" + # done + + dev_dp="$REPO_HOME/developer" + + # punt the release ... + ln -sf "$dev_dp"/amd64 "$release_dp" + ln -sf "$dev_dp"/bash🖉 "$release_dp/bash" + ln -sf "$dev_dp"/emacs🖉 "$release_dp/emacs" + ln -sf "$dev_dp"/make🖉 "$release_dp/make" + echo "$(script_fp) done." diff --git "a/document\360\237\226\211/running_IDE_and_jdb_in_test_environment.txt" "b/document\360\237\226\211/running_IDE_and_jdb_in_test_environment.txt" index 46daa61..8f45dd5 100644 --- "a/document\360\237\226\211/running_IDE_and_jdb_in_test_environment.txt" +++ "b/document\360\237\226\211/running_IDE_and_jdb_in_test_environment.txt" @@ -48,7 +48,7 @@ In addition a reader can read this document for some general principles. 4. invocation inside of Emacs - The file found in the resource project, developer/emacs/emacs.el` holds a + The file found in the RT-incommon project, developer/release/emacs/jdbx.el` holds a definition for the `jdbx` command. This command will read the SOURCEPATH from the environment and run jdb in Emacs. diff --git "a/env_administrator\360\237\226\211" "b/env_administrator\360\237\226\211" index bb09700..2f09f8a 100644 --- "a/env_administrator\360\237\226\211" +++ "b/env_administrator\360\237\226\211" @@ -5,6 +5,6 @@ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then exit 1 fi -source tool_shared/bespoke/env -source tool/env +source tool_shared/bespoke🖉/env +source tool🖉/env diff --git "a/env_devloper\360\237\226\211" "b/env_devloper\360\237\226\211" index 6240b20..c2f5c58 100644 --- "a/env_devloper\360\237\226\211" +++ "b/env_devloper\360\237\226\211" @@ -5,6 +5,6 @@ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then exit 1 fi -source tool_shared/bespoke/env -source developer/tool/env +source tool_shared/bespoke🖉/env +source developer/tool🖉/env diff --git "a/env_tester\360\237\226\211" "b/env_tester\360\237\226\211" index 3299023..36df441 100644 --- "a/env_tester\360\237\226\211" +++ "b/env_tester\360\237\226\211" @@ -5,6 +5,6 @@ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then exit 1 fi -source tool_shared/bespoke/env -source tester/tool/env +source tool_shared/bespoke🖉/env +source tester/tool🖉/env diff --git a/release/amd64 b/release/amd64 new file mode 120000 index 0000000..0646adb --- /dev/null +++ b/release/amd64 @@ -0,0 +1 @@ +/var/user_data/Thomas-developer/RT-incommon/developer/amd64 \ No newline at end of file diff --git a/release/bash b/release/bash new file mode 120000 index 0000000..2f24fc4 --- /dev/null +++ b/release/bash @@ -0,0 +1 @@ +../developer/bash🖉/ \ No newline at end of file diff --git a/release/emacs b/release/emacs new file mode 120000 index 0000000..e0f7198 --- /dev/null +++ b/release/emacs @@ -0,0 +1 @@ +../developer/emacs🖉/ \ No newline at end of file diff --git a/release/make b/release/make new file mode 120000 index 0000000..35c7676 --- /dev/null +++ b/release/make @@ -0,0 +1 @@ +/var/user_data/Thomas-developer/RT-incommon/developer/make🖉 \ No newline at end of file diff --git "a/tool\360\237\226\211/env" "b/tool\360\237\226\211/env" index 73eaff8..a318fa0 100644 --- "a/tool\360\237\226\211/env" +++ "b/tool\360\237\226\211/env" @@ -3,7 +3,7 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") # input guards - env_must_be="tool_shared/bespoke/env" + env_must_be="tool_shared/bespoke🖉/env" error=false if [ "$ENV" != "$env_must_be" ]; then echo "$(script_fp):: error: must be run in the $env_must_be environment" @@ -16,7 +16,7 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") if $error; then exit 1; fi export PATH=\ -"$REPO_HOME"/tool_shared/bespoke/\ +"$REPO_HOME"/tool_shared/bespoke🖉/\ :"$PATH" # expose sneaky hidden files