btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / bin / trash.cpp
blob610eb72955d160d85301b2b76fef5ed0d639496d
1 /*
2 * [un]trash command for Haiku
3 * Copyright (c) 2004, Francois Revol - revol@free.fr
4 * provided under the MIT licence
5 */
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <app/Message.h>
11 #include <app/Messenger.h>
12 #include <kernel/fs_attr.h>
13 #include <kernel/fs_info.h>
14 #include <storage/Directory.h>
15 #include <storage/Entry.h>
16 #include <storage/FindDirectory.h>
17 #include <storage/Node.h>
18 #include <storage/Path.h>
19 #include <support/TypeConstants.h>
21 static const char *kAttrOriginalPath = "_trk/original_path";
22 static const char *kTrackerSig = "application/x-vnd.Be-TRAK";
24 int usage(int ret)
26 printf("\nSend files to trash, or restore them.\nUsage:\n");
27 printf("trash [--restore|--empty|--list] file ...\n");
28 printf("\t--restore\trestore files (act as untrash)\n");
29 printf("\t--empty\t\tempty the Trash\n");
30 printf("\t--list\t\tlist what's already in the Trash\n");
31 printf("untrash [--all] [file ...]\n");
32 //printf("restore [--all] [file ...]\n");
33 return ret;
36 status_t untrash(const char *f)
38 status_t err;
39 char original_path[B_PATH_NAME_LENGTH];
40 BPath path(f);
41 BNode node(f);
42 err = node.InitCheck();
43 if (err)
44 return err;
45 err = node.ReadAttr(kAttrOriginalPath, B_STRING_TYPE, 0LL, original_path, B_PATH_NAME_LENGTH);
46 if (err < 0)
47 return err;
48 err = rename(path.Path(), original_path);
49 if (err < 0)
50 return err;
51 node.RemoveAttr(kAttrOriginalPath);
52 return 0;
55 status_t trash(const char *f)
57 status_t err;
58 attr_info ai;
59 dev_t dev = -1;
60 int nr;
61 const char *original_path;
62 char trash_dir[B_PATH_NAME_LENGTH];
63 char trashed_file[B_PATH_NAME_LENGTH];
64 dev = dev_for_path(f);
65 err = find_directory(B_TRASH_DIRECTORY, dev, false, trash_dir, B_PATH_NAME_LENGTH);
66 if (err < 0)
67 return err;
68 BNode node(f);
69 err = node.InitCheck();
70 if (err < 0)
71 return err;
72 err = node.GetAttrInfo(kAttrOriginalPath, &ai);
73 if (err == B_OK)
74 return EALREADY;
75 if (!strncmp(f, trash_dir, strlen(trash_dir)))
76 return EALREADY;
77 entry_ref er;
78 err = get_ref_for_path(f, &er);
79 BPath orgPath(&er);
80 err = orgPath.InitCheck();
81 if (err < 0)
82 return err;
83 original_path = orgPath.Path();
84 BDirectory trashDir(trash_dir);
85 err = trashDir.InitCheck();
86 if (err < 0)
87 return err;
88 for (nr = 0; ; nr++) {
89 if (nr > INT_MAX - 1)
90 return B_ERROR;
91 if (nr)
92 snprintf(trashed_file, B_PATH_NAME_LENGTH-1, "%s/%s %d", trash_dir, er.name, nr);
93 else
94 snprintf(trashed_file, B_PATH_NAME_LENGTH-1, "%s/%s", trash_dir, er.name);
95 if (!trashDir.Contains(trashed_file))
96 break;
98 err = rename(original_path, trashed_file);
99 if (err < 0)
100 return err;
102 err = node.WriteAttr(kAttrOriginalPath, B_STRING_TYPE, 0LL, original_path, strlen(original_path)+1);
103 if (err < 0)
104 return err;
105 return 0;
108 status_t show_trashed_file(const char *f)
110 status_t err;
111 char original_path[B_PATH_NAME_LENGTH];
112 BPath path(f);
113 BNode node(f);
114 err = node.ReadAttr(kAttrOriginalPath, B_STRING_TYPE, 0LL, original_path, B_PATH_NAME_LENGTH);
115 if (err < 0)
116 return 0;
117 //printf("%s\n\t[from] %s\n", f, original_path);
118 printf("%s\n\tas: %s\n", original_path, f);
119 return 0;
122 status_t foreach_in_trash(status_t (*iterator)(const char *))
124 status_t err;
125 dev_t dev;
126 char trash_dir[B_PATH_NAME_LENGTH];
127 for (dev = 0; ; ) {
128 if (next_dev(&dev) < B_OK)
129 break;
130 //for each in trash_dir
131 err = find_directory(B_TRASH_DIRECTORY, dev, false, trash_dir, B_PATH_NAME_LENGTH);
132 if (err)
133 continue; /* skip trashless volumes */
134 BDirectory trashDir(trash_dir);
135 err = trashDir.InitCheck();
136 if (err < 0)
137 return err;
138 entry_ref er;
139 while (trashDir.GetNextRef(&er) == B_OK) {
140 BPath path(&er);
141 if ((err = path.InitCheck()))
142 return err;
143 err = iterator(path.Path());
144 if (err)
145 return err;
148 return B_OK;
152 int main(int argc, char **argv)
154 int dountrash = 0;
155 int i = 1;
156 int err = 0;
157 if (strstr(argv[0], "untrash") || strstr(argv[0], "restore"))
158 dountrash = 1;
159 if (argc < 2)
160 return usage(1);
161 if (!strcmp(argv[1], "--help"))
162 return usage(0);
163 if (!strcmp(argv[1], "--restore")) {
164 dountrash = 1;
165 i++;
167 if (!dountrash && !strcmp(argv[1], "--empty")) {
168 /* XXX: clean that */
169 BMessage msg(B_DELETE_PROPERTY);
170 msg.AddSpecifier("Trash");
171 BMessenger msgr(kTrackerSig);
172 err = msgr.SendMessage(&msg);
173 if (err < 0) {
174 fprintf(stderr, "Emptying Trash: %s\n", strerror(err));
175 return 1;
177 return 0;
179 if (dountrash && !strcmp(argv[i], "--all")) {
180 /* restore all trashed files */
181 err = foreach_in_trash(untrash);
182 if (err) {
183 fprintf(stderr, "untrash: %s\n", strerror(err));
184 return 1;
186 return 0;
188 if (!strcmp(argv[i], "--list")) {
189 err = foreach_in_trash(show_trashed_file);
190 return 0;
192 /* restore files... */
193 if (dountrash) {
194 for (; i < argc; i++) {
195 err = untrash(argv[i]);
196 if (err) {
197 fprintf(stderr, "%s: %s\n", argv[i], strerror(err));
198 return 1;
201 return err;
203 /* or trash them */
204 for (i = 1; i < argc; i++) {
205 err = trash(argv[i]);
206 if (err) {
207 fprintf(stderr, "%s: %s\n", argv[i], strerror(err));
208 return 1;
212 return err;