Subversion Repositories HelenOS

Rev

Rev 2787 | Rev 3011 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2787 Rev 2925
Line 140... Line 140...
140
    unsigned next = IPC_GET_ARG1(*request);
140
    unsigned next = IPC_GET_ARG1(*request);
141
    unsigned last = IPC_GET_ARG2(*request);
141
    unsigned last = IPC_GET_ARG2(*request);
142
    dev_handle_t dev_handle = IPC_GET_ARG3(*request);
142
    dev_handle_t dev_handle = IPC_GET_ARG3(*request);
143
    int lflag = IPC_GET_ARG4(*request);
143
    int lflag = IPC_GET_ARG4(*request);
144
    fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */
144
    fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */
-
 
145
    char component[NAME_MAX + 1];
-
 
146
    int len;
145
 
147
 
146
    if (last < next)
148
    if (last < next)
147
        last += PLB_SIZE;
149
        last += PLB_SIZE;
148
 
150
 
149
    void *par = NULL;
151
    void *par = NULL;
150
    void *cur = ops->root_get();
152
    void *cur = ops->root_get(dev_handle);
151
    void *tmp = ops->child_get(cur);
153
    void *tmp = NULL;
152
 
154
 
153
    if (ops->plb_get_char(next) == '/')
155
    if (ops->plb_get_char(next) == '/')
154
        next++;     /* eat slash */
156
        next++;     /* eat slash */
155
   
157
   
156
    char component[NAME_MAX + 1];
-
 
157
    int len = 0;
-
 
158
    while (tmp && next <= last) {
158
    while (ops->has_children(cur) && next <= last) {
159
 
-
 
160
        /* collect the component */
159
        /* collect the component */
-
 
160
        len = 0;
161
        if (ops->plb_get_char(next) != '/') {
161
        while ((ops->plb_get_char(next) != '/') && (next <= last)) {
162
            if (len + 1 == NAME_MAX) {
162
            if (len + 1 == NAME_MAX) {
163
                /* comopnent length overflow */
163
                /* comopnent length overflow */
164
                ipc_answer_0(rid, ENAMETOOLONG);
164
                ipc_answer_0(rid, ENAMETOOLONG);
165
                return;
165
                goto out;
166
            }
166
            }
167
            component[len++] = ops->plb_get_char(next);
167
            component[len++] = ops->plb_get_char(next);
168
            next++; /* process next character */
168
            next++; /* process next character */
169
            if (next <= last)
-
 
170
                continue;
-
 
171
        }
169
        }
172
 
170
 
173
        assert(len);
171
        assert(len);
174
        component[len] = '\0';
172
        component[len] = '\0';
175
        next++;     /* eat slash */
173
        next++;     /* eat slash */
176
        len = 0;
-
 
177
 
174
 
178
        /* match the component */
175
        /* match the component */
179
        while (tmp && !ops->match(cur, tmp, component))
176
        tmp = ops->match(cur, component);
180
            tmp = ops->sibling_get(tmp);
-
 
181
 
177
 
182
        /* handle miss: match amongst siblings */
178
        /* handle miss: match amongst siblings */
183
        if (!tmp) {
179
        if (!tmp) {
184
            if (next <= last) {
180
            if (next <= last) {
185
                /* there are unprocessed components */
181
                /* there are unprocessed components */
186
                ipc_answer_0(rid, ENOENT);
182
                ipc_answer_0(rid, ENOENT);
187
                return;
183
                goto out;
188
            }
184
            }
189
            /* miss in the last component */
185
            /* miss in the last component */
190
            if (lflag & (L_CREATE | L_LINK)) {
186
            if (lflag & (L_CREATE | L_LINK)) {
191
                /* request to create a new link */
187
                /* request to create a new link */
192
                if (!ops->is_directory(cur)) {
188
                if (!ops->is_directory(cur)) {
193
                    ipc_answer_0(rid, ENOTDIR);
189
                    ipc_answer_0(rid, ENOTDIR);
194
                    return;
190
                    goto out;
195
                }
191
                }
196
                void *nodep;
192
                void *nodep;
197
                if (lflag & L_CREATE)
193
                if (lflag & L_CREATE)
198
                    nodep = ops->create(lflag);
194
                    nodep = ops->create(lflag);
199
                else
195
                else
200
                    nodep = ops->node_get(fs_handle,
196
                    nodep = ops->node_get(dev_handle,
201
                        dev_handle, index);
197
                        index);
202
                if (nodep) {
198
                if (nodep) {
203
                    if (!ops->link(cur, nodep, component)) {
199
                    if (!ops->link(cur, nodep, component)) {
204
                        if (lflag & L_CREATE)
200
                        if (lflag & L_CREATE)
205
                            ops->destroy(nodep);
201
                            (void)ops->destroy(nodep);
206
                        ipc_answer_0(rid, ENOSPC);
202
                        ipc_answer_0(rid, ENOSPC);
207
                    } else {
203
                    } else {
208
                        ipc_answer_5(rid, EOK,
204
                        ipc_answer_5(rid, EOK,
209
                            fs_handle, dev_handle,
205
                            fs_handle, dev_handle,
210
                            ops->index_get(nodep),
206
                            ops->index_get(nodep),
211
                            ops->size_get(nodep),
207
                            ops->size_get(nodep),
212
                            ops->lnkcnt_get(nodep));
208
                            ops->lnkcnt_get(nodep));
-
 
209
                        ops->node_put(nodep);
213
                    }
210
                    }
214
                } else {
211
                } else {
215
                    ipc_answer_0(rid, ENOSPC);
212
                    ipc_answer_0(rid, ENOSPC);
216
                }
213
                }
217
                return;
214
                goto out;
218
            } else if (lflag & L_PARENT) {
215
            } else if (lflag & L_PARENT) {
219
                /* return parent */
216
                /* return parent */
220
                ipc_answer_5(rid, EOK, fs_handle, dev_handle,
217
                ipc_answer_5(rid, EOK, fs_handle, dev_handle,
221
                    ops->index_get(cur), ops->size_get(cur),
218
                    ops->index_get(cur), ops->size_get(cur),
222
                    ops->lnkcnt_get(cur));
219
                    ops->lnkcnt_get(cur));
223
            }
220
            }
224
            ipc_answer_0(rid, ENOENT);
221
            ipc_answer_0(rid, ENOENT);
225
            return;
222
            goto out;
226
        }
223
        }
227
 
224
 
-
 
225
        if (par)
-
 
226
            ops->node_put(par);
-
 
227
 
228
        /* descend one level */
228
        /* descend one level */
229
        par = cur;
229
        par = cur;
230
        cur = tmp;
230
        cur = tmp;
231
        tmp = ops->child_get(tmp);
231
        tmp = NULL;
232
    }
232
    }
233
 
233
 
234
    /* handle miss: excessive components */
234
    /* handle miss: excessive components */
235
    if (!tmp && next <= last) {
235
    if (!ops->has_children(cur) && next <= last) {
236
        if (lflag & (L_CREATE | L_LINK)) {
236
        if (lflag & (L_CREATE | L_LINK)) {
237
            if (!ops->is_directory(cur)) {
237
            if (!ops->is_directory(cur)) {
238
                ipc_answer_0(rid, ENOTDIR);
238
                ipc_answer_0(rid, ENOTDIR);
239
                return;
239
                goto out;
240
            }
240
            }
241
 
241
 
242
            /* collect next component */
242
            /* collect next component */
-
 
243
            len = 0;
243
            while (next <= last) {
244
            while (next <= last) {
244
                if (ops->plb_get_char(next) == '/') {
245
                if (ops->plb_get_char(next) == '/') {
245
                    /* more than one component */
246
                    /* more than one component */
246
                    ipc_answer_0(rid, ENOENT);
247
                    ipc_answer_0(rid, ENOENT);
247
                    return;
248
                    goto out;
248
                }
249
                }
249
                if (len + 1 == NAME_MAX) {
250
                if (len + 1 == NAME_MAX) {
250
                    /* component length overflow */
251
                    /* component length overflow */
251
                    ipc_answer_0(rid, ENAMETOOLONG);
252
                    ipc_answer_0(rid, ENAMETOOLONG);
252
                    return;
253
                    goto out;
253
                }
254
                }
254
                component[len++] = ops->plb_get_char(next);
255
                component[len++] = ops->plb_get_char(next);
255
                next++; /* process next character */
256
                next++; /* process next character */
256
            }
257
            }
257
            assert(len);
258
            assert(len);
258
            component[len] = '\0';
259
            component[len] = '\0';
259
            len = 0;
-
 
260
               
260
               
261
            void *nodep;
261
            void *nodep;
262
            if (lflag & L_CREATE)
262
            if (lflag & L_CREATE)
263
                nodep = ops->create(lflag);
263
                nodep = ops->create(lflag);
264
            else
264
            else
265
                nodep = ops->node_get(fs_handle, dev_handle,
265
                nodep = ops->node_get(dev_handle, index);
266
                    index);
-
 
267
            if (nodep) {
266
            if (nodep) {
268
                if (!ops->link(cur, nodep, component)) {
267
                if (!ops->link(cur, nodep, component)) {
269
                    if (lflag & L_CREATE)
268
                    if (lflag & L_CREATE)
270
                        ops->destroy(nodep);
269
                        (void)ops->destroy(nodep);
271
                    ipc_answer_0(rid, ENOSPC);
270
                    ipc_answer_0(rid, ENOSPC);
272
                } else {
271
                } else {
273
                    ipc_answer_5(rid, EOK,
272
                    ipc_answer_5(rid, EOK,
274
                        fs_handle, dev_handle,
273
                        fs_handle, dev_handle,
275
                        ops->index_get(nodep),
274
                        ops->index_get(nodep),
276
                        ops->size_get(nodep),
275
                        ops->size_get(nodep),
277
                        ops->lnkcnt_get(nodep));
276
                        ops->lnkcnt_get(nodep));
-
 
277
                    ops->node_put(nodep);
278
                }
278
                }
279
            } else {
279
            } else {
280
                ipc_answer_0(rid, ENOSPC);
280
                ipc_answer_0(rid, ENOSPC);
281
            }
281
            }
282
            return;
282
            goto out;
283
        }
283
        }
284
        ipc_answer_0(rid, ENOENT);
284
        ipc_answer_0(rid, ENOENT);
285
        return;
285
        goto out;
286
    }
286
    }
287
 
287
 
288
    /* handle hit */
288
    /* handle hit */
289
    if (lflag & L_PARENT) {
289
    if (lflag & L_PARENT) {
-
 
290
        ops->node_put(cur);
290
        cur = par;
291
        cur = par;
-
 
292
        par = NULL;
291
        if (!cur) {
293
        if (!cur) {
292
            ipc_answer_0(rid, ENOENT);
294
            ipc_answer_0(rid, ENOENT);
293
            return;
295
            goto out;
294
        }
296
        }
295
    }
297
    }
296
    if (lflag & L_UNLINK) {
298
    if (lflag & L_UNLINK) {
297
        unsigned old_lnkcnt = ops->lnkcnt_get(cur);
299
        unsigned old_lnkcnt = ops->lnkcnt_get(cur);
298
        int res = ops->unlink(par, cur);
300
        int res = ops->unlink(par, cur);
299
        ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
301
        ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
300
            ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
302
            ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
301
        return;
303
        goto out;
302
    }
304
    }
303
    if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) ||
305
    if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) ||
304
        (lflag & L_LINK)) {
306
        (lflag & L_LINK)) {
305
        ipc_answer_0(rid, EEXIST);
307
        ipc_answer_0(rid, EEXIST);
306
        return;
308
        goto out;
307
    }
309
    }
308
    if ((lflag & L_FILE) && (ops->is_directory(cur))) {
310
    if ((lflag & L_FILE) && (ops->is_directory(cur))) {
309
        ipc_answer_0(rid, EISDIR);
311
        ipc_answer_0(rid, EISDIR);
310
        return;
312
        goto out;
311
    }
313
    }
312
    if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
314
    if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
313
        ipc_answer_0(rid, ENOTDIR);
315
        ipc_answer_0(rid, ENOTDIR);
314
        return;
316
        goto out;
315
    }
317
    }
316
 
318
 
317
    ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur),
319
    ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur),
318
        ops->size_get(cur), ops->lnkcnt_get(cur));
320
        ops->size_get(cur), ops->lnkcnt_get(cur));
-
 
321
 
-
 
322
out:
-
 
323
    if (par)
-
 
324
        ops->node_put(par);
-
 
325
    if (cur)
-
 
326
        ops->node_put(cur);
-
 
327
    if (tmp)
-
 
328
        ops->node_put(tmp);
319
}
329
}
320
 
330
 
321
/** @}
331
/** @}
322
 */
332
 */